IPF Tools source

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/IPF-Tools@1846 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/Source/Common/CommonLib.c b/Source/Common/CommonLib.c
new file mode 100644
index 0000000..618abd8
--- /dev/null
+++ b/Source/Common/CommonLib.c
@@ -0,0 +1,516 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  CommonLib.c

+

+Abstract:

+

+  Common Library Functions

+ 

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include "CommonLib.h"

+

+VOID

+PeiZeroMem (

+  IN VOID   *Buffer,

+  IN UINTN  Size

+  )

+/*++

+

+Routine Description:

+

+  Set Buffer to zero for Size bytes.

+

+Arguments:

+

+  Buffer  - Memory to set.

+

+  Size    - Number of bytes to set

+

+Returns:

+

+  None

+

+--*/

+{

+  INT8  *Ptr;

+

+  Ptr = Buffer;

+  while (Size--) {

+    *(Ptr++) = 0;

+  }

+}

+

+VOID

+PeiCopyMem (

+  IN VOID   *Destination,

+  IN VOID   *Source,

+  IN UINTN  Length

+  )

+/*++

+

+Routine Description:

+

+  Copy Length bytes from Source to Destination.

+

+Arguments:

+

+  Destination - Target of copy

+

+  Source      - Place to copy from

+

+  Length      - Number of bytes to copy

+

+Returns:

+

+  None

+

+--*/

+{

+  CHAR8 *Destination8;

+  CHAR8 *Source8;

+

+  Destination8  = Destination;

+  Source8       = Source;

+  while (Length--) {

+    *(Destination8++) = *(Source8++);

+  }

+}

+

+VOID

+ZeroMem (

+  IN VOID   *Buffer,

+  IN UINTN  Size

+  )

+{

+  PeiZeroMem (Buffer, Size);

+}

+

+VOID

+CopyMem (

+  IN VOID   *Destination,

+  IN VOID   *Source,

+  IN UINTN  Length

+  )

+{

+  PeiCopyMem (Destination, Source, Length);

+}

+

+INTN

+CompareGuid (

+  IN EFI_GUID     *Guid1,

+  IN EFI_GUID     *Guid2

+  )

+/*++

+

+Routine Description:

+

+  Compares to GUIDs

+

+Arguments:

+

+  Guid1 - guid to compare

+  Guid2 - guid to compare

+

+Returns:

+  =  0  if Guid1 == Guid2

+  != 0  if Guid1 != Guid2 

+

+--*/

+{

+  INT32 *g1;

+  INT32 *g2;

+  INT32 r;

+

+  //

+  // Compare 32 bits at a time

+  //

+  g1  = (INT32 *) Guid1;

+  g2  = (INT32 *) Guid2;

+

+  r   = g1[0] - g2[0];

+  r |= g1[1] - g2[1];

+  r |= g1[2] - g2[2];

+  r |= g1[3] - g2[3];

+

+  return r;

+}

+

+EFI_STATUS

+GetFileImage (

+  IN CHAR8    *InputFileName,

+  OUT CHAR8   **InputFileImage,

+  OUT UINT32  *BytesRead

+  )

+/*++

+

+Routine Description:

+

+  This function opens a file and reads it into a memory buffer.  The function 

+  will allocate the memory buffer and returns the size of the buffer.

+

+Arguments:

+

+  InputFileName     The name of the file to read.

+  InputFileImage    A pointer to the memory buffer.

+  BytesRead         The size of the memory buffer.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              An error occurred.

+  EFI_OUT_OF_RESOURCES     No resource to complete operations.

+

+--*/

+{

+  FILE    *InputFile;

+  UINT32  FileSize;

+

+  //

+  // Verify input parameters.

+  //

+  if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Open the file and copy contents into a memory buffer.

+  //

+  //

+  // Open the file

+  //

+  InputFile = fopen (InputFileName, "rb");

+  if (InputFile == NULL) {

+    printf ("ERROR: Could not open input file \"%s\".\n", InputFileName);

+    return EFI_ABORTED;

+  }

+  //

+  // Go to the end so that we can determine the file size

+  //

+  if (fseek (InputFile, 0, SEEK_END)) {

+    printf ("ERROR: System error reading input file \"%s\".\n", InputFileName);

+    fclose (InputFile);

+    return EFI_ABORTED;

+  }

+  //

+  // Get the file size

+  //

+  FileSize = ftell (InputFile);

+  if (FileSize == -1) {

+    printf ("ERROR: System error parsing input file \"%s\".\n", InputFileName);

+    fclose (InputFile);

+    return EFI_ABORTED;

+  }

+  //

+  // Allocate a buffer

+  //

+  *InputFileImage = malloc (FileSize);

+  if (*InputFileImage == NULL) {

+    fclose (InputFile);

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Reset to the beginning of the file

+  //

+  if (fseek (InputFile, 0, SEEK_SET)) {

+    printf ("ERROR: System error reading input file \"%s\".\n", InputFileName);

+    fclose (InputFile);

+    free (*InputFileImage);

+    *InputFileImage = NULL;

+    return EFI_ABORTED;

+  }

+  //

+  // Read all of the file contents.

+  //

+  *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);

+  if (*BytesRead != sizeof (UINT8) * FileSize) {

+    printf ("ERROR: Reading file \"%s\"%i.\n", InputFileName);

+    fclose (InputFile);

+    free (*InputFileImage);

+    *InputFileImage = NULL;

+    return EFI_ABORTED;

+  }

+  //

+  // Close the file

+  //

+  fclose (InputFile);

+

+  return EFI_SUCCESS;

+}

+

+UINT8

+CalculateChecksum8 (

+  IN UINT8        *Buffer,

+  IN UINTN        Size

+  )

+/*++

+  

+Routine Description:

+

+  This function calculates the value needed for a valid UINT8 checksum

+

+Arguments:

+

+  Buffer      Pointer to buffer containing byte data of component.

+  Size        Size of the buffer

+

+Returns:

+

+  The 8 bit checksum value needed.

+

+--*/

+{

+  return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));

+}

+

+UINT8

+CalculateSum8 (

+  IN UINT8  *Buffer,

+  IN UINTN  Size

+  )

+/*++

+  

+Routine Description::

+

+  This function calculates the UINT8 sum for the requested region.

+

+Arguments:

+

+  Buffer      Pointer to buffer containing byte data of component.

+  Size        Size of the buffer

+

+Returns:

+

+  The 8 bit checksum value needed.

+

+--*/

+{

+  UINTN Index;

+  UINT8 Sum;

+

+  Sum = 0;

+

+  //

+  // Perform the byte sum for buffer

+  //

+  for (Index = 0; Index < Size; Index++) {

+    Sum = (UINT8) (Sum + Buffer[Index]);

+  }

+

+  return Sum;

+}

+

+UINT16

+CalculateChecksum16 (

+  IN UINT16       *Buffer,

+  IN UINTN        Size

+  )

+/*++

+  

+Routine Description::

+

+  This function calculates the value needed for a valid UINT16 checksum

+

+Arguments:

+

+  Buffer      Pointer to buffer containing byte data of component.

+  Size        Size of the buffer

+

+Returns:

+

+  The 16 bit checksum value needed.

+

+--*/

+{

+  return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));

+}

+

+UINT16

+CalculateSum16 (

+  IN UINT16       *Buffer,

+  IN UINTN        Size

+  )

+/*++

+  

+Routine Description:

+

+  This function calculates the UINT16 sum for the requested region.

+

+Arguments:

+

+  Buffer      Pointer to buffer containing byte data of component.

+  Size        Size of the buffer

+

+Returns:

+

+  The 16 bit checksum

+

+--*/

+{

+  UINTN   Index;

+  UINT16  Sum;

+

+  Sum = 0;

+

+  //

+  // Perform the word sum for buffer

+  //

+  for (Index = 0; Index < Size; Index++) {

+    Sum = (UINT16) (Sum + Buffer[Index]);

+  }

+

+  return (UINT16) Sum;

+}

+

+EFI_STATUS

+PrintGuid (

+  IN EFI_GUID *Guid

+  )

+/*++

+

+Routine Description:

+

+  This function prints a GUID to STDOUT.

+

+Arguments:

+

+  Guid    Pointer to a GUID to print.

+

+Returns:

+

+  EFI_SUCCESS             The GUID was printed.

+  EFI_INVALID_PARAMETER   The input was NULL.

+

+--*/

+{

+  if (Guid == NULL) {

+    printf ("ERROR: PrintGuid called with a NULL value.\n");

+    return EFI_INVALID_PARAMETER;

+  }

+

+  printf (

+    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",

+    Guid->Data1,

+    Guid->Data2,

+    Guid->Data3,

+    Guid->Data4[0],

+    Guid->Data4[1],

+    Guid->Data4[2],

+    Guid->Data4[3],

+    Guid->Data4[4],

+    Guid->Data4[5],

+    Guid->Data4[6],

+    Guid->Data4[7]

+    );

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PrintGuidToBuffer (

+  IN EFI_GUID     *Guid,

+  IN OUT UINT8    *Buffer,

+  IN UINT32       BufferLen,

+  IN BOOLEAN      Uppercase

+  )

+/*++

+

+Routine Description:

+

+  This function prints a GUID to a buffer

+

+Arguments:

+

+  Guid      - Pointer to a GUID to print.

+  Buffer    - Pointer to a user-provided buffer to print to

+  BufferLen - Size of the Buffer

+  Uppercase - If use upper case.

+

+Returns:

+

+  EFI_SUCCESS             The GUID was printed.

+  EFI_INVALID_PARAMETER   The input was NULL.

+  EFI_BUFFER_TOO_SMALL    The input buffer was not big enough

+  

+--*/

+{

+  if (Guid == NULL) {

+    printf ("ERROR: PrintGuidToBuffer() called with a NULL value\n");

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {

+    printf ("ERORR: PrintGuidToBuffer() called with invalid buffer size\n");

+    return EFI_BUFFER_TOO_SMALL;

+  }

+

+  if (Uppercase) {

+    sprintf (

+      Buffer,

+      "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",

+      Guid->Data1,

+      Guid->Data2,

+      Guid->Data3,

+      Guid->Data4[0],

+      Guid->Data4[1],

+      Guid->Data4[2],

+      Guid->Data4[3],

+      Guid->Data4[4],

+      Guid->Data4[5],

+      Guid->Data4[6],

+      Guid->Data4[7]

+      );

+  } else {

+    sprintf (

+      Buffer,

+      "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",

+      Guid->Data1,

+      Guid->Data2,

+      Guid->Data3,

+      Guid->Data4[0],

+      Guid->Data4[1],

+      Guid->Data4[2],

+      Guid->Data4[3],

+      Guid->Data4[4],

+      Guid->Data4[5],

+      Guid->Data4[6],

+      Guid->Data4[7]

+      );

+  }

+

+  return EFI_SUCCESS;

+}

+

+#ifdef __GNUC__

+

+size_t _filelength(FILE *file)

+{

+  struct stat stat_buf;

+  fstat(fileno(file), &stat_buf);

+  return stat_buf.st_size;

+}

+

+#ifndef __CYGWIN__

+char *strlwr(char *s)

+{

+  char *p = s;

+  for(;*s;s++) {

+    *s = tolower(*s);

+  }

+  return p;

+}

+#endif

+#endif

diff --git a/Source/Common/CommonLib.h b/Source/Common/CommonLib.h
new file mode 100644
index 0000000..f6c29ef
--- /dev/null
+++ b/Source/Common/CommonLib.h
@@ -0,0 +1,139 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  CommonLib.h

+

+Abstract:

+

+  Common library assistance routines.

+

+--*/

+

+#ifndef _EFI_COMMON_LIB_H

+#define _EFI_COMMON_LIB_H

+

+#include <Common/UefiBaseTypes.h>

+

+#ifndef _MAX_PATH

+#define _MAX_PATH 500

+#endif

+

+#define PRINTED_GUID_BUFFER_SIZE  37  // including null-termination

+//

+// Function declarations

+//

+VOID

+PeiZeroMem (

+  IN VOID   *Buffer,

+  IN UINTN  Size

+  )

+;

+

+VOID

+PeiCopyMem (

+  IN VOID   *Destination,

+  IN VOID   *Source,

+  IN UINTN  Length

+  )

+;

+

+VOID

+ZeroMem (

+  IN VOID   *Buffer,

+  IN UINTN  Size

+  )

+;

+

+VOID

+CopyMem (

+  IN VOID   *Destination,

+  IN VOID   *Source,

+  IN UINTN  Length

+  )

+;

+

+INTN

+CompareGuid (

+  IN EFI_GUID     *Guid1,

+  IN EFI_GUID     *Guid2

+  )

+;

+

+EFI_STATUS

+GetFileImage (

+  IN CHAR8    *InputFileName,

+  OUT CHAR8   **InputFileImage,

+  OUT UINT32  *BytesRead

+  )

+;

+

+UINT8

+CalculateChecksum8 (

+  IN UINT8        *Buffer,

+  IN UINTN        Size

+  )

+;

+

+UINT8

+CalculateSum8 (

+  IN UINT8        *Buffer,

+  IN UINTN        Size

+  )

+;

+

+UINT16

+CalculateChecksum16 (

+  IN UINT16       *Buffer,

+  IN UINTN        Size

+  )

+;

+

+UINT16

+CalculateSum16 (

+  IN UINT16       *Buffer,

+  IN UINTN        Size

+  )

+;

+

+EFI_STATUS

+PrintGuid (

+  IN EFI_GUID                     *Guid

+  )

+;

+

+#define PRINTED_GUID_BUFFER_SIZE  37  // including null-termination

+EFI_STATUS

+PrintGuidToBuffer (

+  IN EFI_GUID     *Guid,

+  IN OUT UINT8    *Buffer,

+  IN UINT32       BufferLen,

+  IN BOOLEAN      Uppercase

+  )

+;

+

+#define ASSERT(x) assert(x)

+

+#ifdef __GNUC__

+#include <stdio.h>

+#include <sys/stat.h>

+#define stricmp strcasecmp

+#define _stricmp strcasecmp

+#define strnicmp strncasecmp

+#define strcmpi strcasecmp

+size_t _filelength(FILE *file);

+#ifndef __CYGWIN__

+char *strlwr(char *s);

+#endif

+#endif

+

+#endif

diff --git a/Source/Common/Crc32.c b/Source/Common/Crc32.c
new file mode 100644
index 0000000..4ae5eb4
--- /dev/null
+++ b/Source/Common/Crc32.c
@@ -0,0 +1,326 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  crc32.c

+

+Abstract:

+

+  CalcuateCrc32 routine.

+  

+--*/

+

+#include <stdlib.h>

+#include "Crc32.h"

+

+UINT32  mCrcTable[256] = {

+  0x00000000,

+  0x77073096,

+  0xEE0E612C,

+  0x990951BA,

+  0x076DC419,

+  0x706AF48F,

+  0xE963A535,

+  0x9E6495A3,

+  0x0EDB8832,

+  0x79DCB8A4,

+  0xE0D5E91E,

+  0x97D2D988,

+  0x09B64C2B,

+  0x7EB17CBD,

+  0xE7B82D07,

+  0x90BF1D91,

+  0x1DB71064,

+  0x6AB020F2,

+  0xF3B97148,

+  0x84BE41DE,

+  0x1ADAD47D,

+  0x6DDDE4EB,

+  0xF4D4B551,

+  0x83D385C7,

+  0x136C9856,

+  0x646BA8C0,

+  0xFD62F97A,

+  0x8A65C9EC,

+  0x14015C4F,

+  0x63066CD9,

+  0xFA0F3D63,

+  0x8D080DF5,

+  0x3B6E20C8,

+  0x4C69105E,

+  0xD56041E4,

+  0xA2677172,

+  0x3C03E4D1,

+  0x4B04D447,

+  0xD20D85FD,

+  0xA50AB56B,

+  0x35B5A8FA,

+  0x42B2986C,

+  0xDBBBC9D6,

+  0xACBCF940,

+  0x32D86CE3,

+  0x45DF5C75,

+  0xDCD60DCF,

+  0xABD13D59,

+  0x26D930AC,

+  0x51DE003A,

+  0xC8D75180,

+  0xBFD06116,

+  0x21B4F4B5,

+  0x56B3C423,

+  0xCFBA9599,

+  0xB8BDA50F,

+  0x2802B89E,

+  0x5F058808,

+  0xC60CD9B2,

+  0xB10BE924,

+  0x2F6F7C87,

+  0x58684C11,

+  0xC1611DAB,

+  0xB6662D3D,

+  0x76DC4190,

+  0x01DB7106,

+  0x98D220BC,

+  0xEFD5102A,

+  0x71B18589,

+  0x06B6B51F,

+  0x9FBFE4A5,

+  0xE8B8D433,

+  0x7807C9A2,

+  0x0F00F934,

+  0x9609A88E,

+  0xE10E9818,

+  0x7F6A0DBB,

+  0x086D3D2D,

+  0x91646C97,

+  0xE6635C01,

+  0x6B6B51F4,

+  0x1C6C6162,

+  0x856530D8,

+  0xF262004E,

+  0x6C0695ED,

+  0x1B01A57B,

+  0x8208F4C1,

+  0xF50FC457,

+  0x65B0D9C6,

+  0x12B7E950,

+  0x8BBEB8EA,

+  0xFCB9887C,

+  0x62DD1DDF,

+  0x15DA2D49,

+  0x8CD37CF3,

+  0xFBD44C65,

+  0x4DB26158,

+  0x3AB551CE,

+  0xA3BC0074,

+  0xD4BB30E2,

+  0x4ADFA541,

+  0x3DD895D7,

+  0xA4D1C46D,

+  0xD3D6F4FB,

+  0x4369E96A,

+  0x346ED9FC,

+  0xAD678846,

+  0xDA60B8D0,

+  0x44042D73,

+  0x33031DE5,

+  0xAA0A4C5F,

+  0xDD0D7CC9,

+  0x5005713C,

+  0x270241AA,

+  0xBE0B1010,

+  0xC90C2086,

+  0x5768B525,

+  0x206F85B3,

+  0xB966D409,

+  0xCE61E49F,

+  0x5EDEF90E,

+  0x29D9C998,

+  0xB0D09822,

+  0xC7D7A8B4,

+  0x59B33D17,

+  0x2EB40D81,

+  0xB7BD5C3B,

+  0xC0BA6CAD,

+  0xEDB88320,

+  0x9ABFB3B6,

+  0x03B6E20C,

+  0x74B1D29A,

+  0xEAD54739,

+  0x9DD277AF,

+  0x04DB2615,

+  0x73DC1683,

+  0xE3630B12,

+  0x94643B84,

+  0x0D6D6A3E,

+  0x7A6A5AA8,

+  0xE40ECF0B,

+  0x9309FF9D,

+  0x0A00AE27,

+  0x7D079EB1,

+  0xF00F9344,

+  0x8708A3D2,

+  0x1E01F268,

+  0x6906C2FE,

+  0xF762575D,

+  0x806567CB,

+  0x196C3671,

+  0x6E6B06E7,

+  0xFED41B76,

+  0x89D32BE0,

+  0x10DA7A5A,

+  0x67DD4ACC,

+  0xF9B9DF6F,

+  0x8EBEEFF9,

+  0x17B7BE43,

+  0x60B08ED5,

+  0xD6D6A3E8,

+  0xA1D1937E,

+  0x38D8C2C4,

+  0x4FDFF252,

+  0xD1BB67F1,

+  0xA6BC5767,

+  0x3FB506DD,

+  0x48B2364B,

+  0xD80D2BDA,

+  0xAF0A1B4C,

+  0x36034AF6,

+  0x41047A60,

+  0xDF60EFC3,

+  0xA867DF55,

+  0x316E8EEF,

+  0x4669BE79,

+  0xCB61B38C,

+  0xBC66831A,

+  0x256FD2A0,

+  0x5268E236,

+  0xCC0C7795,

+  0xBB0B4703,

+  0x220216B9,

+  0x5505262F,

+  0xC5BA3BBE,

+  0xB2BD0B28,

+  0x2BB45A92,

+  0x5CB36A04,

+  0xC2D7FFA7,

+  0xB5D0CF31,

+  0x2CD99E8B,

+  0x5BDEAE1D,

+  0x9B64C2B0,

+  0xEC63F226,

+  0x756AA39C,

+  0x026D930A,

+  0x9C0906A9,

+  0xEB0E363F,

+  0x72076785,

+  0x05005713,

+  0x95BF4A82,

+  0xE2B87A14,

+  0x7BB12BAE,

+  0x0CB61B38,

+  0x92D28E9B,

+  0xE5D5BE0D,

+  0x7CDCEFB7,

+  0x0BDBDF21,

+  0x86D3D2D4,

+  0xF1D4E242,

+  0x68DDB3F8,

+  0x1FDA836E,

+  0x81BE16CD,

+  0xF6B9265B,

+  0x6FB077E1,

+  0x18B74777,

+  0x88085AE6,

+  0xFF0F6A70,

+  0x66063BCA,

+  0x11010B5C,

+  0x8F659EFF,

+  0xF862AE69,

+  0x616BFFD3,

+  0x166CCF45,

+  0xA00AE278,

+  0xD70DD2EE,

+  0x4E048354,

+  0x3903B3C2,

+  0xA7672661,

+  0xD06016F7,

+  0x4969474D,

+  0x3E6E77DB,

+  0xAED16A4A,

+  0xD9D65ADC,

+  0x40DF0B66,

+  0x37D83BF0,

+  0xA9BCAE53,

+  0xDEBB9EC5,

+  0x47B2CF7F,

+  0x30B5FFE9,

+  0xBDBDF21C,

+  0xCABAC28A,

+  0x53B39330,

+  0x24B4A3A6,

+  0xBAD03605,

+  0xCDD70693,

+  0x54DE5729,

+  0x23D967BF,

+  0xB3667A2E,

+  0xC4614AB8,

+  0x5D681B02,

+  0x2A6F2B94,

+  0xB40BBE37,

+  0xC30C8EA1,

+  0x5A05DF1B,

+  0x2D02EF8D

+};

+

+EFI_STATUS

+CalculateCrc32 (

+  IN  UINT8                             *Data,

+  IN  UINTN                             DataSize,

+  IN OUT UINT32                         *CrcOut

+  )

+/*++

+

+Routine Description:

+

+  The CalculateCrc32 routine.

+

+Arguments:

+

+  Data        - The buffer contaning the data to be processed

+  DataSize    - The size of data to be processed

+  CrcOut      - A pointer to the caller allocated UINT32 that on

+                contains the CRC32 checksum of Data

+

+Returns:

+

+  EFI_SUCCESS               - Calculation is successful.

+  EFI_INVALID_PARAMETER     - Data / CrcOut = NULL, or DataSize = 0

+

+--*/

+{

+  UINT32  Crc;

+  UINTN   Index;

+  UINT8   *Ptr;

+

+  if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Crc = 0xffffffff;

+  for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {

+    Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];

+  }

+

+  *CrcOut = Crc ^ 0xffffffff;

+

+  return EFI_SUCCESS;

+}

diff --git a/Source/Common/Crc32.h b/Source/Common/Crc32.h
new file mode 100644
index 0000000..ec48cdd
--- /dev/null
+++ b/Source/Common/Crc32.h
@@ -0,0 +1,54 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  Crc32.h

+

+Abstract:

+

+  Header file for CalcuateCrc32 routine

+  

+--*/

+

+#ifndef _CRC32_H

+#define _CRC32_H

+

+#include <Common/UefiBaseTypes.h>

+

+EFI_STATUS

+CalculateCrc32 (

+  IN  UINT8                             *Data,

+  IN  UINTN                             DataSize,

+  IN OUT UINT32                         *CrcOut

+  )

+/*++

+

+Routine Description:

+

+  The CalculateCrc32 routine.

+

+Arguments:

+

+  Data        - The buffer contaning the data to be processed

+  DataSize    - The size of data to be processed

+  CrcOut      - A pointer to the caller allocated UINT32 that on

+                contains the CRC32 checksum of Data

+

+Returns:

+

+  EFI_SUCCESS               - Calculation is successful.

+  EFI_INVALID_PARAMETER     - Data / CrcOut = NULL, or DataSize = 0

+

+--*/

+;

+

+#endif

diff --git a/Source/Common/EfiCompress.c b/Source/Common/EfiCompress.c
new file mode 100644
index 0000000..5b91b1d
--- /dev/null
+++ b/Source/Common/EfiCompress.c
@@ -0,0 +1,1742 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiCompress.c

+

+Abstract:

+

+  Compression routine. The compression algorithm is a mixture of

+  LZ77 and Huffman coding. LZ77 transforms the source data into a

+  sequence of Original Characters and Pointers to repeated strings.

+  This sequence is further divided into Blocks and Huffman codings

+  are applied to each Block.

+

+--*/

+

+#include "EfiCompress.h"

+

+//

+// Macro Definitions

+//

+typedef INT32 NODE;

+#define UINT8_BIT     8

+#define THRESHOLD     3

+#define INIT_CRC      0

+#define WNDBIT        19

+#define WNDSIZ        (1U << WNDBIT)

+#define MAXMATCH      256

+#define BLKSIZ        (1U << 14)  // 16 * 1024U

+#define PERC_FLAG     0x80000000U

+#define CODE_BIT      16

+#define NIL           0

+#define MAX_HASH_VAL  (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)

+#define HASH(p, c)    ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)

+#define CRCPOLY       0xA001

+#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)

+

+//

+// C: the Char&Len Set; P: the Position Set; T: the exTra Set

+//

+#define NC    (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)

+#define CBIT  9

+#define NP    (WNDBIT + 1)

+#define PBIT  5

+#define NT    (CODE_BIT + 3)

+#define TBIT  5

+#if NT > NP

+#define NPT NT

+#else

+#define NPT NP

+#endif

+//

+// Function Prototypes

+//

+STATIC VOID PutDword(IN UINT32 Data);

+

+STATIC

+EFI_STATUS

+AllocateMemory (

+  VOID

+  );

+

+STATIC

+VOID

+FreeMemory (

+  VOID

+  );

+

+STATIC

+VOID

+InitSlide (

+  VOID

+  );

+

+STATIC

+NODE

+Child (

+  IN NODE   NodeQ,

+  IN UINT8  CharC

+  );

+

+STATIC

+VOID

+MakeChild (

+  IN NODE  NodeQ,

+  IN UINT8 CharC,

+  IN NODE  NodeR

+  );

+

+STATIC

+VOID

+Split (

+  IN NODE Old

+  );

+

+STATIC

+VOID

+InsertNode (

+  VOID

+  );

+

+STATIC

+VOID

+DeleteNode (

+  VOID

+  );

+

+STATIC

+VOID

+GetNextMatch (

+  VOID

+  );

+

+STATIC

+EFI_STATUS

+Encode (

+  VOID

+  );

+

+STATIC

+VOID

+CountTFreq (

+  VOID

+  );

+

+STATIC

+VOID

+WritePTLen (

+  IN INT32 Number,

+  IN INT32 nbit,

+  IN INT32 Special

+  );

+

+STATIC

+VOID

+WriteCLen (

+  VOID

+  );

+

+STATIC

+VOID

+EncodeC (

+  IN INT32 Value

+  );

+

+STATIC

+VOID

+EncodeP (

+  IN UINT32 Value

+  );

+

+STATIC

+VOID

+SendBlock (

+  VOID

+  );

+

+STATIC

+VOID

+Output (

+  IN UINT32 c,

+  IN UINT32 p

+  );

+

+STATIC

+VOID

+HufEncodeStart (

+  VOID

+  );

+

+STATIC

+VOID

+HufEncodeEnd (

+  VOID

+  );

+

+STATIC

+VOID

+MakeCrcTable (

+  VOID

+  );

+

+STATIC

+VOID

+PutBits (

+  IN INT32  Number,

+  IN UINT32 Value

+  );

+

+STATIC

+INT32

+FreadCrc (

+  OUT UINT8 *Pointer,

+  IN  INT32 Number

+  );

+

+STATIC

+VOID

+InitPutBits (

+  VOID

+  );

+

+STATIC

+VOID

+CountLen (

+  IN INT32 Index

+  );

+

+STATIC

+VOID

+MakeLen (

+  IN INT32 Root

+  );

+

+STATIC

+VOID

+DownHeap (

+  IN INT32 Index

+  );

+

+STATIC

+VOID

+MakeCode (

+  IN  INT32       Number,

+  IN  UINT8 Len[  ],

+  OUT UINT16 Code[]

+  );

+

+STATIC

+INT32

+MakeTree (

+  IN  INT32            NParm,

+  IN  UINT16  FreqParm[],

+  OUT UINT8   LenParm[ ],

+  OUT UINT16  CodeParm[]

+  );

+

+//

+//  Global Variables

+//

+static UINT8  *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;

+

+static UINT8  *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;

+static INT16  mHeap[NC + 1];

+static INT32  mRemainder, mMatchLen, mBitCount, mHeapSize, mN;

+static UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;

+static UINT32 mCompSize, mOrigSize;

+

+static UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],

+  mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];

+

+static NODE   mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;

+

+//

+// functions

+//

+EFI_STATUS

+Compress (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  )

+/*++

+

+Routine Description:

+

+  The main compression routine.

+

+Arguments:

+

+  SrcBuffer   - The buffer storing the source data

+  SrcSize     - The size of source data

+  DstBuffer   - The buffer to store the compressed data

+  DstSize     - On input, the size of DstBuffer; On output,

+                the size of the actual compressed data.

+

+Returns:

+

+  EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,

+                DstSize contains the size needed.

+  EFI_SUCCESS           - Compression is successful.

+  EFI_OUT_OF_RESOURCES  - No resource to complete function.

+

+--*/

+{

+  EFI_STATUS  Status;

+

+  //

+  // Initializations

+  //

+  mBufSiz         = 0;

+  mBuf            = NULL;

+  mText           = NULL;

+  mLevel          = NULL;

+  mChildCount     = NULL;

+  mPosition       = NULL;

+  mParent         = NULL;

+  mPrev           = NULL;

+  mNext           = NULL;

+

+  mSrc            = SrcBuffer;

+  mSrcUpperLimit  = mSrc + SrcSize;

+  mDst            = DstBuffer;

+  mDstUpperLimit  = mDst +*DstSize;

+

+  PutDword (0L);

+  PutDword (0L);

+

+  MakeCrcTable ();

+

+  mOrigSize             = mCompSize = 0;

+  mCrc                  = INIT_CRC;

+

+  //

+  // Compress it

+  //

+  Status = Encode ();

+  if (EFI_ERROR (Status)) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Null terminate the compressed data

+  //

+  if (mDst < mDstUpperLimit) {

+    *mDst++ = 0;

+  }

+  //

+  // Fill in compressed size and original size

+  //

+  mDst = DstBuffer;

+  PutDword (mCompSize + 1);

+  PutDword (mOrigSize);

+

+  //

+  // Return

+  //

+  if (mCompSize + 1 + 8 > *DstSize) {

+    *DstSize = mCompSize + 1 + 8;

+    return EFI_BUFFER_TOO_SMALL;

+  } else {

+    *DstSize = mCompSize + 1 + 8;

+    return EFI_SUCCESS;

+  }

+

+}

+

+STATIC

+VOID

+PutDword (

+  IN UINT32 Data

+  )

+/*++

+

+Routine Description:

+

+  Put a dword to output stream

+  

+Arguments:

+

+  Data    - the dword to put

+  

+Returns: (VOID)

+  

+--*/

+{

+  if (mDst < mDstUpperLimit) {

+    *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);

+  }

+

+  if (mDst < mDstUpperLimit) {

+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);

+  }

+

+  if (mDst < mDstUpperLimit) {

+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);

+  }

+

+  if (mDst < mDstUpperLimit) {

+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);

+  }

+}

+

+STATIC

+EFI_STATUS

+AllocateMemory (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Allocate memory spaces for data structures used in compression process

+  

+Argements: 

+  VOID

+

+Returns:

+

+  EFI_SUCCESS           - Memory is allocated successfully

+  EFI_OUT_OF_RESOURCES  - Allocation fails

+

+--*/

+{

+  UINT32  Index;

+

+  mText = malloc (WNDSIZ * 2 + MAXMATCH);

+  for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {

+    mText[Index] = 0;

+  }

+

+  mLevel      = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));

+  mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));

+  mPosition   = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));

+  mParent     = malloc (WNDSIZ * 2 * sizeof (*mParent));

+  mPrev       = malloc (WNDSIZ * 2 * sizeof (*mPrev));

+  mNext       = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));

+

+  mBufSiz     = BLKSIZ;

+  mBuf        = malloc (mBufSiz);

+  while (mBuf == NULL) {

+    mBufSiz = (mBufSiz / 10U) * 9U;

+    if (mBufSiz < 4 * 1024U) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    mBuf = malloc (mBufSiz);

+  }

+

+  mBuf[0] = 0;

+

+  return EFI_SUCCESS;

+}

+

+VOID

+FreeMemory (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Called when compression is completed to free memory previously allocated.

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  if (mText != NULL) {

+    free (mText);

+  }

+

+  if (mLevel != NULL) {

+    free (mLevel);

+  }

+

+  if (mChildCount != NULL) {

+    free (mChildCount);

+  }

+

+  if (mPosition != NULL) {

+    free (mPosition);

+  }

+

+  if (mParent != NULL) {

+    free (mParent);

+  }

+

+  if (mPrev != NULL) {

+    free (mPrev);

+  }

+

+  if (mNext != NULL) {

+    free (mNext);

+  }

+

+  if (mBuf != NULL) {

+    free (mBuf);

+  }

+

+  return ;

+}

+

+STATIC

+VOID

+InitSlide (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Initialize String Info Log data structures

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  NODE  Index;

+

+  for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {

+    mLevel[Index]     = 1;

+    mPosition[Index]  = NIL;  /* sentinel */

+  }

+

+  for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {

+    mParent[Index] = NIL;

+  }

+

+  mAvail = 1;

+  for (Index = 1; Index < WNDSIZ - 1; Index++) {

+    mNext[Index] = (NODE) (Index + 1);

+  }

+

+  mNext[WNDSIZ - 1] = NIL;

+  for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {

+    mNext[Index] = NIL;

+  }

+}

+

+STATIC

+NODE

+Child (

+  IN NODE  NodeQ,

+  IN UINT8 CharC

+  )

+/*++

+

+Routine Description:

+

+  Find child node given the parent node and the edge character

+  

+Arguments:

+

+  NodeQ       - the parent node

+  CharC       - the edge character

+  

+Returns:

+

+  The child node (NIL if not found)  

+  

+--*/

+{

+  NODE  NodeR;

+

+  NodeR = mNext[HASH (NodeQ, CharC)];

+  //

+  // sentinel

+  //

+  mParent[NIL] = NodeQ;

+  while (mParent[NodeR] != NodeQ) {

+    NodeR = mNext[NodeR];

+  }

+

+  return NodeR;

+}

+

+STATIC

+VOID

+MakeChild (

+  IN NODE  Parent,

+  IN UINT8 CharC,

+  IN NODE  Child

+  )

+/*++

+

+Routine Description:

+

+  Create a new child for a given parent node.

+  

+Arguments:

+

+  Parent       - the parent node

+  CharC   - the edge character

+  Child       - the child node

+  

+Returns: (VOID)

+

+--*/

+{

+  NODE  Node1;

+  NODE  Node2;

+

+  Node1           = (NODE) HASH (Parent, CharC);

+  Node2           = mNext[Node1];

+  mNext[Node1]    = Child;

+  mNext[Child]    = Node2;

+  mPrev[Node2]    = Child;

+  mPrev[Child]    = Node1;

+  mParent[Child]  = Parent;

+  mChildCount[Parent]++;

+}

+

+STATIC

+VOID

+Split (

+  NODE Old

+  )

+/*++

+

+Routine Description:

+

+  Split a node.

+  

+Arguments:

+

+  Old     - the node to split

+  

+Returns: (VOID)

+

+--*/

+{

+  NODE  New;

+  NODE  TempNode;

+

+  New               = mAvail;

+  mAvail            = mNext[New];

+  mChildCount[New]  = 0;

+  TempNode          = mPrev[Old];

+  mPrev[New]        = TempNode;

+  mNext[TempNode]   = New;

+  TempNode          = mNext[Old];

+  mNext[New]        = TempNode;

+  mPrev[TempNode]   = New;

+  mParent[New]      = mParent[Old];

+  mLevel[New]       = (UINT8) mMatchLen;

+  mPosition[New]    = mPos;

+  MakeChild (New, mText[mMatchPos + mMatchLen], Old);

+  MakeChild (New, mText[mPos + mMatchLen], mPos);

+}

+

+STATIC

+VOID

+InsertNode (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Insert string info for current position into the String Info Log

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  NODE  NodeQ;

+  NODE  NodeR;

+  NODE  Index2;

+  NODE  NodeT;

+  UINT8 CharC;

+  UINT8 *t1;

+  UINT8 *t2;

+

+  if (mMatchLen >= 4) {

+    //

+    // We have just got a long match, the target tree

+    // can be located by MatchPos + 1. Travese the tree

+    // from bottom up to get to a proper starting point.

+    // The usage of PERC_FLAG ensures proper node deletion

+    // in DeleteNode() later.

+    //

+    mMatchLen--;

+    NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);

+    NodeQ = mParent[NodeR];

+    while (NodeQ == NIL) {

+      NodeR = mNext[NodeR];

+      NodeQ = mParent[NodeR];

+    }

+

+    while (mLevel[NodeQ] >= mMatchLen) {

+      NodeR = NodeQ;

+      NodeQ = mParent[NodeQ];

+    }

+

+    NodeT = NodeQ;

+    while (mPosition[NodeT] < 0) {

+      mPosition[NodeT]  = mPos;

+      NodeT             = mParent[NodeT];

+    }

+

+    if (NodeT < WNDSIZ) {

+      mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);

+    }

+  } else {

+    //

+    // Locate the target tree

+    //

+    NodeQ = (NODE) (mText[mPos] + WNDSIZ);

+    CharC = mText[mPos + 1];

+    NodeR = Child (NodeQ, CharC);

+    if (NodeR == NIL) {

+      MakeChild (NodeQ, CharC, mPos);

+      mMatchLen = 1;

+      return ;

+    }

+

+    mMatchLen = 2;

+  }

+  //

+  // Traverse down the tree to find a match.

+  // Update Position value along the route.

+  // Node split or creation is involved.

+  //

+  for (;;) {

+    if (NodeR >= WNDSIZ) {

+      Index2    = MAXMATCH;

+      mMatchPos = NodeR;

+    } else {

+      Index2    = mLevel[NodeR];

+      mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);

+    }

+

+    if (mMatchPos >= mPos) {

+      mMatchPos -= WNDSIZ;

+    }

+

+    t1  = &mText[mPos + mMatchLen];

+    t2  = &mText[mMatchPos + mMatchLen];

+    while (mMatchLen < Index2) {

+      if (*t1 != *t2) {

+        Split (NodeR);

+        return ;

+      }

+

+      mMatchLen++;

+      t1++;

+      t2++;

+    }

+

+    if (mMatchLen >= MAXMATCH) {

+      break;

+    }

+

+    mPosition[NodeR]  = mPos;

+    NodeQ             = NodeR;

+    NodeR             = Child (NodeQ, *t1);

+    if (NodeR == NIL) {

+      MakeChild (NodeQ, *t1, mPos);

+      return ;

+    }

+

+    mMatchLen++;

+  }

+

+  NodeT           = mPrev[NodeR];

+  mPrev[mPos]     = NodeT;

+  mNext[NodeT]    = mPos;

+  NodeT           = mNext[NodeR];

+  mNext[mPos]     = NodeT;

+  mPrev[NodeT]    = mPos;

+  mParent[mPos]   = NodeQ;

+  mParent[NodeR]  = NIL;

+

+  //

+  // Special usage of 'next'

+  //

+  mNext[NodeR] = mPos;

+

+}

+

+STATIC

+VOID

+DeleteNode (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Delete outdated string info. (The Usage of PERC_FLAG

+  ensures a clean deletion)

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  NODE  NodeQ;

+  NODE  NodeR;

+  NODE  NodeS;

+  NODE  NodeT;

+  NODE  NodeU;

+

+  if (mParent[mPos] == NIL) {

+    return ;

+  }

+

+  NodeR         = mPrev[mPos];

+  NodeS         = mNext[mPos];

+  mNext[NodeR]  = NodeS;

+  mPrev[NodeS]  = NodeR;

+  NodeR         = mParent[mPos];

+  mParent[mPos] = NIL;

+  if (NodeR >= WNDSIZ) {

+    return ;

+  }

+

+  mChildCount[NodeR]--;

+  if (mChildCount[NodeR] > 1) {

+    return ;

+  }

+

+  NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);

+  if (NodeT >= mPos) {

+    NodeT -= WNDSIZ;

+  }

+

+  NodeS = NodeT;

+  NodeQ = mParent[NodeR];

+  NodeU = mPosition[NodeQ];

+  while (NodeU & (UINT32) PERC_FLAG) {

+    NodeU &= (UINT32)~PERC_FLAG;

+    if (NodeU >= mPos) {

+      NodeU -= WNDSIZ;

+    }

+

+    if (NodeU > NodeS) {

+      NodeS = NodeU;

+    }

+

+    mPosition[NodeQ]  = (NODE) (NodeS | WNDSIZ);

+    NodeQ             = mParent[NodeQ];

+    NodeU             = mPosition[NodeQ];

+  }

+

+  if (NodeQ < WNDSIZ) {

+    if (NodeU >= mPos) {

+      NodeU -= WNDSIZ;

+    }

+

+    if (NodeU > NodeS) {

+      NodeS = NodeU;

+    }

+

+    mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);

+  }

+

+  NodeS           = Child (NodeR, mText[NodeT + mLevel[NodeR]]);

+  NodeT           = mPrev[NodeS];

+  NodeU           = mNext[NodeS];

+  mNext[NodeT]    = NodeU;

+  mPrev[NodeU]    = NodeT;

+  NodeT           = mPrev[NodeR];

+  mNext[NodeT]    = NodeS;

+  mPrev[NodeS]    = NodeT;

+  NodeT           = mNext[NodeR];

+  mPrev[NodeT]    = NodeS;

+  mNext[NodeS]    = NodeT;

+  mParent[NodeS]  = mParent[NodeR];

+  mParent[NodeR]  = NIL;

+  mNext[NodeR]    = mAvail;

+  mAvail          = NodeR;

+}

+

+STATIC

+VOID

+GetNextMatch (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Advance the current position (read in new data if needed).

+  Delete outdated string info. Find a match string for current position.

+

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  INT32 Number;

+

+  mRemainder--;

+  mPos++;

+  if (mPos == WNDSIZ * 2) {

+    memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);

+    Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);

+    mRemainder += Number;

+    mPos = WNDSIZ;

+  }

+

+  DeleteNode ();

+  InsertNode ();

+}

+

+STATIC

+EFI_STATUS

+Encode (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  The main controlling routine for compression process.

+

+Arguments: (VOID)

+

+Returns:

+  

+  EFI_SUCCESS           - The compression is successful

+  EFI_OUT_0F_RESOURCES  - Not enough memory for compression process

+

+--*/

+{

+  EFI_STATUS  Status;

+  INT32       LastMatchLen;

+  NODE        LastMatchPos;

+

+  Status = AllocateMemory ();

+  if (EFI_ERROR (Status)) {

+    FreeMemory ();

+    return Status;

+  }

+

+  InitSlide ();

+

+  HufEncodeStart ();

+

+  mRemainder  = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);

+

+  mMatchLen   = 0;

+  mPos        = WNDSIZ;

+  InsertNode ();

+  if (mMatchLen > mRemainder) {

+    mMatchLen = mRemainder;

+  }

+

+  while (mRemainder > 0) {

+    LastMatchLen  = mMatchLen;

+    LastMatchPos  = mMatchPos;

+    GetNextMatch ();

+    if (mMatchLen > mRemainder) {

+      mMatchLen = mRemainder;

+    }

+

+    if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {

+      //

+      // Not enough benefits are gained by outputting a pointer,

+      // so just output the original character

+      //

+      Output (mText[mPos - 1], 0);

+

+    } else {

+

+      if (LastMatchLen == THRESHOLD) {

+        if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {

+          Output (mText[mPos - 1], 0);

+          continue;

+        }

+      }

+      //

+      // Outputting a pointer is beneficial enough, do it.

+      //

+      Output (

+        LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),

+        (mPos - LastMatchPos - 2) & (WNDSIZ - 1)

+        );

+      LastMatchLen--;

+      while (LastMatchLen > 0) {

+        GetNextMatch ();

+        LastMatchLen--;

+      }

+

+      if (mMatchLen > mRemainder) {

+        mMatchLen = mRemainder;

+      }

+    }

+  }

+

+  HufEncodeEnd ();

+  FreeMemory ();

+  return EFI_SUCCESS;

+}

+

+STATIC

+VOID

+CountTFreq (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Count the frequencies for the Extra Set

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  INT32 Index;

+  INT32 Index3;

+  INT32 Number;

+  INT32 Count;

+

+  for (Index = 0; Index < NT; Index++) {

+    mTFreq[Index] = 0;

+  }

+

+  Number = NC;

+  while (Number > 0 && mCLen[Number - 1] == 0) {

+    Number--;

+  }

+

+  Index = 0;

+  while (Index < Number) {

+    Index3 = mCLen[Index++];

+    if (Index3 == 0) {

+      Count = 1;

+      while (Index < Number && mCLen[Index] == 0) {

+        Index++;

+        Count++;

+      }

+

+      if (Count <= 2) {

+        mTFreq[0] = (UINT16) (mTFreq[0] + Count);

+      } else if (Count <= 18) {

+        mTFreq[1]++;

+      } else if (Count == 19) {

+        mTFreq[0]++;

+        mTFreq[1]++;

+      } else {

+        mTFreq[2]++;

+      }

+    } else {

+      mTFreq[Index3 + 2]++;

+    }

+  }

+}

+

+STATIC

+VOID

+WritePTLen (

+  IN INT32 Number,

+  IN INT32 nbit,

+  IN INT32 Special

+  )

+/*++

+

+Routine Description:

+

+  Outputs the code length array for the Extra Set or the Position Set.

+  

+Arguments:

+

+  Number       - the number of symbols

+  nbit    - the number of bits needed to represent 'n'

+  Special - the special symbol that needs to be take care of

+  

+Returns: (VOID)

+

+--*/

+{

+  INT32 Index;

+  INT32 Index3;

+

+  while (Number > 0 && mPTLen[Number - 1] == 0) {

+    Number--;

+  }

+

+  PutBits (nbit, Number);

+  Index = 0;

+  while (Index < Number) {

+    Index3 = mPTLen[Index++];

+    if (Index3 <= 6) {

+      PutBits (3, Index3);

+    } else {

+      PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);

+    }

+

+    if (Index == Special) {

+      while (Index < 6 && mPTLen[Index] == 0) {

+        Index++;

+      }

+

+      PutBits (2, (Index - 3) & 3);

+    }

+  }

+}

+

+STATIC

+VOID

+WriteCLen (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Outputs the code length array for Char&Length Set

+  

+Arguments: (VOID)

+

+Returns: (VOID)

+

+--*/

+{

+  INT32 Index;

+  INT32 Index3;

+  INT32 Number;

+  INT32 Count;

+

+  Number = NC;

+  while (Number > 0 && mCLen[Number - 1] == 0) {

+    Number--;

+  }

+

+  PutBits (CBIT, Number);

+  Index = 0;

+  while (Index < Number) {

+    Index3 = mCLen[Index++];

+    if (Index3 == 0) {

+      Count = 1;

+      while (Index < Number && mCLen[Index] == 0) {

+        Index++;

+        Count++;

+      }

+

+      if (Count <= 2) {

+        for (Index3 = 0; Index3 < Count; Index3++) {

+          PutBits (mPTLen[0], mPTCode[0]);

+        }

+      } else if (Count <= 18) {

+        PutBits (mPTLen[1], mPTCode[1]);

+        PutBits (4, Count - 3);

+      } else if (Count == 19) {

+        PutBits (mPTLen[0], mPTCode[0]);

+        PutBits (mPTLen[1], mPTCode[1]);

+        PutBits (4, 15);

+      } else {

+        PutBits (mPTLen[2], mPTCode[2]);

+        PutBits (CBIT, Count - 20);

+      }

+    } else {

+      PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);

+    }

+  }

+}

+

+STATIC

+VOID

+EncodeC (

+  IN INT32 Value

+  )

+{

+  PutBits (mCLen[Value], mCCode[Value]);

+}

+

+STATIC

+VOID

+EncodeP (

+  IN UINT32 Value

+  )

+{

+  UINT32  Index;

+  UINT32  NodeQ;

+

+  Index = 0;

+  NodeQ = Value;

+  while (NodeQ) {

+    NodeQ >>= 1;

+    Index++;

+  }

+

+  PutBits (mPTLen[Index], mPTCode[Index]);

+  if (Index > 1) {

+    PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));

+  }

+}

+

+STATIC

+VOID

+SendBlock (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Huffman code the block and output it.

+  

+Arguments: 

+  (VOID)

+

+Returns: 

+  (VOID)

+

+--*/

+{

+  UINT32  Index;

+  UINT32  Index2;

+  UINT32  Index3;

+  UINT32  Flags;

+  UINT32  Root;

+  UINT32  Pos;

+  UINT32  Size;

+  Flags = 0;

+

+  Root  = MakeTree (NC, mCFreq, mCLen, mCCode);

+  Size  = mCFreq[Root];

+  PutBits (16, Size);

+  if (Root >= NC) {

+    CountTFreq ();

+    Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);

+    if (Root >= NT) {

+      WritePTLen (NT, TBIT, 3);

+    } else {

+      PutBits (TBIT, 0);

+      PutBits (TBIT, Root);

+    }

+

+    WriteCLen ();

+  } else {

+    PutBits (TBIT, 0);

+    PutBits (TBIT, 0);

+    PutBits (CBIT, 0);

+    PutBits (CBIT, Root);

+  }

+

+  Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);

+  if (Root >= NP) {

+    WritePTLen (NP, PBIT, -1);

+  } else {

+    PutBits (PBIT, 0);

+    PutBits (PBIT, Root);

+  }

+

+  Pos = 0;

+  for (Index = 0; Index < Size; Index++) {

+    if (Index % UINT8_BIT == 0) {

+      Flags = mBuf[Pos++];

+    } else {

+      Flags <<= 1;

+    }

+

+    if (Flags & (1U << (UINT8_BIT - 1))) {

+      EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));

+      Index3 = mBuf[Pos++];

+      for (Index2 = 0; Index2 < 3; Index2++) {

+        Index3 <<= UINT8_BIT;

+        Index3 += mBuf[Pos++];

+      }

+

+      EncodeP (Index3);

+    } else {

+      EncodeC (mBuf[Pos++]);

+    }

+  }

+

+  for (Index = 0; Index < NC; Index++) {

+    mCFreq[Index] = 0;

+  }

+

+  for (Index = 0; Index < NP; Index++) {

+    mPFreq[Index] = 0;

+  }

+}

+

+STATIC

+VOID

+Output (

+  IN UINT32 CharC,

+  IN UINT32 Pos

+  )

+/*++

+

+Routine Description:

+

+  Outputs an Original Character or a Pointer

+

+Arguments:

+

+  CharC     - The original character or the 'String Length' element of a Pointer

+  Pos     - The 'Position' field of a Pointer

+

+Returns: (VOID)

+

+--*/

+{

+  static UINT32 CPos;

+

+  if ((mOutputMask >>= 1) == 0) {

+    mOutputMask = 1U << (UINT8_BIT - 1);

+    //

+    // Check the buffer overflow per outputing UINT8_BIT symbols

+    // which is an Original Character or a Pointer. The biggest

+    // symbol is a Pointer which occupies 5 bytes.

+    //

+    if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {

+      SendBlock ();

+      mOutputPos = 0;

+    }

+

+    CPos        = mOutputPos++;

+    mBuf[CPos]  = 0;

+  }

+

+  mBuf[mOutputPos++] = (UINT8) CharC;

+  mCFreq[CharC]++;

+  if (CharC >= (1U << UINT8_BIT)) {

+    mBuf[CPos] |= mOutputMask;

+    mBuf[mOutputPos++]  = (UINT8) (Pos >> 24);

+    mBuf[mOutputPos++]  = (UINT8) (Pos >> 16);

+    mBuf[mOutputPos++]  = (UINT8) (Pos >> (UINT8_BIT));

+    mBuf[mOutputPos++]  = (UINT8) Pos;

+    CharC               = 0;

+    while (Pos) {

+      Pos >>= 1;

+      CharC++;

+    }

+

+    mPFreq[CharC]++;

+  }

+}

+

+STATIC

+VOID

+HufEncodeStart (

+  VOID

+  )

+{

+  INT32 Index;

+

+  for (Index = 0; Index < NC; Index++) {

+    mCFreq[Index] = 0;

+  }

+

+  for (Index = 0; Index < NP; Index++) {

+    mPFreq[Index] = 0;

+  }

+

+  mOutputPos = mOutputMask = 0;

+  InitPutBits ();

+  return ;

+}

+

+STATIC

+VOID

+HufEncodeEnd (

+  VOID

+  )

+{

+  SendBlock ();

+

+  //

+  // Flush remaining bits

+  //

+  PutBits (UINT8_BIT - 1, 0);

+

+  return ;

+}

+

+STATIC

+VOID

+MakeCrcTable (

+  VOID

+  )

+{

+  UINT32  Index;

+  UINT32  Index2;

+  UINT32  Temp;

+

+  for (Index = 0; Index <= UINT8_MAX; Index++) {

+    Temp = Index;

+    for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {

+      if (Temp & 1) {

+        Temp = (Temp >> 1) ^ CRCPOLY;

+      } else {

+        Temp >>= 1;

+      }

+    }

+

+    mCrcTable[Index] = (UINT16) Temp;

+  }

+}

+

+STATIC

+VOID

+PutBits (

+  IN INT32  Number,

+  IN UINT32 Value

+  )

+/*++

+

+Routine Description:

+

+  Outputs rightmost n bits of x

+

+Arguments:

+

+  Number   - the rightmost n bits of the data is used

+  x   - the data 

+

+Returns: (VOID)

+

+--*/

+{

+  UINT8 Temp;

+

+  while (Number >= mBitCount) {

+    //

+    // Number -= mBitCount should never equal to 32

+    //

+    Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));

+    if (mDst < mDstUpperLimit) {

+      *mDst++ = Temp;

+    }

+

+    mCompSize++;

+    mSubBitBuf  = 0;

+    mBitCount   = UINT8_BIT;

+  }

+

+  mSubBitBuf |= Value << (mBitCount -= Number);

+}

+

+STATIC

+INT32

+FreadCrc (

+  OUT UINT8 *Pointer,

+  IN  INT32 Number

+  )

+/*++

+

+Routine Description:

+

+  Read in source data

+  

+Arguments:

+

+  Pointer   - the buffer to hold the data

+  Number   - number of bytes to read

+

+Returns:

+

+  number of bytes actually read

+  

+--*/

+{

+  INT32 Index;

+

+  for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {

+    *Pointer++ = *mSrc++;

+  }

+

+  Number = Index;

+

+  Pointer -= Number;

+  mOrigSize += Number;

+  Index--;

+  while (Index >= 0) {

+    UPDATE_CRC (*Pointer++);

+    Index--;

+  }

+

+  return Number;

+}

+

+STATIC

+VOID

+InitPutBits (

+  VOID

+  )

+{

+  mBitCount   = UINT8_BIT;

+  mSubBitBuf  = 0;

+}

+

+STATIC

+VOID

+CountLen (

+  IN INT32 Index

+  )

+/*++

+

+Routine Description:

+

+  Count the number of each code length for a Huffman tree.

+  

+Arguments:

+

+  Index   - the top node

+  

+Returns: (VOID)

+

+--*/

+{

+  static INT32  Depth = 0;

+

+  if (Index < mN) {

+    mLenCnt[(Depth < 16) ? Depth : 16]++;

+  } else {

+    Depth++;

+    CountLen (mLeft[Index]);

+    CountLen (mRight[Index]);

+    Depth--;

+  }

+}

+

+STATIC

+VOID

+MakeLen (

+  IN INT32 Root

+  )

+/*++

+

+Routine Description:

+

+  Create code length array for a Huffman tree

+  

+Arguments:

+

+  Root   - the root of the tree

+  

+Returns:

+

+  VOID

+

+--*/

+{

+  INT32   Index;

+  INT32   Index3;

+  UINT32  Cum;

+

+  for (Index = 0; Index <= 16; Index++) {

+    mLenCnt[Index] = 0;

+  }

+

+  CountLen (Root);

+

+  //

+  // Adjust the length count array so that

+  // no code will be generated longer than its designated length

+  //

+  Cum = 0;

+  for (Index = 16; Index > 0; Index--) {

+    Cum += mLenCnt[Index] << (16 - Index);

+  }

+

+  while (Cum != (1U << 16)) {

+    mLenCnt[16]--;

+    for (Index = 15; Index > 0; Index--) {

+      if (mLenCnt[Index] != 0) {

+        mLenCnt[Index]--;

+        mLenCnt[Index + 1] += 2;

+        break;

+      }

+    }

+

+    Cum--;

+  }

+

+  for (Index = 16; Index > 0; Index--) {

+    Index3 = mLenCnt[Index];

+    Index3--;

+    while (Index3 >= 0) {

+      mLen[*mSortPtr++] = (UINT8) Index;

+      Index3--;

+    }

+  }

+}

+

+STATIC

+VOID

+DownHeap (

+  IN INT32 Index

+  )

+{

+  INT32 Index2;

+  INT32 Index3;

+

+  //

+  // priority queue: send Index-th entry down heap

+  //

+  Index3  = mHeap[Index];

+  Index2  = 2 * Index;

+  while (Index2 <= mHeapSize) {

+    if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {

+      Index2++;

+    }

+

+    if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {

+      break;

+    }

+

+    mHeap[Index]  = mHeap[Index2];

+    Index         = Index2;

+    Index2        = 2 * Index;

+  }

+

+  mHeap[Index] = (INT16) Index3;

+}

+

+STATIC

+VOID

+MakeCode (

+  IN  INT32       Number,

+  IN  UINT8 Len[  ],

+  OUT UINT16 Code[]

+  )

+/*++

+

+Routine Description:

+

+  Assign code to each symbol based on the code length array

+  

+Arguments:

+

+  Number     - number of symbols

+  Len   - the code length array

+  Code  - stores codes for each symbol

+

+Returns: (VOID)

+

+--*/

+{

+  INT32   Index;

+  UINT16  Start[18];

+

+  Start[1] = 0;

+  for (Index = 1; Index <= 16; Index++) {

+    Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);

+  }

+

+  for (Index = 0; Index < Number; Index++) {

+    Code[Index] = Start[Len[Index]]++;

+  }

+}

+

+STATIC

+INT32

+MakeTree (

+  IN  INT32            NParm,

+  IN  UINT16  FreqParm[],

+  OUT UINT8   LenParm[ ],

+  OUT UINT16  CodeParm[]

+  )

+/*++

+

+Routine Description:

+

+  Generates Huffman codes given a frequency distribution of symbols

+  

+Arguments:

+

+  NParm    - number of symbols

+  FreqParm - frequency of each symbol

+  LenParm  - code length for each symbol

+  CodeParm - code for each symbol

+  

+Returns:

+

+  Root of the Huffman tree.

+  

+--*/

+{

+  INT32 Index;

+  INT32 Index2;

+  INT32 Index3;

+  INT32 Avail;

+

+  //

+  // make tree, calculate len[], return root

+  //

+  mN        = NParm;

+  mFreq     = FreqParm;

+  mLen      = LenParm;

+  Avail     = mN;

+  mHeapSize = 0;

+  mHeap[1]  = 0;

+  for (Index = 0; Index < mN; Index++) {

+    mLen[Index] = 0;

+    if (mFreq[Index]) {

+      mHeapSize++;

+      mHeap[mHeapSize] = (INT16) Index;

+    }

+  }

+

+  if (mHeapSize < 2) {

+    CodeParm[mHeap[1]] = 0;

+    return mHeap[1];

+  }

+

+  for (Index = mHeapSize / 2; Index >= 1; Index--) {

+    //

+    // make priority queue

+    //

+    DownHeap (Index);

+  }

+

+  mSortPtr = CodeParm;

+  do {

+    Index = mHeap[1];

+    if (Index < mN) {

+      *mSortPtr++ = (UINT16) Index;

+    }

+

+    mHeap[1] = mHeap[mHeapSize--];

+    DownHeap (1);

+    Index2 = mHeap[1];

+    if (Index2 < mN) {

+      *mSortPtr++ = (UINT16) Index2;

+    }

+

+    Index3        = Avail++;

+    mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);

+    mHeap[1]      = (INT16) Index3;

+    DownHeap (1);

+    mLeft[Index3]   = (UINT16) Index;

+    mRight[Index3]  = (UINT16) Index2;

+  } while (mHeapSize > 1);

+

+  mSortPtr = CodeParm;

+  MakeLen (Index3);

+  MakeCode (NParm, LenParm, CodeParm);

+

+  //

+  // return root

+  //

+  return Index3;

+}

diff --git a/Source/Common/EfiCompress.h b/Source/Common/EfiCompress.h
new file mode 100644
index 0000000..6ad80e4
--- /dev/null
+++ b/Source/Common/EfiCompress.h
@@ -0,0 +1,69 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiCompress.h

+

+Abstract:

+

+  Header file for compression routine

+  

+--*/

+

+#ifndef _EFICOMPRESS_H

+#define _EFICOMPRESS_H

+

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+

+EFI_STATUS

+Compress (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  )

+;

+

+/*++

+

+Routine Description:

+

+  The compression routine.

+

+Arguments:

+

+  SrcBuffer   - The buffer storing the source data

+  SrcSize     - The size of source data

+  DstBuffer   - The buffer to store the compressed data

+  DstSize     - On input, the size of DstBuffer; On output,

+                the size of the actual compressed data.

+

+Returns:

+

+  EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,

+                DstSize contains the size needed.

+  EFI_SUCCESS           - Compression is successful.

+

+--*/

+typedef

+EFI_STATUS

+(*COMPRESS_FUNCTION) (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  );

+

+#endif

diff --git a/Source/Common/EfiCustomizedCompress.h b/Source/Common/EfiCustomizedCompress.h
new file mode 100644
index 0000000..af26b6f
--- /dev/null
+++ b/Source/Common/EfiCustomizedCompress.h
@@ -0,0 +1,141 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  EfiCustomizedCompress.h

+

+Abstract:

+

+  Header file for Customized compression routine

+  

+--*/

+

+#ifndef _EFICUSTOMIZEDCOMPRESS_H

+#define _EFICUSTOMIZEDCOMPRESS_H

+

+#include <Common/UefiBaseTypes.h>

+

+EFI_STATUS

+SetCustomizedCompressionType (

+  IN  CHAR8   *Type

+  )

+;

+

+/*++

+

+Routine Description:

+

+The implementation of Customized SetCompressionType().

+

+Arguments:

+  Type        - The type if compression.

+    

+Returns:

+    

+  EFI_SUCCESS           - The type has been set.

+  EFI_UNSUPPORTED       - This type is unsupported.

+

+    

+--*/

+EFI_STATUS

+CustomizedGetInfo (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  )

+;

+

+/*++

+

+Routine Description:

+

+  The implementation of Customized GetInfo().

+

+Arguments:

+

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+EFI_STATUS

+CustomizedDecompress (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize

+  )

+;

+

+/*++

+

+Routine Description:

+

+  The implementation of Customized Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+EFI_STATUS

+CustomizedCompress (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  )

+;

+

+/*++

+

+Routine Description:

+

+  The Customized compression routine.

+

+Arguments:

+

+  SrcBuffer   - The buffer storing the source data

+  SrcSize     - The size of source data

+  DstBuffer   - The buffer to store the compressed data

+  DstSize     - On input, the size of DstBuffer; On output,

+                the size of the actual compressed data.

+

+Returns:

+

+  EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,

+                          DstSize contains the size needed.

+  EFI_SUCCESS           - Compression is successful.

+

+--*/

+

+#endif

diff --git a/Source/Common/EfiDecompress.c b/Source/Common/EfiDecompress.c
new file mode 100644
index 0000000..288c425
--- /dev/null
+++ b/Source/Common/EfiDecompress.c
@@ -0,0 +1,790 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  EfiDecompress.c

+

+Abstract:

+

+  Decompressor. Algorithm Ported from OPSD code (Decomp.asm)

+  

+--*/

+

+#include "EfiDecompress.h"

+

+//

+// Decompression algorithm begins here

+//

+#define BITBUFSIZ 32

+#define MAXMATCH  256

+#define THRESHOLD 3

+#define CODE_BIT  16

+#define BAD_TABLE - 1

+

+//

+// C: Char&Len Set; P: Position Set; T: exTra Set

+//

+#define NC    (0xff + MAXMATCH + 2 - THRESHOLD)

+#define CBIT  9

+#define PBIT  5

+#define TBIT  5

+#define MAXNP ((1U << PBIT) - 1)

+#define NT    (CODE_BIT + 3)

+#if NT > MAXNP

+#define NPT NT

+#else

+#define NPT MAXNP

+#endif

+

+typedef struct {

+  UINT8   *mSrcBase;  // Starting address of compressed data

+  UINT8   *mDstBase;  // Starting address of decompressed data

+  UINT32  mOutBuf;

+  UINT32  mInBuf;

+

+  UINT16  mBitCount;

+  UINT32  mBitBuf;

+  UINT32  mSubBitBuf;

+  UINT16  mBlockSize;

+  UINT32  mCompSize;

+  UINT32  mOrigSize;

+

+  UINT16  mBadTableFlag;

+

+  UINT16  mLeft[2 * NC - 1];

+  UINT16  mRight[2 * NC - 1];

+  UINT8   mCLen[NC];

+  UINT8   mPTLen[NPT];

+  UINT16  mCTable[4096];

+  UINT16  mPTTable[256];

+} SCRATCH_DATA;

+

+STATIC

+VOID

+FillBuf (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfBits

+  )

+/*++

+

+Routine Description:

+

+  Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.

+

+Arguments:

+

+  Sd        - The global scratch data

+  NumOfBit  - The number of bits to shift and read.

+

+Returns: (VOID)

+

+--*/

+{

+  Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);

+

+  while (NumOfBits > Sd->mBitCount) {

+

+    Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));

+

+    if (Sd->mCompSize > 0) {

+      //

+      // Get 1 byte into SubBitBuf

+      //

+      Sd->mCompSize--;

+      Sd->mSubBitBuf  = 0;

+      Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];

+      Sd->mBitCount   = 8;

+

+    } else {

+      //

+      // No more bits from the source, just pad zero bit.

+      //

+      Sd->mSubBitBuf  = 0;

+      Sd->mBitCount   = 8;

+

+    }

+  }

+

+  Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);

+  Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;

+}

+

+STATIC

+UINT32

+GetBits (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfBits

+  )

+/*++

+

+Routine Description:

+

+  Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent 

+  NumOfBits of bits from source. Returns NumOfBits of bits that are 

+  popped out.

+

+Arguments:

+

+  Sd            - The global scratch data.

+  NumOfBits     - The number of bits to pop and read.

+

+Returns:

+

+  The bits that are popped out.

+

+--*/

+{

+  UINT32  OutBits;

+

+  OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));

+

+  FillBuf (Sd, NumOfBits);

+

+  return OutBits;

+}

+

+STATIC

+UINT16

+MakeTable (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfChar,

+  IN  UINT8         *BitLen,

+  IN  UINT16        TableBits,

+  OUT UINT16        *Table

+  )

+/*++

+

+Routine Description:

+

+  Creates Huffman Code mapping table according to code length array.

+

+Arguments:

+

+  Sd        - The global scratch data

+  NumOfChar - Number of symbols in the symbol set

+  BitLen    - Code length array

+  TableBits - The width of the mapping table

+  Table     - The table

+  

+Returns:

+  

+  0         - OK.

+  BAD_TABLE - The table is corrupted.

+

+--*/

+{

+  UINT16  Count[17];

+  UINT16  Weight[17];

+  UINT16  Start[18];

+  UINT16  *Pointer;

+  UINT16  Index3;

+  UINT16  Index;

+  UINT16  Len;

+  UINT16  Char;

+  UINT16  JuBits;

+  UINT16  Avail;

+  UINT16  NextCode;

+  UINT16  Mask;

+

+  for (Index = 1; Index <= 16; Index++) {

+    Count[Index] = 0;

+  }

+

+  for (Index = 0; Index < NumOfChar; Index++) {

+    Count[BitLen[Index]]++;

+  }

+

+  Start[1] = 0;

+

+  for (Index = 1; Index <= 16; Index++) {

+    Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));

+  }

+

+  if (Start[17] != 0) {

+    /*(1U << 16)*/

+    return (UINT16) BAD_TABLE;

+  }

+

+  JuBits = (UINT16) (16 - TableBits);

+

+  for (Index = 1; Index <= TableBits; Index++) {

+    Start[Index] >>= JuBits;

+    Weight[Index] = (UINT16) (1U << (TableBits - Index));

+  }

+

+  while (Index <= 16) {

+    Weight[Index++] = (UINT16) (1U << (16 - Index));

+  }

+

+  Index = (UINT16) (Start[TableBits + 1] >> JuBits);

+

+  if (Index != 0) {

+    Index3 = (UINT16) (1U << TableBits);

+    while (Index != Index3) {

+      Table[Index++] = 0;

+    }

+  }

+

+  Avail = NumOfChar;

+  Mask  = (UINT16) (1U << (15 - TableBits));

+

+  for (Char = 0; Char < NumOfChar; Char++) {

+

+    Len = BitLen[Char];

+    if (Len == 0) {

+      continue;

+    }

+

+    NextCode = (UINT16) (Start[Len] + Weight[Len]);

+

+    if (Len <= TableBits) {

+

+      for (Index = Start[Len]; Index < NextCode; Index++) {

+        Table[Index] = Char;

+      }

+

+    } else {

+

+      Index3  = Start[Len];

+      Pointer = &Table[Index3 >> JuBits];

+      Index   = (UINT16) (Len - TableBits);

+

+      while (Index != 0) {

+        if (*Pointer == 0) {

+          Sd->mRight[Avail]                     = Sd->mLeft[Avail] = 0;

+          *Pointer = Avail++;

+        }

+

+        if (Index3 & Mask) {

+          Pointer = &Sd->mRight[*Pointer];

+        } else {

+          Pointer = &Sd->mLeft[*Pointer];

+        }

+

+        Index3 <<= 1;

+        Index--;

+      }

+

+      *Pointer = Char;

+

+    }

+

+    Start[Len] = NextCode;

+  }

+  //

+  // Succeeds

+  //

+  return 0;

+}

+

+STATIC

+UINT32

+DecodeP (

+  IN  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decodes a position value.

+

+Arguments:

+

+  Sd      - the global scratch data

+

+Returns:

+

+  The position value decoded.

+

+--*/

+{

+  UINT16  Val;

+  UINT32  Mask;

+  UINT32  Pos;

+

+  Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];

+

+  if (Val >= MAXNP) {

+    Mask = 1U << (BITBUFSIZ - 1 - 8);

+

+    do {

+

+      if (Sd->mBitBuf & Mask) {

+        Val = Sd->mRight[Val];

+      } else {

+        Val = Sd->mLeft[Val];

+      }

+

+      Mask >>= 1;

+    } while (Val >= MAXNP);

+  }

+  //

+  // Advance what we have read

+  //

+  FillBuf (Sd, Sd->mPTLen[Val]);

+

+  Pos = Val;

+  if (Val > 1) {

+    Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));

+  }

+

+  return Pos;

+}

+

+STATIC

+UINT16

+ReadPTLen (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        nn,

+  IN  UINT16        nbit,

+  IN  UINT16        Special

+  )

+/*++

+

+Routine Description:

+

+  Reads code lengths for the Extra Set or the Position Set

+

+Arguments:

+

+  Sd        - The global scratch data

+  nn        - Number of symbols

+  nbit      - Number of bits needed to represent nn

+  Special   - The special symbol that needs to be taken care of 

+

+Returns:

+

+  0         - OK.

+  BAD_TABLE - Table is corrupted.

+

+--*/

+{

+  UINT16  Number;

+  UINT16  CharC;

+  UINT16  Index;

+  UINT32  Mask;

+

+  Number = (UINT16) GetBits (Sd, nbit);

+

+  if (Number == 0) {

+    CharC = (UINT16) GetBits (Sd, nbit);

+

+    for (Index = 0; Index < 256; Index++) {

+      Sd->mPTTable[Index] = CharC;

+    }

+

+    for (Index = 0; Index < nn; Index++) {

+      Sd->mPTLen[Index] = 0;

+    }

+

+    return 0;

+  }

+

+  Index = 0;

+

+  while (Index < Number) {

+

+    CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));

+

+    if (CharC == 7) {

+      Mask = 1U << (BITBUFSIZ - 1 - 3);

+      while (Mask & Sd->mBitBuf) {

+        Mask >>= 1;

+        CharC += 1;

+      }

+    }

+

+    FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));

+

+    Sd->mPTLen[Index++] = (UINT8) CharC;

+

+    if (Index == Special) {

+      CharC = (UINT16) GetBits (Sd, 2);

+      CharC--;

+      while ((INT16) (CharC) >= 0) {

+        Sd->mPTLen[Index++] = 0;

+        CharC--;

+      }

+    }

+  }

+

+  while (Index < nn) {

+    Sd->mPTLen[Index++] = 0;

+  }

+

+  return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);

+}

+

+STATIC

+VOID

+ReadCLen (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Reads code lengths for Char&Len Set.

+

+Arguments:

+

+  Sd    - the global scratch data

+

+Returns: (VOID)

+

+--*/

+{

+  UINT16  Number;

+  UINT16  CharC;

+  UINT16  Index;

+  UINT32  Mask;

+

+  Number = (UINT16) GetBits (Sd, CBIT);

+

+  if (Number == 0) {

+    CharC = (UINT16) GetBits (Sd, CBIT);

+

+    for (Index = 0; Index < NC; Index++) {

+      Sd->mCLen[Index] = 0;

+    }

+

+    for (Index = 0; Index < 4096; Index++) {

+      Sd->mCTable[Index] = CharC;

+    }

+

+    return ;

+  }

+

+  Index = 0;

+  while (Index < Number) {

+

+    CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];

+    if (CharC >= NT) {

+      Mask = 1U << (BITBUFSIZ - 1 - 8);

+

+      do {

+

+        if (Mask & Sd->mBitBuf) {

+          CharC = Sd->mRight[CharC];

+        } else {

+          CharC = Sd->mLeft[CharC];

+        }

+

+        Mask >>= 1;

+

+      } while (CharC >= NT);

+    }

+    //

+    // Advance what we have read

+    //

+    FillBuf (Sd, Sd->mPTLen[CharC]);

+

+    if (CharC <= 2) {

+

+      if (CharC == 0) {

+        CharC = 1;

+      } else if (CharC == 1) {

+        CharC = (UINT16) (GetBits (Sd, 4) + 3);

+      } else if (CharC == 2) {

+        CharC = (UINT16) (GetBits (Sd, CBIT) + 20);

+      }

+

+      CharC--;

+      while ((INT16) (CharC) >= 0) {

+        Sd->mCLen[Index++] = 0;

+        CharC--;

+      }

+

+    } else {

+

+      Sd->mCLen[Index++] = (UINT8) (CharC - 2);

+

+    }

+  }

+

+  while (Index < NC) {

+    Sd->mCLen[Index++] = 0;

+  }

+

+  MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);

+

+  return ;

+}

+

+STATIC

+UINT16

+DecodeC (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decode a character/length value.

+

+Arguments:

+

+  Sd    - The global scratch data.

+

+Returns:

+

+  The value decoded.

+

+--*/

+{

+  UINT16  Index2;

+  UINT32  Mask;

+

+  if (Sd->mBlockSize == 0) {

+    //

+    // Starting a new block

+    //

+    Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);

+    Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);

+    if (Sd->mBadTableFlag != 0) {

+      return 0;

+    }

+

+    ReadCLen (Sd);

+

+    Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, PBIT, (UINT16) (-1));

+    if (Sd->mBadTableFlag != 0) {

+      return 0;

+    }

+  }

+

+  Sd->mBlockSize--;

+  Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];

+

+  if (Index2 >= NC) {

+    Mask = 1U << (BITBUFSIZ - 1 - 12);

+

+    do {

+      if (Sd->mBitBuf & Mask) {

+        Index2 = Sd->mRight[Index2];

+      } else {

+        Index2 = Sd->mLeft[Index2];

+      }

+

+      Mask >>= 1;

+    } while (Index2 >= NC);

+  }

+  //

+  // Advance what we have read

+  //

+  FillBuf (Sd, Sd->mCLen[Index2]);

+

+  return Index2;

+}

+

+STATIC

+VOID

+Decode (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decode the source data and put the resulting data into the destination buffer.

+

+Arguments:

+

+  Sd            - The global scratch data

+

+Returns: (VOID)

+

+ --*/

+{

+  UINT16  BytesRemain;

+  UINT32  DataIdx;

+  UINT16  CharC;

+

+  BytesRemain = (UINT16) (-1);

+

+  DataIdx     = 0;

+

+  for (;;) {

+    CharC = DecodeC (Sd);

+    if (Sd->mBadTableFlag != 0) {

+      return ;

+    }

+

+    if (CharC < 256) {

+      //

+      // Process an Original character

+      //

+      Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;

+      if (Sd->mOutBuf >= Sd->mOrigSize) {

+        return ;

+      }

+

+    } else {

+      //

+      // Process a Pointer

+      //

+      CharC       = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));

+

+      BytesRemain = CharC;

+

+      DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;

+

+      BytesRemain--;

+      while ((INT16) (BytesRemain) >= 0) {

+        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];

+        if (Sd->mOutBuf >= Sd->mOrigSize) {

+          return ;

+        }

+

+        BytesRemain--;

+      }

+    }

+  }

+

+  return ;

+}

+

+EFI_STATUS

+GetInfo (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  UINT8 *Src;

+

+  *ScratchSize  = sizeof (SCRATCH_DATA);

+

+  Src           = Source;

+  if (SrcSize < 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+Decompress (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  UINT32        Index;

+  UINT32        CompSize;

+  UINT32        OrigSize;

+  EFI_STATUS    Status;

+  SCRATCH_DATA  *Sd;

+  UINT8         *Src;

+  UINT8         *Dst;

+

+  Status  = EFI_SUCCESS;

+  Src     = Source;

+  Dst     = Destination;

+

+  if (ScratchSize < sizeof (SCRATCH_DATA)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Sd = (SCRATCH_DATA *) Scratch;

+

+  if (SrcSize < 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);

+  OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);

+

+  if (SrcSize < CompSize + 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (DstSize != OrigSize) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Src = Src + 8;

+

+  for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {

+    ((UINT8 *) Sd)[Index] = 0;

+  }

+

+  Sd->mSrcBase  = Src;

+  Sd->mDstBase  = Dst;

+  Sd->mCompSize = CompSize;

+  Sd->mOrigSize = OrigSize;

+

+  //

+  // Fill the first BITBUFSIZ bits

+  //

+  FillBuf (Sd, BITBUFSIZ);

+

+  //

+  // Decompress it

+  //

+  Decode (Sd);

+

+  if (Sd->mBadTableFlag != 0) {

+    //

+    // Something wrong with the source

+    //

+    Status = EFI_INVALID_PARAMETER;

+  }

+

+  return Status;

+}

diff --git a/Source/Common/EfiDecompress.h b/Source/Common/EfiDecompress.h
new file mode 100644
index 0000000..3f82ac6
--- /dev/null
+++ b/Source/Common/EfiDecompress.h
@@ -0,0 +1,106 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  EfiDecompress.h

+

+Abstract:

+

+  Header file for compression routine

+  

+--*/

+

+#ifndef _EFI_DECOMPRESS_H

+#define _EFI_DECOMPRESS_H

+

+#include <Common/UefiBaseTypes.h>

+

+EFI_STATUS

+GetInfo (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  );

+

+/*++

+

+Routine Description:

+

+  The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+EFI_STATUS

+Decompress (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize

+  )

+;

+

+/*++

+

+Routine Description:

+

+  The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+typedef

+EFI_STATUS

+(*GETINFO_FUNCTION) (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  );

+

+typedef

+EFI_STATUS

+(*DECOMPRESS_FUNCTION) (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize

+  );

+#endif

diff --git a/Source/Common/EfiUtilityMsgs.c b/Source/Common/EfiUtilityMsgs.c
new file mode 100644
index 0000000..566d214
--- /dev/null
+++ b/Source/Common/EfiUtilityMsgs.c
@@ -0,0 +1,755 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  EfiUtilityMsgs.c

+  

+Abstract:

+

+  EFI tools utility functions to display warning, error, and informational

+  messages.

+  

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <ctype.h>

+#include <stdarg.h>

+

+#include "EfiUtilityMsgs.h"

+

+#define MAX_LINE_LEN  200

+

+//

+// Declare module globals for keeping track of the the utility's

+// name and other settings.

+//

+static STATUS mStatus                 = STATUS_SUCCESS;

+static CHAR8  mUtilityName[50]        = { 0 };

+static UINT32 mDebugMsgMask           = 0;

+static CHAR8  *mSourceFileName        = NULL;

+static UINT32 mSourceFileLineNum      = 0;

+static UINT32 mErrorCount             = 0;

+static UINT32 mWarningCount           = 0;

+static UINT32 mMaxErrors              = 0;

+static UINT32 mMaxWarnings            = 0;

+static UINT32 mMaxWarningsPlusErrors  = 0;

+static INT8   mPrintLimitsSet         = 0;

+

+static

+void

+PrintMessage (

+  CHAR8   *Type,

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  va_list List

+  );

+

+static

+void

+PrintLimitExceeded (

+  VOID

+  );

+

+void

+Error (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Prints an error message.

+  

+Arguments:

+  All arguments are optional, though the printed message may be useless if

+  at least something valid is not specified.

+  

+  FileName - name of the file or application. If not specified, then the

+             utilty name (as set by the utility calling SetUtilityName()

+             earlier) is used. Otherwise "Unknown utility" is used.

+  

+  LineNumber - the line number of error, typically used by parsers. If the

+               utility is not a parser, then 0 should be specified. Otherwise

+               the FileName and LineNumber info can be used to cause

+               MS Visual Studio to jump to the error.

+               

+  MessageCode - an application-specific error code that can be referenced in

+              other documentation. 

+

+  Text        - the text in question, typically used by parsers.

+  

+  MsgFmt - the format string for the error message. Can contain formatting

+           controls for use with the varargs.

+           

+Returns:

+  None.

+  

+Notes:

+  We print the following (similar to the Warn() and Debug() 

+  W

+  Typical error/warning message format:

+

+  bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters

+

+  BUGBUG -- these three utility functions are almost identical, and

+  should be modified to share code.

+

+  Visual Studio does not find error messages with:

+  

+     " error :"

+     " error 1:"

+     " error c1:"

+     " error 1000:"

+     " error c100:"

+

+  It does find:

+     " error c1000:"     

+--*/

+{

+  va_list List;

+  //

+  // If limits have been set, then check that we have not exceeded them

+  //

+  if (mPrintLimitsSet) {

+    //

+    // See if we've exceeded our total count

+    //

+    if (mMaxWarningsPlusErrors != 0) {

+      if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+    //

+    // See if we've exceeded our error count

+    //

+    if (mMaxErrors != 0) {

+      if (mErrorCount > mMaxErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+  }

+

+  mErrorCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_ERROR) {

+    mStatus = STATUS_ERROR;

+  }

+}

+

+void

+ParserError (

+  UINT32  MessageCode,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a parser error, using the source file name and line number

+  set by a previous call to SetParserPosition().

+

+Arguments:

+  MessageCode   - application-specific error code

+  Text          - text to print in the error message

+  MsgFmt        - format string to print at the end of the error message

+

+Returns:

+  NA

+

+--*/

+{

+  va_list List;

+  //

+  // If limits have been set, then check them

+  //

+  if (mPrintLimitsSet) {

+    //

+    // See if we've exceeded our total count

+    //

+    if (mMaxWarningsPlusErrors != 0) {

+      if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+    //

+    // See if we've exceeded our error count

+    //

+    if (mMaxErrors != 0) {

+      if (mErrorCount > mMaxErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+  }

+

+  mErrorCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_ERROR) {

+    mStatus = STATUS_ERROR;

+  }

+}

+

+void

+ParserWarning (

+  UINT32  ErrorCode,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a parser warning, using the source file name and line number

+  set by a previous call to SetParserPosition().

+

+Arguments:

+  ErrorCode     - application-specific error code

+  OffendingText - text to print in the warning message

+  MsgFmt        - format string to print at the end of the warning message

+

+Returns:

+  NA

+

+--*/

+{

+  va_list List;

+  //

+  // If limits have been set, then check them

+  //

+  if (mPrintLimitsSet) {

+    //

+    // See if we've exceeded our total count

+    //

+    if (mMaxWarningsPlusErrors != 0) {

+      if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+    //

+    // See if we've exceeded our warning count

+    //

+    if (mMaxWarnings != 0) {

+      if (mWarningCount > mMaxWarnings) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+  }

+

+  mWarningCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_WARNING) {

+    mStatus = STATUS_WARNING;

+  }

+}

+

+void

+Warning (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a warning message.

+

+Arguments:

+  FileName    - name of the file where the warning was detected, or the name

+                of the application that detected the warning

+  

+  LineNumber  - the line number where the warning was detected (parsers).

+                0 should be specified if the utility is not a parser.

+               

+  MessageCode - an application-specific warning code that can be referenced in

+                other documentation. 

+

+  Text        - the text in question (parsers)

+  

+  MsgFmt      - the format string for the warning message. Can contain formatting

+                controls for use with varargs.

+           

+Returns:

+  None.

+

+--*/

+{

+  va_list List;

+  //

+  // If limits have been set, then check them

+  //

+  if (mPrintLimitsSet) {

+    //

+    // See if we've exceeded our total count

+    //

+    if (mMaxWarningsPlusErrors != 0) {

+      if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+    //

+    // See if we've exceeded our warning count

+    //

+    if (mMaxWarnings != 0) {

+      if (mWarningCount > mMaxWarnings) {

+        PrintLimitExceeded ();

+        return ;

+      }

+    }

+  }

+

+  mWarningCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_WARNING) {

+    mStatus = STATUS_WARNING;

+  }

+}

+

+void

+DebugMsg (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MsgMask,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a warning message.

+

+Arguments:

+  FileName    - typically the name of the utility printing the debug message, but

+                can be the name of a file being parsed.

+  

+  LineNumber  - the line number in FileName (parsers) 

+               

+  MsgMask     - an application-specific bitmask that, in combination with mDebugMsgMask,

+                determines if the debug message gets printed.

+

+  Text        - the text in question (parsers)

+  

+  MsgFmt      - the format string for the debug message. Can contain formatting

+                controls for use with varargs.

+           

+Returns:

+  None.

+

+--*/

+{

+  va_list List;

+  //

+  // If the debug mask is not applicable, then do nothing.

+  //

+  if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {

+    return ;

+  }

+

+  va_start (List, MsgFmt);

+  PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);

+  va_end (List);

+}

+

+static

+void

+PrintMessage (

+  CHAR8   *Type,

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  CHAR8   *Text,

+  CHAR8   *MsgFmt,

+  va_list List

+  )

+/*++

+

+Routine Description:

+  Worker routine for all the utility printing services. Prints the message in

+  a format that Visual Studio will find when scanning build outputs for

+  errors or warnings.

+

+Arguments:

+  Type        - "warning" or "error" string to insert into the message to be

+                printed. The first character of this string (converted to uppercase)

+                is used to preceed the MessageCode value in the output string.

+

+  FileName    - name of the file where the warning was detected, or the name

+                of the application that detected the warning

+  

+  LineNumber  - the line number where the warning was detected (parsers).

+                0 should be specified if the utility is not a parser.

+               

+  MessageCode - an application-specific warning code that can be referenced in

+                other documentation. 

+

+  Text        - part of the message to print

+  

+  MsgFmt      - the format string for the message. Can contain formatting

+                controls for use with varargs.

+  List        - the variable list.

+           

+Returns:

+  None.

+

+Notes:

+  If FileName == NULL then this utility will use the string passed into SetUtilityName(). 

+  

+  LineNumber is only used if the caller is a parser, in which case FileName refers to the

+  file being parsed.

+

+  Text and MsgFmt are both optional, though it would be of little use calling this function with

+  them both NULL.

+

+  Output will typically be of the form:

+    <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>

+

+    Parser (LineNumber != 0)

+      VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters

+    Generic utility (LineNumber == 0) 

+      UtilityName : error E1234 : Text string : MsgFmt string and args

+

+--*/

+{

+  CHAR8 Line[MAX_LINE_LEN];

+  CHAR8 Line2[MAX_LINE_LEN];

+  CHAR8 *Cptr;

+  //

+  // If given a filename, then add it (and the line number) to the string.

+  // If there's no filename, then use the program name if provided.

+  //

+  if (FileName != NULL) {

+    Cptr = FileName;

+  } else if (mUtilityName[0] != 0) {

+    Cptr = mUtilityName;

+  } else {

+    Cptr = "Unknown utility";

+  }

+

+  strcpy (Line, Cptr);

+  if (LineNumber != 0) {

+    sprintf (Line2, "(%d)", LineNumber);

+    strcat (Line, Line2);

+  }

+  //

+  // Have to print an error code or Visual Studio won't find the

+  // message for you. It has to be decimal digits too.

+  //

+  sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);

+  strcat (Line, Line2);

+  fprintf (stdout, "%s", Line);

+  //

+  // If offending text was provided, then print it

+  //

+  if (Text != NULL) {

+    fprintf (stdout, ": %s ", Text);

+  }

+  //

+  // Print formatted message if provided

+  //

+  if (MsgFmt != NULL) {

+    vsprintf (Line2, MsgFmt, List);

+    fprintf (stdout, ": %s", Line2);

+  }

+

+  fprintf (stdout, "\n");

+}

+

+void

+ParserSetPosition (

+  CHAR8   *SourceFileName,

+  UINT32  LineNum

+  )

+/*++

+

+Routine Description:

+  Set the position in a file being parsed. This can be used to 

+  print error messages deeper down in a parser.

+

+Arguments:

+  SourceFileName - name of the source file being parsed

+  LineNum        - line number of the source file being parsed

+

+Returns:

+  NA

+

+--*/

+{

+  mSourceFileName     = SourceFileName;

+  mSourceFileLineNum  = LineNum;

+}

+

+void

+SetUtilityName (

+  CHAR8   *UtilityName

+  )

+/*++

+

+Routine Description:

+  All printed error/warning/debug messages follow the same format, and

+  typically will print a filename or utility name followed by the error

+  text. However if a filename is not passed to the print routines, then

+  they'll print the utility name if you call this function early in your

+  app to set the utility name.

+  

+Arguments:

+  UtilityName  -  name of the utility, which will be printed with all

+                  error/warning/debug messags.

+

+Returns:

+  NA

+  

+--*/

+{

+  //

+  // Save the name of the utility in our local variable. Make sure its

+  // length does not exceed our buffer.

+  //

+  if (UtilityName != NULL) {

+    if (strlen (UtilityName) >= sizeof (mUtilityName)) {

+      Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");

+      strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);

+      mUtilityName[sizeof (mUtilityName) - 1] = 0;

+      return ;

+    } else {

+      strcpy (mUtilityName, UtilityName);

+    }

+  } else {

+    Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");

+  }

+}

+

+STATUS

+GetUtilityStatus (

+  VOID

+  )

+/*++

+

+Routine Description:

+  When you call Error() or Warning(), this module keeps track of it and

+  sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility

+  exits, it can call this function to get the status and use it as a return

+  value.

+  

+Arguments:

+  None.

+

+Returns:

+  Worst-case status reported, as defined by which print function was called.

+  

+--*/

+{

+  return mStatus;

+}

+

+void

+SetDebugMsgMask (

+  UINT32  DebugMask

+  )

+/*++

+

+Routine Description:

+  Set the debug printing mask. This is used by the DebugMsg() function

+  to determine when/if a debug message should be printed.

+

+Arguments:

+  DebugMask  - bitmask, specific to the calling application

+

+Returns:

+  NA

+

+--*/

+{

+  mDebugMsgMask = DebugMask;

+}

+

+void

+SetPrintLimits (

+  UINT32  MaxErrors,

+  UINT32  MaxWarnings,

+  UINT32  MaxWarningsPlusErrors

+  )

+/*++

+

+Routine Description:

+  Set the limits of how many errors, warnings, and errors+warnings

+  we will print.

+

+Arguments:

+  MaxErrors       - maximum number of error messages to print

+  MaxWarnings     - maximum number of warning messages to print

+  MaxWarningsPlusErrors 

+                  - maximum number of errors+warnings to print

+

+Returns:

+  NA

+

+--*/

+{

+  mMaxErrors              = MaxErrors;

+  mMaxWarnings            = MaxWarnings;

+  mMaxWarningsPlusErrors  = MaxWarningsPlusErrors;

+  mPrintLimitsSet         = 1;

+}

+

+static

+void

+PrintLimitExceeded (

+  VOID

+  )

+{

+  static INT8 mPrintLimitExceeded = 0;

+  //

+  // If we've already printed the message, do nothing. Otherwise

+  // temporarily increase our print limits so we can pass one

+  // more message through.

+  //

+  if (mPrintLimitExceeded == 0) {

+    mPrintLimitExceeded++;

+    mMaxErrors++;

+    mMaxWarnings++;

+    mMaxWarningsPlusErrors++;

+    Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);

+    mMaxErrors--;

+    mMaxWarnings--;

+    mMaxWarningsPlusErrors--;

+  }

+}

+

+#if 0

+void

+TestUtilityMessages (

+  VOID

+  )

+{

+  char *ArgStr = "ArgString";

+  int  ArgInt;

+

+  ArgInt  = 0x12345678;

+  //

+  // Test without setting utility name

+  //

+  fprintf (stdout, "* Testing without setting utility name\n");

+  fprintf (stdout, "** Test debug message not printed\n");

+  DebugMsg (NULL, 0, 0x00000001, NULL, NULL);

+  fprintf (stdout, "** Test warning with two strings and two args\n");

+  Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+  fprintf (stdout, "** Test error with two strings and two args\n");

+  Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+  fprintf (stdout, "** Test parser warning with nothing\n");

+  ParserWarning (0, NULL, NULL);

+  fprintf (stdout, "** Test parser error with nothing\n");

+  ParserError (0, NULL, NULL);

+  //

+  // Test with utility name set now

+  //

+  fprintf (stdout, "** Testingin with utility name set\n");

+  SetUtilityName ("MyUtilityName");

+  //

+  // Test debug prints

+  //

+  SetDebugMsgMask (2);

+  fprintf (stdout, "** Test debug message with one string\n");

+  DebugMsg (NULL, 0, 0x00000002, "Text1", NULL);

+  fprintf (stdout, "** Test debug message with one string\n");

+  DebugMsg (NULL, 0, 0x00000002, NULL, "Text2");

+  fprintf (stdout, "** Test debug message with two strings\n");

+  DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2");

+  fprintf (stdout, "** Test debug message with two strings and two args\n");

+  DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+  //

+  // Test warning prints

+  //

+  fprintf (stdout, "** Test warning with no strings\n");

+  Warning (NULL, 0, 1234, NULL, NULL);

+  fprintf (stdout, "** Test warning with one string\n");

+  Warning (NULL, 0, 1234, "Text1", NULL);

+  fprintf (stdout, "** Test warning with one string\n");

+  Warning (NULL, 0, 1234, NULL, "Text2");

+  fprintf (stdout, "** Test warning with two strings and two args\n");

+  Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+  //

+  // Test error prints

+  //

+  fprintf (stdout, "** Test error with no strings\n");

+  Error (NULL, 0, 1234, NULL, NULL);

+  fprintf (stdout, "** Test error with one string\n");

+  Error (NULL, 0, 1234, "Text1", NULL);

+  fprintf (stdout, "** Test error with one string\n");

+  Error (NULL, 0, 1234, NULL, "Text2");

+  fprintf (stdout, "** Test error with two strings and two args\n");

+  Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+  //

+  // Test parser prints

+  //

+  fprintf (stdout, "** Test parser errors\n");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserError (1234, NULL, NULL);

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserError (1234, "Text1", NULL);

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserError (1234, NULL, "Text2");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserError (1234, "Text1", "Text2");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+

+  fprintf (stdout, "** Test parser warnings\n");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserWarning (4321, NULL, NULL);

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserWarning (4321, "Text1", NULL);

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserWarning (4321, NULL, "Text2");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserWarning (4321, "Text1", "Text2");

+  ParserSetPosition (__FILE__, __LINE__ + 1);

+  ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);

+}

+#endif

diff --git a/Source/Common/EfiUtilityMsgs.h b/Source/Common/EfiUtilityMsgs.h
new file mode 100644
index 0000000..a76b822
--- /dev/null
+++ b/Source/Common/EfiUtilityMsgs.h
@@ -0,0 +1,137 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiUtilityMsgs.h

+

+Abstract:

+

+  Defines and prototypes for common EFI utility error and debug messages.

+  

+--*/

+

+#ifndef _EFI_UTILITY_MSGS_H_

+#define _EFI_UTILITY_MSGS_H_

+

+#include <Common/UefiBaseTypes.h>

+

+//

+// Status codes returned by EFI utility programs and functions

+//

+#define STATUS_SUCCESS  0

+#define STATUS_WARNING  1

+#define STATUS_ERROR    2

+#define VOID void 

+

+typedef int STATUS;

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+//

+// When we call Error() or Warning(), the module keeps track of the worst

+// case reported. GetUtilityStatus() will get the worst-case results, which

+// can be used as the return value from the app.

+//

+STATUS

+GetUtilityStatus (

+  void

+  );

+

+//

+// If someone prints an error message and didn't specify a source file name,

+// then we print the utility name instead. However they must tell us the

+// utility name early on via this function.

+//

+void

+SetUtilityName (

+  CHAR8 *ProgramName

+  )

+;

+

+void

+Error (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  ErrorCode,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+;

+

+void

+Warning (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  ErrorCode,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+;

+

+void

+DebugMsg (

+  CHAR8   *FileName,

+  UINT32  LineNumber,

+  UINT32  MsgLevel,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+;

+

+void

+SetDebugMsgMask (

+  UINT32    MsgMask

+  )

+;

+

+void

+ParserSetPosition (

+  CHAR8   *SourceFileName,

+  UINT32  LineNum

+  )

+;

+

+void

+ParserError (

+  UINT32  ErrorCode,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+;

+

+void

+ParserWarning (

+  UINT32  ErrorCode,

+  CHAR8   *OffendingText,

+  CHAR8   *MsgFmt,

+  ...

+  )

+;

+

+void

+SetPrintLimits (

+  UINT32  NumErrors,

+  UINT32  NumWarnings,

+  UINT32  NumWarningsPlusErrors

+  )

+;

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // #ifndef _EFI_UTILITY_MSGS_H_

diff --git a/Source/Common/FvLib.c b/Source/Common/FvLib.c
new file mode 100644
index 0000000..e8d6279
--- /dev/null
+++ b/Source/Common/FvLib.c
@@ -0,0 +1,780 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FvLib.c

+

+Abstract:

+

+  These functions assist in parsing and manipulating a Firmware Volume.

+

+--*/

+

+//

+// Include files

+//

+#include "FvLib.h"

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+

+//

+// Module global variables

+//

+EFI_FIRMWARE_VOLUME_HEADER  *mFvHeader  = NULL;

+UINT32                      mFvLength   = 0;

+

+//

+// External function implementations

+//

+EFI_STATUS

+InitializeFvLib (

+  IN VOID                         *Fv,

+  IN UINT32                       FvLength

+  )

+/*++

+

+Routine Description:

+

+  This initializes the FV lib with a pointer to the FV and length.  It does not

+  verify the FV in any way.

+

+Arguments:

+

+  Fv            Buffer containing the FV.

+  FvLength      Length of the FV

+    

+Returns:

+ 

+  EFI_SUCCESS             Function Completed successfully.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+

+--*/

+{

+  //

+  // Verify input arguments

+  //

+  if (Fv == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv;

+  mFvLength = FvLength;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetFvHeader (

+  OUT EFI_FIRMWARE_VOLUME_HEADER  **FvHeader,

+  OUT UINT32                      *FvLength

+  )

+/*++

+

+Routine Description:

+

+  This function returns a pointer to the current FV and the size.

+

+Arguments:

+

+  FvHeader      Pointer to the FV buffer.

+  FvLength      Length of the FV

+    

+Returns:

+ 

+  EFI_SUCCESS             Function Completed successfully.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+  EFI_ABORTED             The library needs to be initialized.

+

+--*/

+{

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify input arguments

+  //

+  if (FvHeader == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *FvHeader = mFvHeader;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetNextFile (

+  IN EFI_FFS_FILE_HEADER          *CurrentFile,

+  OUT EFI_FFS_FILE_HEADER         **NextFile

+  )

+/*++

+

+Routine Description:

+

+  This function returns the next file.  If the current file is NULL, it returns

+  the first file in the FV.  If the function returns EFI_SUCCESS and the file 

+  pointer is NULL, then there are no more files in the FV.

+

+Arguments:

+

+  CurrentFile   Pointer to the current file, must be within the current FV.

+  NextFile      Pointer to the next file in the FV.

+    

+Returns:

+ 

+  EFI_SUCCESS             Function completed successfully.

+  EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.

+  EFI_ABORTED             The library needs to be initialized.

+

+--*/

+{

+  EFI_STATUS  Status;

+

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify input arguments

+  //

+  if (NextFile == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Verify FV header

+  //

+  Status = VerifyFv (mFvHeader);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Get first file

+  //

+  if (CurrentFile == NULL) {

+    CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength);

+

+    //

+    // Verify file is valid

+    //

+    Status = VerifyFfsFile (CurrentFile);

+    if (EFI_ERROR (Status)) {

+      //

+      // no files in this FV

+      //

+      *NextFile = NULL;

+      return EFI_SUCCESS;

+    } else {

+      //

+      // Verify file is in this FV.

+      //

+      if ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {

+        *NextFile = NULL;

+        return EFI_SUCCESS;

+      }

+

+      *NextFile = CurrentFile;

+      return EFI_SUCCESS;

+    }

+  }

+  //

+  // Verify current file is in range

+  //

+  if (((UINTN) CurrentFile < (UINTN) mFvHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)) ||

+      ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER))

+      ) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Get next file, compensate for 8 byte alignment if necessary.

+  //

+  *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));

+

+  //

+  // Verify file is in this FV.

+  //

+  if ((UINTN) *NextFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {

+    *NextFile = NULL;

+    return EFI_SUCCESS;

+  }

+  //

+  // Verify file is valid

+  //

+  Status = VerifyFfsFile (*NextFile);

+  if (EFI_ERROR (Status)) {

+    //

+    // no more files in this FV

+    //

+    *NextFile = NULL;

+    return EFI_SUCCESS;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetFileByName (

+  IN EFI_GUID                     *FileName,

+  OUT EFI_FFS_FILE_HEADER         **File

+  )

+/*++

+

+Routine Description:

+

+  Find a file by name.  The function will return NULL if the file is not found.

+

+Arguments:

+

+  FileName    The GUID file name of the file to search for.

+  File        Return pointer.  In the case of an error, contents are undefined.

+

+Returns:

+

+  EFI_SUCCESS             The function completed successfully.

+  EFI_ABORTED             An error was encountered.

+  EFI_INVALID_PARAMETER   One of the parameters was NULL.

+

+--*/

+{

+  EFI_FFS_FILE_HEADER *CurrentFile;

+  EFI_STATUS          Status;

+

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify input parameters

+  //

+  if (FileName == NULL || File == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Verify FV header

+  //

+  Status = VerifyFv (mFvHeader);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Get the first file

+  //

+  Status = GetNextFile (NULL, &CurrentFile);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "error parsing the FV", NULL);

+    return EFI_ABORTED;

+  }

+  //

+  // Loop as long as we have a valid file

+  //

+  while (CurrentFile) {

+    if (!CompareGuid (&CurrentFile->Name, FileName)) {

+      *File = CurrentFile;

+      return EFI_SUCCESS;

+    }

+

+    Status = GetNextFile (CurrentFile, &CurrentFile);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "error parsing the FV", NULL);

+      return EFI_ABORTED;

+    }

+  }

+  //

+  // File not found in this FV.

+  //

+  *File = NULL;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetFileByType (

+  IN EFI_FV_FILETYPE              FileType,

+  IN UINTN                        Instance,

+  OUT EFI_FFS_FILE_HEADER         **File

+  )

+/*++

+

+Routine Description:

+

+  Find a file by type and instance.  An instance of 1 is the first instance.

+  The function will return NULL if a matching file cannot be found.

+  File type EFI_FV_FILETYPE_ALL means any file type is valid.

+

+Arguments:

+

+  FileType    Type of file to search for.

+  Instance    Instace of the file type to return.

+  File        Return pointer.  In the case of an error, contents are undefined.

+

+Returns:

+

+  EFI_SUCCESS             The function completed successfully.

+  EFI_ABORTED             An error was encountered.

+  EFI_INVALID_PARAMETER   One of the parameters was NULL.

+

+--*/

+{

+  EFI_FFS_FILE_HEADER *CurrentFile;

+  EFI_STATUS          Status;

+  UINTN               FileCount;

+

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify input parameters

+  //

+  if (File == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Verify FV header

+  //

+  Status = VerifyFv (mFvHeader);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Initialize the number of matching files found.

+  //

+  FileCount = 0;

+

+  //

+  // Get the first file

+  //

+  Status = GetNextFile (NULL, &CurrentFile);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "error parsing FV", NULL);

+    return EFI_ABORTED;

+  }

+  //

+  // Loop as long as we have a valid file

+  //

+  while (CurrentFile) {

+    if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {

+      FileCount++;

+    }

+

+    if (FileCount == Instance) {

+      *File = CurrentFile;

+      return EFI_SUCCESS;

+    }

+

+    Status = GetNextFile (CurrentFile, &CurrentFile);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "error parsing the FV", NULL);

+      return EFI_ABORTED;

+    }

+  }

+

+  *File = NULL;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetSectionByType (

+  IN EFI_FFS_FILE_HEADER          *File,

+  IN EFI_SECTION_TYPE             SectionType,

+  IN UINTN                        Instance,

+  OUT EFI_FILE_SECTION_POINTER    *Section

+  )

+/*++

+

+Routine Description:

+

+  Find a section in a file by type and instance.  An instance of 1 is the first 

+  instance.  The function will return NULL if a matching section cannot be found.

+  The function will not handle encapsulating sections.

+

+Arguments:

+

+  File        The file to search.

+  SectionType Type of file to search for.

+  Instance    Instace of the section to return.

+  Section     Return pointer.  In the case of an error, contents are undefined.

+

+Returns:

+

+  EFI_SUCCESS             The function completed successfully.

+  EFI_ABORTED             An error was encountered.

+  EFI_INVALID_PARAMETER   One of the parameters was NULL.

+  EFI_NOT_FOUND           No found.

+--*/

+{

+  EFI_FILE_SECTION_POINTER  CurrentSection;

+  EFI_STATUS                Status;

+  UINTN                     SectionCount;

+

+  //

+  // Verify input parameters

+  //

+  if (File == NULL || Instance == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Verify FFS header

+  //

+  Status = VerifyFfsFile (File);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "invalid FFS file", NULL);

+    return EFI_ABORTED;

+  }

+  //

+  // Initialize the number of matching sections found.

+  //

+  SectionCount = 0;

+

+  //

+  // Get the first section

+  //

+  CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));

+

+  //

+  // Loop as long as we have a valid file

+  //

+  while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) {

+    if (CurrentSection.CommonHeader->Type == SectionType) {

+      SectionCount++;

+    }

+

+    if (SectionCount == Instance) {

+      *Section = CurrentSection;

+      return EFI_SUCCESS;

+    }

+    //

+    // Find next section (including compensating for alignment issues.

+    //

+    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));

+  }

+  //

+  // Section not found

+  //

+  (*Section).Code16Section = NULL;

+  return EFI_NOT_FOUND;

+}

+//

+// will not parse compressed sections

+//

+EFI_STATUS

+VerifyFv (

+  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader

+  )

+/*++

+

+Routine Description:

+

+  Verify the current pointer points to a valid FV header.

+

+Arguments:

+

+  FvHeader     Pointer to an alleged FV file.

+

+Returns:

+

+  EFI_SUCCESS             The FV header is valid.

+  EFI_VOLUME_CORRUPTED    The FV header is not valid.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+  EFI_ABORTED             Operation aborted.

+

+--*/

+{

+  UINT16  Checksum;

+

+  //

+  // Verify input parameters

+  //

+  if (FvHeader == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (FvHeader->Signature != EFI_FVH_SIGNATURE) {

+    Error (NULL, 0, 0, "invalid FV header signature", NULL);

+    return EFI_VOLUME_CORRUPTED;

+  }

+  //

+  // Verify header checksum

+  //

+  Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));

+

+  if (Checksum != 0) {

+    Error (NULL, 0, 0, "invalid FV header checksum", NULL);

+    return EFI_ABORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+VerifyFfsFile (

+  IN EFI_FFS_FILE_HEADER  *FfsHeader

+  )

+/*++

+

+Routine Description:

+

+  Verify the current pointer points to a FFS file header.

+

+Arguments:

+

+  FfsHeader     Pointer to an alleged FFS file.

+

+Returns:

+

+  EFI_SUCCESS           The Ffs header is valid.

+  EFI_NOT_FOUND         This "file" is the beginning of free space.

+  EFI_VOLUME_CORRUPTED  The Ffs header is not valid.

+  EFI_ABORTED           The erase polarity is not known.

+

+--*/

+{

+  BOOLEAN             ErasePolarity;

+  EFI_STATUS          Status;

+  EFI_FFS_FILE_HEADER BlankHeader;

+  UINT8               Checksum;

+  UINT32              FileLength;

+  UINT32              OccupiedFileLength;

+  EFI_FFS_FILE_TAIL   *Tail;

+  UINT8               SavedChecksum;

+  UINT8               SavedState;

+  UINT8               FileGuidString[80];

+  UINT32              TailSize;

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify FV header

+  //

+  Status = VerifyFv (mFvHeader);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Get the erase polarity.

+  //

+  Status = GetErasePolarity (&ErasePolarity);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Check if we have free space

+  //

+  if (ErasePolarity) {

+    memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));

+  } else {

+    memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));

+  }

+

+  if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {

+    return EFI_NOT_FOUND;

+  }

+  //

+  // Convert the GUID to a string so we can at least report which file

+  // if we find an error.

+  //

+  PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);

+  if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+    TailSize = sizeof (EFI_FFS_FILE_TAIL);

+  } else {

+    TailSize = 0;

+  }

+  //

+  // Verify file header checksum

+  //

+  SavedState = FfsHeader->State;

+  FfsHeader->State = 0;

+  SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;

+  FfsHeader->IntegrityCheck.Checksum.File = 0;

+  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));

+  FfsHeader->State = SavedState;

+  FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;

+  if (Checksum != 0) {

+    Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum");

+    return EFI_ABORTED;

+  }

+  //

+  // Verify file checksum

+  //

+  if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {

+    //

+    // Verify file data checksum

+    //

+    FileLength          = GetLength (FfsHeader->Size);

+    OccupiedFileLength  = (FileLength + 0x07) & (-1 << 3);

+    Checksum            = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize);

+    Checksum            = (UINT8) (Checksum - FfsHeader->State);

+    if (Checksum != 0) {

+      Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum");

+      return EFI_ABORTED;

+    }

+  } else {

+    //

+    // File does not have a checksum

+    // Verify contents are 0x5A as spec'd

+    //

+    if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {

+      Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum");

+      return EFI_ABORTED;

+    }

+  }

+  //

+  // Check if the tail is present and verify it if it is.

+  //

+  if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+    //

+    // Verify tail is complement of integrity check field in the header.

+    //

+    Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL));

+    if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) {

+      Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail");

+      return EFI_ABORTED;

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+UINT32

+GetLength (

+  UINT8     *ThreeByteLength

+  )

+/*++

+

+Routine Description:

+

+  Converts a three byte length value into a UINT32.

+

+Arguments:

+

+  ThreeByteLength   Pointer to the first of the 3 byte length.

+

+Returns:

+

+  UINT32      Size of the section

+

+--*/

+{

+  UINT32  Length;

+

+  if (ThreeByteLength == NULL) {

+    return 0;

+  }

+

+  Length  = *((UINT32 *) ThreeByteLength);

+  Length  = Length & 0x00FFFFFF;

+

+  return Length;

+}

+

+EFI_STATUS

+GetErasePolarity (

+  OUT BOOLEAN   *ErasePolarity

+  )

+/*++

+

+Routine Description:

+

+  This function returns with the FV erase polarity.  If the erase polarity

+  for a bit is 1, the function return TRUE.

+

+Arguments:

+

+  ErasePolarity   A pointer to the erase polarity.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              Operation aborted.

+  

+--*/

+{

+  EFI_STATUS  Status;

+

+  //

+  // Verify library has been initialized.

+  //

+  if (mFvHeader == NULL || mFvLength == 0) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify FV header

+  //

+  Status = VerifyFv (mFvHeader);

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+  //

+  // Verify input parameters.

+  //

+  if (ErasePolarity == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {

+    *ErasePolarity = TRUE;

+  } else {

+    *ErasePolarity = FALSE;

+  }

+

+  return EFI_SUCCESS;

+}

+

+UINT8

+GetFileState (

+  IN BOOLEAN              ErasePolarity,

+  IN EFI_FFS_FILE_HEADER  *FfsHeader

+  )

+/*++

+

+Routine Description:

+

+  This function returns a the highest state bit in the FFS that is set.

+  It in no way validate the FFS file.

+

+Arguments:

+  

+  ErasePolarity The erase polarity for the file state bits.

+  FfsHeader     Pointer to a FFS file.

+

+Returns:

+

+  UINT8   The hightest set state of the file.

+

+--*/

+{

+  UINT8 FileState;

+  UINT8 HighestBit;

+

+  FileState = FfsHeader->State;

+

+  if (ErasePolarity) {

+    FileState = (UINT8)~FileState;

+  }

+

+  HighestBit = 0x80;

+  while (HighestBit != 0 && (HighestBit & FileState) == 0) {

+    HighestBit >>= 1;

+  }

+

+  return HighestBit;

+}

diff --git a/Source/Common/FvLib.h b/Source/Common/FvLib.h
new file mode 100644
index 0000000..1ad1e81
--- /dev/null
+++ b/Source/Common/FvLib.h
@@ -0,0 +1,181 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FvLib.h

+

+Abstract:

+

+  These functions assist in parsing and manipulating a Firmware Volume.

+

+--*/

+

+#ifndef _EFI_FV_LIB_H

+#define _EFI_FV_LIB_H

+

+//

+// Include files

+//

+#include <string.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Common/MultiPhase.h>

+

+EFI_STATUS

+InitializeFvLib (

+  IN VOID                         *Fv,

+  IN UINT32                       FvLength

+  )

+;

+

+EFI_STATUS

+GetFvHeader (

+  OUT EFI_FIRMWARE_VOLUME_HEADER  **FvHeader,

+  OUT UINT32                      *FvLength

+  )

+;

+

+EFI_STATUS

+GetNextFile (

+  IN EFI_FFS_FILE_HEADER          *CurrentFile,

+  OUT EFI_FFS_FILE_HEADER         **NextFile

+  )

+;

+

+EFI_STATUS

+GetFileByName (

+  IN EFI_GUID                     *FileName,

+  OUT EFI_FFS_FILE_HEADER         **File

+  )

+;

+

+EFI_STATUS

+GetFileByType (

+  IN EFI_FV_FILETYPE              FileType,

+  IN UINTN                        Instance,

+  OUT EFI_FFS_FILE_HEADER         **File

+  )

+;

+

+EFI_STATUS

+GetSectionByType (

+  IN EFI_FFS_FILE_HEADER          *File,

+  IN EFI_SECTION_TYPE             SectionType,

+  IN UINTN                        Instance,

+  OUT EFI_FILE_SECTION_POINTER    *Section

+  )

+;

+//

+// will not parse compressed sections

+//

+EFI_STATUS

+VerifyFv (

+  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader

+  )

+;

+

+EFI_STATUS

+VerifyFfsFile (

+  IN EFI_FFS_FILE_HEADER          *FfsHeader

+  )

+;

+

+/*++

+

+Routine Description:

+

+  Verify the current pointer points to a FFS file header.

+

+Arguments:

+

+  FfsHeader     Pointer to an alleged FFS file.

+

+Returns:

+

+  EFI_SUCCESS           The Ffs header is valid.

+  EFI_NOT_FOUND         This "file" is the beginning of free space.

+  EFI_VOLUME_CORRUPTED  The Ffs header is not valid.

+

+--*/

+UINT32

+GetLength (

+  UINT8                           *ThreeByteLength

+  )

+;

+

+/*++

+

+Routine Description:

+

+  Converts a three byte length value into a UINT32.

+

+Arguments:

+

+  ThreeByteLength   Pointer to the first of the 3 byte length.

+

+Returns:

+

+  UINT32      Size of the section

+

+--*/

+EFI_STATUS

+GetErasePolarity (

+  OUT BOOLEAN   *ErasePolarity

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function returns with the FV erase polarity.  If the erase polarity

+  for a bit is 1, the function return TRUE.

+

+Arguments:

+

+  ErasePolarity   A pointer to the erase polarity.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+

+--*/

+UINT8

+GetFileState (

+  IN BOOLEAN              ErasePolarity,

+  IN EFI_FFS_FILE_HEADER  *FfsHeader

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function returns a the highest state bit in the FFS that is set.

+  It in no way validate the FFS file.

+

+Arguments:

+  

+  ErasePolarity The erase polarity for the file state bits.

+  FfsHeader     Pointer to a FFS file.

+

+Returns:

+

+  UINT8   The hightest set state of the file.

+

+--*/

+#endif

diff --git a/Source/Common/MyAlloc.c b/Source/Common/MyAlloc.c
new file mode 100644
index 0000000..39fddf7
--- /dev/null
+++ b/Source/Common/MyAlloc.c
@@ -0,0 +1,516 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  MyAlloc.c

+

+Abstract:

+

+  File for memory allocation tracking functions.

+

+--*/

+

+#include "MyAlloc.h"

+

+#if USE_MYALLOC

+//

+// Get back to original alloc/free calls.

+//

+#undef malloc

+#undef calloc

+#undef realloc

+#undef free

+//

+// Start of allocation list.

+//

+static MY_ALLOC_STRUCT  *MyAllocData = NULL;

+

+//

+//

+//

+static UINT32           MyAllocHeadMagik  = MYALLOC_HEAD_MAGIK;

+static UINT32           MyAllocTailMagik  = MYALLOC_TAIL_MAGIK;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+//

+VOID

+MyCheck (

+  BOOLEAN      Final,

+  UINT8        File[],

+  UINTN        Line

+  )

+// *++

+// Description:

+//

+//  Check for corruptions in the allocated memory chain.  If a corruption

+//  is detection program operation stops w/ an exit(1) call.

+//

+// Parameters:

+//

+//  Final := When FALSE, MyCheck() returns if the allocated memory chain

+//           has not been corrupted.  When TRUE, MyCheck() returns if there

+//           are no un-freed allocations.  If there are un-freed allocations,

+//           they are displayed and exit(1) is called.

+//

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  n/a

+//

+// --*/

+//

+{

+  MY_ALLOC_STRUCT *Tmp;

+

+  //

+  // Check parameters.

+  //

+  if (File == NULL || Line == 0) {

+    printf (

+      "\nMyCheck(Final=%u, File=%xh, Line=%u)"

+      "Invalid parameter(s).\n",

+      Final,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+

+  if (strlen (File) == 0) {

+    printf (

+      "\nMyCheck(Final=%u, File=%s, Line=%u)"

+      "Invalid parameter.\n",

+      Final,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Check structure contents.

+  //

+  for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {

+    if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||

+        memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {

+      break;

+    }

+  }

+  //

+  // If Tmp is not NULL, the structure is corrupt.

+  //

+  if (Tmp != NULL) {

+    printf (

+      "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"

+      "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",

+      Final,

+      File,

+      Line,

+      Tmp->File,

+      Tmp->Line,

+      Tmp->Size,

+      *(UINT32 *) (Tmp->Buffer),

+      *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])

+      );

+

+    exit (1);

+  }

+  //

+  // If Final is TRUE, display the state of the structure chain.

+  //

+  if (Final) {

+    if (MyAllocData != NULL) {

+      printf (

+        "\nMyCheck(Final=%u, File=%s, Line=%u)"

+        "\nSome allocated items have not been freed.\n",

+        Final,

+        File,

+        Line

+        );

+

+      for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {

+        printf (

+          "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",

+          Tmp->File,

+          Tmp->Line,

+          Tmp->Size,

+          *(UINT32 *) (Tmp->Buffer),

+          *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])

+          );

+      }

+    }

+  }

+}

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+//

+VOID *

+MyAlloc (

+  UINTN      Size,

+  UINT8 File[],

+  UINTN      Line

+  )

+// *++

+// Description:

+//

+//  Allocate a new link in the allocation chain along with enough storage

+//  for the File[] string, requested Size and alignment overhead.  If

+//  memory cannot be allocated or the allocation chain has been corrupted,

+//  exit(1) will be called.

+//

+// Parameters:

+//

+//  Size := Number of bytes (UINT8) requested by the called.

+//          Size cannot be zero.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  Pointer to the caller's buffer.

+//

+// --*/

+//

+{

+  MY_ALLOC_STRUCT *Tmp;

+  UINTN           Len;

+

+  //

+  // Check for invalid parameters.

+  //

+  if (Size == 0 || File == NULL || Line == 0) {

+    printf (

+      "\nMyAlloc(Size=%u, File=%xh, Line=%u)"

+      "\nInvalid parameter(s).\n",

+      Size,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+

+  Len = strlen (File);

+  if (Len == 0) {

+    printf (

+      "\nMyAlloc(Size=%u, File=%s, Line=%u)"

+      "\nInvalid parameter.\n",

+      Size,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Check the allocation list for corruption.

+  //

+  MyCheck (0, __FILE__, __LINE__);

+

+  //

+  // Allocate a new entry.

+  //

+  Tmp = calloc (

+          1,

+          sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)

+          );

+

+  if (Tmp == NULL) {

+    printf (

+      "\nMyAlloc(Size=%u, File=%s, Line=%u)"

+      "\nOut of memory.\n",

+      Size,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Fill in the new entry.

+  //

+  Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);

+  strcpy (Tmp->File, File);

+  Tmp->Line   = Line;

+  Tmp->Size   = Size;

+  Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);

+

+  memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);

+

+  memcpy (

+    &Tmp->Buffer[Size + sizeof (UINT32)],

+    &MyAllocTailMagik,

+    sizeof MyAllocTailMagik

+    );

+

+  Tmp->Next   = MyAllocData;

+  Tmp->Cksum  = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);

+

+  MyAllocData = Tmp;

+

+  return Tmp->Buffer + sizeof (UINT32);

+}

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+//

+VOID *

+MyRealloc (

+  VOID       *Ptr,

+  UINTN      Size,

+  UINT8 File[],

+  UINTN      Line

+  )

+// *++

+// Description:

+//

+//  This does a MyAlloc(), memcpy() and MyFree().  There is no optimization

+//  for shrinking or expanding buffers.  An invalid parameter will cause

+//  MyRealloc() to fail with a call to exit(1).

+//

+// Parameters:

+//

+//  Ptr := Pointer to the caller's buffer to be re-allocated.

+//

+//  Size := Size of new buffer.  Size cannot be zero.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  Pointer to new caller's buffer.

+//

+// --*/

+//

+{

+  MY_ALLOC_STRUCT *Tmp;

+  VOID            *Buffer;

+

+  //

+  // Check for invalid parameter(s).

+  //

+  if (Size == 0 || File == NULL || Line == 0) {

+    printf (

+      "\nMyRealloc(Ptr=%xh, Size=%u, File=%xh, Line=%u)"

+      "\nInvalid parameter(s).\n",

+      Ptr,

+      Size,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+

+  if (strlen (File) == 0) {

+    printf (

+      "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)"

+      "\nInvalid parameter.\n",

+      Ptr,

+      Size,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Find existing buffer in allocation list.

+  //

+  if (Ptr == NULL) {

+    Tmp = NULL;

+  } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {

+    Tmp = MyAllocData;

+  } else {

+    for (Tmp = MyAllocData;; Tmp = Tmp->Next) {

+      if (Tmp->Next == NULL) {

+        printf (

+          "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)"

+          "\nCould not find buffer.\n",

+          Ptr,

+          Size,

+          File,

+          Line

+          );

+

+        exit (1);

+      }

+

+      Tmp = Tmp->Next;

+    }

+  }

+  //

+  // Allocate new buffer, copy old data, free old buffer.

+  //

+  Buffer = MyAlloc (Size, File, Line);

+

+  if (Buffer != NULL && Tmp != NULL) {

+    memcpy (

+      Buffer,

+      &Tmp->Buffer[sizeof (UINT32)],

+      ((Size <= Tmp->Size) ? Size : Tmp->Size)

+      );

+

+    MyFree (Ptr, __FILE__, __LINE__);

+  }

+

+  return Buffer;

+}

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+//

+VOID

+MyFree (

+  VOID       *Ptr,

+  UINT8 File[],

+  UINTN      Line

+  )

+// *++

+// Description:

+//

+//  Release a previously allocated buffer.  Invalid parameters will cause

+//  MyFree() to fail with an exit(1) call.

+//

+// Parameters:

+//

+//  Ptr := Pointer to the caller's buffer to be freed.

+//         A NULL pointer will be ignored.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  n/a

+//

+// --*/

+//

+{

+  MY_ALLOC_STRUCT *Tmp;

+  MY_ALLOC_STRUCT *Tmp2;

+

+  //

+  // Check for invalid parameter(s).

+  //

+  if (File == NULL || Line == 0) {

+    printf (

+      "\nMyFree(Ptr=%xh, File=%xh, Line=%u)"

+      "\nInvalid parameter(s).\n",

+      Ptr,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+

+  if (strlen (File) == 0) {

+    printf (

+      "\nMyFree(Ptr=%xh, File=%s, Line=%u)"

+      "\nInvalid parameter.\n",

+      Ptr,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Freeing NULL is always valid.

+  //

+  if (Ptr == NULL) {

+    return ;

+  }

+  //

+  // Fail if nothing is allocated.

+  //

+  if (MyAllocData == NULL) {

+    printf (

+      "\nMyFree(Ptr=%xh, File=%s, Line=%u)"

+      "\nCalled before memory allocated.\n",

+      Ptr,

+      File,

+      Line

+      );

+

+    exit (1);

+  }

+  //

+  // Check for corrupted allocation list.

+  //

+  MyCheck (0, __FILE__, __LINE__);

+

+  //

+  // Need special check for first item in list.

+  //

+  if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {

+    //

+    // Unlink first item in list.

+    //

+    Tmp         = MyAllocData;

+    MyAllocData = MyAllocData->Next;

+  } else {

+    //

+    // Walk list looking for matching item.

+    //

+    for (Tmp = MyAllocData;; Tmp = Tmp->Next) {

+      //

+      // Fail if end of list is reached.

+      //

+      if (Tmp->Next == NULL) {

+        printf (

+          "\nMyFree(Ptr=%xh, File=%s, Line=%u)\n"

+          "\nNot found.\n",

+          Ptr,

+          File,

+          Line

+          );

+

+        exit (1);

+      }

+      //

+      // Leave loop when match is found.

+      //

+      if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {

+        break;

+      }

+    }

+    //

+    // Unlink item from list.

+    //

+    Tmp2      = Tmp->Next;

+    Tmp->Next = Tmp->Next->Next;

+    Tmp       = Tmp2;

+  }

+  //

+  // Release item.

+  //

+  free (Tmp);

+}

+

+#endif /* USE_MYALLOC */

+

+/* eof - MyAlloc.c */

diff --git a/Source/Common/MyAlloc.h b/Source/Common/MyAlloc.h
new file mode 100644
index 0000000..9697012
--- /dev/null
+++ b/Source/Common/MyAlloc.h
@@ -0,0 +1,222 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  MyAlloc.h

+

+Abstract:

+

+  Header file for memory allocation tracking functions.

+

+--*/

+

+#ifndef _MYALLOC_H_

+#define _MYALLOC_H_

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+

+#include <Common/BaseTypes.h>

+

+//

+// Default operation is to use the memory allocation tracking functions.

+// To over-ride add "#define USE_MYALLOC 0" to your program header and/or

+// source files as needed.  Or, just do not include this header file in

+// your project.

+//

+#ifndef USE_MYALLOC

+#define USE_MYALLOC 1

+#endif

+

+#if USE_MYALLOC

+//

+// Replace C library allocation routines with MyAlloc routines.

+//

+#define malloc(size)        MyAlloc ((size), __FILE__, __LINE__)

+#define calloc(count, size) MyAlloc ((count) * (size), __FILE__, __LINE__)

+#define realloc(ptr, size)  MyRealloc ((ptr), (size), __FILE__, __LINE__)

+#define free(ptr)           MyFree ((ptr), __FILE__, __LINE__)

+#define alloc_check(final)  MyCheck ((final), __FILE__, __LINE__)

+

+//

+// Structure for checking/tracking memory allocations.

+//

+typedef struct MyAllocStruct {

+  UINTN                 Cksum;

+  struct MyAllocStruct  *Next;

+  UINTN                 Line;

+  UINTN                 Size;

+  UINT8                 *File;

+  UINT8                 *Buffer;

+} MY_ALLOC_STRUCT;

+//

+// Cksum := (UINTN)This + (UINTN)Next + Line + Size + (UINTN)File +

+//          (UINTN)Buffer;

+//

+// Next := Pointer to next allocation structure in the list.

+//

+// Line := __LINE__

+//

+// Size := Size of allocation request.

+//

+// File := Pointer to __FILE__ string stored immediately following

+//         MY_ALLOC_STRUCT in memory.

+//

+// Buffer := Pointer to UINT32 aligned storage immediately following

+//           the NULL terminated __FILE__ string.  This is UINT32

+//           aligned because the underflow signature is 32-bits and

+//           this will place the first caller address on a 64-bit

+//           boundary.

+//

+//

+// Signatures used to check for buffer overflow/underflow conditions.

+//

+#define MYALLOC_HEAD_MAGIK  0xBADFACED

+#define MYALLOC_TAIL_MAGIK  0xDEADBEEF

+

+VOID

+MyCheck (

+  BOOLEAN      Final,

+  UINT8        File[],

+  UINTN        Line

+  )

+;

+//

+// *++

+// Description:

+//

+//  Check for corruptions in the allocated memory chain.  If a corruption

+//  is detection program operation stops w/ an exit(1) call.

+//

+// Parameters:

+//

+//  Final := When FALSE, MyCheck() returns if the allocated memory chain

+//           has not been corrupted.  When TRUE, MyCheck() returns if there

+//           are no un-freed allocations.  If there are un-freed allocations,

+//           they are displayed and exit(1) is called.

+//

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  n/a

+//

+// --*/

+//

+VOID  *

+MyAlloc (

+  UINTN      Size,

+  UINT8      File[],

+  UINTN      Line

+  )

+;

+//

+// *++

+// Description:

+//

+//  Allocate a new link in the allocation chain along with enough storage

+//  for the File[] string, requested Size and alignment overhead.  If

+//  memory cannot be allocated or the allocation chain has been corrupted,

+//  exit(1) will be called.

+//

+// Parameters:

+//

+//  Size := Number of bytes (UINT8) requested by the called.

+//          Size cannot be zero.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  Pointer to the caller's buffer.

+//

+// --*/

+//

+VOID  *

+MyRealloc (

+  VOID       *Ptr,

+  UINTN      Size,

+  UINT8      File[],

+  UINTN      Line

+  )

+;

+//

+// *++

+// Description:

+//

+//  This does a MyAlloc(), memcpy() and MyFree().  There is no optimization

+//  for shrinking or expanding buffers.  An invalid parameter will cause

+//  MyRealloc() to fail with a call to exit(1).

+//

+// Parameters:

+//

+//  Ptr := Pointer to the caller's buffer to be re-allocated.

+//         Ptr cannot be NULL.

+//

+//  Size := Size of new buffer.  Size cannot be zero.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  Pointer to new caller's buffer.

+//

+// --*/

+//

+VOID

+MyFree (

+  VOID       *Ptr,

+  UINT8      File[],

+  UINTN      Line

+  )

+;

+//

+// *++

+// Description:

+//

+//  Release a previously allocated buffer.  Invalid parameters will cause

+//  MyFree() to fail with an exit(1) call.

+//

+// Parameters:

+//

+//  Ptr := Pointer to the caller's buffer to be freed.

+//         A NULL pointer will be ignored.

+//

+//  File := Set to __FILE__ by macro expansion.

+//

+//  Line := Set to __LINE__ by macro expansion.

+//

+// Returns:

+//

+//  n/a

+//

+// --*/

+//

+#else /* USE_MYALLOC */

+

+//

+// Nothing to do when USE_MYALLOC is zero.

+//

+#define alloc_check(final)

+

+#endif /* USE_MYALLOC */

+#endif /* _MYALLOC_H_ */

+

+/* eof - MyAlloc.h */

diff --git a/Source/Common/ParseInf.c b/Source/Common/ParseInf.c
new file mode 100644
index 0000000..de0ffd8
--- /dev/null
+++ b/Source/Common/ParseInf.c
@@ -0,0 +1,630 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  ParseInf.c

+

+Abstract:

+

+  This contains some useful functions for parsing INF files.

+

+--*/

+

+#include <assert.h>

+#include <string.h>

+#include <ctype.h>

+#include <stdlib.h>

+#include "ParseInf.h"

+

+#ifndef _MAX_PATH

+#define _MAX_PATH 500

+#endif

+

+CHAR8 *

+ReadLine (

+  IN MEMORY_FILE    *InputFile,

+  IN OUT CHAR8      *InputBuffer,

+  IN UINTN          MaxLength

+  )

+/*++

+

+Routine Description:

+

+  This function reads a line, stripping any comments.

+  The function reads a string from the input stream argument and stores it in 

+  the input string. ReadLine reads characters from the current file position 

+  to and including the first newline character, to the end of the stream, or 

+  until the number of characters read is equal to MaxLength - 1, whichever 

+  comes first.  The newline character, if read, is replaced with a \0. 

+

+Arguments:

+

+  InputFile     Memory file image.

+  InputBuffer   Buffer to read into, must be _MAX_PATH size.

+  MaxLength     The maximum size of the input buffer.

+

+Returns:

+

+  NULL if error or EOF

+  InputBuffer otherwise

+

+--*/

+{

+  CHAR8 *CharPtr;

+  CHAR8 *EndOfLine;

+  UINTN CharsToCopy;

+

+  //

+  // Verify input parameters are not null

+  //

+  assert (InputBuffer);

+  assert (InputFile->FileImage);

+  assert (InputFile->Eof);

+  assert (InputFile->CurrentFilePointer);

+

+  //

+  // Check for end of file condition

+  //

+  if (InputFile->CurrentFilePointer >= InputFile->Eof) {

+    return NULL;

+  }

+  //

+  // Find the next newline char

+  //

+  EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');

+

+  //

+  // Determine the number of characters to copy.

+  //

+  if (EndOfLine == 0) {

+    //

+    // If no newline found, copy to the end of the file.

+    //

+    CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;

+  } else if (EndOfLine >= InputFile->Eof) {

+    //

+    // If the newline found was beyond the end of file, copy to the eof.

+    //

+    CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;

+  } else {

+    //

+    // Newline found in the file.

+    //

+    CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;

+  }

+  //

+  // If the end of line is too big for the current buffer, set it to the max

+  // size of the buffer (leaving room for the \0.

+  //

+  if (CharsToCopy > MaxLength - 1) {

+    CharsToCopy = MaxLength - 1;

+  }

+  //

+  // Copy the line.

+  //

+  memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);

+

+  //

+  // Add the null termination over the 0x0D

+  //

+  InputBuffer[CharsToCopy - 1] = '\0';

+

+  //

+  // Increment the current file pointer (include the 0x0A)

+  //

+  InputFile->CurrentFilePointer += CharsToCopy + 1;

+

+  //

+  // Strip any comments

+  //

+  CharPtr = strstr (InputBuffer, "//");

+  if (CharPtr != 0) {

+    CharPtr[0] = 0;

+  }

+  //

+  // Return the string

+  //

+  return InputBuffer;

+}

+

+BOOLEAN

+FindSection (

+  IN MEMORY_FILE    *InputFile,

+  IN CHAR8          *Section

+  )

+/*++

+

+Routine Description:

+

+  This function parses a file from the beginning to find a section.

+  The section string may be anywhere within a line.

+

+Arguments:

+

+  InputFile     Memory file image.

+  Section       Section to search for

+

+Returns:

+

+  FALSE if error or EOF

+  TRUE if section found

+

+--*/

+{

+  CHAR8 InputBuffer[_MAX_PATH];

+  CHAR8 *CurrentToken;

+

+  //

+  // Verify input is not NULL

+  //

+  assert (InputFile->FileImage);

+  assert (InputFile->Eof);

+  assert (InputFile->CurrentFilePointer);

+  assert (Section);

+

+  //

+  // Rewind to beginning of file

+  //

+  InputFile->CurrentFilePointer = InputFile->FileImage;

+

+  //

+  // Read lines until the section is found

+  //

+  while (InputFile->CurrentFilePointer < InputFile->Eof) {

+    //

+    // Read a line

+    //

+    ReadLine (InputFile, InputBuffer, _MAX_PATH);

+

+    //

+    // Check if the section is found

+    //

+    CurrentToken = strstr (InputBuffer, Section);

+    if (CurrentToken != NULL) {

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

+

+EFI_STATUS

+FindToken (

+  IN MEMORY_FILE    *InputFile,

+  IN CHAR8          *Section,

+  IN CHAR8          *Token,

+  IN UINTN          Instance,

+  OUT CHAR8         *Value

+  )

+/*++

+

+Routine Description:

+

+  Finds a token value given the section and token to search for.

+

+Arguments:

+

+  InputFile Memory file image.

+  Section   The section to search for, a string within [].

+  Token     The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.

+  Instance  The instance of the token to search for.  Zero is the first instance.

+  Value     The string that holds the value following the =.  Must be _MAX_PATH in size.

+

+Returns:

+

+  EFI_SUCCESS             Value found.

+  EFI_ABORTED             Format error detected in INF file.

+  EFI_INVALID_PARAMETER   Input argument was null.

+  EFI_LOAD_ERROR          Error reading from the file.

+  EFI_NOT_FOUND           Section/Token/Value not found.

+

+--*/

+{

+  CHAR8   InputBuffer[_MAX_PATH];

+  CHAR8   *CurrentToken;

+  BOOLEAN ParseError;

+  BOOLEAN ReadError;

+  UINTN   Occurrance;

+

+  //

+  // Check input parameters

+  //

+  if (InputFile->FileImage == NULL ||

+      InputFile->Eof == NULL ||

+      InputFile->CurrentFilePointer == NULL ||

+      Section == NULL ||

+      strlen (Section) == 0 ||

+      Token == NULL ||

+      strlen (Token) == 0 ||

+      Value == NULL

+      ) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Initialize error codes

+  //

+  ParseError  = FALSE;

+  ReadError   = FALSE;

+

+  //

+  // Initialize our instance counter for the search token

+  //

+  Occurrance = 0;

+

+  if (FindSection (InputFile, Section)) {

+    //

+    // Found the desired section, find and read the desired token

+    //

+    do {

+      //

+      // Read a line from the file

+      //

+      if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {

+        //

+        // Error reading from input file

+        //

+        ReadError = TRUE;

+        break;

+      }

+      //

+      // Get the first non-whitespace string

+      //

+      CurrentToken = strtok (InputBuffer, " \t\n");

+      if (CurrentToken == NULL) {

+        //

+        // Whitespace line found (or comment) so continue

+        //

+        CurrentToken = InputBuffer;

+        continue;

+      }

+      //

+      // Make sure we have not reached the end of the current section

+      //

+      if (CurrentToken[0] == '[') {

+        break;

+      }

+      //

+      // Compare the current token with the desired token

+      //

+      if (strcmp (CurrentToken, Token) == 0) {

+        //

+        // Found it

+        //

+        //

+        // Check if it is the correct instance

+        //

+        if (Instance == Occurrance) {

+          //

+          // Copy the contents following the =

+          //

+          CurrentToken = strtok (NULL, "= \t\n");

+          if (CurrentToken == NULL) {

+            //

+            // Nothing found, parsing error

+            //

+            ParseError = TRUE;

+          } else {

+            //

+            // Copy the current token to the output value

+            //

+            strcpy (Value, CurrentToken);

+            return EFI_SUCCESS;

+          }

+        } else {

+          //

+          // Increment the occurrance found

+          //

+          Occurrance++;

+        }

+      }

+    } while (

+      !ParseError &&

+      !ReadError &&

+      InputFile->CurrentFilePointer < InputFile->Eof &&

+      CurrentToken[0] != '[' &&

+      Occurrance <= Instance

+    );

+  }

+  //

+  // Distinguish between read errors and INF file format errors.

+  //

+  if (ReadError) {

+    return EFI_LOAD_ERROR;

+  }

+

+  if (ParseError) {

+    return EFI_ABORTED;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+EFI_STATUS

+StringToGuid (

+  IN CHAR8      *AsciiGuidBuffer,

+  OUT EFI_GUID  *GuidBuffer

+  )

+/*++

+

+Routine Description: 

+

+  Converts a string to an EFI_GUID.  The string must be in the 

+  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.

+

+Arguments:  

+

+  AsciiGuidBuffer - pointer to ascii string

+  GuidBuffer      - pointer to destination Guid

+

+Returns:  

+

+  EFI_ABORTED             Could not convert the string

+  EFI_SUCCESS             The string was successfully converted

+  EFI_INVALID_PARAMETER   Input parameter is invalid.

+

+--*/

+{

+  INT32 Index;

+  UINTN Data1;

+  UINTN Data2;

+  UINTN Data3;

+  UINTN Data4[8];

+

+  if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Scan the guid string into the buffer

+  //

+  Index = sscanf (

+            AsciiGuidBuffer,

+            "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",

+            &Data1,

+            &Data2,

+            &Data3,

+            &Data4[0],

+            &Data4[1],

+            &Data4[2],

+            &Data4[3],

+            &Data4[4],

+            &Data4[5],

+            &Data4[6],

+            &Data4[7]

+            );

+

+  //

+  // Verify the correct number of items were scanned.

+  //

+  if (Index != 11) {

+    printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);

+    return EFI_ABORTED;

+  }

+  //

+  // Copy the data into our GUID.

+  //

+  GuidBuffer->Data1     = (UINT32) Data1;

+  GuidBuffer->Data2     = (UINT16) Data2;

+  GuidBuffer->Data3     = (UINT16) Data3;

+  GuidBuffer->Data4[0]  = (UINT8) Data4[0];

+  GuidBuffer->Data4[1]  = (UINT8) Data4[1];

+  GuidBuffer->Data4[2]  = (UINT8) Data4[2];

+  GuidBuffer->Data4[3]  = (UINT8) Data4[3];

+  GuidBuffer->Data4[4]  = (UINT8) Data4[4];

+  GuidBuffer->Data4[5]  = (UINT8) Data4[5];

+  GuidBuffer->Data4[6]  = (UINT8) Data4[6];

+  GuidBuffer->Data4[7]  = (UINT8) Data4[7];

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AsciiStringToUint64 (

+  IN CONST CHAR8  *AsciiString,

+  IN BOOLEAN      IsHex,

+  OUT UINT64      *ReturnValue

+  )

+/*++

+

+Routine Description:

+

+  Converts a null terminated ascii string that represents a number into a 

+  UINT64 value.  A hex number may be preceeded by a 0x, but may not be 

+  succeeded by an h.  A number without 0x or 0X is considered to be base 10 

+  unless the IsHex input is true.

+

+Arguments:

+

+  AsciiString   The string to convert.

+  IsHex         Force the string to be treated as a hex number.

+  ReturnValue   The return value.

+

+Returns:

+

+  EFI_SUCCESS   Number successfully converted.

+  EFI_ABORTED   Invalid character encountered.

+

+--*/

+{

+  UINT8   Index;

+  UINT64  HexNumber;

+  CHAR8   CurrentChar;

+

+  //

+  // Initialize the result

+  //

+  HexNumber = 0;

+

+  //

+  // Add each character to the result

+  //

+  if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {

+    //

+    // Verify string is a hex number

+    //

+    for (Index = 2; Index < strlen (AsciiString); Index++) {

+      if (isxdigit (AsciiString[Index]) == 0) {

+        return EFI_ABORTED;

+      }

+    }

+    //

+    // Convert the hex string.

+    //

+    for (Index = 2; AsciiString[Index] != '\0'; Index++) {

+      CurrentChar = AsciiString[Index];

+      HexNumber *= 16;

+      if (CurrentChar >= '0' && CurrentChar <= '9') {

+        HexNumber += CurrentChar - '0';

+      } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {

+        HexNumber += CurrentChar - 'a' + 10;

+      } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {

+        HexNumber += CurrentChar - 'A' + 10;

+      } else {

+        //

+        // Unrecognized character

+        //

+        return EFI_ABORTED;

+      }

+    }

+

+    *ReturnValue = HexNumber;

+  } else {

+    //

+    // Verify string is a number

+    //

+    for (Index = 0; Index < strlen (AsciiString); Index++) {

+      if (isdigit (AsciiString[Index]) == 0) {

+        return EFI_ABORTED;

+      }

+    }

+

+    *ReturnValue = atol (AsciiString);

+  }

+

+  return EFI_SUCCESS;

+};

+

+CHAR8 *

+ReadLineInStream (

+  IN FILE       *InputFile,

+  IN OUT CHAR8  *InputBuffer

+  )

+/*++

+

+Routine Description:

+

+  This function reads a line, stripping any comments.

+  // BUGBUG:  This is obsolete once genmake goes away...

+

+Arguments:

+

+  InputFile     Stream pointer.

+  InputBuffer   Buffer to read into, must be _MAX_PATH size.

+

+Returns:

+

+  NULL if error or EOF

+  InputBuffer otherwise

+

+--*/

+{

+  CHAR8 *CharPtr;

+

+  //

+  // Verify input parameters are not null

+  //

+  assert (InputFile);

+  assert (InputBuffer);

+

+  //

+  // Read a line

+  //

+  if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {

+    return NULL;

+  }

+  //

+  // Strip any comments

+  //

+  CharPtr = strstr (InputBuffer, "//");

+  if (CharPtr != 0) {

+    CharPtr[0] = 0;

+  }

+

+  CharPtr = strstr (InputBuffer, "#");

+  if (CharPtr != 0) {

+    CharPtr[0] = 0;

+  }

+  //

+  // Return the string

+  //

+  return InputBuffer;

+}

+

+BOOLEAN

+FindSectionInStream (

+  IN FILE       *InputFile,

+  IN CHAR8      *Section

+  )

+/*++

+

+Routine Description:

+

+  This function parses a stream file from the beginning to find a section.

+  The section string may be anywhere within a line.

+  // BUGBUG:  This is obsolete once genmake goes away...

+

+Arguments:

+

+  InputFile     Stream pointer.

+  Section       Section to search for

+

+Returns:

+

+  FALSE if error or EOF

+  TRUE if section found

+

+--*/

+{

+  CHAR8 InputBuffer[_MAX_PATH];

+  CHAR8 *CurrentToken;

+

+  //

+  // Verify input is not NULL

+  //

+  assert (InputFile);

+  assert (Section);

+

+  //

+  // Rewind to beginning of file

+  //

+  if (fseek (InputFile, 0, SEEK_SET) != 0) {

+    return FALSE;

+  }

+  //

+  // Read lines until the section is found

+  //

+  while (feof (InputFile) == 0) {

+    //

+    // Read a line

+    //

+    ReadLineInStream (InputFile, InputBuffer);

+

+    //

+    // Check if the section is found

+    //

+    CurrentToken = strstr (InputBuffer, Section);

+    if (CurrentToken != NULL) {

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

diff --git a/Source/Common/ParseInf.h b/Source/Common/ParseInf.h
new file mode 100644
index 0000000..ff98635
--- /dev/null
+++ b/Source/Common/ParseInf.h
@@ -0,0 +1,234 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  ParseInf.h

+

+Abstract:

+

+  Header file for helper functions useful for parsing INF files.

+

+--*/

+

+#ifndef _EFI_PARSE_INF_H

+#define _EFI_PARSE_INF_H

+

+#include <stdio.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+

+//

+// Common data structures

+//

+typedef struct {

+  CHAR8 *FileImage;

+  CHAR8 *Eof;

+  CHAR8 *CurrentFilePointer;

+} MEMORY_FILE;

+

+//

+// Functions declarations

+//

+CHAR8 *

+ReadLine (

+  IN MEMORY_FILE    *InputFile,

+  IN OUT CHAR8      *InputBuffer,

+  IN UINTN          MaxLength

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function reads a line, stripping any comments.

+  The function reads a string from the input stream argument and stores it in 

+  the input string. ReadLine reads characters from the current file position 

+  to and including the first newline character, to the end of the stream, or 

+  until the number of characters read is equal to MaxLength - 1, whichever 

+  comes first.  The newline character, if read, is replaced with a \0. 

+

+Arguments:

+

+  InputFile     Memory file image.

+  InputBuffer   Buffer to read into, must be _MAX_PATH size.

+  MaxLength     The maximum size of the input buffer.

+

+Returns:

+

+  NULL if error or EOF

+  InputBuffer otherwise

+

+--*/

+BOOLEAN

+FindSection (

+  IN MEMORY_FILE    *InputFile,

+  IN CHAR8          *Section

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function parses a file from the beginning to find a section.

+  The section string may be anywhere within a line.

+

+Arguments:

+

+  InputFile     Memory file image.

+  Section       Section to search for

+

+Returns:

+

+  FALSE if error or EOF

+  TRUE if section found

+

+--*/

+EFI_STATUS

+FindToken (

+  IN MEMORY_FILE    *InputFile,

+  IN CHAR8          *Section,

+  IN CHAR8          *Token,

+  IN UINTN          Instance,

+  OUT CHAR8         *Value

+  )

+;

+

+/*++

+

+Routine Description:

+

+  Finds a token value given the section and token to search for.

+

+Arguments:

+

+  InputFile Memory file image.

+  Section   The section to search for, a string within [].

+  Token     The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.

+  Instance  The instance of the token to search for.  Zero is the first instance.

+  Value     The string that holds the value following the =.  Must be _MAX_PATH in size.

+

+Returns:

+

+  EFI_SUCCESS             Value found.

+  EFI_ABORTED             Format error detected in INF file.

+  EFI_INVALID_PARAMETER   Input argument was null.

+  EFI_LOAD_ERROR          Error reading from the file.

+  EFI_NOT_FOUND           Section/Token/Value not found.

+

+--*/

+EFI_STATUS

+StringToGuid (

+  IN CHAR8        *AsciiGuidBuffer,

+  OUT EFI_GUID    *GuidBuffer

+  )

+;

+

+/*++

+

+Routine Description: 

+

+  Converts a string to an EFI_GUID.  The string must be in the 

+  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.

+

+Arguments:  

+

+  GuidBuffer      - pointer to destination Guid

+  AsciiGuidBuffer - pointer to ascii string

+

+Returns:  

+

+  EFI_ABORTED    Could not convert the string

+  EFI_SUCCESS    The string was successfully converted

+

+--*/

+EFI_STATUS

+AsciiStringToUint64 (

+  IN CONST CHAR8  *AsciiString,

+  IN BOOLEAN      IsHex,

+  OUT UINT64      *ReturnValue

+  )

+;

+

+/*++

+

+Routine Description:

+

+  Converts a null terminated ascii string that represents a number into a 

+  UINT64 value.  A hex number may be preceeded by a 0x, but may not be 

+  succeeded by an h.  A number without 0x or 0X is considered to be base 10 

+  unless the IsHex input is true.

+

+Arguments:

+

+  AsciiString   The string to convert.

+  IsHex         Force the string to be treated as a hex number.

+  ReturnValue   The return value.

+

+Returns:

+

+  EFI_SUCCESS   Number successfully converted.

+  EFI_ABORTED   Invalid character encountered.

+

+--*/

+CHAR8 *

+ReadLineInStream (

+  IN FILE       *InputFile,

+  IN OUT CHAR8  *InputBuffer

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function reads a line, stripping any comments.

+

+Arguments:

+

+  InputFile     Stream pointer.

+  InputBuffer   Buffer to read into, must be _MAX_PATH size.

+

+Returns:

+

+  NULL if error or EOF

+  InputBuffer otherwise

+

+--*/

+BOOLEAN

+FindSectionInStream (

+  IN FILE       *InputFile,

+  IN CHAR8      *Section

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function parses a stream file from the beginning to find a section.

+  The section string may be anywhere within a line.

+

+Arguments:

+

+  InputFile     Stream pointer.

+  Section       Section to search for

+

+Returns:

+

+  FALSE if error or EOF

+  TRUE if section found

+

+--*/

+#endif

diff --git a/Source/Common/SimpleFileParsing.c b/Source/Common/SimpleFileParsing.c
new file mode 100644
index 0000000..73b74cd
--- /dev/null
+++ b/Source/Common/SimpleFileParsing.c
@@ -0,0 +1,1457 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  SimpleFileParsing.c  

+

+Abstract:

+

+  Generic but simple file parsing routines.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include "EfiUtilityMsgs.h"

+#include "SimpleFileParsing.h"

+

+#ifndef MAX_PATH

+#define MAX_PATH  255

+#endif

+//

+// just in case we get in an endless loop.

+//

+#define MAX_NEST_DEPTH  20

+//

+// number of wchars

+//

+#define MAX_STRING_IDENTIFIER_NAME  100

+

+#define MAX_LINE_LEN                400

+

+#define T_CHAR_SPACE                ' '

+#define T_CHAR_NULL                 0

+#define T_CHAR_CR                   '\r'

+#define T_CHAR_TAB                  '\t'

+#define T_CHAR_LF                   '\n'

+#define T_CHAR_SLASH                '/'

+#define T_CHAR_BACKSLASH            '\\'

+#define T_CHAR_DOUBLE_QUOTE         '"'

+#define T_CHAR_LC_X                 'x'

+#define T_CHAR_0                    '0'

+#define T_CHAR_STAR                 '*'

+

+//

+// We keep a linked list of these for the source files we process

+//

+typedef struct _SOURCE_FILE {

+  FILE                *Fptr;

+  T_CHAR              *FileBuffer;

+  T_CHAR              *FileBufferPtr;

+  unsigned int        FileSize;

+  char                FileName[MAX_PATH];

+  unsigned int        LineNum;

+  BOOLEAN             EndOfFile;

+  BOOLEAN             SkipToHash;

+  struct _SOURCE_FILE *Previous;

+  struct _SOURCE_FILE *Next;

+  T_CHAR              ControlCharacter;

+} SOURCE_FILE;

+

+typedef struct {

+  T_CHAR  *FileBufferPtr;

+} FILE_POSITION;

+

+//

+// Keep all our module globals in this structure

+//

+static struct {

+  SOURCE_FILE SourceFile;

+  BOOLEAN     VerboseFile;

+  BOOLEAN     VerboseToken;

+} mGlobals;

+

+static

+unsigned int

+t_strcmp (

+  T_CHAR *Buffer,

+  T_CHAR *Str

+  );

+

+static

+unsigned int

+t_strncmp (

+  T_CHAR *Str1,

+  T_CHAR *Str2,

+  int    Len

+  );

+

+static

+unsigned int

+t_strlen (

+  T_CHAR *Str

+  );

+

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+unsigned int

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+T_CHAR  *

+t_strcpy (

+  T_CHAR *Dest,

+  T_CHAR *Src

+  );

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  );

+

+static

+STATUS

+ParseFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+FILE    *

+FindFile (

+  char          *FileName,

+  char          *FoundFileName,

+  unsigned int  FoundFileNameLen

+  );

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+STATUS

+GetFilePosition (

+  FILE_POSITION *Fpos

+  );

+

+static

+STATUS

+SetFilePosition (

+  FILE_POSITION *Fpos

+  );

+

+STATUS

+SFPInit (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+  None.

+

+Returns:

+  STATUS_SUCCESS always

+

+--*/

+{

+  memset ((void *) &mGlobals, 0, sizeof (mGlobals));

+  return STATUS_SUCCESS;

+}

+

+unsigned

+int

+SFPGetLineNumber (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Return the line number of the file we're parsing. Used

+  for error reporting purposes.

+

+Arguments:

+  None.

+

+Returns:

+  The line number, or 0 if no file is being processed

+

+--*/

+{

+  return mGlobals.SourceFile.LineNum;

+}

+

+T_CHAR *

+SFPGetFileName (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Return the name of the file we're parsing. Used

+  for error reporting purposes.

+

+Arguments:

+  None.

+

+Returns:

+  A pointer to the file name. Null if no file is being

+  processed.

+

+--*/

+{

+  if (mGlobals.SourceFile.FileName[0]) {

+    return mGlobals.SourceFile.FileName;

+  }

+

+  return NULL;

+}

+

+STATUS

+SFPOpenFile (

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+  Open a file for parsing.

+

+Arguments:

+  FileName  - name of the file to parse

+

+Returns:

+  

+

+--*/

+{

+  STATUS  Status;

+  t_strcpy (mGlobals.SourceFile.FileName, FileName);

+  Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);

+  return Status;

+}

+

+BOOLEAN

+SFPIsToken (

+  T_CHAR *Str

+  )

+/*++

+

+Routine Description:

+  Check to see if the specified token is found at

+  the current position in the input file.

+

+Arguments:

+  Str - the token to look for

+

+Returns:

+  TRUE - the token is next

+  FALSE - the token is not next

+

+Notes:

+  We do a simple string comparison on this function. It is

+  the responsibility of the caller to ensure that the token

+  is not a subset of some other token.

+

+  The file pointer is advanced past the token in the input file.

+

+--*/

+{

+  unsigned int  Len;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {

+    mGlobals.SourceFile.FileBufferPtr += Len;

+    if (mGlobals.VerboseToken) {

+      printf ("Token: '%s'\n", Str);

+    }

+

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+SFPIsKeyword (

+  T_CHAR *Str

+  )

+/*++

+

+Routine Description:

+  Check to see if the specified keyword is found at

+  the current position in the input file.

+

+Arguments:

+  Str - keyword to look for

+

+Returns:

+  TRUE - the keyword is next

+  FALSE - the keyword is not next

+

+Notes:

+  A keyword is defined as a "special" string that has a non-alphanumeric

+  character following it.

+

+--*/

+{

+  unsigned int  Len;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {

+    if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) {

+      return FALSE;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr += Len;

+    if (mGlobals.VerboseToken) {

+      printf ("Token: '%s'\n", Str);

+    }

+

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+SFPGetNextToken (

+  T_CHAR        *Str,

+  unsigned int  Len

+  )

+/*++

+

+Routine Description:

+  Get the next token from the input stream. 

+

+Arguments:

+  Str - pointer to a copy of the next token

+  Len - size of buffer pointed to by Str

+

+Returns:

+  TRUE  - next token successfully returned

+  FALSE - otherwise

+

+Notes:

+  Preceeding white space is ignored. 

+  The parser's buffer pointer is advanced past the end of the

+  token.

+

+--*/

+{

+  unsigned int  Index;

+  T_CHAR        TempChar;

+

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+  //

+  // Have to have enough string for at least one char and a null-terminator

+  //

+  if (Len < 2) {

+    return FALSE;

+  }

+  //

+  // Look at the first character. If it's an identifier, then treat it

+  // as such

+  //

+  TempChar = mGlobals.SourceFile.FileBufferPtr[0];

+  if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {

+    Str[0] = TempChar;

+    mGlobals.SourceFile.FileBufferPtr++;

+    Index = 1;

+    while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {

+      TempChar = mGlobals.SourceFile.FileBufferPtr[0];

+      if (((TempChar >= 'a') && (TempChar <= 'z')) ||

+          ((TempChar >= 'A') && (TempChar <= 'Z')) ||

+          ((TempChar >= '0') && (TempChar <= '9')) ||

+          (TempChar == '_')

+          ) {

+        Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];

+        mGlobals.SourceFile.FileBufferPtr++;

+        Index++;

+      } else {

+        //

+        // Invalid character for symbol name, so break out

+        //

+        break;

+      }

+    }

+    //

+    // Null terminate and return success

+    //

+    Str[Index] = 0;

+    return TRUE;

+  } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {

+    Str[0] = mGlobals.SourceFile.FileBufferPtr[0];

+    mGlobals.SourceFile.FileBufferPtr++;

+    Str[1] = 0;

+    return TRUE;

+  } else {

+    //

+    // Everything else is white-space (or EOF) separated

+    //

+    Index = 0;

+    while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {

+      if (IsWhiteSpace (&mGlobals.SourceFile)) {

+        if (Index > 0) {

+          Str[Index] = 0;

+          return TRUE;

+        }

+

+        return FALSE;

+      } else {

+        Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];

+        mGlobals.SourceFile.FileBufferPtr++;

+        Index++;

+      }

+    }

+    //

+    // See if we just ran out of file contents, but did find a token

+    //

+    if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {

+      Str[Index] = 0;

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+SFPGetGuidToken (

+  T_CHAR *Str,

+  UINT32 Len

+  )

+/*++

+

+Routine Description:

+  Parse a GUID from the input stream. Stop when you discover white space.

+

+Arguments:

+  Str - pointer to a copy of the next token

+  Len - size of buffer pointed to by Str

+

+Returns:

+  TRUE  - GUID string returned successfully

+  FALSE - otherwise

+

+--*/

+{

+  UINT32  Index;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  Index = 0;

+  while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {

+    if (IsWhiteSpace (&mGlobals.SourceFile)) {

+      if (Index > 0) {

+        Str[Index] = 0;

+        return TRUE;

+      }

+

+      return FALSE;

+    } else {

+      Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];

+      mGlobals.SourceFile.FileBufferPtr++;

+      Index++;

+    }

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+SFPSkipToToken (

+  T_CHAR *Str

+  )

+{

+  unsigned int  Len;

+  T_CHAR        *SavePos;

+  Len     = t_strlen (Str);

+  SavePos = mGlobals.SourceFile.FileBufferPtr;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  while (!EndOfFile (&mGlobals.SourceFile)) {

+    if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {

+      mGlobals.SourceFile.FileBufferPtr += Len;

+      return TRUE;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    SkipWhiteSpace (&mGlobals.SourceFile);

+  }

+

+  mGlobals.SourceFile.FileBufferPtr = SavePos;

+  return FALSE;

+}

+

+BOOLEAN

+SFPGetNumber (

+  unsigned int *Value

+  )

+/*++

+

+Routine Description:

+  Check the token at the current file position for a numeric value.

+  May be either decimal or hex.

+

+Arguments:

+  Value  - pointer where to store the value

+

+Returns:

+  FALSE    - current token is not a number

+  TRUE     - current token is a number

+

+--*/

+{

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+    //

+    // Check for hex value

+    //

+    if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {

+      if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {

+        return FALSE;

+      }

+

+      mGlobals.SourceFile.FileBufferPtr += 2;

+      sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);

+      while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+        mGlobals.SourceFile.FileBufferPtr++;

+      }

+

+      return TRUE;

+    } else {

+      *Value = atoi (mGlobals.SourceFile.FileBufferPtr);

+      while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+        mGlobals.SourceFile.FileBufferPtr++;

+      }

+

+      return TRUE;

+    }

+  } else {

+    return FALSE;

+  }

+}

+

+STATUS

+SFPCloseFile (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Close the file being parsed.

+

+Arguments:

+  None.

+

+Returns:

+  STATUS_SUCCESS - the file was closed 

+  STATUS_ERROR   - no file is currently open

+

+--*/

+{

+  if (mGlobals.SourceFile.FileBuffer != NULL) {

+    free (mGlobals.SourceFile.FileBuffer);

+    memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));

+    return STATUS_SUCCESS;

+  }

+

+  return STATUS_ERROR;

+}

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  )

+/*++

+

+Routine Description:

+

+  Given a source file, open the file and parse it

+  

+Arguments:

+

+  SourceFile        - name of file to parse

+  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.

+

+Returns:

+

+  Standard status.

+  

+--*/

+{

+  static unsigned int NestDepth = 0;

+  char                FoundFileName[MAX_PATH];

+  STATUS              Status;

+

+  Status = STATUS_SUCCESS;

+  NestDepth++;

+  //

+  // Print the file being processed. Indent so you can tell the include nesting

+  // depth.

+  //

+  if (mGlobals.VerboseFile) {

+    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);

+    fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile);

+  }

+

+  //

+  // Make sure we didn't exceed our maximum nesting depth

+  //

+  if (NestDepth > MAX_NEST_DEPTH) {

+    Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+  //

+  // Try to open the file locally, and if that fails try along our include paths.

+  //

+  strcpy (FoundFileName, SourceFile->FileName);

+  if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {

+    return STATUS_ERROR;

+  }

+  //

+  // Process the file found

+  //

+  ProcessFile (SourceFile);

+Finish:

+  //

+  // Close open files and return status

+  //

+  if (SourceFile->Fptr != NULL) {

+    fclose (SourceFile->Fptr);

+    SourceFile->Fptr = NULL;

+  }

+

+  return Status;

+}

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  )

+/*++

+

+Routine Description:

+

+  Given a source file that's been opened, read the contents into an internal

+  buffer and pre-process it to remove comments.

+  

+Arguments:

+

+  SourceFile        - structure containing info on the file to process

+

+Returns:

+

+  Standard status.

+  

+--*/

+{

+  //

+  // Get the file size, and then read the entire thing into memory.

+  // Allocate extra space for a terminator character.

+  //

+  fseek (SourceFile->Fptr, 0, SEEK_END);

+  SourceFile->FileSize = ftell (SourceFile->Fptr);

+  if (mGlobals.VerboseFile) {

+    printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);

+  }

+

+  fseek (SourceFile->Fptr, 0, SEEK_SET);

+  SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));

+  if (SourceFile->FileBuffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  fread ((void *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);

+  SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;

+  //

+  // Pre-process the file to replace comments with spaces

+  //

+  PreprocessFile (SourceFile);

+  SourceFile->LineNum = 1;

+  return STATUS_SUCCESS;

+}

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  )

+/*++

+

+Routine Description:

+  Preprocess a file to replace all carriage returns with NULLs so

+  we can print lines (as part of error messages) from the file to the screen.

+  

+Arguments:

+  SourceFile - structure that we use to keep track of an input file.

+

+Returns:

+  Nothing.

+  

+--*/

+{

+  BOOLEAN InComment;

+  BOOLEAN SlashSlashComment;

+  int     LineNum;

+

+  RewindFile (SourceFile);

+  InComment         = FALSE;

+  SlashSlashComment = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    //

+    // If a line-feed, then no longer in a comment if we're in a // comment

+    //

+    if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      if (InComment && SlashSlashComment) {

+        InComment         = FALSE;

+        SlashSlashComment = FALSE;

+      }

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {

+      //

+      // Replace all carriage returns with a NULL so we can print stuff

+      //

+      SourceFile->FileBufferPtr[0] = 0;

+      SourceFile->FileBufferPtr++;

+      //

+      // Check for */ comment end

+      //

+    } else if (InComment &&

+             !SlashSlashComment &&

+             (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&

+             (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)

+            ) {

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+      InComment = FALSE;

+    } else if (InComment) {

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+      //

+      // Check for // comments

+      //

+    } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {

+      InComment         = TRUE;

+      SlashSlashComment = TRUE;

+      //

+      // Check for /* comment start

+      //

+    } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+      SlashSlashComment = FALSE;

+      InComment         = TRUE;

+    } else {

+      SourceFile->FileBufferPtr++;

+    }

+  }

+  //

+  // Could check for end-of-file and still in a comment, but

+  // should not be necessary. So just restore the file pointers.

+  //

+  RewindFile (SourceFile);

+  //

+  // Dump the reformatted file if verbose mode

+  //

+  if (mGlobals.VerboseFile) {

+    LineNum = 1;

+    printf ("%04d: ", LineNum);

+    while (!EndOfFile (SourceFile)) {

+      if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {

+        printf ("'\n%04d: '", ++LineNum);

+      } else {

+        printf ("%c", SourceFile->FileBufferPtr[0]);

+      }

+

+      SourceFile->FileBufferPtr++;

+    }

+

+    printf ("'\n");

+    printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);

+    RewindFile (SourceFile);

+  }

+}

+

+BOOLEAN

+SFPGetQuotedString (

+  T_CHAR      *Str,

+  int         Length

+  )

+/*++

+

+Routine Description:

+  Retrieve a quoted-string from the input file. 

+  

+Arguments:

+  Str    - pointer to a copy of the quoted string parsed

+  Length - size of buffer pointed to by Str

+

+Returns:

+  TRUE    - next token in input stream was a quoted string, and

+            the string value was returned in Str

+  FALSE   - otherwise

+  

+--*/

+{

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {

+    mGlobals.SourceFile.FileBufferPtr++;

+    while (Length > 0) {

+      if (EndOfFile (&mGlobals.SourceFile)) {

+        return FALSE;

+      }

+      //

+      // Check for closing quote

+      //

+      if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {

+        mGlobals.SourceFile.FileBufferPtr++;

+        *Str = 0;

+        return TRUE;

+      }

+

+      *Str = mGlobals.SourceFile.FileBufferPtr[0];

+      Str++;

+      Length--;

+      mGlobals.SourceFile.FileBufferPtr++;

+    }

+  }

+  //

+  // First character was not a quote, or the input string length was

+  // insufficient to contain the quoted string, so return failure code.

+  //

+  return FALSE;

+}

+

+BOOLEAN

+SFPIsEOF (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Return TRUE of FALSE to indicate whether or not we've reached the end of the

+  file we're parsing.

+  

+Arguments:

+  NA

+

+Returns:

+  TRUE    - EOF reached

+  FALSE   - otherwise

+  

+--*/

+{

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  return EndOfFile (&mGlobals.SourceFile);

+}

+

+#if 0

+static

+T_CHAR *

+GetQuotedString (

+  SOURCE_FILE *SourceFile,

+  BOOLEAN     Optional

+  )

+{

+  T_CHAR        *String;

+  T_CHAR        *Start;

+  T_CHAR        *Ptr;

+  unsigned int  Len;

+  BOOLEAN       PreviousBackslash;

+

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    if (Optional == FALSE) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);

+    }

+

+    return NULL;

+  }

+

+  Len = 0;

+  SourceFile->FileBufferPtr++;

+  Start             = Ptr = SourceFile->FileBufferPtr;

+  PreviousBackslash = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {

+      break;

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {

+      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);

+      PreviousBackslash = FALSE;

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {

+      PreviousBackslash = TRUE;

+    } else {

+      PreviousBackslash = FALSE;

+    }

+

+    SourceFile->FileBufferPtr++;

+    Len++;

+  }

+

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);

+  } else {

+    SourceFile->FileBufferPtr++;

+  }

+  //

+  // Now allocate memory for the string and save it off

+  //

+  String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));

+  if (String == NULL) {

+    Error (NULL, 0, 0, "memory allocation failed", NULL);

+    return NULL;

+  }

+  //

+  // Copy the string from the file buffer to the local copy.

+  // We do no reformatting of it whatsoever at this point.

+  //

+  Ptr = String;

+  while (Len > 0) {

+    *Ptr = *Start;

+    Start++;

+    Ptr++;

+    Len--;

+  }

+

+  *Ptr = 0;

+  return String;

+}

+#endif

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  //

+  // The file buffer pointer will typically get updated before the End-of-file flag in the

+  // source file structure, so check it first.

+  //

+  if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {

+    SourceFile->EndOfFile = TRUE;

+    return TRUE;

+  }

+

+  if (SourceFile->EndOfFile) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+#if 0

+static

+void

+ProcessTokenInclude (

+  SOURCE_FILE *SourceFile

+  )

+{

+  char          IncludeFileName[MAX_PATH];

+  char          *To;

+  unsigned int  Len;

+  BOOLEAN       ReportedError;

+  SOURCE_FILE   IncludedSourceFile;

+

+  ReportedError = FALSE;

+  if (SkipWhiteSpace (SourceFile) == 0) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);

+  }

+  //

+  // Should be quoted file name

+  //

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);

+    goto FailDone;

+  }

+

+  SourceFile->FileBufferPtr++;

+  //

+  // Copy the filename as ascii to our local string

+  //

+  To  = IncludeFileName;

+  Len = 0;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);

+      goto FailDone;

+    }

+

+    if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {

+      SourceFile->FileBufferPtr++;

+      break;

+    }

+    //

+    // If too long, then report the error once and process until the closing quote

+    //

+    Len++;

+    if (!ReportedError && (Len >= sizeof (IncludeFileName))) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);

+      ReportedError = TRUE;

+    }

+

+    if (!ReportedError) {

+      *To = (T_CHAR) SourceFile->FileBufferPtr[0];

+      To++;

+    }

+

+    SourceFile->FileBufferPtr++;

+  }

+

+  if (!ReportedError) {

+    *To = 0;

+    memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));

+    strcpy (IncludedSourceFile.FileName, IncludeFileName);

+    ProcessIncludeFile (&IncludedSourceFile, SourceFile);

+  }

+

+  return ;

+FailDone:

+  //

+  // Error recovery -- skip to next #

+  //

+  SourceFile->SkipToHash = TRUE;

+}

+#endif

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  switch (*SourceFile->FileBufferPtr) {

+  case T_CHAR_NULL:

+  case T_CHAR_CR:

+  case T_CHAR_SPACE:

+  case T_CHAR_TAB:

+  case T_CHAR_LF:

+    return TRUE;

+

+  default:

+    return FALSE;

+  }

+}

+

+unsigned int

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  unsigned int  Count;

+

+  Count = 0;

+  while (!EndOfFile (SourceFile)) {

+    Count++;

+    switch (*SourceFile->FileBufferPtr) {

+    case T_CHAR_NULL:

+    case T_CHAR_CR:

+    case T_CHAR_SPACE:

+    case T_CHAR_TAB:

+      SourceFile->FileBufferPtr++;

+      break;

+

+    case T_CHAR_LF:

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      break;

+

+    default:

+      return Count - 1;

+    }

+  }

+  //

+  // Some tokens require trailing whitespace. If we're at the end of the

+  // file, then we count that as well.

+  //

+  if ((Count == 0) && (EndOfFile (SourceFile))) {

+    Count++;

+  }

+

+  return Count;

+}

+

+static

+unsigned int

+t_strcmp (

+  T_CHAR *Buffer,

+  T_CHAR *Str

+  )

+/*++

+

+Routine Description:

+  Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,

+  so only compare up to the length of Str.

+

+Arguments:

+  Buffer  - pointer to first (possibly not null-terminated) string

+  Str     - pointer to null-terminated string to compare to Buffer

+

+Returns:

+  Number of bytes matched if exact match

+  0 if Buffer does not start with Str

+

+--*/

+{

+  unsigned int  Len;

+

+  Len = 0;

+  while (*Str && (*Str == *Buffer)) {

+    Buffer++;

+    Str++;

+    Len++;

+  }

+

+  if (*Str) {

+    return 0;

+  }

+

+  return Len;

+}

+

+static

+unsigned int

+t_strlen (

+  T_CHAR *Str

+  )

+{

+  unsigned int  Len;

+  Len = 0;

+  while (*Str) {

+    Len++;

+    Str++;

+  }

+

+  return Len;

+}

+

+static

+unsigned int

+t_strncmp (

+  T_CHAR *Str1,

+  T_CHAR *Str2,

+  int    Len

+  )

+{

+  while (Len > 0) {

+    if (*Str1 != *Str2) {

+      return Len;

+    }

+

+    Len--;

+    Str1++;

+    Str2++;

+  }

+

+  return 0;

+}

+

+static

+T_CHAR *

+t_strcpy (

+  T_CHAR *Dest,

+  T_CHAR *Src

+  )

+{

+  T_CHAR  *SaveDest;

+  SaveDest = Dest;

+  while (*Src) {

+    *Dest = *Src;

+    Dest++;

+    Src++;

+  }

+

+  *Dest = 0;

+  return SaveDest;

+}

+

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  SourceFile->LineNum       = 1;

+  SourceFile->FileBufferPtr = SourceFile->FileBuffer;

+  SourceFile->EndOfFile     = 0;

+}

+

+static

+UINT32

+GetHexChars (

+  T_CHAR      *Buffer,

+  UINT32      BufferLen

+  )

+{

+  UINT32  Len;

+  Len = 0;

+  while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) {

+    if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+      *Buffer = mGlobals.SourceFile.FileBufferPtr[0];

+      Buffer++;

+      Len++;

+      BufferLen--;

+      mGlobals.SourceFile.FileBufferPtr++;

+    } else {

+      break;

+    }

+  }

+  //

+  // Null terminate if we can

+  //

+  if ((Len > 0) && (BufferLen > 0)) {

+    *Buffer = 0;

+  }

+

+  return Len;

+}

+

+BOOLEAN

+SFPGetGuid (

+  int         GuidStyle,

+  EFI_GUID    *Value

+  )

+/*++

+

+Routine Description:

+  Parse a GUID from the input stream. Stop when you discover white space.

+

+Arguments:

+  GuidStyle - Style of the following GUID token

+  Value     - pointer to EFI_GUID struct for output

+

+Returns:

+  TRUE  - GUID string parsed successfully

+  FALSE - otherwise

+

+  GUID styles

+    Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD

+

+--*/

+{

+  UINT32        Value32;

+  UINT32        Index;

+  FILE_POSITION FPos;

+  T_CHAR        TempString[20];

+  T_CHAR        TempString2[3];

+  T_CHAR        *From;

+  T_CHAR        *To;

+  UINT32        Len;

+  BOOLEAN       Status;

+

+  Status = FALSE;

+  //

+  // Skip white space, then start parsing

+  //

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  GetFilePosition (&FPos);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {

+    //

+    // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD

+    //

+    Len = GetHexChars (TempString, sizeof (TempString));

+    if ((Len == 0) || (Len > 8)) {

+      goto Done;

+    }

+

+    sscanf (TempString, "%x", &Value32);

+    Value->Data1 = Value32;

+    //

+    // Next two UINT16 fields

+    //

+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {

+      goto Done;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    Len = GetHexChars (TempString, sizeof (TempString));

+    if ((Len == 0) || (Len > 4)) {

+      goto Done;

+    }

+

+    sscanf (TempString, "%x", &Value32);

+    Value->Data2 = (UINT16) Value32;

+

+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {

+      goto Done;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    Len = GetHexChars (TempString, sizeof (TempString));

+    if ((Len == 0) || (Len > 4)) {

+      goto Done;

+    }

+

+    sscanf (TempString, "%x", &Value32);

+    Value->Data3 = (UINT16) Value32;

+    //

+    // Parse the "AAAA" as two bytes

+    //

+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {

+      goto Done;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    Len = GetHexChars (TempString, sizeof (TempString));

+    if ((Len == 0) || (Len > 4)) {

+      goto Done;

+    }

+

+    sscanf (TempString, "%x", &Value32);

+    Value->Data4[0] = (UINT8) (Value32 >> 8);

+    Value->Data4[1] = (UINT8) Value32;

+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {

+      goto Done;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    //

+    // Read the last 6 bytes of the GUID

+    //

+    //

+    Len = GetHexChars (TempString, sizeof (TempString));

+    if ((Len == 0) || (Len > 12)) {

+      goto Done;

+    }

+    //

+    // Insert leading 0's to make life easier

+    //

+    if (Len != 12) {

+      From            = TempString + Len - 1;

+      To              = TempString + 11;

+      TempString[12]  = 0;

+      while (From >= TempString) {

+        *To = *From;

+        To--;

+        From--;

+      }

+

+      while (To >= TempString) {

+        *To = '0';

+        To--;

+      }

+    }

+    //

+    // Now parse each byte

+    //

+    TempString2[2] = 0;

+    for (Index = 0; Index < 6; Index++) {

+      //

+      // Copy the two characters from the input string to something

+      // we can parse.

+      //

+      TempString2[0]  = TempString[Index * 2];

+      TempString2[1]  = TempString[Index * 2 + 1];

+      sscanf (TempString2, "%x", &Value32);

+      Value->Data4[Index + 2] = (UINT8) Value32;

+    }

+

+    Status = TRUE;

+  } else {

+    //

+    // Unsupported GUID style

+    //

+    return FALSE;

+  }

+

+Done:

+  if (Status == FALSE) {

+    SetFilePosition (&FPos);

+  }

+

+  return Status;

+}

+

+static

+STATUS

+GetFilePosition (

+  FILE_POSITION *Fpos

+  )

+{

+  Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+SetFilePosition (

+  FILE_POSITION *Fpos

+  )

+{

+  //

+  // Should check range of pointer

+  //

+  mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;

+  return STATUS_SUCCESS;

+}

diff --git a/Source/Common/SimpleFileParsing.h b/Source/Common/SimpleFileParsing.h
new file mode 100644
index 0000000..7cf25a6
--- /dev/null
+++ b/Source/Common/SimpleFileParsing.h
@@ -0,0 +1,120 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  SimpleFileParsing.h

+

+Abstract:

+

+  Function prototypes and defines for the simple file parsing routines.

+

+--*/

+

+#ifndef _SIMPLE_FILE_PARSING_H_

+#define _SIMPLE_FILE_PARSING_H_

+

+#include <Common/UefiBaseTypes.h>

+

+#define T_CHAR  char

+

+STATUS

+SFPInit (

+  VOID

+  )

+;

+

+STATUS

+SFPOpenFile (

+  char    *FileName

+  )

+;

+

+BOOLEAN

+SFPIsKeyword (

+  T_CHAR *Str

+  )

+;

+

+BOOLEAN

+SFPIsToken (

+  T_CHAR *Str

+  )

+;

+

+BOOLEAN

+SFPGetNextToken (

+  T_CHAR        *Str,

+  unsigned int  Len

+  )

+;

+

+BOOLEAN

+SFPGetGuidToken (

+  T_CHAR *Str,

+  UINT32 Len

+  )

+;

+

+#define PARSE_GUID_STYLE_5_FIELDS 0

+

+BOOLEAN

+SFPGetGuid (

+  int         GuidStyle,

+  EFI_GUID    *Value

+  )

+;

+

+BOOLEAN

+SFPSkipToToken (

+  T_CHAR *Str

+  )

+;

+

+BOOLEAN

+SFPGetNumber (

+  unsigned int   *Value

+  )

+;

+

+BOOLEAN

+SFPGetQuotedString (

+  T_CHAR      *Str,

+  int         Length

+  )

+;

+

+BOOLEAN

+SFPIsEOF (

+  VOID

+  )

+;

+

+STATUS

+SFPCloseFile (

+  VOID

+  )

+;

+

+unsigned

+int

+SFPGetLineNumber (

+  VOID

+  )

+;

+

+T_CHAR  *

+SFPGetFileName (

+  VOID

+  )

+;

+

+#endif // #ifndef _SIMPLE_FILE_PARSING_H_

diff --git a/Source/Common/WinNtInclude.h b/Source/Common/WinNtInclude.h
new file mode 100644
index 0000000..80e45b4
--- /dev/null
+++ b/Source/Common/WinNtInclude.h
@@ -0,0 +1,73 @@
+/*--

+

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+  WinNtInclude.h

+

+Abstract:

+  Include file for the WinNt Library

+

+--*/

+

+#ifndef __WIN_NT_INCLUDE_H__

+#define __WIN_NT_INCLUDE_H__

+

+//

+// Win32 include files do not compile clean with /W4, so we use the warning

+// pragma to suppress the warnings for Win32 only. This way our code can stil

+// compile at /W4 (highest warning level) with /WX (warnings cause build

+// errors).

+//

+#pragma warning(disable : 4115)

+#pragma warning(disable : 4201)

+#pragma warning(disable : 4214)

+#pragma warning(disable : 4028)

+#pragma warning(disable : 4133)

+

+#define GUID  _WINNT_DUP_GUID_____

+#define _LIST_ENTRY  _WINNT_DUP_LIST_ENTRY_FORWARD

+#define LIST_ENTRY   _WINNT_DUP_LIST_ENTRY

+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement

+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement

+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64

+#undef UNALIGNED

+#undef CONST

+#undef VOID

+

+#ifndef __GNUC__

+#include "windows.h"

+#endif

+

+#undef GUID

+#undef _LIST_ENTRY

+#undef LIST_ENTRY

+#undef InterlockedIncrement

+#undef InterlockedDecrement

+#undef InterlockedCompareExchange64

+#undef InterlockedCompareExchangePointer

+

+#define VOID void

+

+//

+// Prevent collisions with Windows API name macros that deal with Unicode/Not issues

+//

+#undef LoadImage

+#undef CreateEvent

+

+//

+// Set the warnings back on as the EFI code must be /W4.

+//

+#pragma warning(default : 4115)

+#pragma warning(default : 4201)

+#pragma warning(default : 4214)

+

+

+#endif

diff --git a/Source/Common/build.xml b/Source/Common/build.xml
new file mode 100644
index 0000000..38ae477
--- /dev/null
+++ b/Source/Common/build.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="CommonTools.lib" basedir=".">

+<!--

+    EDK Common Tools Library

+  Copyright (c) 2006, Intel Corporation

+-->

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="tmp" value="tmp"/>

+  <property name="LibName" value="CommonTool"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/Common/tmp"/>

+

+  <target name="CommonTools.lib" depends="init, ToolsLibrary">

+    <echo message="The EDK Tool Library: ${LibName} build has completed."/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool Library: ${LibName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="ToolsLibrary" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${LIB_DIR}/CommonTools"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <compilerarg value="-fPIC" if="x86_64_linux"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+

+      <fileset dir="${basedir}/Common" 

+        includes="*.c" />

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only from ${BUILD_DIR}"/>  

+    <delete dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/CompressDll/CompressDll.c b/Source/CompressDll/CompressDll.c
new file mode 100644
index 0000000..cc06f26
--- /dev/null
+++ b/Source/CompressDll/CompressDll.c
@@ -0,0 +1,105 @@
+/** @file

+  Compression DLL used by PCD Tools

+

+  Copyright (c) 2006, Intel Corporation   All rights reserved.

+  This program and the accompanying materials are licensed and made available 

+  under the terms and conditions of the BSD License which accompanies this 

+  distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php 

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+#if defined(__GNUC__)

+typedef long long __int64;/*For cygwin build*/

+#endif

+#include "CompressDll.h"

+#include "EfiCompress.h"

+

+extern

+EFI_STATUS

+Compress (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  );

+  

+JNIEXPORT jbyteArray JNICALL  Java_org_tianocore_framework_tasks_Compress_CallCompress 

+(JNIEnv *env, jobject obj, jbyteArray SourceBuffer, jint SourceSize, jstring path)

+{

+  char*          DestBuffer;

+  int            DestSize;   

+  int            Result;

+  char           *InputBuffer;

+  jbyteArray     OutputBuffer;

+  jbyte          *TempByte;

+  

+  DestSize   = 0;

+  DestBuffer = NULL;

+  

+  TempByte = (*env)->GetByteArrayElements(env, SourceBuffer, 0);

+  InputBuffer = (char*) TempByte;

+

+  

+   //

+   //  First call compress function and get need buffer size

+   //

+

+   Result = Compress (

+        (char*) InputBuffer, 

+        SourceSize,  

+        DestBuffer,

+        &DestSize

+        );

+

+   if (Result = EFI_BUFFER_TOO_SMALL) {

+     DestBuffer = malloc (DestSize);

+   }

+

+   //

+   //  Second call compress and get the DestBuffer value

+   //

+   Result = Compress(

+              (char*) InputBuffer, 

+        SourceSize,  

+        DestBuffer,

+        &DestSize  

+     );

+

+   //

+   // new a MV array to store the return compressed buffer

+   //

+   OutputBuffer = (*env)->NewByteArray(env, DestSize);

+   (*env)->SetByteArrayRegion(env, OutputBuffer,0, DestSize, (jbyte*) DestBuffer);

+

+   //

+   // Free Ouputbuffer.

+   //

+   free (DestBuffer);

+  

+

+  if (Result != 0) {

+    return NULL;

+  } else {

+    return OutputBuffer;

+  }

+}

+

+#ifdef _MSC_VER

+BOOLEAN 

+__stdcall 

+DllMainCRTStartup(

+    unsigned int hDllHandle, 

+    unsigned int nReason,    

+    void*   Reserved    

+)

+{

+  return TRUE;

+}

+#else

+#ifdef __GNUC__

+#endif

+#endif

+

diff --git a/Source/CompressDll/CompressDll.h b/Source/CompressDll/CompressDll.h
new file mode 100644
index 0000000..fa3b83c
--- /dev/null
+++ b/Source/CompressDll/CompressDll.h
@@ -0,0 +1,22 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */

+

+#include <jni.h>

+/* Header for class org_tianocore_frameworktasks_Compress */

+

+#ifndef _Included_org_tianocore_framework_tasks_Compress

+#define _Included_org_tianocore_framework_tasks_Compress

+#ifdef __cplusplus

+extern "C" {

+#endif

+/*

+ * Class:     org_tianocore_frameworktasks_Compress

+ * Method:    CallCompress

+ * Signature: ([BILjava/lang/String;)[B

+ */

+JNIEXPORT jbyteArray JNICALL Java_org_tianocore_framework_tasks_Compress_CallCompress

+  (JNIEnv *, jobject, jbyteArray, jint, jstring);

+

+#ifdef __cplusplus

+}

+#endif

+#endif

diff --git a/Source/CompressDll/build.xml b/Source/CompressDll/build.xml
new file mode 100644
index 0000000..6f591b3
--- /dev/null
+++ b/Source/CompressDll/build.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK CompressDll Tool Library

+  Copyright (c) 2006, Intel Corporation

+-->

+

+  <property name="WORKSPACE" value="${env.WORKSPACE}"/>

+  <property name="LibName" value="CompressDll"/>

+  <property name="FileSet" value="CompressDll.c CompressDll.h"/>

+  <property name="LibFileSet" value="CompressDll.c DepexParser.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${WORKSPACE}/Tools/CCode/Source/${LibName}/tmp"/>

+

+  <target name="GenTool" depends="init,Lib" >

+    <echo message="The EDK Tool Library: ${LibName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool Library: ${LibName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+  

+  <target name="Lib" depends="init">

+    <cc name="${ToolChain}" 

+      objdir="${BUILD_DIR}" 

+      outtype="shared" 

+      debug="true"

+      optimize="speed" 

+      outfile="${BIN_DIR}/${LibName}"

+      outputfileproperty="result"

+      >

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <fileset dir="${LibName}" includes="${LibFileSet}" defaultexcludes="TRUE" excludes="*.xml *.inf"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <includepath path="${env.JAVA_HOME}/include"/>

+      <includepath path="${env.JAVA_HOME}/include/linux" if="gcc"/>

+      <includepath path="${env.JAVA_HOME}/include/win32" if="cygwin"/>

+      <includepath path="${env.JAVA_HOME}/include/win32" if="msft"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+      <syslibset libs="kernel32" if="msft"/>

+      <linkerarg value="-mno-cygwin" if="cygwin"/>

+      <linkerarg value="--add-stdcall-alias" if="cygwin"/>

+    </cc>

+    <copy file="${result}" tofile="${BIN_DIR}/CompressDll.dll"/>

+    <chmod file="${BIN_DIR}/CompressDll.dll" perm="ugo+x"/>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${LibName}${ext_dynamic}"/>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${LibName}.*"/>

+    </delete>

+  </target>

+</project>

diff --git a/Source/CreateMtFile/CreateMtFile.c b/Source/CreateMtFile/CreateMtFile.c
new file mode 100644
index 0000000..1c17b3d
--- /dev/null
+++ b/Source/CreateMtFile/CreateMtFile.c
@@ -0,0 +1,247 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  CreateMtFile.c

+

+Abstract:

+

+  Simple utility to create a pad file containing fixed data.

+  

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#define PROGRAM_NAME  "CreateMtFile"

+

+typedef struct {

+  INT8    *OutFileName;

+  INT8    ByteValue;

+  UINT32  FileSize;

+} OPTIONS;

+

+static

+EFI_STATUS

+ProcessArgs (

+  IN INT32          Argc,

+  IN INT8           *Argv[],

+  IN OUT OPTIONS    *Options

+  );

+

+static

+void

+Usage (

+  VOID

+  );

+

+int

+main (

+  IN INT32  Argc,

+  IN INT8   *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+  Main entry point for this utility.

+

+Arguments:

+

+  Standard C entry point args Argc and Argv

+

+Returns:

+

+  EFI_SUCCESS if good to go

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment

+// GC_TODO:    EFI_DEVICE_ERROR - add return value to function comment

+// GC_TODO:    EFI_DEVICE_ERROR - add return value to function comment

+{

+  FILE    *OutFptr;

+  OPTIONS Options;

+

+  //

+  // Process the command-line arguments.

+  //

+  if (ProcessArgs (Argc, Argv, &Options) != EFI_SUCCESS) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Open the output file

+  //

+  if ((OutFptr = fopen (Options.OutFileName, "wb")) == NULL) {

+    fprintf (

+      stdout,

+      PROGRAM_NAME " ERROR: Could not open output file '%s' for writing\n",

+      Options.OutFileName

+      );

+    return EFI_DEVICE_ERROR;

+  }

+  //

+  // Write the pad bytes. Do it the slow way (one at a time) for now.

+  //

+  while (Options.FileSize > 0) {

+    if (fwrite (&Options.ByteValue, 1, 1, OutFptr) != 1) {

+      fclose (OutFptr);

+      fprintf (stdout, PROGRAM_NAME " ERROR: Failed to write to output file\n");

+      return EFI_DEVICE_ERROR;

+    }

+

+    Options.FileSize--;

+  }

+  //

+  // Close the file

+  //

+  fclose (OutFptr);

+  return EFI_SUCCESS;

+}

+

+static

+EFI_STATUS

+ProcessArgs (

+  IN INT32          Argc,

+  IN INT8           *Argv[],

+  IN OUT OPTIONS    *Options

+  )

+/*++

+

+Routine Description:

+  

+  Process the command line arguments.

+

+Arguments:

+

+  Argc    - argument count as passed in to the entry point function

+  Argv    - array of arguments as passed in to the entry point function

+  Options - stucture of where to put the values of the parsed arguments

+

+Returns:

+

+  EFI_SUCCESS if everything looks good

+  EFI_INVALID_PARAMETER otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  UINT32  Multiplier;

+

+  //

+  // Clear the options

+  //

+  memset ((char *) Options, 0, sizeof (OPTIONS));

+

+  //

+  // Skip program name

+  //

+  Argv++;

+  Argc--;

+  if (Argc < 2) {

+    Usage ();

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // If first arg is dash-option, then print usage.

+  //

+  if (Argv[0][0] == '-') {

+    Usage ();

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // First arg is file name

+  //

+  Options->OutFileName = Argv[0];

+  Argc--;

+  Argv++;

+

+  //

+  // Second arg is file size. Allow 0x1000, 0x100K, 1024, 1K

+  //

+  Multiplier = 1;

+  if ((Argv[0][strlen (Argv[0]) - 1] == 'k') || (Argv[0][strlen (Argv[0]) - 1] == 'K')) {

+    Multiplier = 1024;

+  }

+  //

+  // Look for 0x prefix on file size

+  //

+  if ((Argv[0][0] == '0') && ((Argv[0][1] == 'x') || (Argv[0][1] == 'X'))) {

+    if (sscanf (Argv[0], "%x", &Options->FileSize) != 1) {

+      fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);

+      Usage ();

+      return EFI_INVALID_PARAMETER;

+    }

+    //

+    // Otherwise must be a decimal number

+    //

+  } else {

+    if (sscanf (Argv[0], "%d", &Options->FileSize) != 1) {

+      fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);

+      Usage ();

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+

+  Options->FileSize *= Multiplier;

+  //

+  // Assume byte value of 0xff

+  //

+  Options->ByteValue = (INT8) (UINT8) 0xFF;

+  return EFI_SUCCESS;

+}

+//

+// Print utility usage info

+//

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  UINT32            Index;

+  static const INT8 *Text[] = {

+    " ",

+    "Usage:  "PROGRAM_NAME " OutFileName FileSize",

+    "  where:",

+    "    OutFileName is the name of the output file to generate",

+    "    FileSize is the size of the file to create",

+    "  Examples:",

+    "    "PROGRAM_NAME " OutFile.bin 32K",

+    "    "PROGRAM_NAME " OutFile.bin 0x1000",

+    " ",

+    NULL

+  };

+

+  for (Index = 0; Text[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Text[Index]);

+  }

+}

diff --git a/Source/CreateMtFile/build.xml b/Source/CreateMtFile/build.xml
new file mode 100644
index 0000000..3be4c90
--- /dev/null
+++ b/Source/CreateMtFile/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK CreateMtFile Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="CreateMtFile"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/CustomizedCompress/CustomizedCompress.c b/Source/CustomizedCompress/CustomizedCompress.c
new file mode 100644
index 0000000..0dc6612
--- /dev/null
+++ b/Source/CustomizedCompress/CustomizedCompress.c
@@ -0,0 +1,146 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  CustomizedCompress.c

+

+Abstract:

+

+  Header file for Customized compression routine

+  

+--*/

+

+#include <Common/UefiBaseTypes.h>

+

+EFI_STATUS

+SetCustomizedCompressionType (

+  IN  CHAR8   *Type

+  )

+/*++

+

+Routine Description:

+

+The implementation of Customized SetCompressionType().

+

+Arguments:

+  Type        - The type if compression.

+    

+Returns:

+    

+  EFI_SUCCESS           - The type has been set.

+  EFI_UNSUPPORTED       - This type is unsupported.

+

+    

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

+

+EFI_STATUS

+CustomizedGetInfo (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+The implementation of Customized GetInfo().

+

+Arguments:

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+    

+Returns:

+    

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+  EFI_UNSUPPORTED       - The operation is unsupported.

+

+    

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

+

+EFI_STATUS

+CustomizedDecompress (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation of Customized Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+  EFI_UNSUPPORTED       - The operation is unsupported.

+

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

+

+EFI_STATUS

+CustomizedCompress (

+  IN      UINT8   *SrcBuffer,

+  IN      UINT32  SrcSize,

+  IN      UINT8   *DstBuffer,

+  IN OUT  UINT32  *DstSize

+  )

+/*++

+

+Routine Description:

+

+  The Customized compression routine.

+

+Arguments:

+

+  SrcBuffer   - The buffer storing the source data

+  SrcSize     - The size of source data

+  DstBuffer   - The buffer to store the compressed data

+  DstSize     - On input, the size of DstBuffer; On output,

+                the size of the actual compressed data.

+

+Returns:

+

+  EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,

+                DstSize contains the size needed.

+  EFI_SUCCESS           - Compression is successful.

+

+  EFI_UNSUPPORTED       - The operation is unsupported.

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

diff --git a/Source/CustomizedCompress/build.xml b/Source/CustomizedCompress/build.xml
new file mode 100644
index 0000000..35bffa4
--- /dev/null
+++ b/Source/CustomizedCompress/build.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenLib" basedir="." name="CustomizedCompressLibrary">

+<!--

+    EDK Customized Compress Library

+  Copyright (c) 2006, Intel Corporation

+-->

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LibName" value="CustomizedCompress"/>

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/CustomizedCompress/tmp"/>

+

+  <target name="GenLib" depends="init, CustomizedCompress">

+    <echo message="The EDK Tool Library ${LibName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool Library: ${LibName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="CustomizedCompress" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${LIB_DIR}/${LibName}"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/CustomizedCompress" 

+        includes="*.c" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+    </cc>

+    <if>

+      <istrue value="msft"/>

+      <then>

+        <exec dir="${BUILD_DIR}" executable="lib" failonerror="false">

+          <arg line="/NOLOGO *.lib /OUT:${LIB_DIR}/CustomizedCompress${ext_static}"/>

+        </exec>

+      </then>

+    </if>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/EfiCompress/EfiCompressMain.c b/Source/EfiCompress/EfiCompressMain.c
new file mode 100644
index 0000000..492210f
--- /dev/null
+++ b/Source/EfiCompress/EfiCompressMain.c
@@ -0,0 +1,165 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+  

+  EfiCompressMain.c

+

+Abstract:

+

+  The main function for the compression utility.

+  

+--*/

+

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>

+#include <stdarg.h>

+#include <stdio.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "EfiCompress.h"

+

+int

+main (

+  INT32 argc,

+  CHAR8 *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Compresses the input files

+

+Arguments:

+

+  argc   - number of arguments passed into the command line.

+  argv[] - files to compress and files to output compressed data to.

+

+Returns:

+

+  int: 0 for successful execution of the function.

+

+--*/

+{

+  EFI_STATUS  Status;

+  FILE        *infile;

+  FILE        *outfile;

+  UINT32      SrcSize;

+  UINT32      DstSize;

+  UINT8       *SrcBuffer;

+  UINT8       *DstBuffer;

+  UINT8       Buffer[8];

+

+  //

+  //  Added for makefile debug - KCE

+  //

+  INT32       arg_counter;

+  printf ("\n\n");

+  for (arg_counter = 0; arg_counter < argc; arg_counter++) {

+    printf ("%s ", argv[arg_counter]);

+  }

+

+  printf ("\n\n");

+

+  SrcBuffer             = DstBuffer = NULL;

+

+  infile                = outfile = NULL;

+

+  if (argc != 3) {

+    printf ("Usage: EFICOMPRESS <infile> <outfile>\n");

+    goto Done;

+  }

+

+  if ((outfile = fopen (argv[2], "wb")) == NULL) {

+    printf ("Can't open output file\n");

+    goto Done;

+  }

+

+  if ((infile = fopen (argv[1], "rb")) == NULL) {

+    printf ("Can't open input file\n");

+    goto Done;

+  }

+  //

+  // Get the size of source file

+  //

+  SrcSize = 0;

+  while (fread (Buffer, 1, 1, infile)) {

+    SrcSize++;

+

+  }

+  //

+  // Read in the source data

+  //

+  if ((SrcBuffer = malloc (SrcSize)) == NULL) {

+    printf ("Can't allocate memory\n");

+    goto Done;

+  }

+

+  rewind (infile);

+  if (fread (SrcBuffer, 1, SrcSize, infile) != SrcSize) {

+    printf ("Can't read from source\n");

+    goto Done;

+  }

+  //

+  // Get destination data size and do the compression

+  //

+  DstSize = 0;

+  Status  = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);

+  if (Status == EFI_BUFFER_TOO_SMALL) {

+    if ((DstBuffer = malloc (DstSize)) == NULL) {

+      printf ("Can't allocate memory\n");

+      goto Done;

+    }

+

+    Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);

+  }

+

+  if (EFI_ERROR (Status)) {

+    printf ("Compress Error\n");

+    goto Done;

+  }

+

+  printf ("\nOrig Size = %ld\n", SrcSize);

+  printf ("Comp Size = %ld\n", DstSize);

+

+  if (DstBuffer == NULL) {

+    printf ("No destination to write to.\n");

+    goto Done;

+  }

+  //

+  // Write out the result

+  //

+  if (fwrite (DstBuffer, 1, DstSize, outfile) != DstSize) {

+    printf ("Can't write to destination file\n");

+  }

+

+Done:

+  if (SrcBuffer) {

+    free (SrcBuffer);

+  }

+

+  if (DstBuffer) {

+    free (DstBuffer);

+  }

+

+  if (infile) {

+    fclose (infile);

+  }

+

+  if (outfile) {

+    fclose (outfile);

+  }

+

+  return 0;

+}

diff --git a/Source/EfiCompress/build.xml b/Source/EfiCompress/build.xml
new file mode 100644
index 0000000..32826d2
--- /dev/null
+++ b/Source/EfiCompress/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK EfiCompress Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="EfiCompress"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/EfiRom/EfiRom.c b/Source/EfiRom/EfiRom.c
new file mode 100644
index 0000000..2cc478b
--- /dev/null
+++ b/Source/EfiRom/EfiRom.c
@@ -0,0 +1,1536 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  EfiRom.c

+  

+Abstract:

+

+  Utility program to create an EFI option ROM image from binary and 

+  EFI PE32 files.

+

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>  // for PE32 structure definitions

+#include <Common/MultiPhase.h>

+

+#include <IndustryStandard/pci22.h>  // for option ROM header structures

+

+#include "EfiCompress.h"

+#include "CommonLib.h"

+

+//

+// Version of this utility

+//

+#define UTILITY_VERSION "v2.5"

+

+//

+// Define some status return values

+//

+#define STATUS_SUCCESS  0

+#define STATUS_WARNING  1

+#define STATUS_ERROR    2

+

+//

+// Define the max length of a filename

+//

+#define MAX_PATH                  200

+

+#define DEFAULT_OUTPUT_EXTENSION  ".rom"

+

+//

+// Max size for an option ROM image

+//

+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16)  // 16MB

+//

+// Values for the indicator field in the PCI data structure

+//

+#define INDICATOR_LAST  0x80  // last file in series of files

+//

+// Masks for the FILE_LIST.FileFlags field

+//

+#define FILE_FLAG_BINARY    0x01

+#define FILE_FLAG_EFI       0x02

+#define FILE_FLAG_COMPRESS  0x04

+

+//

+// Use this linked list structure to keep track of all the filenames

+// specified on the command line.

+//

+typedef struct _FILE_LIST {

+  struct _FILE_LIST *Next;

+  INT8              *FileName;

+  UINT32            FileFlags;

+  UINT32            ClassCode;

+  UINT16            CodeRevision;

+} FILE_LIST;

+

+//

+// Use this to track our command-line options

+//

+typedef struct {

+  INT8      OutFileName[MAX_PATH];

+  INT8      NoLast;

+  INT8      Verbose;

+  INT8      DumpOption;

+  UINT8     DevIdValid;

+  UINT8     VendIdValid;

+  UINT16    VendId;

+  UINT16    DevId;

+  FILE_LIST *FileList;

+} OPTIONS;

+

+//

+// Make a global structure to keep track of command-line options

+//

+static OPTIONS  mOptions;

+

+//

+// Use these to convert from machine type value to a named type

+//

+typedef struct {

+  UINT16  Value;

+  char    *Name;

+} STRING_LOOKUP;

+

+static STRING_LOOKUP  mMachineTypes[] = {

+  EFI_IMAGE_MACHINE_IA32,

+  "IA32",

+  EFI_IMAGE_MACHINE_IA64,

+  "IA64",

+  EFI_IMAGE_MACHINE_EBC,

+  "EBC",

+  0,

+  NULL

+};

+

+static STRING_LOOKUP  mSubsystemTypes[] = {

+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,

+  "EFI application",

+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,

+  "EFI boot service driver",

+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,

+  "EFI runtime driver",

+  0,

+  NULL

+};

+//

+//  Function prototypes

+//

+static

+void

+Usage (

+  VOID

+  );

+

+static

+int

+ParseCommandLine (

+  int       Argc,

+  char      *Argv[],

+  OPTIONS   *Options

+  );

+

+static

+int

+CheckPE32File (

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  );

+

+static

+int

+ProcessEfiFile (

+  FILE      *OutFptr,

+  FILE_LIST *InFile,

+  UINT16    VendId,

+  UINT16    DevId,

+  UINT32    *Size

+  );

+

+static

+int

+ProcessBinFile (

+  FILE      *OutFptr,

+  FILE_LIST *InFile,

+  UINT32    *Size

+  );

+

+static

+void

+DumpImage (

+  FILE_LIST *InFile

+  );

+

+char                  *

+GetMachineTypeStr (

+  UINT16    MachineType

+  );

+

+static

+char                  *

+GetSubsystemTypeStr (

+  UINT16  SubsystemType

+  );

+

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+  Given an EFI image filename, create a ROM-able image by creating an option 

+  ROM header and PCI data structure, filling them in, and then writing the

+  option ROM header + PCI data structure + EFI image out to the output file.

+

+Arguments:

+

+  Argc            - standard C main() argument count

+

+  Argv            - standard C main() argument list

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  INT8      *Ext;

+  FILE      *FptrOut;

+  UINT32    Status;

+  FILE_LIST *FList;

+  UINT32    TotalSize;

+  UINT32    Size;

+

+  Status  = STATUS_SUCCESS;

+  FptrOut = NULL;

+

+  //

+  // Parse the command line arguments

+  //

+  if (ParseCommandLine (Argc, Argv, &mOptions)) {

+    return STATUS_ERROR;

+  }

+  //

+  // If dumping an image, then do that and quit

+  //

+  if (mOptions.DumpOption) {

+    DumpImage (mOptions.FileList);

+    goto BailOut;

+  }

+  //

+  // Determine the output filename. Either what they specified on

+  // the command line, or the first input filename with a different extension.

+  //

+  if (!mOptions.OutFileName[0]) {

+    strcpy (mOptions.OutFileName, mOptions.FileList->FileName);

+    //

+    // Find the last . on the line and replace the filename extension with

+    // the default

+    //

+    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;

+         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');

+         Ext--

+        )

+      ;

+    //

+    // If dot here, then insert extension here, otherwise append

+    //

+    if (*Ext != '.') {

+      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);

+    }

+

+    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);

+  }

+  //

+  // Make sure we don't have the same filename for input and output files

+  //

+  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {

+    if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {

+      Status = STATUS_ERROR;

+      fprintf (

+        stdout,

+        "ERROR: Input and output file names must be different - %s = %s\n",

+        FList->FileName,

+        mOptions.OutFileName

+        );

+      goto BailOut;

+    }

+  }

+  //

+  // Now open our output file

+  //

+  if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {

+    fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);

+    goto BailOut;

+  }

+  //

+  // Process all our files

+  //

+  TotalSize = 0;

+  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {

+    Size = 0;

+    if (FList->FileFlags & FILE_FLAG_EFI) {

+      if (mOptions.Verbose) {

+        fprintf (stdout, "Processing EFI file    %s\n", FList->FileName);

+      }

+

+      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);

+    } else if (FList->FileFlags & FILE_FLAG_BINARY) {

+      if (mOptions.Verbose) {

+        fprintf (stdout, "Processing binary file %s\n", FList->FileName);

+      }

+

+      Status = ProcessBinFile (FptrOut, FList, &Size);

+    } else {

+      fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);

+      Status = STATUS_ERROR;

+    }

+

+    if (mOptions.Verbose) {

+      fprintf (stdout, "  Output size = 0x%X\n", Size);

+    }

+

+    if (Status != STATUS_SUCCESS) {

+      break;

+    }

+

+    TotalSize += Size;

+  }

+  //

+  // Check total size

+  //

+  if (TotalSize > MAX_OPTION_ROM_SIZE) {

+    fprintf (

+      stdout,

+      "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",

+      MAX_OPTION_ROM_SIZE

+      );

+    Status = STATUS_ERROR;

+  }

+

+BailOut:

+  if (FptrOut != NULL) {

+    fclose (FptrOut);

+  }

+  //

+  // Clean up our file list

+  //

+  while (mOptions.FileList != NULL) {

+    FList = mOptions.FileList->Next;

+    free (mOptions.FileList);

+    mOptions.FileList = FList;

+  }

+

+  return Status;

+}

+

+static

+int

+ProcessBinFile (

+  FILE      *OutFptr,

+  FILE_LIST *InFile,

+  UINT32    *Size

+  )

+/*++

+

+Routine Description:

+  

+  Process a binary input file.

+

+Arguments:

+

+  OutFptr     - file pointer to output binary ROM image file we're creating

+  InFile      - structure contains information on the binary file to process

+  Size        - pointer to where to return the size added to the output file

+

+Returns:

+

+  0 - successful

+

+--*/

+{

+  FILE                      *InFptr;

+  UINT32                    TotalSize;

+  UINT32                    FileSize;

+  UINT8                     *Buffer;

+  UINT32                    Status;

+  PCI_EXPANSION_ROM_HEADER  *RomHdr;

+  PCI_DATA_STRUCTURE        *PciDs;

+  UINT32                    Index;

+  UINT8                     ByteCheckSum;

+

+  Status = STATUS_SUCCESS;

+

+  //

+  // Try to open the input file

+  //

+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {

+    fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);

+    return STATUS_ERROR;

+  }

+  //

+  // Seek to the end of the input file and get the file size. Then allocate

+  // a buffer to read it in to.

+  //

+  fseek (InFptr, 0, SEEK_END);

+  FileSize = ftell (InFptr);

+  if (mOptions.Verbose) {

+    fprintf (stdout, "  File size   = 0x%X\n", FileSize);

+  }

+

+  fseek (InFptr, 0, SEEK_SET);

+  Buffer = (INT8 *) malloc (FileSize);

+  if (Buffer == NULL) {

+    fprintf (stdout, "ERROR: Memory allocation failed\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  if (fread (Buffer, FileSize, 1, InFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Total size must be an even multiple of 512 bytes, and can't exceed

+  // the option ROM image size.

+  //

+  TotalSize = FileSize;

+  if (TotalSize & 0x1FF) {

+    TotalSize = (TotalSize + 0x200) &~0x1ff;

+  }

+

+  if (TotalSize > MAX_OPTION_ROM_SIZE) {

+    fprintf (

+      stdout,

+      "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",

+      InFile->FileName,

+      MAX_OPTION_ROM_SIZE

+      );

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Return the size to the caller so they can keep track of the running total.

+  //

+  *Size = TotalSize;

+

+  //

+  // Crude check to make sure it's a legitimate ROM image

+  //

+  RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;

+  if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {

+    fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Make sure the pointer to the PCI data structure is within the size of the image.

+  // Then check it for valid signature.

+  //

+  if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {

+    fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);

+  if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {

+    fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // If this is the last image, then set the LAST bit unless requested not

+  // to via the command-line -l argument. Otherwise, make sure you clear it.

+  //

+  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {

+    PciDs->Indicator = INDICATOR_LAST;

+  } else {

+    PciDs->Indicator = 0;

+  }

+

+  ByteCheckSum = 0;

+  for (Index = 0; Index < FileSize - 1; Index++) {

+    ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);

+  }

+

+  Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);

+  fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);

+

+  //

+  // Now copy the input file contents out to the output file

+  //

+  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  TotalSize -= FileSize;

+  //

+  // Pad the rest of the image to make it a multiple of 512 bytes

+  //

+  while (TotalSize > 0) {

+    putc (~0, OutFptr);

+    TotalSize--;

+  }

+

+BailOut:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+  //

+  // Print the file name if errors occurred

+  //

+  if (Status != STATUS_SUCCESS) {

+    fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);

+  }

+

+  return Status;

+}

+

+static

+int

+ProcessEfiFile (

+  FILE      *OutFptr,

+  FILE_LIST *InFile,

+  UINT16    VendId,

+  UINT16    DevId,

+  UINT32    *Size

+  )

+/*++

+

+Routine Description:

+  

+  Process a PE32 EFI file.

+

+Arguments:

+

+  OutFptr     - file pointer to output binary ROM image file we're creating

+  InFile      - structure contains information on the PE32 file to process

+  VendId      - vendor ID as required in the option ROM header

+  DevId       - device ID as required in the option ROM header

+  Size        - pointer to where to return the size added to the output file

+

+Returns:

+

+  0 - successful

+

+--*/

+{

+  UINT32                        Status;

+  FILE                          *InFptr;

+  EFI_PCI_EXPANSION_ROM_HEADER  RomHdr;

+  PCI_DATA_STRUCTURE            PciDs;

+  UINT32                        FileSize;

+  UINT32                        CompressedFileSize;

+  UINT8                         *Buffer;

+  UINT8                         *CompressedBuffer;

+  UINT8                         *TempBufferPtr;

+  UINT32                        TotalSize;

+  UINT32                        HeaderSize;

+  UINT16                        MachineType;

+  UINT16                        SubSystem;

+  UINT32                        HeaderPadBytes;

+

+  //

+  // Try to open the input file

+  //

+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {

+    fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);

+    return STATUS_ERROR;

+  }

+  //

+  // Initialize our buffer pointers to null.

+  //

+  Buffer            = NULL;

+  CompressedBuffer  = NULL;

+

+  //

+  // Double-check the file to make sure it's what we expect it to be

+  //

+  Status = CheckPE32File (InFptr, &MachineType, &SubSystem);

+  if (Status != STATUS_SUCCESS) {

+    goto BailOut;

+  }

+  //

+  // Seek to the end of the input file and get the file size

+  //

+  fseek (InFptr, 0, SEEK_END);

+  FileSize = ftell (InFptr);

+

+  //

+  // Get the size of the headers we're going to put in front of the image. The

+  // EFI header must be aligned on a 4-byte boundary, so pad accordingly.

+  //

+  if (sizeof (RomHdr) & 0x03) {

+    HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);

+  } else {

+    HeaderPadBytes = 0;

+  }

+

+  HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);

+  if (mOptions.Verbose) {

+    fprintf (stdout, "  File size   = 0x%X\n", FileSize);

+  }

+  //

+  // Allocate memory for the entire file (in case we have to compress), then

+  // seek back to the beginning of the file and read it into our buffer.

+  //

+  Buffer = (INT8 *) malloc (FileSize);

+  if (Buffer == NULL) {

+    fprintf (stdout, "ERROR: Memory allocation failed\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  fseek (InFptr, 0, SEEK_SET);

+  if (fread (Buffer, FileSize, 1, InFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Now determine the size of the final output file. It's either the header size

+  // plus the file's size, or the header size plus the compressed file size.

+  //

+  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {

+    //

+    // Allocate a buffer into which we can compress the image, compress it,

+    // and use that size as the new size.

+    //

+    CompressedBuffer = (INT8 *) malloc (FileSize);

+    if (CompressedBuffer == NULL) {

+      fprintf (stdout, "ERROR: Memory allocation failed\n");

+      Status = STATUS_ERROR;

+      goto BailOut;

+    }

+

+    CompressedFileSize  = FileSize;

+    Status              = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);

+    if (Status != STATUS_SUCCESS) {

+      fprintf (stdout, "ERROR: Compression failed\n");

+      goto BailOut;

+    }

+    //

+    // Now compute the size, then swap buffer pointers.

+    //

+    if (mOptions.Verbose) {

+      fprintf (stdout, "  Comp size   = 0x%X\n", CompressedFileSize);

+    }

+

+    TotalSize         = CompressedFileSize + HeaderSize;

+    FileSize          = CompressedFileSize;

+    TempBufferPtr     = Buffer;

+    Buffer            = CompressedBuffer;

+    CompressedBuffer  = TempBufferPtr;

+  } else {

+    TotalSize = FileSize + HeaderSize;

+  }

+  //

+  // Total size must be an even multiple of 512 bytes

+  //

+  if (TotalSize & 0x1FF) {

+    TotalSize = (TotalSize + 0x200) &~0x1ff;

+  }

+  //

+  // Check size

+  //

+  if (TotalSize > MAX_OPTION_ROM_SIZE) {

+    fprintf (

+      stdout,

+      "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",

+      InFile->FileName,

+      MAX_OPTION_ROM_SIZE

+      );

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Return the size to the caller so they can keep track of the running total.

+  //

+  *Size = TotalSize;

+

+  //

+  // Now fill in the ROM header. These values come from chapter 18 of the

+  // EFI 1.02 specification.

+  //

+  memset (&RomHdr, 0, sizeof (RomHdr));

+  RomHdr.Signature            = PCI_EXPANSION_ROM_HEADER_SIGNATURE;

+  RomHdr.InitializationSize   = (UINT16) (TotalSize / 512);

+  RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;

+  RomHdr.EfiSubsystem         = SubSystem;

+  RomHdr.EfiMachineType       = MachineType;

+  RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;

+  RomHdr.PcirOffset           = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);

+  //

+  // Set image as compressed or not

+  //

+  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {

+    RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;

+  }

+  //

+  // Fill in the PCI data structure

+  //

+  memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE));

+

+  PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE;

+  PciDs.VendorId  = VendId;

+  PciDs.DeviceId  = DevId;

+  PciDs.Length    = (UINT16) sizeof (PCI_DATA_STRUCTURE);

+  PciDs.Revision  = 0;

+  //

+  // Class code and code revision from the command line (optional)

+  //

+  PciDs.ClassCode[0]  = (UINT8) InFile->ClassCode;

+  PciDs.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);

+  PciDs.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);

+  PciDs.ImageLength   = RomHdr.InitializationSize;

+  PciDs.CodeRevision  = InFile->CodeRevision;

+  PciDs.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;

+

+  //

+  // If this is the last image, then set the LAST bit unless requested not

+  // to via the command-line -l argument.

+  //

+  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {

+    PciDs.Indicator = INDICATOR_LAST;

+  }

+  //

+  // Write the ROM header to the output file

+  //

+  if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  //

+  // Write pad bytes to align the PciDs

+  //

+  while (HeaderPadBytes > 0) {

+    if (putc (0, OutFptr) == EOF) {

+      fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");

+      Status = STATUS_ERROR;

+      goto BailOut;

+    }

+

+    HeaderPadBytes--;

+  }

+  //

+  // Write the PCI data structure header to the output file

+  //

+  if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+  //

+  // Keep track of how many bytes left to write

+  //

+  TotalSize -= HeaderSize;

+

+  //

+  // Now dump the input file's contents to the output file

+  //

+  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");

+    Status = STATUS_ERROR;

+    goto BailOut;

+  }

+

+  TotalSize -= FileSize;

+  //

+  // Pad the rest of the image to make it a multiple of 512 bytes

+  //

+  while (TotalSize > 0) {

+    if (putc (~0, OutFptr) == EOF) {

+      fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");

+      Status = STATUS_ERROR;

+      goto BailOut;

+    }

+

+    TotalSize--;

+  }

+

+BailOut:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  //

+  // Free up our buffers

+  //

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  if (CompressedBuffer != NULL) {

+    free (CompressedBuffer);

+  }

+  //

+  // Print the file name if errors occurred

+  //

+  if (Status != STATUS_SUCCESS) {

+    fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);

+  }

+

+  return Status;

+}

+

+static

+int

+CheckPE32File (

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Fptr        - GC_TODO: add argument description

+  MachineType - GC_TODO: add argument description

+  SubSystem   - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  /*++

+

+Routine Description:

+  

+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a

+  PE32 image file, and then return the machine type in the supplied pointer.

+

+Arguments:

+

+  Fptr          File pointer to the already-opened PE32 file

+  MachineType   Location to stuff the machine type of the PE32 file. This is needed

+                because the image may be Itanium-based, IA32, or EBC.

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+  EFI_IMAGE_DOS_HEADER      DosHeader;

+  EFI_IMAGE_FILE_HEADER     FileHdr;

+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;

+  UINT32                    PESig;

+

+  //

+  // Position to the start of the file

+  //

+  fseek (Fptr, 0, SEEK_SET);

+

+  //

+  // Read the DOS header

+  //

+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");

+    return STATUS_ERROR;

+  }

+  //

+  // Check the magic number (0x5A4D)

+  //

+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");

+    return STATUS_ERROR;

+  }

+  //

+  // Position into the file and check the PE signature

+  //

+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);

+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");

+    return STATUS_ERROR;

+  }

+  //

+  // Check the PE signature in the header "PE\0\0"

+  //

+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {

+    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");

+    return STATUS_ERROR;

+  }

+  //

+  // Read the file header and stuff their MachineType

+  //

+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");

+    return STATUS_ERROR;

+  }

+

+  memcpy ((char *) MachineType, &FileHdr.Machine, 2);

+

+  //

+  // Read the optional header so we can get the subsystem

+  //

+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {

+    fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");

+    return STATUS_ERROR;

+  }

+

+  *SubSystem = OptionalHdr.Subsystem;

+  if (mOptions.Verbose) {

+    fprintf (stdout, "  Got subsystem = 0x%X from image\n", (int) *SubSystem);

+  }

+  //

+  // Good to go

+  //

+  return STATUS_SUCCESS;

+}

+

+static

+int

+ParseCommandLine (

+  int         Argc,

+  char        *Argv[],

+  OPTIONS     *Options

+  )

+/*++

+

+Routine Description:

+  

+  Given the Argc/Argv program arguments, and a pointer to an options structure,

+  parse the command-line options and check their validity.

+

+

+Arguments:

+

+  Argc            - standard C main() argument count

+  Argv[]          - standard C main() argument list

+  Options         - pointer to a structure to store the options in

+

+Returns:

+

+  STATUS_SUCCESS    success

+  non-zero          otherwise

+

+--*/

+//

+{

+  FILE_LIST *FileList;

+

+  FILE_LIST *PrevFileList;

+  UINT32    FileFlags;

+  UINT32    ClassCode;

+  UINT32    CodeRevision;

+

+  FileFlags = 0;

+

+  //

+  // Clear out the options

+  //

+  memset ((char *) Options, 0, sizeof (OPTIONS));

+

+  //

+  // To avoid compile warnings

+  //

+  FileList                = PrevFileList = NULL;

+

+  ClassCode               = 0;

+  CodeRevision            = 0;

+  //

+  // Skip over the program name

+  //

+  Argc--;

+  Argv++;

+

+  //

+  // If no arguments, assume they want usage info

+  //

+  if (Argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Process until no more arguments

+  //

+  while (Argc > 0) {

+    if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {

+      //

+      // To simplify string comparisons, replace slashes with dashes

+      //

+      Argv[0][0] = '-';

+

+      //

+      // Vendor ID specified with -v

+      //

+      if (stricmp (Argv[0], "-v") == 0) {

+        //

+        // Make sure there's another parameter

+        //

+        if (Argc > 1) {

+          Options->VendId       = (UINT16) strtol (Argv[1], NULL, 16);

+          Options->VendIdValid  = 1;

+        } else {

+          fprintf (

+            stdout,

+            "ERROR: Missing Vendor ID with %s\n\n",

+            Argv[0]

+            );

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        Argv++;

+        Argc--;

+      } else if (stricmp (Argv[0], "-d") == 0) {

+        //

+        // Device ID specified with -d

+        // Make sure there's another parameter

+        //

+        if (Argc > 1) {

+          Options->DevId      = (UINT16) strtol (Argv[1], NULL, 16);

+          Options->DevIdValid = 1;

+        } else {

+          fprintf (

+            stdout,

+            "ERROR: Missing Device ID with %s\n\n",

+            Argv[0]

+            );

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        Argv++;

+        Argc--;

+      } else if (stricmp (Argv[0], "-o") == 0) {

+        //

+        // Output filename specified with -o

+        // Make sure there's another parameter

+        //

+        if (Argc > 1) {

+          strcpy (Options->OutFileName, Argv[1]);

+        } else {

+          fprintf (

+            stdout,

+            "ERROR: Missing output file name with %s\n\n",

+            Argv[0]

+            );

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        Argv++;

+        Argc--;

+      } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {

+        //

+        // Help option

+        //

+        Usage ();

+        return STATUS_ERROR;

+      } else if (stricmp (Argv[0], "-b") == 0) {

+        //

+        // Specify binary files with -b

+        //

+        FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;

+      } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {

+        //

+        // Specify EFI files with -e. Specify EFI-compressed with -ec.

+        //

+        FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI;

+        if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {

+          FileFlags |= FILE_FLAG_COMPRESS;

+        }

+        //

+        // Specify not to set the LAST bit in the last file with -l

+        //

+      } else if (stricmp (Argv[0], "-l") == 0) {

+        Options->NoLast = 1;

+      } else if (stricmp (Argv[0], "-p") == 0) {

+        //

+        // -v for verbose would have been nicer, but it's already used. Let's use

+        // -p for prolix (wordy) output

+        //

+        Options->Verbose = 1;

+      } else if (stricmp (Argv[0], "-dump") == 0) {

+        //

+        // -dump for dumping a ROM image. In this case, say that the device id

+        // and vendor id are valid so we don't have to specify bogus ones on the

+        // command line.

+        //

+        Options->DumpOption   = 1;

+

+        Options->VendIdValid  = 1;

+        Options->DevIdValid   = 1;

+        FileFlags             = FILE_FLAG_BINARY;

+      } else if (stricmp (Argv[0], "-cc") == 0) {

+        //

+        // Class code value for the next file in the list.

+        // Make sure there's another parameter

+        //

+        if (Argc > 1) {

+          //

+          // No error checking on the return value. Could check for LONG_MAX,

+          // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)

+          // at least.

+          //

+          ClassCode = (UINT32) strtol (Argv[1], NULL, 16);

+          if (ClassCode & 0xFF000000) {

+            fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]);

+            return STATUS_ERROR;

+          }

+        } else {

+          fprintf (

+            stdout,

+            "ERROR: Missing class code value with %s\n\n",

+            Argv[0]

+            );

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        Argv++;

+        Argc--;

+      } else if (stricmp (Argv[0], "-rev") == 0) {

+        //

+        // Code revision in the PCI data structure. The value is for the next

+        // file in the list.

+        // Make sure there's another parameter

+        //

+        if (Argc > 1) {

+          //

+          // No error checking on the return value. Could check for LONG_MAX,

+          // LONG_MIN, or 0 value if desired. Check range (2 bytes)

+          // at least.

+          //

+          CodeRevision = (UINT32) strtol (Argv[1], NULL, 16);

+          if (CodeRevision & 0xFFFF0000) {

+            fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]);

+            return STATUS_ERROR;

+          }

+        } else {

+          fprintf (

+            stdout,

+            "ERROR: Missing code revision value with %s\n\n",

+            Argv[0]

+            );

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        Argv++;

+        Argc--;

+      } else {

+        fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]);

+        Usage ();

+        return STATUS_ERROR;

+      }

+    } else {

+      //

+      // Not a slash-option argument. Must be a file name. Make sure they've specified

+      // -e or -b already.

+      //

+      if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {

+        fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]);

+        return STATUS_ERROR;

+      }

+      //

+      // Create a new file structure

+      //

+      FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));

+      if (FileList == NULL) {

+        fprintf (stdout, "ERROR: Memory allocation failure\n");

+        return STATUS_ERROR;

+      }

+

+      memset ((char *) FileList, 0, sizeof (FILE_LIST));

+      FileList->FileName  = Argv[0];

+      FileList->FileFlags = FileFlags;

+      if (Options->FileList == NULL) {

+        Options->FileList = FileList;

+      } else {

+        if (PrevFileList == NULL) {

+          PrevFileList = FileList;

+        } else {          

+          PrevFileList->Next = FileList;

+        }

+      }

+

+      PrevFileList = FileList;

+      //

+      // Set the class code and code revision for this file, then reset the values.

+      //

+      FileList->ClassCode     = ClassCode;

+      FileList->CodeRevision  = (UINT16) CodeRevision;

+      ClassCode               = 0;

+      CodeRevision            = 0;

+    }

+    //

+    // Next argument

+    //

+    Argv++;

+    Argc--;

+  }

+  //

+  // Make sure they specified a device ID and vendor ID

+  //

+  if (!Options->VendIdValid) {

+    fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n");

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  if (!Options->DevIdValid) {

+    fprintf (stdout, "ERROR: Missing Device ID on command line\n\n");

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Must have specified some files

+  //

+  if (Options->FileList == NULL) {

+    fprintf (stdout, "ERROR: Missing input file name\n");

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  return 0;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+  

+  Print usage information for this utility.

+

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+

+--*/

+{

+  int               Index;

+  static const char *Msg[] = {

+    "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility",

+    "  Copyright (C), 1999-2002 Intel Coproration\n",

+    "  Create an option ROM image from a list of input files",

+    "  Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",

+    "                [-e|-b] [FileName(s)]",

+    "    where:",

+    "      VendorId       - required hex PCI Vendor ID for the device",

+    "      DeviceId       - required hex PCI Device ID for the device",

+    "      OutFileName    - optional output file name. Default is the first input",

+    "                       file name with a "DEFAULT_OUTPUT_EXTENSION " file extension",

+    "      FileNames      - input PE32 or binary file name(s)",

+    "      BinFileName    - input binary file name(s)",

+    "      -p             - for verbose output",

+    "      -l             - to not automatically set the LAST bit on the last file",

+    "      -b             - following FileNames are binary files",

+    "      -e             - following FileNames are EFI PE32 image files",

+    "      -ec            - following FileNames are EFI PE32 image files, and should",

+    "                       be compressed by this utility",

+    "      -cc ClassCode  - to use hex ClassCode in the PCI data structure header for",

+    "                       the following FileName",

+    "      -rev Revision  - to use hex Revision in the PCI data structure header for",

+    "                       the following FileName",

+    "      -dump          - to dump the headers of an existing option ROM image",

+    "",

+    "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",

+    "",

+    NULL

+  };

+

+  for (Index = 0; Msg[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Msg[Index]);

+  }

+}

+

+static

+void

+DumpImage (

+  FILE_LIST *InFile

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  InFile  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  PCI_EXPANSION_ROM_HEADER      PciRomHdr;

+  FILE                          *InFptr;

+  UINT32                        ImageStart;

+  UINT32                        ImageCount;

+  EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;

+  PCI_DATA_STRUCTURE            PciDs;

+

+  //

+  // Open the input file

+  //

+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {

+    fprintf (

+      stdout,

+      "ERROR: Could not open input file %s\n",

+      InFile->FileName

+      );

+    return ;

+  }

+  //

+  // Go through the image and dump the header stuff for each

+  //

+  ImageCount = 0;

+  for (;;) {

+    //

+    // Save our postition in the file, since offsets in the headers

+    // are relative to the particular image.

+    //

+    ImageStart = ftell (InFptr);

+    ImageCount++;

+

+    //

+    // Read the option ROM header. Have to assume a raw binary image for now.

+    //

+    if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {

+      fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n");

+      goto BailOut;

+    }

+

+    //

+    // Dump the contents of the header

+    //

+    fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart);

+    fprintf (stdout, "  ROM header contents\n");

+    fprintf (stdout, "    Signature              0x%04X\n", (UINT32) PciRomHdr.Signature);

+    fprintf (stdout, "    PCIR offset            0x%04X\n", (UINT32) PciRomHdr.PcirOffset);

+    //

+    // Find PCI data structure

+    //

+    if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {

+      fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n");

+      goto BailOut;

+    }

+    //

+    // Read and dump the PCI data structure

+    //

+    if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) {

+      fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n");

+      goto BailOut;

+    }

+

+    fprintf (stdout, "  PCI Data Structure\n");

+    fprintf (

+      stdout,

+      "    Signature              %c%c%c%c\n",

+      (char) PciDs.Signature,

+      (char) (PciDs.Signature >> 8),

+      (char) (PciDs.Signature >> 16),

+      (char) (PciDs.Signature >> 24)

+      );

+    fprintf (stdout, "    Vendor ID              0x%04X\n", PciDs.VendorId);

+    fprintf (stdout, "    Device ID              0x%04X\n", PciDs.DeviceId);

+    fprintf (

+      stdout,

+      "    Class Code             0x%06X\n",

+      (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))

+      );

+    fprintf (stdout, "    Image size             0x%X\n", PciDs.ImageLength * 512);

+    fprintf (stdout, "    Code revision:         0x%04X\n", PciDs.CodeRevision);

+    fprintf (stdout, "    Indicator              0x%02X", (UINT32) PciDs.Indicator);

+    //

+    // Print the indicator, used to flag the last image

+    //

+    if (PciDs.Indicator == INDICATOR_LAST) {

+      fprintf (stdout, "   (last image)\n");

+    } else {

+      fprintf (stdout, "\n");

+    }

+    //

+    // Print the code type. If EFI code, then we can provide more info.

+    //

+    fprintf (stdout, "    Code type              0x%02X", (UINT32) PciDs.CodeType);

+    if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {

+      fprintf (stdout, "   (EFI image)\n");

+      //

+      // Re-read the header as an EFI ROM header, then dump more info

+      //

+      fprintf (stdout, "  EFI ROM header contents\n");

+      if (fseek (InFptr, ImageStart, SEEK_SET)) {

+        fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");

+        goto BailOut;

+      }

+

+      if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {

+        fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");

+        goto BailOut;

+      }

+      //

+      // Now dump more info

+      //

+      fprintf (stdout, "    EFI Signature          0x%04X\n", EfiRomHdr.EfiSignature);

+      fprintf (

+        stdout,

+        "    Compression Type       0x%04X ",

+        (UINT32) EfiRomHdr.CompressionType

+        );

+      if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {

+        fprintf (stdout, "(compressed)\n");

+      } else {

+        fprintf (stdout, "(not compressed)\n");

+      }

+

+      fprintf (

+        stdout,

+        "    Machine type           0x%04X (%s)\n",

+        EfiRomHdr.EfiMachineType,

+        GetMachineTypeStr (EfiRomHdr.EfiMachineType)

+        );

+      fprintf (

+        stdout,

+        "    Subsystem              0x%04X (%s)\n",

+        EfiRomHdr.EfiSubsystem,

+        GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)

+        );

+      fprintf (

+        stdout,

+        "    EFI image offset       0x%04X (@0x%X)\n",

+        (UINT32) EfiRomHdr.EfiImageHeaderOffset,

+        (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)

+        );

+

+    } else {

+      //

+      // Not an EFI image

+      //

+      fprintf (stdout, "\n");

+    }

+    //

+    // If code type is EFI image, then dump it as well?

+    //

+    // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {

+    // }

+    //

+    // If last image, then we're done

+    //

+    if (PciDs.Indicator == INDICATOR_LAST) {

+      goto BailOut;

+    }

+    //

+    // Seek to the start of the next image

+    //

+    if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) {

+      fprintf (stdout, "ERROR: Failed to seek to next image\n");

+      goto BailOut;

+    }

+  }

+

+BailOut:

+  fclose (InFptr);

+}

+

+char *

+GetMachineTypeStr (

+  UINT16    MachineType

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  MachineType - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  int Index;

+

+  for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {

+    if (mMachineTypes[Index].Value == MachineType) {

+      return mMachineTypes[Index].Name;

+    }

+  }

+

+  return "unknown";

+}

+

+static

+char *

+GetSubsystemTypeStr (

+  UINT16  SubsystemType

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  SubsystemType - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  int Index;

+

+  for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {

+    if (mSubsystemTypes[Index].Value == SubsystemType) {

+      return mSubsystemTypes[Index].Name;

+    }

+  }

+

+  return "unknown";

+}

diff --git a/Source/EfiRom/build.xml b/Source/EfiRom/build.xml
new file mode 100644
index 0000000..3369eca
--- /dev/null
+++ b/Source/EfiRom/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK EfiRom Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="EfiRom"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/FlashMap/FlashDefFile.c b/Source/FlashMap/FlashDefFile.c
new file mode 100644
index 0000000..0bfdad2
--- /dev/null
+++ b/Source/FlashMap/FlashDefFile.c
@@ -0,0 +1,2788 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  FlashDefFile.c

+

+Abstract:

+

+  Utility for flash management in the Intel Platform Innovation Framework

+  for EFI build environment.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Common/MultiPhase.h>

+

+#include "EfiUtilityMsgs.h"

+#include "FlashDefFile.h"

+#include "SimpleFileParsing.h"

+#include "Symbols.h"

+

+//

+// #include "TrackMallocFree.h"

+//

+#define WCHAR_T           char

+#define MAX_STRING_LEN    256

+#define MAX_NAME_LEN      128

+#define BUFFER_SIZE       1024

+#define MAX_ATTR_LEN      128

+#define MAX_AREATYPE_LEN  128

+#define COLUMN2_START     60

+#define COLUMN3_START     70

+//

+// Information for each subregions defined in the fdf file will be saved in these

+//

+typedef struct _FLASH_SUBREGION_DESCRIPTION {

+  struct _FLASH_SUBREGION_DESCRIPTION *Next;

+  int                                 CreateHob;                  // to add to the auto-created HOB array

+  WCHAR_T                             Name[MAX_NAME_LEN];         // each subregion within a region must have a unique name

+  unsigned int                        Size;                       // size, in bytes, of this subregion

+  unsigned int                        SizeLeft;                   // used when creating the image

+  WCHAR_T                             Attributes[MAX_ATTR_LEN];   // subregion attributes used in the output HOB

+  WCHAR_T                             AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB

+  EFI_GUID                            NameGuid;                   // used in the output HOB

+  WCHAR_T                             NameGuidString[MAX_NAME_LEN];

+  EFI_GUID                            AreaTypeGuid;               // used in the output HOB

+  WCHAR_T                             AreaTypeGuidString[MAX_NAME_LEN];

+  EFI_GUID                            FileSystemGuid;             // used in the output HOB

+  WCHAR_T                             FileSystemGuidString[MAX_NAME_LEN];

+} FLASH_SUBREGION_DESCRIPTION;

+

+//

+// Information for each block in a flash device will be saved in one of these.

+// We'll also use it for region definitions.

+//

+typedef struct _FLASH_BLOCK_DESCRIPTION {

+  struct _FLASH_BLOCK_DESCRIPTION *Next;                      // next block in the linked list

+  WCHAR_T                         Name[MAX_NAME_LEN];         // each block must have a unique name

+  unsigned int                    Size;                       // size, in bytes, of this block

+  unsigned int                    SizeLeft;                   // for use when creating image

+  unsigned int                    Flags;                      // user-defined flags for the block

+  unsigned int                    Alignment;                  // power of 2 alignment

+  WCHAR_T                         Attributes[MAX_ATTR_LEN];   // only used for Region definitions

+  WCHAR_T                         AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions

+  FLASH_SUBREGION_DESCRIPTION     *Subregions;

+  FLASH_SUBREGION_DESCRIPTION     *LastSubregion;

+} FLASH_BLOCK_DESCRIPTION;

+

+//

+// Information for each flash device will be saved in one of these

+//

+typedef struct _FLASH_DEVICE_DESCRIPTION {

+  struct _FLASH_DEVICE_DESCRIPTION  *Next;              // next flash device in our linked list

+  int                               ErasePolarity;      // erase polarity of the flash device

+  unsigned int                      BaseAddress;        // base address of the flash device

+  unsigned int                      Size;               // total size, in bytes, of the flash device

+  WCHAR_T                           Name[MAX_NAME_LEN]; // name of the flash device

+  FLASH_BLOCK_DESCRIPTION           *PBlocks;           // linked list of physical block descriptors

+  FLASH_BLOCK_DESCRIPTION           *LastPBlock;        // last block in the linked list

+  FLASH_BLOCK_DESCRIPTION           *Regions;           // linked list of flash region descriptors

+  FLASH_BLOCK_DESCRIPTION           *LastRegion;        // last region in the linked list

+} FLASH_DEVICE_DESCRIPTION;

+

+//

+// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.

+//

+typedef struct _IMAGE_DEFINITION_ENTRY {

+  struct _IMAGE_DEFINITION_ENTRY  *Next;

+  WCHAR_T                         RegionName[MAX_NAME_LEN];

+  WCHAR_T                         SubregionName[MAX_NAME_LEN];

+  WCHAR_T                         Name[MAX_NAME_LEN]; // file or data name

+  int                             IsRawData;          // non-zero if raw data bytes

+  unsigned int                    RawDataSize;

+  char                            *RawData;

+  int                             Optional;           // optional file (don't include if it doesn't exist)

+} IMAGE_DEFINITION_ENTRY;

+

+//

+// When we parse an image definition, save all the data for each in one of these

+//

+typedef struct _IMAGE_DEFINITION {

+  struct _IMAGE_DEFINITION  *Next;

+  WCHAR_T                   Name[MAX_NAME_LEN];

+  IMAGE_DEFINITION_ENTRY    *Entries;

+  IMAGE_DEFINITION_ENTRY    *LastEntry;

+} IMAGE_DEFINITION;

+

+typedef struct {

+  char  *BufferStart;

+  char  *BufferEnd;

+  char  *BufferPos;

+} BUFFER_DATA;

+

+static const char               *CIncludeHeader = "/*++\n\n"

+"  DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"

+"#define _FLASH_MAP_H_\n\n";

+//

+//  "#include \"EfiFlashMap.h\"\n\n";

+//

+static const char               *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";

+

+static const char               *CFlashMapDataFileHeader = "/*++\n\n"

+"  DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";

+

+static FLASH_DEVICE_DESCRIPTION *mFlashDevices      = NULL;

+static IMAGE_DEFINITION         *mImageDefinitions  = NULL;

+

+//

+// Local function prototypes

+//

+static

+BUFFER_DATA                     *

+CreateBufferData (

+  VOID

+  );

+

+static

+BOOLEAN

+AddBufferDataByte (

+  BUFFER_DATA *Buffer,

+  char        Data

+  );

+

+static

+void

+FreeBufferData (

+  BUFFER_DATA *Buffer,

+  BOOLEAN     FreeData

+  );

+

+static

+char                            *

+GetBufferData (

+  BUFFER_DATA *Buffer,

+  int         *BufferSize

+  );

+

+static

+FLASH_SUBREGION_DESCRIPTION     *

+ParseSubregionDefinition (

+  unsigned int  SizeLeft

+  );

+

+void

+FDFConstructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Initialization routine for the services that operate on a flash

+  definition file.

+

+Arguments:

+  None.

+

+Returns:

+  NA

+

+--*/

+{

+  mFlashDevices     = NULL;

+  mImageDefinitions = NULL;

+}

+

+void

+FDFDestructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Finalization/cleanup routine for the services that operate on a flash

+  definition file.

+

+Arguments:

+  None.

+

+Returns:

+  NA

+

+--*/

+{

+  FLASH_BLOCK_DESCRIPTION     *FBNext;

+  FLASH_DEVICE_DESCRIPTION    *FDNext;

+  IMAGE_DEFINITION            *IDNext;

+  IMAGE_DEFINITION_ENTRY      *IDENext;

+  FLASH_SUBREGION_DESCRIPTION *SubNext;

+  //

+  // Go through all our flash devices and free the memory

+  //

+  while (mFlashDevices != NULL) {

+    //

+    // Free the physical block definitions

+    //

+    while (mFlashDevices->PBlocks != NULL) {

+      FBNext = mFlashDevices->PBlocks->Next;

+      _free (mFlashDevices->PBlocks);

+      mFlashDevices->PBlocks = FBNext;

+    }

+    //

+    // Free the region definitions

+    //

+    while (mFlashDevices->Regions != NULL) {

+      FBNext = mFlashDevices->Regions->Next;

+      //

+      // First free the subregion definitions

+      //

+      while (mFlashDevices->Regions->Subregions != NULL) {

+        SubNext = mFlashDevices->Regions->Subregions->Next;

+        _free (mFlashDevices->Regions->Subregions);

+        mFlashDevices->Regions->Subregions = SubNext;

+      }

+

+      _free (mFlashDevices->Regions);

+      mFlashDevices->Regions = FBNext;

+    }

+

+    FDNext = mFlashDevices->Next;

+    _free (mFlashDevices);

+    mFlashDevices = FDNext;

+  }

+  //

+  // Free up the image definitions, and the data

+  //

+  while (mImageDefinitions != NULL) {

+    //

+    // Free the entries

+    //

+    while (mImageDefinitions->Entries != NULL) {

+      IDENext = mImageDefinitions->Entries->Next;

+      if (mImageDefinitions->Entries->RawData != NULL) {

+        _free (mImageDefinitions->Entries->RawData);

+      }

+

+      _free (mImageDefinitions->Entries);

+      mImageDefinitions->Entries = IDENext;

+    }

+

+    IDNext = mImageDefinitions->Next;

+    _free (mImageDefinitions);

+    mImageDefinitions = IDNext;

+  }

+}

+

+STATUS

+FDFParseFile (

+  char    *FileName

+  )

+/*++

+

+Routine Description:

+  Parse the specified flash definition file, saving the definitions in

+  file-static variables for use by other functions.

+  

+Arguments:

+  FileName    - name of the input flash definition text file.

+

+Returns:

+  STATUS_SUCCESS    - file parsed with no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered while parsing

+  STATUS_ERROR      - errors were encountered while parsing

+  

+--*/

+{

+  FILE                        *Fptr;

+  STATUS                      Status;

+  unsigned int                Num;

+  FLASH_DEVICE_DESCRIPTION    *FDDesc;

+  FLASH_BLOCK_DESCRIPTION     *FBlockDesc;

+  FLASH_BLOCK_DESCRIPTION     *TempBlockDesc;

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  FLASH_SUBREGION_DESCRIPTION *TempSubregion;

+  unsigned int                BlockSizeLeft;

+  unsigned int                RegionSizeLeft;

+  unsigned int                SubregionSizeLeft;

+  int                         ErrorCount;

+  int                         WarningCount;

+  IMAGE_DEFINITION            *ImageDef;

+  IMAGE_DEFINITION_ENTRY      *ImageDefEntry;

+  IMAGE_DEFINITION_ENTRY      *TempImageDefEntry;

+  BUFFER_DATA                 *BufferData;

+  char                        Str[100];

+  BOOLEAN                     PreviousComma;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");

+    return STATUS_ERROR;

+  }

+

+  fclose (Fptr);

+  Status        = STATUS_SUCCESS;

+  ErrorCount    = 0;

+  WarningCount  = 0;

+  //

+  // Initialize the simple-file-parsing routines

+  //

+  SFPInit ();

+  //

+  // Open the file

+  //

+  if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {

+    return Status;

+  }

+  //

+  // Parse the file. Should start with a series of these:

+  // FlashDevice {

+  //   Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,

+  //   Block { Name = "BLOCK1",  Size = 0x1000, Flags = 0x0001 }

+  //   Block { Name = "BLOCK2",  Size = 0x1004, Flags = 0x0002 }

+  //   Region  { Name = "REGION_NAME", Size = 0x2004, Align= 4 }

+  // }

+  //

+  while (SFPIsKeyword ("FlashDevice")) {

+    //

+    // Allocate memory for new flash device description block

+    //

+    FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));

+    if (FDDesc == NULL) {

+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));

+    //

+    // Open brace -- warning if not there

+    //

+    if (!SFPIsToken ("{")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+      WarningCount++;

+    }

+    //

+    // Parse:  Name = "DeviceName",

+    //

+    if (!SFPIsKeyword ("Name")) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken (",")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);

+      WarningCount++;

+    }

+    //

+    // Parse: Size = 0x20000,

+    //

+    if (!SFPIsKeyword ("Size")) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPGetNumber (&FDDesc->Size)) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+    //

+    // Check for 0 size

+    //

+    if (FDDesc->Size == 0) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    SFPIsToken (",");

+    //

+    // Parse: BaseAddress = 0xFFF0000,

+    //

+    if (!SFPIsKeyword ("BaseAddress")) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPGetNumber (&FDDesc->BaseAddress)) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken (",")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);

+      WarningCount++;

+    }

+    //

+    // Parse: ErasePolarity = 1,

+    //

+    if (!SFPIsKeyword ("ErasePolarity")) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    FDDesc->ErasePolarity = Num;

+    if (!SFPIsToken (",")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);

+      WarningCount++;

+    }

+    //

+    // Parse array of:

+    //   Block {  Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }

+    //

+    // Keep track of size to make sure the sum of the physical blocks and region sizes do not

+    // exceed the size of the flash device.

+    //

+    BlockSizeLeft   = FDDesc->Size;

+    RegionSizeLeft  = FDDesc->Size;

+    while (SFPIsKeyword ("Block")) {

+      //

+      // Allocate memory for a new physical block descriptor

+      //

+      FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));

+      if (FBlockDesc == NULL) {

+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));

+      //

+      // Open brace -- warning if not there

+      //

+      if (!SFPIsToken ("{")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+        WarningCount++;

+      }

+      //

+      // Parse:  Name = "BlockName",

+      //

+      if (!SFPIsKeyword ("Name")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+      //

+      // Make sure there are no other physical block names with this same name

+      //

+      for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {

+        if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {

+          Error (

+            SFPGetFileName (),

+            SFPGetLineNumber (),

+            0,

+            TempBlockDesc->Name,

+            "physical block with this name already defined"

+            );

+          ErrorCount++;

+        }

+      }

+

+      if (!SFPIsToken (",")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);

+        WarningCount++;

+      }

+      //

+      // Parse: Size = 0x2000,

+      //

+      if (!SFPIsKeyword ("Size")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetNumber (&FBlockDesc->Size)) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+      //

+      // Make sure the sum of physical blocks so far does not exceed flash device size

+      //

+      if (BlockSizeLeft < FBlockDesc->Size) {

+        Error (

+          SFPGetFileName (),

+          SFPGetLineNumber (),

+          0,

+          "sum of physical block sizes exceeds flash device size",

+          NULL

+          );

+        ErrorCount++;

+      }

+

+      BlockSizeLeft -= FBlockDesc->Size;

+      SFPIsToken (",");

+      //

+      // Optional parse: Flags = 0xFFF0000,

+      //

+      if (SFPIsKeyword ("Flags")) {

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetNumber (&FBlockDesc->Flags)) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+      }

+

+      if (!SFPIsToken ("}")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);

+        WarningCount++;

+      }

+      //

+      // Add the physical block descriptor to the end of the linked list

+      //

+      if (FDDesc->LastPBlock != NULL) {

+        FDDesc->LastPBlock->Next = FBlockDesc;

+      } else {

+        FDDesc->PBlocks = FBlockDesc;

+      }

+

+      FDDesc->LastPBlock = FBlockDesc;

+    }

+    //

+    // Make sure sum of sizes of physical blocks added up to size of flash device

+    //

+    if (BlockSizeLeft != 0) {

+      Error (

+        SFPGetFileName (),

+        SFPGetLineNumber (),

+        0,

+        NULL,

+        "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",

+        FDDesc->Size - BlockSizeLeft,

+        FDDesc->Size,

+        BlockSizeLeft

+        );

+      ErrorCount++;

+    }

+    //

+    // Parse array of:

+    //   Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }

+    //

+    while (SFPIsKeyword ("Region")) {

+      //

+      // Allocate memory for a new physical block descriptor

+      //

+      FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));

+      if (FBlockDesc == NULL) {

+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));

+      //

+      // Open brace -- warning if not there

+      //

+      if (!SFPIsToken ("{")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+        WarningCount++;

+      }

+      //

+      // Parse:  Name = "BlockName",

+      //

+      if (!SFPIsKeyword ("Name")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+      //

+      // Make sure there are no other region names with this same name

+      //

+      for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {

+        if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {

+          Error (

+            SFPGetFileName (),

+            SFPGetLineNumber (),

+            0,

+            TempBlockDesc->Name,

+            "Region with this name already defined"

+            );

+          ErrorCount++;

+        }

+      }

+

+      if (!SFPIsToken (",")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);

+        WarningCount++;

+      }

+      //

+      // Parse: Size = 0x2000,

+      //

+      if (!SFPIsKeyword ("Size")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetNumber (&FBlockDesc->Size)) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken (",")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);

+      }

+      //

+      // Make sure the sum of regions so far does not exceed flash device size

+      //

+      if (RegionSizeLeft < FBlockDesc->Size) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);

+        ErrorCount++;

+      }

+

+      RegionSizeLeft -= FBlockDesc->Size;

+      //

+      // Optional parse: Flags = 0xFFF0000,

+      //

+      if (SFPIsKeyword ("Flags")) {

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetNumber (&FBlockDesc->Flags)) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+        //

+        // comma

+        //

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);

+        }

+      }

+      //

+      // Optional parse: Alignment = 4

+      //

+      if (SFPIsKeyword ("Alignment")) {

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetNumber (&FBlockDesc->Alignment)) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+        //

+        // comma

+        //

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);

+        }

+      }

+      //

+      // Parse:  Attributes = "String",

+      //

+      if (!SFPIsKeyword ("Attributes")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken (",")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);

+      }

+      //

+      // Parse:  AreaType = "String",

+      //

+      if (!SFPIsKeyword ("AreaType")) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+        WarningCount++;

+      }

+

+      if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);

+        ErrorCount++;

+        goto Done;

+      }

+

+      PreviousComma = SFPIsToken (",");

+      //

+      // Parse optional Subregion definitions

+      //

+      SubregionSizeLeft = FBlockDesc->Size;

+      while (SFPIsToken ("Subregion")) {

+        if (!PreviousComma) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);

+          WarningCount++;

+          PreviousComma = TRUE;

+        }

+

+        Subregion = ParseSubregionDefinition (SubregionSizeLeft);

+        if (Subregion == NULL) {

+          ErrorCount++;

+          goto Done;

+        }

+

+        SubregionSizeLeft -= Subregion->Size;

+        //

+        // Add it to the end of our list

+        //

+        if (FBlockDesc->Subregions == NULL) {

+          FBlockDesc->Subregions = Subregion;

+        } else {

+          FBlockDesc->LastSubregion->Next = Subregion;

+        }

+

+        FBlockDesc->LastSubregion = Subregion;

+        //

+        // Make sure all subregion names are unique. We do this each time

+        // through so that we catch the error immediately after it happens, in

+        // which case the reported line number is at least close to where the

+        // problem lies. We don't exit on the error because we can continue parsing

+        // the script to perhaps catch other errors or warnings.

+        //

+        for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+          for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {

+            if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {

+              Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");

+              ErrorCount++;

+            }

+          }

+        }

+      }

+

+      if (!SFPIsToken ("}")) {

+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);

+        WarningCount++;

+      }

+      //

+      // Add the region descriptor to the end of the linked list

+      //

+      if (FDDesc->LastRegion != NULL) {

+        FDDesc->LastRegion->Next = FBlockDesc;

+      } else {

+        FDDesc->Regions = FBlockDesc;

+      }

+

+      FDDesc->LastRegion = FBlockDesc;

+    }

+    //

+    // Make sure sum of sizes of regions adds up to size of flash device

+    //

+    if (RegionSizeLeft != 0) {

+      Error (

+        SFPGetFileName (),

+        SFPGetLineNumber (),

+        0,

+        NULL,

+        "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",

+        FDDesc->Size - RegionSizeLeft,

+        FDDesc->Size,

+        RegionSizeLeft

+        );

+      ErrorCount++;

+    }

+    //

+    // Look for closing brace

+    //

+    if (!SFPIsToken ("}")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);

+      WarningCount++;

+    }

+    //

+    // Add this flash description to the list

+    //

+    FDDesc->Next  = mFlashDevices;

+    mFlashDevices = FDDesc;

+  }

+

+  while (SFPIsKeyword ("FlashDeviceImage")) {

+    //

+    // Allocate memory for a new FD image definition

+    //

+    ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));

+    if (ImageDef == NULL) {

+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));

+    //

+    // Open brace -- warning if not there

+    //

+    if (!SFPIsToken ("{")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+      WarningCount++;

+    }

+    //

+    // Parse:  Name = "ImageName",

+    //

+    if (!SFPIsKeyword ("Name")) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);

+      ErrorCount++;

+      goto Done;

+    }

+

+    if (!SFPIsToken (",")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);

+      WarningCount++;

+    }

+

+    while (1) {

+      //

+      // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }

+      //

+      if (SFPIsKeyword ("File")) {

+        ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));

+        if (ImageDefEntry == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));

+        //

+        // Open brace -- warning if not there

+        //

+        if (!SFPIsToken ("{")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+          WarningCount++;

+        }

+        //

+        // Parse: Name = "FileName.txt"

+        //

+        if (!SFPIsKeyword ("Name")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);

+          WarningCount++;

+        }

+        //

+        // Parse: Region = "REGION_NAME"

+        //

+        if (!SFPIsKeyword ("Region")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);

+          WarningCount++;

+        }

+        //

+        // Parse optional: Subregion = "SUBREGION_NAME"

+        //

+        if (SFPIsKeyword ("Subregion")) {

+          if (!SFPIsToken ("=")) {

+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+            WarningCount++;

+          }

+

+          if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {

+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);

+            ErrorCount++;

+            goto Done;

+          }

+

+          if (!SFPIsToken (",")) {

+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);

+            WarningCount++;

+          }

+          //

+          // For a given region, you can only place data using the region name, or the subregion names.

+          // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that

+          // here by checking that any previous entries with the same Region name had a Subregion specified

+          // as well.

+          //

+          for (TempImageDefEntry = ImageDef->Entries;

+               TempImageDefEntry != NULL;

+               TempImageDefEntry = TempImageDefEntry->Next

+              ) {

+            if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {

+              if (TempImageDefEntry->SubregionName[0] == 0) {

+                Error (

+                  SFPGetFileName (),

+                  SFPGetLineNumber (),

+                  0,

+                  TempImageDefEntry->RegionName,

+                  "data already placed on a region-basis in the region, can't place data using subregions"

+                  );

+                ErrorCount++;

+              }

+            }

+          }

+        }

+        //

+        // Optional parse: Optional = TRUE | FALSE

+        //

+        if (SFPIsKeyword ("Optional")) {

+          if (!SFPIsToken ("=")) {

+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+            WarningCount++;

+          }

+

+          if (!SFPIsKeyword ("TRUE")) {

+            ImageDefEntry->Optional = 1;

+          } else if (SFPIsKeyword ("FALSE")) {

+            //

+            // Already set to 0

+            //

+          } else {

+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);

+            ErrorCount++;

+            goto Done;

+          }

+

+          SFPIsToken (",");

+        }

+        //

+        // Closing brace

+        //

+        if (!SFPIsToken ("}")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+        //

+        // Add the entry to the end of the list

+        //

+        if (ImageDef->LastEntry != NULL) {

+          ImageDef->LastEntry->Next = ImageDefEntry;

+        } else {

+          ImageDef->Entries = ImageDefEntry;

+        }

+

+        ImageDef->LastEntry = ImageDefEntry;

+      } else if (SFPIsKeyword ("RawData")) {

+        //

+        // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}

+        //

+        ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));

+        if (ImageDefEntry == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));

+        ImageDefEntry->IsRawData = 1;

+        //

+        // Open brace -- warning if not there

+        //

+        if (!SFPIsToken ("{")) {

+          Warning (

+            SFPGetFileName (),

+            SFPGetLineNumber (),

+            0,

+            "expected '{' opening brace for RawData definition",

+            NULL

+            );

+          WarningCount++;

+        }

+        //

+        // Parse: Name = "PadBytes"

+        //

+        if (!SFPIsKeyword ("Name")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);

+          WarningCount++;

+        }

+        //

+        // Parse: Region = "REGION_NAME"

+        //

+        if (!SFPIsKeyword ("Region")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken (",")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);

+          WarningCount++;

+        }

+        //

+        // Parse optional: Subregion = "SUBREGION_NAME"

+        //

+        if (SFPIsKeyword ("Subregion")) {

+          if (!SFPIsToken ("=")) {

+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+            WarningCount++;

+          }

+

+          if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {

+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);

+            ErrorCount++;

+            goto Done;

+          }

+

+          if (!SFPIsToken (",")) {

+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);

+            WarningCount++;

+          }

+          //

+          // For a given region, you can only place data using the region name, or the subregion names.

+          // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that

+          // here by checking that any previous entries with the same Region name had a Subregion specified

+          // as well.

+          //

+          for (TempImageDefEntry = ImageDef->Entries;

+               TempImageDefEntry != NULL;

+               TempImageDefEntry = TempImageDefEntry->Next

+              ) {

+            if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {

+              if (TempImageDefEntry->SubregionName[0] == 0) {

+                Error (

+                  SFPGetFileName (),

+                  SFPGetLineNumber (),

+                  0,

+                  TempImageDefEntry->RegionName,

+                  "data already placed on a region-basis in the region, can't place data using subregions"

+                  );

+                ErrorCount++;

+              }

+            }

+          }

+        }

+        //

+        // Parse: Data = { 0x78, 0x56, 0x34, 0x12 }

+        //

+        if (!SFPIsKeyword ("Data")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+

+        if (!SFPIsToken ("=")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+          WarningCount++;

+        }

+

+        if (!SFPIsToken ("{")) {

+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);

+          WarningCount++;

+        }

+

+        if ((BufferData = CreateBufferData ()) == NULL) {

+          ErrorCount++;

+          goto Done;

+        }

+        //

+        // Read bytes from input file until closing brace

+        //

+        while (!SFPIsToken ("}")) {

+          if (!SFPGetNumber (&Num)) {

+            SFPGetNextToken (Str, sizeof (Str));

+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);

+            ErrorCount++;

+            FreeBufferData (BufferData, TRUE);

+            goto Done;

+          } else {

+            //

+            // Only allow bytes

+            //

+            if (Num > 0xFF) {

+              Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);

+              ErrorCount++;

+              FreeBufferData (BufferData, TRUE);

+              goto Done;

+            }

+

+            AddBufferDataByte (BufferData, (char) Num);

+            SFPIsToken (",");

+          }

+        }

+        //

+        // Now get the data and save it in our image entry

+        //

+        ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);

+        FreeBufferData (BufferData, 0);

+        //

+        // Closing brace for RawData {}

+        //

+        if (!SFPIsToken ("}")) {

+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);

+          ErrorCount++;

+          goto Done;

+        }

+        //

+        // Add the entry to the end of the list

+        //

+        if (ImageDef->LastEntry != NULL) {

+          ImageDef->LastEntry->Next = ImageDefEntry;

+        } else {

+          ImageDef->Entries = ImageDefEntry;

+        }

+

+        ImageDef->LastEntry = ImageDefEntry;

+      } else if (SFPIsToken ("}")) {

+        //

+        // Closing brace for FDImage {}

+        //

+        break;

+      } else {

+        SFPGetNextToken (Str, sizeof (Str));

+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);

+        ErrorCount++;

+        goto Done;

+      }

+    }

+    //

+    // Add this image definition to our global list

+    //

+    ImageDef->Next    = mImageDefinitions;

+    mImageDefinitions = ImageDef;

+  }

+  //

+  // Check for end-of-file

+  //

+  if (!SFPIsEOF ()) {

+    SFPGetNextToken (Str, sizeof (Str));

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);

+    ErrorCount++;

+  }

+

+Done:

+  SFPCloseFile ();

+  if (ErrorCount != 0) {

+    return STATUS_ERROR;

+  } else if (WarningCount != 0) {

+    return STATUS_WARNING;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+FLASH_SUBREGION_DESCRIPTION *

+ParseSubregionDefinition (

+  unsigned int  SizeLeft

+  )

+/*++

+  

+Routine Description:

+

+  Parse Subregion definitions from the input flash definition file. Format:

+

+    Subregion {

+      CreateHob       = TRUE,

+      Name            = "FOO",

+      Size            = 0xA000,

+      Attributes      = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",

+      AreaType        = "EFI_FLASH_AREA_EFI_VARIABLES",

+      NameGuid        = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),

+      AreaTypeGuid    = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)

+      FileSystemGuid  = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)

+    }

+

+    NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.

+

+Arguments:

+   

+   SizeLeft   - in the flash definition file, a Region can be broken up into

+                one or more subregions. As we parse the subregion definitions,

+                the caller keeps track of how much space is left in the region

+                that we're parsing subregions for. SizeLeft is that size, and

+                so the size of the subregion we're now parsing better not

+                exceed the size left.

+  Returns:

+

+    NULL    - unrecoverable errors detected while parsing the subregion definition

+

+    pointer to a subregion definition created from the parsed subregion

+

+--*/

+{

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  int                         ErrorCount;

+  int                         WarningCount;

+  unsigned int                Number;

+  BOOLEAN                     PreviousComma;

+  //

+  // Allocate memory for the new subregion descriptor

+  //

+  ErrorCount    = 0;

+  WarningCount  = 0;

+  Subregion     = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));

+  if (Subregion == NULL) {

+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));

+  //

+  // Open brace -- warning if not there

+  //

+  if (!SFPIsToken ("{")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);

+    WarningCount++;

+  }

+  //

+  // Parse:  CreateHob = TRUE | FALSE,

+  //

+  if (!SFPIsKeyword ("CreateHob")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+

+  if (SFPIsToken ("TRUE")) {

+    Subregion->CreateHob = 1;

+  } else if (SFPIsToken ("FALSE")) {

+    //

+    // Subregion->CreateHob = 0; -- not required since we did a memset earlier

+    //

+  } else {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken (",")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);

+    WarningCount++;

+  }

+  //

+  // Parse:  Name = "Name",

+  //

+  if (!SFPIsKeyword ("Name")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+

+  if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken (",")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);

+    WarningCount++;

+  }

+  //

+  // Parse: Size = 0x2000,

+  //

+  if (!SFPIsKeyword ("Size")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+

+  if (!SFPGetNumber (&Subregion->Size)) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  //

+  // Check that the size does not exceed the size left passed in

+  //

+  if (Subregion->Size > SizeLeft) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken (",")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);

+  }

+  //

+  // Parse:  Attributes = Number | "String",

+  //

+  if (!SFPIsKeyword ("Attributes")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+

+  if (SFPGetNumber (&Number)) {

+    sprintf (Subregion->Attributes, "0x%X", Number);

+  } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken (",")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);

+  }

+  //

+  // Parse:  AreaType = Number | "String",

+  // AreaType is a UINT8, so error if it exceeds the size

+  //

+  if (!SFPIsKeyword ("AreaType")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+

+  if (SFPGetNumber (&Number)) {

+    if (Number > 0xFF) {

+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);

+      ErrorCount++;

+    }

+

+    sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);

+  } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken (",")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);

+  }

+  //

+  // Parse the three GUIDs (last two are optional)

+  //

+  //    NameGuid        = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")

+  //    AreaTypeGuid    = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")

+  //    FileSysteGuid   = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")

+  //

+  if (!SFPIsKeyword ("NameGuid")) {

+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);

+    ErrorCount++;

+    goto Done;

+  }

+

+  if (!SFPIsToken ("=")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+    WarningCount++;

+  }

+  //

+  // Allow a GUID or a quoted string identifier, which we'll just copy as a string

+  //

+  if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {

+    //

+    // Nothing else to do

+    //

+  } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {

+    Error (

+      SFPGetFileName (),

+      SFPGetLineNumber (),

+      0,

+      "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",

+      NULL

+      );

+    ErrorCount++;

+    goto Done;

+  }

+  //

+  // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid

+  //

+  PreviousComma = SFPIsToken (",");

+  if (SFPIsKeyword ("AreaTypeGuid")) {

+    //

+    // Check for preceeding comma now

+    //

+    if (!PreviousComma) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+

+    if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {

+      //

+      // Nothing else to do

+      //

+    } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {

+      Error (

+        SFPGetFileName (),

+        SFPGetLineNumber (),

+        0,

+        "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",

+        NULL

+        );

+      ErrorCount++;

+      goto Done;

+    }

+

+    PreviousComma = SFPIsToken (",");

+  }

+

+  if (SFPIsKeyword ("FileSystemGuid")) {

+    //

+    // Check for preceeding comma now

+    //

+    if (!PreviousComma) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);

+      WarningCount++;

+    }

+

+    if (!SFPIsToken ("=")) {

+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);

+      WarningCount++;

+    }

+    //

+    // Allow a GUID or a quoted string identifier, which we'll just copy as a string

+    //

+    if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {

+      //

+      // Nothing else to do

+      //

+    } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {

+      Error (

+        SFPGetFileName (),

+        SFPGetLineNumber (),

+        0,

+        "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",

+        NULL

+        );

+      ErrorCount++;

+      goto Done;

+    }

+

+    SFPIsToken (",");

+  }

+  //

+  // Look for subregion closing brace

+  //

+  if (!SFPIsToken ("}")) {

+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);

+    WarningCount++;

+  }

+

+Done:

+  //

+  // If any errors were encountered, then delete the subregion definition

+  //

+  if (ErrorCount != 0) {

+    _free (Subregion);

+    Subregion = NULL;

+  }

+

+  return Subregion;

+}

+

+STATUS

+FDFCreateCIncludeFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+  Create a header file with #define definitions per an already-parsed

+  flash definition file.

+

+Arguments:

+  FlashDeviceName - name of flash device (from the flash definition file)

+                    to use

+  FileName        - name of output file to create

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  FILE                        *OutFptr;

+  FLASH_BLOCK_DESCRIPTION     *FBlock;

+  FLASH_DEVICE_DESCRIPTION    *FDev;

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  unsigned int                Offset;

+  unsigned int                SubregionOffset;

+  int                         CreateHobs;

+  //

+  // Find the definition we're supposed to use

+  //

+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {

+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {

+      break;

+    }

+  }

+

+  if (FDev == NULL) {

+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");

+    return STATUS_ERROR;

+  }

+

+  if ((OutFptr = fopen (FileName, "w")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Write a header

+  //

+  fprintf (OutFptr, CIncludeHeader);

+  //

+  // Write flash block base and size defines

+  //

+  fprintf (OutFptr, "#define FLASH_BASE                                          0x%08X\n", FDev->BaseAddress);

+  fprintf (OutFptr, "#define FLASH_SIZE                                          0x%08X\n\n", FDev->Size);

+  //

+  // Write flash regions base, size and offset defines

+  //

+  Offset      = 0;

+  CreateHobs  = 0;

+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+    fprintf (

+      OutFptr,

+      "#define FLASH_REGION_%s_BASE              %*c0x%08X\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      Offset + FDev->BaseAddress

+      );

+    fprintf (

+      OutFptr,

+      "#define FLASH_REGION_%s_SIZE              %*c0x%08X\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      FBlock->Size

+      );

+    fprintf (

+      OutFptr,

+      "#define FLASH_REGION_%s_OFFSET            %*c0x%08X\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      Offset

+      );

+    //

+    // Create defines for any subregions

+    //

+    SubregionOffset = 0;

+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+      fprintf (

+        OutFptr,

+        "#define FLASH_REGION_%s_SUBREGION_%s_BASE     %*c0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        FDev->BaseAddress + Offset + SubregionOffset

+        );

+      fprintf (

+        OutFptr,

+        "#define FLASH_REGION_%s_SUBREGION_%s_SIZE     %*c0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Subregion->Size

+        );

+      fprintf (

+        OutFptr,

+        "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*c0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Offset + SubregionOffset

+        );

+      SubregionOffset += Subregion->Size;

+      if (Subregion->CreateHob != 0) {

+        CreateHobs = 1;

+      }

+    }

+

+    Offset += FBlock->Size;

+  }

+  //

+  // Now create a #define for the flash map data definition

+  //

+  fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");

+  //

+  // Emit entry for each region

+  //

+  Offset = 0;

+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+    fprintf (OutFptr, "  /* %s region */\\\n", FBlock->Name);

+    fprintf (OutFptr, "  {\\\n");

+    fprintf (OutFptr, "    FLASH_REGION_%s_BASE,\\\n", FBlock->Name);

+    fprintf (OutFptr, "    FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);

+    fprintf (OutFptr, "    %s,\\\n", FBlock->Attributes);

+    fprintf (OutFptr, "    %s,\\\n  },\\\n", FBlock->AreaType);

+  }

+

+  fprintf (OutFptr, "\n\n");

+  //

+  // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition

+  //

+  if (CreateHobs != 0) {

+    fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");

+    fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");

+    for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+      //

+      // See if the block has subregions, and that the CreateHobs flag is set

+      // for any of them.

+      //

+      CreateHobs = 0;

+      for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+        if (Subregion->CreateHob != 0) {

+          CreateHobs = 1;

+          break;

+        }

+      }

+      //

+      // If any of the subregions had the CreateHobs flag set, then create the entries in the

+      // output file

+      //

+      if (CreateHobs != 0) {

+        for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+          if (Subregion->CreateHob != 0) {

+            fprintf (OutFptr, " \\\n");

+            fprintf (OutFptr, "  /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);

+            fprintf (OutFptr, "  {\\\n");

+            fprintf (OutFptr, "    {EFI_HOB_TYPE_GUID_EXTENSION,\\\n");

+            fprintf (OutFptr, "    sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");

+            fprintf (OutFptr, "    0},\\\n");

+            //

+            // The NameGuid may have been specified in the input flash definition file as a GUID, or

+            // as a quoted string. Do the right one.

+            //

+            if (Subregion->NameGuidString[0] != 0) {

+              fprintf (OutFptr, "    %s, \\\n", Subregion->NameGuidString);

+            } else {

+              fprintf (

+                OutFptr,

+                "    { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",

+                Subregion->NameGuid.Data1,

+                (unsigned int) Subregion->NameGuid.Data2,

+                (unsigned int) Subregion->NameGuid.Data3,

+                (unsigned int) Subregion->NameGuid.Data4[0],

+                (unsigned int) Subregion->NameGuid.Data4[1],

+                (unsigned int) Subregion->NameGuid.Data4[2],

+                (unsigned int) Subregion->NameGuid.Data4[3],

+                (unsigned int) Subregion->NameGuid.Data4[4],

+                (unsigned int) Subregion->NameGuid.Data4[5],

+                (unsigned int) Subregion->NameGuid.Data4[6],

+                (unsigned int) Subregion->NameGuid.Data4[7]

+                );

+            }

+

+            fprintf (OutFptr, "    {0, 0, 0},\\\n");

+            fprintf (OutFptr, "    %s,\\\n", Subregion->AreaType);

+            //

+            // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or

+            // as a quoted string. Do the right one.

+            //

+            if (Subregion->AreaTypeGuidString[0] != 0) {

+              fprintf (OutFptr, "    %s, \\\n", Subregion->AreaTypeGuidString);

+            } else {

+              fprintf (

+                OutFptr,

+                "    { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",

+                Subregion->AreaTypeGuid.Data1,

+                (unsigned int) Subregion->AreaTypeGuid.Data2,

+                (unsigned int) Subregion->AreaTypeGuid.Data3,

+                (unsigned int) Subregion->AreaTypeGuid.Data4[0],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[1],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[2],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[3],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[4],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[5],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[6],

+                (unsigned int) Subregion->AreaTypeGuid.Data4[7]

+                );

+            }

+

+            fprintf (OutFptr, "    1,\\\n");

+            fprintf (OutFptr, "    {{\\\n");

+            fprintf (OutFptr, "      %s,\\\n", Subregion->Attributes);

+            fprintf (OutFptr, "      0,\\\n");

+            fprintf (OutFptr, "      FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);

+            fprintf (OutFptr, "      FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);

+            //

+            // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or

+            // as a quoted string. Do the right one.

+            //

+            if (Subregion->FileSystemGuidString[0] != 0) {

+              fprintf (OutFptr, "      %s, \\\n", Subregion->FileSystemGuidString);

+            } else {

+              fprintf (

+                OutFptr,

+                "      { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",

+                Subregion->FileSystemGuid.Data1,

+                (unsigned int) Subregion->FileSystemGuid.Data2,

+                (unsigned int) Subregion->FileSystemGuid.Data3,

+                (unsigned int) Subregion->FileSystemGuid.Data4[0],

+                (unsigned int) Subregion->FileSystemGuid.Data4[1],

+                (unsigned int) Subregion->FileSystemGuid.Data4[2],

+                (unsigned int) Subregion->FileSystemGuid.Data4[3],

+                (unsigned int) Subregion->FileSystemGuid.Data4[4],

+                (unsigned int) Subregion->FileSystemGuid.Data4[5],

+                (unsigned int) Subregion->FileSystemGuid.Data4[6],

+                (unsigned int) Subregion->FileSystemGuid.Data4[7]

+                );

+            }

+

+            fprintf (OutFptr, "    }},\\\n");

+            fprintf (OutFptr, "  },");

+          }

+        }

+      }

+    }

+

+    fprintf (OutFptr, "\n\n");

+  }

+

+  //

+  // Write the file's closing #endif

+  //

+  fprintf (OutFptr, CIncludeFooter);

+  fclose (OutFptr);

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FDFCreateAsmIncludeFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+  Create an assembly header file with equate definitions per an already-parsed

+  flash definition file.

+

+Arguments:

+  FlashDeviceName - name of flash device (from the flash definition file)

+                    to use

+  FileName        - name of output file to create

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  FILE                        *OutFptr;

+  FLASH_BLOCK_DESCRIPTION     *FBlock;

+  FLASH_DEVICE_DESCRIPTION    *FDev;

+  unsigned int                Offset;

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  unsigned int                SubregionOffset;

+  //

+  // Find the definition we're supposed to use

+  //

+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {

+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {

+      break;

+    }

+  }

+

+  if (FDev == NULL) {

+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");

+    return STATUS_ERROR;

+  }

+

+  if ((OutFptr = fopen (FileName, "w")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Write a header

+  //

+  fprintf (OutFptr, "\n\n");

+  //

+  // Write flash block size and offset defines

+  //

+  fprintf (

+    OutFptr,

+    "FLASH_BASE                               %*cequ 0%08Xh\n",

+    COLUMN2_START - 40,

+    ' ',

+    FDev->BaseAddress

+    );

+  fprintf (OutFptr, "FLASH_SIZE                               %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);

+  //

+  // Write flash region size and offset defines

+  //

+  fprintf (OutFptr, "\n");

+  Offset = 0;

+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_BASE   %*cequ 0%08Xh\n",

+      FBlock->Name,

+      COLUMN2_START - 20 - strlen (FBlock->Name),

+      ' ',

+      FDev->BaseAddress + Offset

+      );

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_SIZE   %*cequ 0%08Xh\n",

+      FBlock->Name,

+      COLUMN2_START - 20 - strlen (FBlock->Name),

+      ' ',

+      FBlock->Size

+      );

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",

+      FBlock->Name,

+      COLUMN2_START - 20 - strlen (FBlock->Name),

+      ' ',

+      Offset

+      );

+    //

+    // Create defines for any subregions

+    //

+    SubregionOffset = 0;

+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_BASE     %*cequ 0%08Xh\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        FDev->BaseAddress + Offset + SubregionOffset

+        );

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_SIZE     %*cequ 0%08Xh\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Subregion->Size

+        );

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*cequ 0%08Xh\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Offset + SubregionOffset

+        );

+      SubregionOffset += Subregion->Size;

+    }

+

+    Offset += FBlock->Size;

+  }

+

+  //

+  // Write closing \n

+  //

+  fprintf (OutFptr, "\n\n");

+  fclose (OutFptr);

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FDFCreateSymbols (

+  char      *FlashDeviceName

+  )

+/*++

+

+Routine Description:

+  Using the given flash device name, add symbols to the global symbol table. This

+  allows other functions to use the symbol definitions for other purposes.

+

+Arguments:

+  FlashDeviceName - name of flash device (from the flash definition file)

+                    to use

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  FLASH_BLOCK_DESCRIPTION     *FBlock;

+  FLASH_DEVICE_DESCRIPTION    *FDev;

+  unsigned int                Offset;

+  char                        SymName[120];

+  char                        SymValue[120];

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  unsigned int                SubregionOffset;

+  //

+  // Find the definition we're supposed to use

+  //

+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {

+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {

+      break;

+    }

+  }

+

+  if (FDev == NULL) {

+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");

+    return STATUS_ERROR;

+  }

+

+  sprintf (SymValue, "0x%08X", FDev->BaseAddress);

+  SymbolAdd ("FLASH_BASE", SymValue, 0);

+  sprintf (SymValue, "0x%08X", FDev->Size);

+  SymbolAdd ("FLASH_SIZE", SymValue, 0);

+  //

+  // Add flash block size and offset defines

+  //

+  // Offset = 0;

+  // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {

+  //  sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);

+  //  sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);

+  //  SymbolAdd (SymName, SymValue, 0);

+  //  sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);

+  //  sprintf (SymValue, "0x%08X", FBlock->Size);

+  //  SymbolAdd (SymName, SymValue, 0);

+  //  sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);

+  //  sprintf (SymValue, "0x%08X", Offset);

+  //  SymbolAdd (SymName, SymValue, 0);

+  //  Offset += FBlock->Size;

+  // }

+  //

+  // Add flash region block base, size, and offset defines

+  //

+  Offset = 0;

+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+    sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);

+    sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);

+    SymbolAdd (SymName, SymValue, 0);

+    sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);

+    sprintf (SymValue, "0x%08X", FBlock->Size);

+    SymbolAdd (SymName, SymValue, 0);

+    sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);

+    sprintf (SymValue, "0x%08X", Offset);

+    SymbolAdd (SymName, SymValue, 0);

+    //

+    // Add subregion symbols

+    //

+    if (FBlock->Subregions != NULL) {

+      SubregionOffset = 0;

+      for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);

+        sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);

+        SymbolAdd (SymName, SymValue, 0);

+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);

+        sprintf (SymValue, "0x%08X", Subregion->Size);

+        SymbolAdd (SymName, SymValue, 0);

+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);

+        sprintf (SymValue, "0x%08X", Offset + SubregionOffset);

+        SymbolAdd (SymName, SymValue, 0);

+        SubregionOffset += Subregion->Size;

+      }

+    }

+

+    Offset += FBlock->Size;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FDFCreateImage (

+  char      *FlashDeviceName,

+  char      *ImageName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+  Create a flash image using the given device and image names.

+

+Arguments:

+  FlashDeviceName - name of flash device (from the flash definition file)

+                    to use

+  ImageName       - name of image (from the flash definition file) to create

+  FileName        - name of output file to create

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  STATUS                      Status;

+  FILE                        *OutFptr;

+  FLASH_BLOCK_DESCRIPTION     *RegionDef;

+  FLASH_DEVICE_DESCRIPTION    *FDev;

+  IMAGE_DEFINITION            *ImageDef;

+  unsigned int                Offset;

+  char                        *Buffer;

+  FILE                        *InFptr;

+  long                        FileSize;

+  IMAGE_DEFINITION_ENTRY      *IDefEntry;

+  FLASH_SUBREGION_DESCRIPTION *SubregionDef;

+  //

+  // Find the flash definition we're supposed to use

+  //

+  InFptr  = NULL;

+  Status  = STATUS_ERROR;

+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {

+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {

+      break;

+    }

+  }

+

+  if (FDev == NULL) {

+    Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");

+    return STATUS_ERROR;

+  }

+  //

+  // Find the image name we're supposed to create

+  //

+  for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {

+    if (strcmp (ImageDef->Name, ImageName) == 0) {

+      break;

+    }

+  }

+

+  if (ImageDef == NULL) {

+    Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");

+    return STATUS_ERROR;

+  }

+  //

+  // Open the output file

+  //

+  if ((OutFptr = fopen (FileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Allocate a buffer to copy the input data to

+  //

+  Buffer = (char *) _malloc (FDev->Size);

+  if (Buffer == NULL) {

+    Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);

+    goto Done;

+  }

+  //

+  // Set contents of buffer to the erased value

+  //

+  if (FDev->ErasePolarity) {

+    memset (Buffer, 0xFF, FDev->Size);

+  } else {

+    memset (Buffer, 0, FDev->Size);

+  }

+  //

+  // Set all region and subregion size-left fields to the size of the region/subregion

+  //

+  for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {

+    RegionDef->SizeLeft = RegionDef->Size;

+    for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {

+      SubregionDef->SizeLeft = SubregionDef->Size;

+    }

+  }

+  //

+  // Now go through the image list, read files into the buffer.

+  //

+  for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {

+    //

+    // If it's a file name, open the file, get the size, find the corresponding

+    // flash region it's in, and copy the data.

+    //

+    if (IDefEntry->IsRawData == 0) {

+      if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {

+        Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");

+        goto Done;

+      }

+

+      fseek (InFptr, 0, SEEK_END);

+      FileSize = ftell (InFptr);

+      fseek (InFptr, 0, SEEK_SET);

+    } else {

+      FileSize = IDefEntry->RawDataSize;

+    }

+    //

+    // Find the region/subregion it's in, see if we have space left

+    //

+    Offset = 0;

+    for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {

+      if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {

+        break;

+      }

+

+      Offset += RegionDef->Size;

+    }

+

+    if (RegionDef == NULL) {

+      Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);

+      goto Done;

+    }

+

+    //

+    // Check for subregion

+    //

+    if (IDefEntry->SubregionName[0] != 0) {

+      for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {

+        if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {

+          break;

+        }

+

+        Offset += SubregionDef->Size;

+      }

+

+      if (SubregionDef == NULL) {

+        Error (

+          NULL,

+          0,

+          0,

+          IDefEntry->SubregionName,

+          "Subregion name not found in FlashDevice %s.%s Region definition",

+          FDev->Name,

+          RegionDef->Name

+          );

+        goto Done;

+      }

+      //

+      // Enough space in the subregion?

+      //

+      if (SubregionDef->SizeLeft < (unsigned int) FileSize) {

+        Error (

+          NULL,

+          0,

+          0,

+          IDefEntry->Name,

+          "insufficient space in Subregion (at least 0x%X additional bytes required)",

+          FileSize - SubregionDef->SizeLeft

+          );

+        goto Done;

+      }

+

+      //

+      // Read the file into the buffer if it's a file. Otherwise copy the raw data

+      //

+      if (IDefEntry->IsRawData == 0) {

+        if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {

+          Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");

+          goto Done;

+        }

+

+        fclose (InFptr);

+        InFptr = NULL;

+      } else {

+        memcpy (

+          Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),

+          IDefEntry->RawData,

+          IDefEntry->RawDataSize

+          );

+      }

+

+      SubregionDef->SizeLeft -= FileSize;

+      //

+      // Align based on the Region alignment requirements.

+      //

+      if (RegionDef->Alignment != 0) {

+        while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {

+          if (SubregionDef->SizeLeft == 0) {

+            break;

+          }

+

+          SubregionDef->SizeLeft--;

+        }

+      }

+    } else {

+      //

+      // Placing data in a region. Check for enough space in the region left.

+      //

+      if (RegionDef->SizeLeft < (unsigned int) FileSize) {

+        Error (

+          NULL,

+          0,

+          0,

+          IDefEntry->Name,

+          "insufficient space in Region (at least 0x%X additional bytes required)",

+          FileSize - RegionDef->SizeLeft

+          );

+        goto Done;

+      }

+

+      //

+      // Read the file into the buffer if it's a file. Otherwise copy the raw data

+      //

+      if (IDefEntry->IsRawData == 0) {

+        if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {

+          Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");

+          goto Done;

+        }

+

+        fclose (InFptr);

+        InFptr = NULL;

+      } else {

+        memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);

+      }

+

+      RegionDef->SizeLeft -= FileSize;

+      //

+      // Align

+      //

+      if (RegionDef->Alignment != 0) {

+        while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {

+          if (RegionDef->SizeLeft == 0) {

+            break;

+          }

+

+          RegionDef->SizeLeft--;

+        }

+      }

+    }

+  }

+

+  if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);

+    goto Done;

+  }

+

+  Status = STATUS_SUCCESS;

+Done:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  if (Buffer != NULL) {

+    _free (Buffer);

+  }

+

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+    if (Status == STATUS_ERROR) {

+      remove (FileName);

+    }

+  }

+

+  return Status;

+}

+

+STATUS

+FDFCreateDscFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+  Create a DSC-style output file with equates for flash management.

+

+Arguments:

+  FlashDeviceName - name of flash device (from the flash definition file)

+                    to use

+  FileName        - name of output file to create

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  FILE                        *OutFptr;

+  FLASH_BLOCK_DESCRIPTION     *FBlock;

+  FLASH_DEVICE_DESCRIPTION    *FDev;

+  unsigned int                Offset;

+  FLASH_SUBREGION_DESCRIPTION *Subregion;

+  unsigned int                SubregionOffset;

+  //

+  // Find the definition we're supposed to use

+  //

+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {

+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {

+      break;

+    }

+  }

+

+  if (FDev == NULL) {

+    Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");

+    return STATUS_ERROR;

+  }

+

+  if ((OutFptr = fopen (FileName, "w")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Write the flash base address and size

+  //

+  fprintf (OutFptr, "\n");

+  fprintf (OutFptr, "FLASH_BASE                                      = 0x%08X\n", FDev->BaseAddress);

+  fprintf (OutFptr, "FLASH_SIZE                                      = 0x%08X\n\n", FDev->Size);

+  //

+  // Write flash block size and offset defines

+  //

+  Offset = 0;

+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_BASE          %*c= 0x%08X\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      Offset + FDev->BaseAddress

+      );

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_SIZE          %*c= 0x%08X\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      FBlock->Size

+      );

+    fprintf (

+      OutFptr,

+      "FLASH_REGION_%s_SIZE_BLOCKS   %*c= 0x%x\n",

+      FBlock->Name,

+      COLUMN2_START - 40 - strlen (FBlock->Name),

+      ' ',

+      (FBlock->Size)/(FDev->PBlocks->Size)

+      );      

+    //

+    // Create defines for any subregions

+    //

+    SubregionOffset = 0;

+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_BASE     %*c= 0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        FDev->BaseAddress + Offset + SubregionOffset

+        );

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_SIZE     %*c= 0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Subregion->Size

+        );

+      fprintf (

+        OutFptr,

+        "FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*c= 0x%08X\n",

+        FBlock->Name,

+        Subregion->Name,

+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),

+        ' ',

+        Offset + SubregionOffset

+        );

+

+      SubregionOffset += Subregion->Size;

+    }

+

+    Offset += FBlock->Size;

+  }

+  //

+  // Close file

+  //

+  fprintf (OutFptr, "\n");

+  fclose (OutFptr);

+  return STATUS_SUCCESS;

+}

+

+

+/*++

+

+Routine Description:

+  The following buffer management routines are used to encapsulate functionality

+  for managing a growable data buffer.

+

+Arguments:

+  BUFFER_DATA     - structure that is used to maintain a data buffer

+

+Returns:

+  NA

+

+--*/

+static

+BUFFER_DATA *

+CreateBufferData (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Create a growable data buffer with default buffer length.

+

+Arguments:

+

+  None

+

+Returns:

+

+  NULL          - error occured during data buffer creation

+  Not NULL      - the pointer to the newly created data buffer

+

+--*/

+{

+  BUFFER_DATA *BD;

+  BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));

+  if (BD == NULL) {

+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+    return NULL;

+  }

+

+  memset (BD, 0, sizeof (BUFFER_DATA));

+  BD->BufferStart = (char *) _malloc (BUFFER_SIZE);

+  if (BD->BufferStart == NULL) {

+    _free (BD);

+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+    return NULL;

+  }

+

+  BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;

+  BD->BufferPos = BD->BufferStart;

+  return BD;

+}

+

+static

+BOOLEAN

+AddBufferDataByte (

+  BUFFER_DATA *Buffer,

+  char        Data

+  )

+/*++

+

+Routine Description:

+

+  Add a single byte to a growable data buffer, growing the buffer if required.

+

+Arguments:

+

+  Buffer  - pointer to the growable data buffer to add a single byte to

+  Data    - value of the single byte data to be added

+

+Returns:

+

+  TRUE    - the single byte data was successfully added

+  FALSE   - error occurred, the single byte data was not added

+

+--*/

+{

+  int   Size;

+  char  *NewBuffer;

+  //

+  // See if we have to grow the buffer

+  //

+  if (Buffer->BufferPos >= Buffer->BufferEnd) {

+    Size      = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;

+    NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);

+    if (NewBuffer == NULL) {

+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+      return FALSE;

+    }

+

+    memcpy (NewBuffer, Buffer->BufferStart, Size);

+    _free (Buffer->BufferStart);

+    Buffer->BufferStart = NewBuffer;

+    Buffer->BufferPos   = Buffer->BufferStart + Size;

+    Buffer->BufferEnd   = Buffer->BufferStart + Size + BUFFER_SIZE;

+  }

+

+  *Buffer->BufferPos = Data;

+  Buffer->BufferPos++;

+  return TRUE;

+}

+

+static

+void

+FreeBufferData (

+  BUFFER_DATA *Buffer,

+  BOOLEAN     FreeData

+  )

+/*++

+

+Routine Description:

+

+  Free memory used to manage a growable data buffer.

+

+Arguments:

+

+  Buffer    - pointer to the growable data buffer to be destructed

+  FreeData  - TRUE, free memory containing the buffered data

+              FALSE, do not free the buffered data memory

+

+Returns:

+

+  None

+

+--*/

+{

+  if (Buffer != NULL) {

+    if (FreeData && (Buffer->BufferStart != NULL)) {

+      _free (Buffer->BufferStart);

+    }

+

+    _free (Buffer);

+  }

+}

+

+static

+char *

+GetBufferData (

+  BUFFER_DATA *Buffer,

+  int         *BufferSize

+  )

+/*++

+

+Routine Description:

+

+  Return a pointer and size of the data in a growable data buffer.

+

+Arguments:

+

+  Buffer      - pointer to the growable data buffer

+  BufferSize  - size of the data in the growable data buffer

+

+Returns:

+

+  pointer of the data in the growable data buffer

+

+--*/

+{

+  *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;

+  return Buffer->BufferStart;

+}

+

+STATUS

+FDDiscover (

+  char          *FDFileName,

+  unsigned int  BaseAddr

+  )

+/*++

+

+Routine Description:

+  Walk a binary image and see if you find anything that looks like a

+  firmware volume.

+

+Arguments:

+  FDFileName        - name of input FD image to parse

+  BaseAddr          - base address of input FD image

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_WARNING    - warnings, but no errors, were encountered

+  STATUS_ERROR      - errors were encountered

+

+NOTE:

+  This routine is used for debug purposes only.

+

+--*/

+{

+  FILE                        *InFptr;

+  long                        FileSize;

+  long                        Offset;

+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;

+  EFI_GUID

+    FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };

+

+  if ((InFptr = fopen (FDFileName, "rb")) == NULL) {

+    Error (NULL, 0, 0, FDFileName, "failed to open file for reading");

+    return STATUS_ERROR;

+  }

+

+  fseek (InFptr, 0, SEEK_END);

+  FileSize = ftell (InFptr);

+  fseek (InFptr, 0, SEEK_SET);

+  Offset = 0;

+  while (Offset < FileSize) {

+    fseek (InFptr, Offset, SEEK_SET);

+    //

+    // Read the contents of the file, see if it's an FV header

+    //

+    if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {

+      //

+      // Check version and GUID

+      //

+      if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {

+        fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);

+        if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {

+          fprintf (stdout, "standard FFS file system\n");

+        } else {

+          fprintf (stdout, "non-standard FFS file system\n");

+        }

+      }

+    }

+

+    Offset += 16 * 1024;

+  }

+

+  fclose (InFptr);

+  return STATUS_SUCCESS;

+}

diff --git a/Source/FlashMap/FlashDefFile.h b/Source/FlashMap/FlashDefFile.h
new file mode 100644
index 0000000..0e2ea2c
--- /dev/null
+++ b/Source/FlashMap/FlashDefFile.h
@@ -0,0 +1,281 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  FlashDefFile.h

+

+Abstract:

+

+  Header file for flash management utility in the Intel Platform 

+  Innovation Framework for EFI build environment.

+

+--*/

+

+#ifndef _FLASH_DEF_FILE_H_

+#define _FLASH_DEF_FILE_H_

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+void

+FDFConstructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+void

+FDFDestructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFParseFile (

+  char    *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileName  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateCIncludeFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+  FileName        - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateCFlashMapDataFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+  FileName        - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateAsmIncludeFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+  FileName        - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFParseFile (

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileName  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateImage (

+  char      *FlashDeviceName,

+  char      *ImageName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+  ImageName       - GC_TODO: add argument description

+  FileName        - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateDscFile (

+  char      *FlashDeviceName,

+  char      *FileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+  FileName        - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDFCreateSymbols (

+  char      *FlashDeviceName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FlashDeviceName - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+FDDiscover (

+  char          *FDFileName,

+  unsigned int  BaseAddr

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FDFileName  - GC_TODO: add argument description

+  BaseAddr    - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // #ifndef _FLASH_DEF_FILE_H_

diff --git a/Source/FlashMap/FlashMap.c b/Source/FlashMap/FlashMap.c
new file mode 100644
index 0000000..88f5003
--- /dev/null
+++ b/Source/FlashMap/FlashMap.c
@@ -0,0 +1,769 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  FlashMap.c

+

+Abstract:

+

+  Utility for flash management in the Intel Platform Innovation Framework

+  for EFI build environment.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "EfiUtilityMsgs.h"

+#include "Microcode.h"

+#include "FlashDefFile.h"

+#include "Symbols.h"

+

+#define UTILITY_NAME  "FlashMap"

+

+typedef struct _STRING_LIST {

+  struct _STRING_LIST *Next;

+  char                *Str;

+} STRING_LIST;

+

+//

+// Keep our globals in one of these structures

+//

+static struct {

+  char          *CIncludeFileName;

+  char          *FlashDevice;

+  char          *FlashDeviceImage;

+  char          *MCIFileName;

+  char          *MCOFileName;

+  char          *ImageOutFileName;

+  char          *DscFileName;

+  char          *AsmIncludeFileName;

+  char          *FlashDefinitionFileName;

+  char          *StringReplaceInFileName;

+  char          *StringReplaceOutFileName;

+  char          *DiscoverFDImageName;

+  char          MicrocodePadByteValue;

+  unsigned int  MicrocodeAlignment;

+  STRING_LIST   *MCIFileNames;

+  STRING_LIST   *LastMCIFileNames;

+  unsigned int  BaseAddress;

+} mGlobals;

+

+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF

+#define DEFAULT_MC_ALIGNMENT      16

+

+static

+STATUS

+ProcessCommandLine (

+  int     argc,

+  char    *argv[]

+  );

+

+static

+STATUS

+MergeMicrocodeFiles (

+  char            *OutFileName,

+  STRING_LIST     *FileNames,

+  unsigned int    Alignment,

+  char            PadByteValue

+  );

+

+static

+void

+Usage (

+  VOID

+  );

+

+char* 

+NormalizePath (

+  char* OldPathName

+  );

+

+int

+main (

+  int   argc,

+  char  *argv[]

+  )

+/*++

+

+Routine Description:

+  Parse the command line arguments and then call worker functions to do the work

+  

+Arguments:

+  argc      - number of elements in argv

+  argv      - array of command-line arguments

+

+Returns:

+  STATUS_SUCCESS    - no problems encountered while processing

+  STATUS_WARNING    - warnings, but no errors, were encountered while processing

+  STATUS_ERROR      - errors were encountered while processing

+  

+--*/

+{

+  STATUS  Status;

+

+  SetUtilityName (UTILITY_NAME);

+  Status = ProcessCommandLine (argc, argv);

+  if (Status != STATUS_SUCCESS) {

+    return Status;

+  }

+  //

+  // Check for discovery of an FD (command line option)

+  //

+  if (mGlobals.DiscoverFDImageName != NULL) {

+    Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress);

+    goto Done;

+  }

+  //

+  // If they're doing microcode file parsing, then do that

+  //

+  if (mGlobals.MCIFileName != NULL) {

+    MicrocodeConstructor ();

+    MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName);

+    MicrocodeDestructor ();

+  }

+  //

+  // If they're doing microcode file merging, then do that now

+  //

+  if (mGlobals.MCIFileNames != NULL) {

+    MergeMicrocodeFiles (

+      mGlobals.MCOFileName,

+      mGlobals.MCIFileNames,

+      mGlobals.MicrocodeAlignment,

+      mGlobals.MicrocodePadByteValue

+      );

+  }

+  //

+  // If using a flash definition file, then process that and return

+  //

+  if (mGlobals.FlashDefinitionFileName != NULL) {

+    FDFConstructor ();

+    SymbolsConstructor ();

+    Status = FDFParseFile (mGlobals.FlashDefinitionFileName);

+    if (GetUtilityStatus () != STATUS_ERROR) {

+      //

+      // If they want us to do a string-replace on a file, then add the symbol definitions to

+      // the symbol table, and then do the string replace.

+      //

+      if (mGlobals.StringReplaceInFileName != NULL) {

+        Status  = FDFCreateSymbols (mGlobals.FlashDevice);

+        Status  = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName);

+      }

+      //

+      // If they want us to create a .h defines file or .c flashmap data file, then do so now

+      //

+      if (mGlobals.CIncludeFileName != NULL) {

+        Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName);

+      }

+      if (mGlobals.AsmIncludeFileName != NULL) {

+        Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName);

+      }

+      //

+      // If they want us to create an image, do that now

+      //

+      if (mGlobals.ImageOutFileName != NULL) {

+        Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName);

+      }

+      //

+      // If they want to create an output DSC file, do that now

+      //

+      if (mGlobals.DscFileName != NULL) {

+        Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName);

+      }

+    }

+    SymbolsDestructor ();

+    FDFDestructor ();

+  }

+Done:

+  //

+  // Free up memory

+  //

+  while (mGlobals.MCIFileNames != NULL) {

+    mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next;

+    _free (mGlobals.MCIFileNames);

+    mGlobals.MCIFileNames = mGlobals.LastMCIFileNames;

+  }

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+MergeMicrocodeFiles (

+  char            *OutFileName,

+  STRING_LIST     *FileNames,

+  unsigned int    Alignment,

+  char            PadByteValue

+  )

+/*++

+

+Routine Description:

+

+  Merge binary microcode files into a single file, taking into consideration

+  the alignment and pad value.

+

+Arguments:

+

+  OutFileName     - name of the output file to create

+  FileNames       - linked list of input microcode files to merge

+  Alignment       - alignment for each microcode file in the output image

+  PadByteValue    - value to use when padding to meet alignment requirements

+

+Returns:

+

+  STATUS_SUCCESS  - merge completed successfully or with acceptable warnings

+  STATUS_ERROR    - merge failed, output file not created

+

+--*/

+{

+  long    FileSize;

+  long    TotalFileSize;

+  FILE    *InFptr;

+  FILE    *OutFptr;

+  char    *Buffer;

+  STATUS  Status;

+

+  //

+  // Open the output file

+  //

+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Walk the list of files

+  //

+  Status        = STATUS_ERROR;

+  Buffer        = NULL;

+  InFptr        = NULL;

+  TotalFileSize = 0;

+  while (FileNames != NULL) {

+    //

+    // Open the file, determine the size, then read it in and write

+    // it back out.

+    //

+    if ((InFptr = fopen (NormalizePath(FileNames->Str), "rb")) == NULL) {

+      Error (NULL, 0, 0, NormalizePath(FileNames->Str), "failed to open input file for reading");

+      goto Done;

+    }

+    fseek (InFptr, 0, SEEK_END);

+    FileSize = ftell (InFptr);

+    fseek (InFptr, 0, SEEK_SET);

+    if (FileSize != 0) {

+      Buffer = (char *) _malloc (FileSize);

+      if (Buffer == NULL) {

+        Error (NULL, 0, 0, "memory allocation failure", NULL);

+        goto Done;

+      }

+      if (fread (Buffer, FileSize, 1, InFptr) != 1) {

+        Error (NULL, 0, 0, FileNames->Str, "failed to read file contents");

+        goto Done;

+      }

+      //

+      // Align

+      //

+      if (Alignment != 0) {

+        while ((TotalFileSize % Alignment) != 0) {

+          if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) {

+            Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file");

+            goto Done;

+          }

+          TotalFileSize++;

+        }

+      }

+      TotalFileSize += FileSize;

+      if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, OutFileName, "failed to write to output file");

+        goto Done;

+      }

+      _free (Buffer);

+      Buffer = NULL;

+    } else {

+      Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered");

+    }

+    fclose (InFptr);

+    InFptr    = NULL;

+    FileNames = FileNames->Next;

+  }

+  Status = STATUS_SUCCESS;

+Done:

+  fclose (OutFptr);

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+  if (Buffer != NULL) {

+    _free (Buffer);

+  }

+  if (Status == STATUS_ERROR) {

+    remove (OutFileName);

+  }

+  return Status;

+}

+

+static

+STATUS

+ProcessCommandLine (

+  int   argc,

+  char  *argv[]

+  )

+/*++

+

+Routine Description:

+  Process the command line arguments

+  

+Arguments:

+  argc   - Standard C entry point arguments

+  argv[] - Standard C entry point arguments

+

+Returns:

+  STATUS_SUCCESS    - no problems encountered while processing

+  STATUS_WARNING    - warnings, but no errors, were encountered while processing

+  STATUS_ERROR      - errors were encountered while processing

+  

+--*/

+{

+  int           ThingsToDo;

+  unsigned int  Temp;

+  STRING_LIST   *Str;

+  //

+  // Skip program name arg, process others

+  //

+  argc--;

+  argv++;

+  if (argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Clear out our globals, then start walking the arguments

+  //

+  memset ((void *) &mGlobals, 0, sizeof (mGlobals));

+  mGlobals.MicrocodePadByteValue  = DEFAULT_MC_PAD_BYTE_VALUE;

+  mGlobals.MicrocodeAlignment     = DEFAULT_MC_ALIGNMENT;

+  ThingsToDo                      = 0;

+  while (argc > 0) {

+    if (strcmp (argv[0], "-?") == 0) {

+      Usage ();

+      return STATUS_ERROR;

+    } else if (strcmp (argv[0], "-hfile") == 0) {

+      //

+      // -hfile FileName

+      //

+      // Used to specify an output C #include file to create that contains

+      // #define statements for all the flashmap region offsets and sizes.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an output file name");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.CIncludeFileName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-flashdevice") == 0) {

+      //

+      // -flashdevice FLASH_DEVICE_NAME

+      //

+      // Used to select which flash device definition to operate on.

+      // Check for additional argument

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires a flash device name to use");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.FlashDevice = argv[0];

+    } else if (strcmp (argv[0], "-mco") == 0) {

+      //

+      // -mco OutFileName

+      //

+      // Used to specify a microcode output binary file to create.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.MCOFileName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-asmincfile") == 0) {

+      //

+      // -asmincfile FileName

+      //

+      // Used to specify the name of the output assembly include file that contains

+      // equates for the flash region addresses and sizes.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.AsmIncludeFileName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-mci") == 0) {

+      //

+      // -mci FileName

+      //

+      // Used to specify an input microcode text file to parse.

+      // Check for additional argument

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.MCIFileName = argv[0];

+    } else if (strcmp (argv[0], "-flashdeviceimage") == 0) {

+      //

+      // -flashdeviceimage FlashDeviceImage

+      //

+      // Used to specify which flash device image definition from the input flash definition file

+      // to create.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.FlashDeviceImage = argv[0];

+    } else if (strcmp (argv[0], "-imageout") == 0) {

+      //

+      // -imageout FileName

+      //

+      // Used to specify the name of the output FD image file to create.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an output image filename to create");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.ImageOutFileName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-dsc") == 0) {

+      //

+      // -dsc FileName

+      //

+      // Used to specify the name of the output DSC file to create.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.DscFileName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-fdf") == 0) {

+      //

+      // -fdf FileName

+      //

+      // Used to specify the name of the input flash definition file.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.FlashDefinitionFileName = argv[0];

+    } else if (strcmp (argv[0], "-discover") == 0) {

+      //

+      // -discover FDFileName

+      //

+      // Debug functionality used to scan an existing FD image, trying to find

+      // firmware volumes at 64K boundaries.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an input FD image file name");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.DiscoverFDImageName = argv[0];

+      ThingsToDo++;

+    } else if (strcmp (argv[0], "-baseaddr") == 0) {

+      //

+      // -baseaddr Addr

+      //

+      // Used to specify a base address when doing a discover of an FD image.

+      // Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires a base address");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      if (tolower (argv[0][1]) == 'x') {

+        sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress);

+      } else {

+        sscanf (argv[0], "%d", &mGlobals.BaseAddress);

+      }

+    } else if (strcmp (argv[0], "-padvalue") == 0) {

+      //

+      // -padvalue Value

+      //

+      // Used to specify the value to pad with when aligning data while

+      // creating an FD image. Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires a byte value");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      if (tolower (argv[0][1]) == 'x') {

+        sscanf (argv[0] + 2, "%x", &Temp);

+        mGlobals.MicrocodePadByteValue = (char) Temp;

+      } else {

+        sscanf (argv[0], "%d", &Temp);

+        mGlobals.MicrocodePadByteValue = (char) Temp;

+      }

+    } else if (strcmp (argv[0], "-align") == 0) {

+      //

+      // -align Alignment

+      //

+      // Used to specify how each data file is aligned in the region

+      // when creating an FD image. Check for additional argument.

+      //

+      if (argc < 2) {

+        Error (NULL, 0, 0, argv[0], "option requires an alignment");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      if (tolower (argv[0][1]) == 'x') {

+        sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment);

+      } else {

+        sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment);

+      }

+    } else if (strcmp (argv[0], "-mcmerge") == 0) {

+      //

+      // -mcmerge FileName(s)

+      //

+      // Used to concatenate multiple microde binary files. Can specify

+      // multiple file names with the one -mcmerge flag. Check for additional argument.

+      //

+      if ((argc < 2) || (argv[1][0] == '-')) {

+        Error (NULL, 0, 0, argv[0], "option requires one or more input file names");

+        return STATUS_ERROR;

+      }

+      //

+      // Take input files until another option or end of list

+      //

+      ThingsToDo++;

+      while ((argc > 1) && (argv[1][0] != '-')) {

+        Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST));

+        if (Str == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+        memset (Str, 0, sizeof (STRING_LIST));

+        Str->Str = argv[1];

+        if (mGlobals.MCIFileNames == NULL) {

+          mGlobals.MCIFileNames = Str;

+        } else {

+          mGlobals.LastMCIFileNames->Next = Str;

+        }

+        mGlobals.LastMCIFileNames = Str;

+        argc--;

+        argv++;

+      }

+    } else if (strcmp (argv[0], "-strsub") == 0) {

+      //

+      // -strsub SrcFile DestFile

+      //

+      // Used to perform string substitutions on a file, writing the result to a new

+      // file. Check for two additional arguments.

+      //

+      if (argc < 3) {

+        Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution");

+        return STATUS_ERROR;

+      }

+      argc--;

+      argv++;

+      mGlobals.StringReplaceInFileName = argv[0];

+      argc--;

+      argv++;

+      mGlobals.StringReplaceOutFileName = argv[0];

+      ThingsToDo++;

+    } else {

+      Error (NULL, 0, 0, argv[0], "invalid option");

+      return STATUS_ERROR;

+    }

+    argc--;

+    argv++;

+  }

+  //

+  // If no outputs requested, then report an error

+  //

+  if (ThingsToDo == 0) {

+    Error (NULL, 0, 0, "nothing to do", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // If they want an asm file, #include file, or C file to be created, then they have to specify a

+  // flash device name and flash definition file name.

+  //

+  if ((mGlobals.CIncludeFileName != NULL) &&

+      ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {

+    Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL);

+    return STATUS_ERROR;

+  }

+  if ((mGlobals.AsmIncludeFileName != NULL) &&

+      ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {

+    Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // If they want a dsc file to be created, then they have to specify a

+  // flash device name and a flash definition file name

+  //

+  if (mGlobals.DscFileName != NULL) {

+    if (mGlobals.FlashDevice == NULL) {

+      Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL);

+      return STATUS_ERROR;

+    }

+    if (mGlobals.FlashDefinitionFileName == NULL) {

+      Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL);

+      return STATUS_ERROR;

+    }

+  }

+  //

+  // If they specified an output microcode file name, then they have to specify an input

+  // file name, and vice versa.

+  //

+  if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) {

+    Error (NULL, 0, 0, "must specify output microcode file name", NULL);

+    return STATUS_ERROR;

+  }

+  if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) {

+    Error (NULL, 0, 0, "must specify input microcode file name", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // If doing merge, then have to specify output file name

+  //

+  if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) {

+    Error (NULL, 0, 0, "must specify output microcode file name", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // If they want an output image to be created, then they have to specify

+  // the flash device and the flash device image to use.

+  //

+  if (mGlobals.ImageOutFileName != NULL) {

+    if (mGlobals.FlashDevice == NULL) {

+      Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL);

+      return STATUS_ERROR;

+    }

+    if (mGlobals.FlashDeviceImage == NULL) {

+      Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL);

+      return STATUS_ERROR;

+    }

+    if (mGlobals.FlashDefinitionFileName == NULL) {

+      Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL);

+      return STATUS_ERROR;

+    }

+  }

+  return STATUS_SUCCESS;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Print utility command line help

+  

+Arguments:

+  None

+

+Returns:

+  NA

+

+--*/

+{

+  int   i;

+  char  *Msg[] = {

+    "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",

+    "                 -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",

+    "                 -discover FDImage -dsc DscFile -asmincfile AsmIncFile",

+    "                 -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",

+    "                 -baseaddr BaseAddr -align Alignment -padvalue PadValue",

+    "                 -mcmerge MCIFile(s)",

+    "  where",

+    "    FlashDefFile     - input Flash Definition File",

+    "    FlashDevice      - flash device to use (from flash definition file)",

+    "    FlashDeviceImage - flash device image to use (from flash definition file)",

+    "    MCIFile          - input microcode file to parse",

+    "    MCOFile          - output binary microcode image to create from MCIFile",

+    "    HFile            - output #include file to create",

+    "    FDImage          - name of input FDImage file to scan",

+    "    ImageOutFile     - output image file to create",

+    "    DscFile          - output DSC file to create",

+    "    AsmIncFile       - output ASM include file to create",

+    "    InStrFile        - input file to replace symbol names, writing result to OutStrFile",

+    "    BaseAddr         - base address of FDImage (used with -discover)",

+    "    Alignment        - alignment to use when merging microcode binaries",

+    "    PadValue         - byte value to use as pad value when aligning microcode binaries",

+    "    MCIFile(s)       - one or more microcode binary files to merge/concatenate",

+    "",

+    NULL

+  };

+  for (i = 0; Msg[i] != NULL; i++) {

+    fprintf (stdout, "%s\n", Msg[i]);

+  }

+}

+

+char* 

+NormalizePath (

+  char* OldPathName

+  )

+{

+  char* Visitor;

+  

+  if (OldPathName == NULL) {

+    return NULL;

+  }

+  

+  Visitor = OldPathName;

+  while (*Visitor != '\0') {

+    if (*Visitor == '\\') {

+      *Visitor = '/';

+    }

+    Visitor++;

+  }

+  

+  return OldPathName;

+}

+

diff --git a/Source/FlashMap/Microcode.c b/Source/FlashMap/Microcode.c
new file mode 100644
index 0000000..2335325
--- /dev/null
+++ b/Source/FlashMap/Microcode.c
@@ -0,0 +1,304 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  Microcode.c

+

+Abstract:

+

+  Utility for working with microcode patch files in the Intel 

+  Platform Innovation Framework for EFI build environment.

+

+--*/

+

+#include <stdio.h>

+#include <string.h> // for memset()

+#include <ctype.h>

+#include <stdlib.h> // for malloc()

+

+#include "EfiUtilityMsgs.h"

+#include "Microcode.h"

+

+#define MAX_LINE_LEN  256

+

+//

+// Structure definition for a microcode header

+//

+typedef struct {

+  unsigned int  HeaderVersion;

+  unsigned int  PatchId;

+  unsigned int  Date;

+  unsigned int  CpuId;

+  unsigned int  Checksum;

+  unsigned int  LoaderVersion;

+  unsigned int  PlatformId;

+  unsigned int  DataSize;   // if 0, then TotalSize = 2048, and TotalSize field is invalid

+  unsigned int  TotalSize;  // number of bytes

+  unsigned int  Reserved[3];

+} MICROCODE_IMAGE_HEADER;

+

+static

+STATUS

+MicrocodeReadData (

+  FILE          *InFptr,

+  unsigned int  *Data

+  );

+

+void

+MicrocodeConstructor (

+  void

+  )

+/*++

+

+Routine Description:

+

+  Constructor of module Microcode

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+}

+

+void

+MicrocodeDestructor (

+  void

+  )

+/*++

+

+Routine Description:

+

+  Destructor of module Microcode

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+}

+

+static

+STATUS

+MicrocodeReadData (

+  FILE          *InFptr,

+  unsigned int  *Data

+  )

+/*++

+

+Routine Description:

+  Read a 32-bit microcode data value from a text file and convert to raw binary form.

+

+Arguments:

+  InFptr    - file pointer to input text file

+  Data      - pointer to where to return the data parsed

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings, Data contains valid information

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  char  Line[MAX_LINE_LEN];

+  char  *cptr;

+

+  Line[MAX_LINE_LEN - 1]  = 0;

+  *Data                   = 0;

+  if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {

+    return STATUS_ERROR;

+  }

+  //

+  // If it was a binary file, then it may have overwritten our null terminator

+  //

+  if (Line[MAX_LINE_LEN - 1] != 0) {

+    return STATUS_ERROR;

+  }

+  //

+  // Look for

+  // dd 000000001h ; comment

+  // dd XXXXXXXX

+  // DD  XXXXXXXXX

+  //  DD XXXXXXXXX

+  //

+  for (cptr = Line; *cptr && isspace(*cptr); cptr++) {

+  }

+  if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {

+    //

+    // Skip blanks and look for a hex digit

+    //

+    cptr += 3;

+    for (; *cptr && isspace(*cptr); cptr++) {

+    }

+    if (isxdigit (*cptr)) {

+      if (sscanf (cptr, "%X", Data) != 1) {

+        return STATUS_ERROR;

+      }

+    }

+    return STATUS_SUCCESS;

+  }

+  return STATUS_ERROR;

+}

+

+STATUS

+MicrocodeParseFile (

+  char  *InFileName,

+  char  *OutFileName

+  )

+/*++

+

+Routine Description:

+  Parse a microcode text file, and write the binary results to an output file.

+

+Arguments:

+  InFileName  - input text file to parse

+  OutFileName - output file to write raw binary data from parsed input file

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_ERROR      - errors were encountered

+

+--*/

+{

+  FILE                    *InFptr;

+  FILE                    *OutFptr;

+  STATUS                  Status;

+  MICROCODE_IMAGE_HEADER  *Header;

+  unsigned int            Size;

+  unsigned int            Size2;

+  unsigned int            Data;

+  unsigned int            Checksum;

+  char                    *Buffer;

+  char                    *Ptr;

+  unsigned int            TotalSize;

+

+  Status  = STATUS_ERROR;

+  InFptr  = NULL;

+  OutFptr = NULL;

+  Buffer  = NULL;

+  //

+  // Open the input text file

+  //

+  if ((InFptr = fopen (InFileName, "r")) == NULL) {

+    Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Make two passes on the input file. The first pass is to determine how

+  // much data is in the file so we can allocate a working buffer. Then

+  // we'll allocate a buffer and re-read the file into the buffer for processing.

+  //

+  Size = 0;

+  do {

+    Status = MicrocodeReadData (InFptr, &Data);

+    if (Status == STATUS_SUCCESS) {

+      Size += sizeof (Data);

+    }

+  } while (Status == STATUS_SUCCESS);

+  //

+  // Error if no data.

+  //

+  if (Size == 0) {

+    Error (NULL, 0, 0, InFileName, "no parse-able data found in file");

+    goto Done;

+  }

+  if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {

+    Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");

+    goto Done;

+  }

+  //

+  // Allocate a buffer for the data

+  //

+  Buffer = (char *) _malloc (Size);

+  if (Buffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    goto Done;

+  }

+  //

+  // Re-read the file, storing the data into our buffer

+  //

+  fseek (InFptr, 0, SEEK_SET);

+  Ptr = Buffer;

+  do {

+    Status = MicrocodeReadData (InFptr, &Data);

+    if (Status == STATUS_SUCCESS) {

+      *(unsigned int *) Ptr = Data;

+      Ptr += sizeof (Data);

+    }

+  } while (Status == STATUS_SUCCESS);

+  //

+  // Can't do much checking on the header because, per the spec, the

+  // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,

+  // and the TotalSize field is invalid (actually missing). Thus we can't

+  // even verify the Reserved fields are 0.

+  //

+  Header = (MICROCODE_IMAGE_HEADER *) Buffer;

+  if (Header->DataSize == 0) {

+    TotalSize = 2048;

+  } else {

+    TotalSize = Header->TotalSize;

+  }

+  if (TotalSize != Size) {

+    Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);

+    goto Done;

+  }

+  //

+  // Checksum the contents

+  //

+  Ptr       = Buffer;

+  Checksum  = 0;

+  Size2     = 0;

+  while (Size2 < Size) {

+    Checksum += *(unsigned int *) Ptr;

+    Ptr += 4;

+    Size2 += 4;

+  }

+  if (Checksum != 0) {

+    Error (NULL, 0, 0, InFileName, "checksum failed on file contents");

+    goto Done;

+  }

+  //

+  // Open the output file and write the buffer contents

+  //

+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");

+    goto Done;

+  }

+  if (fwrite (Buffer, Size, 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");

+    goto Done;

+  }

+  Status = STATUS_SUCCESS;

+Done:

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+    if (Status == STATUS_ERROR) {

+      remove (OutFileName);

+    }

+  }

+  return Status;

+}

diff --git a/Source/FlashMap/Microcode.h b/Source/FlashMap/Microcode.h
new file mode 100644
index 0000000..f85313e
--- /dev/null
+++ b/Source/FlashMap/Microcode.h
@@ -0,0 +1,87 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  Microcode.h

+

+Abstract:

+

+  Header file for flash management utility in the Intel Platform 

+  Innovation Framework for EFI build environment.

+

+--*/

+

+#ifndef _MICROCODE_H_

+#define _MICROCODE_H_

+

+void

+MicrocodeConstructor (

+  void

+  );

+/*++

+

+Routine Description:

+

+  Constructor of module Microcode

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+

+void

+MicrocodeDestructor (

+  void

+  );

+/*++

+

+Routine Description:

+

+  Destructor of module Microcode

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+

+STATUS

+MicrocodeParseFile (

+  char  *InFileName,

+  char  *OutFileName

+  );

+/*++

+

+Routine Description:

+  Parse a microcode text file, and write the binary results to an output file.

+

+Arguments:

+  InFileName  - input text file to parse

+  OutFileName - output file to write raw binary data from parsed input file

+

+Returns:

+  STATUS_SUCCESS    - no errors or warnings

+  STATUS_ERROR      - errors were encountered

+

+--*/

+

+

+#endif // #ifndef _MICROCODE_H_

diff --git a/Source/FlashMap/Symbols.c b/Source/FlashMap/Symbols.c
new file mode 100644
index 0000000..8e40814
--- /dev/null
+++ b/Source/FlashMap/Symbols.c
@@ -0,0 +1,648 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  Symbol.c

+

+Abstract:

+

+  Class-like implementation for a symbol table.

+

+--*/

+

+// GC_TODO: fix comment to set correct module name: Symbols.c

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+//

+// for isspace()

+//

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+#include "Symbols.h"

+

+#define MAX_LINE_LEN  512

+

+//

+// Linked list to keep track of all symbols

+//

+typedef struct _SYMBOL {

+  struct _SYMBOL  *Next;

+  int             Type;

+  char            *Name;

+  char            *Value;

+} SYMBOL;

+

+static

+SYMBOL        *

+FreeSymbols (

+  SYMBOL *Syms

+  );

+

+static

+int

+ExpandMacros (

+  char  *SourceLine,

+  char  *DestLine,

+  int   LineLen

+  );

+

+static SYMBOL *mSymbolTable = NULL;

+

+void

+SymbolsConstructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  SymbolsDestructor ();

+}

+

+void

+SymbolsDestructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  mSymbolTable = FreeSymbols (mSymbolTable);

+}

+

+char *

+GetSymbolValue (

+  char *SymbolName

+  )

+/*++

+

+Routine Description:

+  

+  Look up a symbol in our symbol table.

+

+Arguments:

+

+  SymbolName

+

+Returns:

+

+  Pointer to the value of the symbol if found

+  NULL if the symbol is not found

+

+--*/

+// GC_TODO:    SymbolName - add argument and description to function comment

+{

+  SYMBOL  *Symbol;

+  //

+  // Walk the symbol table

+  //

+  Symbol = mSymbolTable;

+  while (Symbol) {

+    if (stricmp (SymbolName, Symbol->Name) == 0) {

+      return Symbol->Value;

+    }

+

+    Symbol = Symbol->Next;

+  }

+

+  return NULL;

+}

+

+int

+SymbolAdd (

+  char    *Name,

+  char    *Value,

+  int     Mode

+  )

+/*++

+

+Routine Description:

+  

+  Add a symbol name/value to the symbol table

+

+Arguments:

+

+  Name  - name of symbol to add

+  Value - value of symbol to add

+  Mode  - currrently unused

+

+Returns:

+

+  Length of symbol added.

+

+Notes:

+  If Value == NULL, then this routine will assume that the Name field

+  looks something like "MySymName = MySymValue", and will try to parse

+  it that way and add the symbol name/pair from the string.

+

+--*/

+{

+  SYMBOL  *Symbol;

+

+  SYMBOL  *NewSymbol;

+  int     Len;

+  char    *Start;

+  char    *Cptr;

+  char    CSave;

+  char    *SaveCptr;

+

+  Len       = 0;

+  SaveCptr  = NULL;

+  CSave     = 0;

+  //

+  // If value pointer is null, then they passed us a line something like:

+  //    varname = value, or simply var =

+  //

+  if (Value == NULL) {

+    Start = Name;

+    while (*Name && isspace (*Name)) {

+      Name++;

+    }

+

+    if (Name == NULL) {

+      return -1;

+    }

+    //

+    // Find the end of the name. Either space or a '='.

+    //

+    for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)

+      ;

+    if (Value == NULL) {

+      return -1;

+    }

+    //

+    // Look for the '='

+    //

+    Cptr = Value;

+    while (*Value && (*Value != '=')) {

+      Value++;

+    }

+

+    if (Value == NULL) {

+      return -1;

+    }

+    //

+    // Now truncate the name

+    //

+    *Cptr = 0;

+    //

+    // Skip over the = and then any spaces

+    //

+    Value++;

+    while (*Value && isspace (*Value)) {

+      Value++;

+

+    }

+    //

+    // Find end of string, checking for quoted string

+    //

+    if (*Value == '\"') {

+      Value++;

+      for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)

+        ;

+    } else {

+      for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)

+        ;

+    }

+    //

+    // Null terminate the value string

+    //

+    CSave     = *Cptr;

+    SaveCptr  = Cptr;

+    *Cptr     = 0;

+    Len       = (int) (Cptr - Start);

+  }

+  //

+  // We now have a symbol name and a value. Look for an existing variable

+  // and overwrite it.

+  //

+  Symbol = mSymbolTable;

+  while (Symbol) {

+    //

+    // Check for symbol name match

+    //

+    if (stricmp (Name, Symbol->Name) == 0) {

+      _free (Symbol->Value);

+      Symbol->Value = (char *) _malloc (strlen (Value) + 1);

+      if (Symbol->Value == NULL) {

+        Error (NULL, 0, 0, NULL, "failed to allocate memory");

+        return -1;

+      }

+

+      strcpy (Symbol->Value, Value);

+      //

+      // If value == "NULL", then make it a 0-length string

+      //

+      if (stricmp (Symbol->Value, "NULL") == 0) {

+        Symbol->Value[0] = 0;

+      }

+

+      return Len;

+    }

+

+    Symbol = Symbol->Next;

+  }

+  //

+  // Does not exist, create a new one

+  //

+  NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));

+  if (NewSymbol == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation failure");

+    return -1;

+  }

+

+  memset ((char *) NewSymbol, 0, sizeof (SYMBOL));

+  NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);

+  if (NewSymbol->Name == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation failure");

+    _free (NewSymbol);

+    return -1;

+  }

+

+  NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);

+  if (NewSymbol->Value == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation failure");

+    _free (NewSymbol->Name);

+    _free (NewSymbol);

+    return -1;

+  }

+

+  strcpy (NewSymbol->Name, Name);

+  strcpy (NewSymbol->Value, Value);

+  //

+  // Remove trailing spaces

+  //

+  Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;

+  while (Cptr > NewSymbol->Value) {

+    if (isspace (*Cptr)) {

+      *Cptr = 0;

+      Cptr--;

+    } else {

+      break;

+    }

+  }

+  //

+  // Add it to the head of the list.

+  //

+  NewSymbol->Next = mSymbolTable;

+  mSymbolTable    = NewSymbol;

+  //

+  // If value == "NULL", then make it a 0-length string

+  //

+  if (stricmp (NewSymbol->Value, "NULL") == 0) {

+    NewSymbol->Value[0] = 0;

+  }

+  //

+  // Restore the terminator we inserted if they passed in var=value

+  //

+  if (SaveCptr != NULL) {

+    *SaveCptr = CSave;

+  }

+  _free (NewSymbol->Value);

+  _free (NewSymbol->Name);

+  _free (NewSymbol);

+  return Len;

+}

+

+static

+STATUS

+RemoveSymbol (

+  char *Name,

+  char SymbolType

+  )

+/*++

+

+Routine Description:

+  

+  Remove a symbol name/value from the symbol table

+

+Arguments:

+

+  Name  - name of symbol to remove

+  SymbolType - type of symbol to remove

+

+Returns:

+

+  STATUS_SUCCESS - matching symbol found and removed

+  STATUS_ERROR   - matching symbol not found in symbol table

+

+--*/

+{

+  SYMBOL  *Symbol;

+

+  SYMBOL  *PrevSymbol;

+

+  PrevSymbol  = NULL;

+  Symbol      = mSymbolTable;

+  //

+  // Walk the linked list of symbols in the symbol table looking

+  // for a match of both symbol name and type.

+  //

+  while (Symbol) {

+    if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {

+      //

+      // If the symbol has a value associated with it, free the memory

+      // allocated for the value.

+      // Then free the memory allocated for the symbols string name.

+      //

+      if (Symbol->Value) {

+        _free (Symbol->Value);

+      }

+

+      _free (Symbol->Name);

+      //

+      // Link the previous symbol to the next symbol to effectively

+      // remove this symbol from the linked list.

+      //

+      if (PrevSymbol) {

+        PrevSymbol->Next = Symbol->Next;

+      } else {

+        mSymbolTable = Symbol->Next;

+      }

+

+      _free (Symbol);

+      return STATUS_SUCCESS;

+    }

+

+    PrevSymbol  = Symbol;

+    Symbol      = Symbol->Next;

+  }

+

+  return STATUS_WARNING;

+}

+

+static

+SYMBOL *

+FreeSymbols (

+  SYMBOL *Syms

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Syms  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  SYMBOL  *Next;

+  while (Syms) {

+    if (Syms->Name != NULL) {

+      _free (Syms->Name);

+    }

+

+    if (Syms->Value != NULL) {

+      _free (Syms->Value);

+    }

+

+    Next = Syms->Next;

+    _free (Syms);

+    Syms = Next;

+  }

+

+  return Syms;

+}

+

+static

+int

+ExpandMacros (

+  char  *SourceLine,

+  char  *DestLine,

+  int   LineLen

+  )

+/*++

+

+Routine Description:

+  

+  Given a line of text, replace all variables of format $(NAME) with values

+  from our symbol table.

+

+Arguments:

+

+  SourceLine    - input line of text to do symbol replacements on

+  DestLine      - on output, SourceLine with symbols replaced

+  LineLen       - length of DestLine, so we don't exceed its allocated length

+

+Returns:

+

+  STATUS_SUCCESS - no problems encountered

+  STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine

+  STATUS_ERROR   - memory allocation failure

+

+--*/

+{

+  static int  NestDepth = 0;

+  char        *FromPtr;

+  char        *ToPtr;

+  char        *SaveStart;

+  char        *Cptr;

+  char        *value;

+  int         Expanded;

+  int         ExpandedCount;

+  INT8        *LocalDestLine;

+  STATUS      Status;

+  int         LocalLineLen;

+

+  NestDepth++;

+  Status        = STATUS_SUCCESS;

+  LocalDestLine = (char *) _malloc (LineLen);

+  if (LocalDestLine == NULL) {

+    Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);

+    return STATUS_ERROR;

+  }

+

+  FromPtr = SourceLine;

+  ToPtr   = LocalDestLine;

+  //

+  // Walk the entire line, replacing $(MACRO_NAME).

+  //

+  LocalLineLen  = LineLen;

+  ExpandedCount = 0;

+  while (*FromPtr && (LocalLineLen > 0)) {

+    if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {

+      //

+      // Save the start in case it's undefined, in which case we copy it as-is.

+      //

+      SaveStart = FromPtr;

+      Expanded  = 0;

+      //

+      // Macro expansion time. Find the end (no spaces allowed)

+      //

+      FromPtr += 2;

+      for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)

+        ;

+      if (*Cptr) {

+        //

+        // Truncate the string at the closing parenthesis for ease-of-use.

+        // Then copy the string directly to the destination line in case we don't find

+        // a definition for it.

+        //

+        *Cptr = 0;

+        strcpy (ToPtr, SaveStart);

+        if ((value = GetSymbolValue (FromPtr)) != NULL) {

+          strcpy (ToPtr, value);

+          LocalLineLen -= strlen (value);

+          ToPtr += strlen (value);

+          Expanded = 1;

+          ExpandedCount++;

+        }

+

+        if (!Expanded) {

+          //

+          // Restore closing parenthesis, and advance to next character

+          //

+          *Cptr   = ')';

+          FromPtr = SaveStart + 1;

+          ToPtr++;

+        } else {

+          FromPtr = Cptr + 1;

+        }

+      } else {

+        Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");

+        strcpy (ToPtr, FromPtr);

+        Status = STATUS_WARNING;

+        goto Done;

+      }

+    } else {

+      *ToPtr = *FromPtr;

+      FromPtr++;

+      ToPtr++;

+      LocalLineLen--;

+    }

+  }

+

+  if (*FromPtr == 0) {

+    *ToPtr = 0;

+  }

+

+  //

+  // If we expanded at least one string successfully, then make a recursive call to try again.

+  //

+  if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {

+    Status = ExpandMacros (LocalDestLine, DestLine, LineLen);

+    _free (LocalDestLine);

+    NestDepth = 0;

+    return Status;

+  }

+

+Done:

+  if (Status != STATUS_ERROR) {

+    strcpy (DestLine, LocalDestLine);

+  }

+

+  NestDepth = 0;

+  _free (LocalDestLine);

+  return Status;

+}

+

+STATUS

+SymbolsFileStringsReplace (

+  char    *InFileName,

+  char    *OutFileName

+  )

+/*++

+

+Routine Description:

+  

+  Given input and output file names, read in the input file, replace variable

+  references of format $(NAME) with appropriate values from our symbol table,

+  and write the result out to the output file.

+

+Arguments:

+

+  InFileName  - name of input text file to replace variable references

+  OutFileName - name of output text file to write results to

+

+Returns:

+

+  STATUS_SUCCESS - no problems encountered

+  STATUS_ERROR   - failed to open input or output file

+

+--*/

+{

+  STATUS  Status;

+  FILE    *InFptr;

+  FILE    *OutFptr;

+  char    Line[MAX_LINE_LEN];

+  char    OutLine[MAX_LINE_LEN];

+

+  Status = STATUS_ERROR;

+  //

+  // Open input and output files

+  //

+  InFptr  = NULL;

+  OutFptr = NULL;

+  if ((InFptr = fopen (InFileName, "r")) == NULL) {

+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");

+    goto Done;

+  }

+

+  if ((OutFptr = fopen (OutFileName, "w")) == NULL) {

+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");

+    goto Done;

+  }

+  //

+  // Read lines from input file until done

+  //

+  while (fgets (Line, sizeof (Line), InFptr) != NULL) {

+    ExpandMacros (Line, OutLine, sizeof (OutLine));

+    fprintf (OutFptr, OutLine);

+  }

+

+  Status = STATUS_SUCCESS;

+Done:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+  }

+

+  return Status;

+}

diff --git a/Source/FlashMap/Symbols.h b/Source/FlashMap/Symbols.h
new file mode 100644
index 0000000..a3cadff
--- /dev/null
+++ b/Source/FlashMap/Symbols.h
@@ -0,0 +1,124 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  Symbols.h

+

+Abstract:

+

+  Defines and prototypes for a class-like symbol table service.

+

+--*/

+

+#ifndef _SYMBOLS_H_

+#define _SYMBOLS_H_

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+int

+SymbolAdd (

+  char    *Name,

+  char    *Value,

+  int     Mode

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Name  - GC_TODO: add argument description

+  Value - GC_TODO: add argument description

+  Mode  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+STATUS

+SymbolsFileStringsReplace (

+  char    *InFileName,

+  char    *OutFileName

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  InFileName  - GC_TODO: add argument description

+  OutFileName - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+void

+SymbolsConstructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+void

+SymbolsDestructor (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // #ifndef _SYMBOLS_H_

diff --git a/Source/FlashMap/build.xml b/Source/FlashMap/build.xml
new file mode 100644
index 0000000..0fc7168
--- /dev/null
+++ b/Source/FlashMap/build.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK FlashMap Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="FlashMap"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <defineset>

+        <define name="_malloc" value="malloc"/>

+        <define name="_free" value="free"/>

+      </defineset>

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/FwImage/build.xml b/Source/FwImage/build.xml
new file mode 100644
index 0000000..d992db2
--- /dev/null
+++ b/Source/FwImage/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK FwImage Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="FwImage"/>

+  <property name="FileSet" value="fwimage.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/FwImage/fwimage.c b/Source/FwImage/fwimage.c
new file mode 100644
index 0000000..5dd1634
--- /dev/null
+++ b/Source/FwImage/fwimage.c
@@ -0,0 +1,510 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    fwimage.c

+

+Abstract:

+

+    Converts a pe32+ image to an FW image type

+

+--*/

+

+#include "WinNtInclude.h"

+

+#ifndef __GNUC__

+#include <windows.h>

+#endif

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <time.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.c"

+

+#define UTILITY_NAME  "FwImage"

+

+#ifdef __GNUC__

+typedef unsigned long ULONG;

+typedef unsigned char UCHAR;

+typedef unsigned char *PUCHAR;

+typedef unsigned short USHORT;

+#endif

+

+VOID

+Usage (

+  VOID

+  )

+{

+  printf ("Usage: " UTILITY_NAME "  {-t time-date} [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|USER_DEFINED] peimage [outimage]");

+}

+

+static

+STATUS

+FCopyFile (

+  FILE    *in,

+  FILE    *out

+  )

+{

+  ULONG filesize;

+  ULONG offset;

+  ULONG length;

+  UCHAR Buffer[8 * 1024];

+

+  fseek (in, 0, SEEK_END);

+  filesize = ftell (in);

+

+  fseek (in, 0, SEEK_SET);

+  fseek (out, 0, SEEK_SET);

+

+  offset = 0;

+  while (offset < filesize) {

+    length = sizeof (Buffer);

+    if (filesize - offset < length) {

+      length = filesize - offset;

+    }

+

+    fread (Buffer, length, 1, in);

+    fwrite (Buffer, length, 1, out);

+    offset += length;

+  }

+

+  if ((ULONG) ftell (out) != filesize) {

+    Error (NULL, 0, 0, "write error", NULL);

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+FReadFile (

+  FILE    *in,

+  VOID    **Buffer,

+  UINTN   *Length

+  )

+{

+  fseek (in, 0, SEEK_END);

+  *Length = ftell (in);

+  *Buffer = malloc (*Length);

+  fseek (in, 0, SEEK_SET);

+  fread (*Buffer, *Length, 1, in);

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+FWriteFile (

+  FILE    *out,

+  VOID    *Buffer,

+  UINTN   Length

+  )

+{

+  fseek (out, 0, SEEK_SET);

+  fwrite (Buffer, Length, 1, out);

+  if ((ULONG) ftell (out) != Length) {

+    Error (NULL, 0, 0, "write error", NULL);

+    return STATUS_ERROR;

+  }

+  free (Buffer);

+  return STATUS_SUCCESS;

+}

+

+int

+main (

+  int  argc,

+  char *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Main function.

+

+Arguments:

+

+  argc - Number of command line parameters.

+  argv - Array of pointers to command line parameter strings.

+

+Returns:

+  STATUS_SUCCESS - Utility exits successfully.

+  STATUS_ERROR   - Some error occurred during execution.

+

+--*/

+{

+  ULONG             Type;

+  PUCHAR            Ext;

+  PUCHAR            p;

+  PUCHAR            pe;

+  PUCHAR            OutImageName;

+  UCHAR             outname[500];

+  FILE              *fpIn;

+  FILE              *fpOut;

+  VOID              *ZeroBuffer;

+  EFI_IMAGE_DOS_HEADER  *DosHdr;

+  EFI_IMAGE_NT_HEADERS  *PeHdr;

+  EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;

+  EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;

+  time_t            TimeStamp;

+  struct tm         TimeStruct;

+  EFI_IMAGE_DOS_HEADER  BackupDosHdr;

+  ULONG             Index;

+  ULONG             Index1;

+  ULONG             Index2;

+  ULONG             Index3;

+  BOOLEAN           TimeStampPresent;

+  UINTN                                 AllignedRelocSize;

+  UINTN                                 Delta;

+  EFI_IMAGE_SECTION_HEADER              *SectionHeader;

+  UINT8      *FileBuffer;

+  UINTN      FileLength;

+  RUNTIME_FUNCTION  *RuntimeFunction;

+  UNWIND_INFO       *UnwindInfo;

+

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Assign to fix compile warning

+  //

+  OutImageName      = NULL;

+  Type              = 0;

+  Ext               = 0;

+  TimeStamp         = 0;

+  TimeStampPresent  = FALSE;

+

+  //

+  // Look for -t time-date option first. If the time is "0", then

+  // skip it.

+  //

+  if ((argc > 2) && !strcmp (argv[1], "-t")) {

+    TimeStampPresent = TRUE;

+    if (strcmp (argv[2], "0") != 0) {

+      //

+      // Convert the string to a value

+      //

+      memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));

+      if (sscanf(

+          argv[2], "%d/%d/%d,%d:%d:%d",

+          &TimeStruct.tm_mon,   /* months since January - [0,11] */

+          &TimeStruct.tm_mday,  /* day of the month - [1,31] */

+          &TimeStruct.tm_year,  /* years since 1900 */

+          &TimeStruct.tm_hour,  /* hours since midnight - [0,23] */

+          &TimeStruct.tm_min,   /* minutes after the hour - [0,59] */

+          &TimeStruct.tm_sec    /* seconds after the minute - [0,59] */

+            ) != 6) {

+        Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");

+        return STATUS_ERROR;

+      }

+      //

+      // Now fixup some of the fields

+      //

+      TimeStruct.tm_mon--;

+      TimeStruct.tm_year -= 1900;

+      //

+      // Sanity-check values?

+      // Convert

+      //

+      TimeStamp = mktime (&TimeStruct);

+      if (TimeStamp == (time_t) - 1) {

+        Error (NULL, 0, 0, argv[2], "failed to convert time");

+        return STATUS_ERROR;

+      }

+    }

+    //

+    // Skip over the args

+    //

+    argc -= 2;

+    argv += 2;

+  }

+  //

+  // Check for enough args

+  //

+  if (argc < 3) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  if (argc == 4) {

+    OutImageName = argv[3];

+  }

+  //

+  // Get new image type

+  //

+  p = argv[1];

+  if (*p == '/' || *p == '\\') {

+    p += 1;

+  }

+

+  if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {

+    Type  = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;

+    Ext   = ".efi";

+

+  } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {

+    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;

+    Ext   = ".efi";

+

+  } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {

+    Type  = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;

+    Ext   = ".efi";

+

+  } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {

+    Type  = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;

+    Ext   = ".efi";

+  } else if (stricmp (p, "SEC") == 0) {

+    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;

+    Ext   = ".sec";

+  } else if (stricmp (p, "peim") == 0 ||

+           stricmp (p, "BASE") == 0 ||

+           stricmp (p, "PEI_CORE") == 0 ||

+           stricmp (p, "PEIM") == 0 ||

+           stricmp (p, "DXE_SMM_DRIVER") == 0 ||

+           stricmp (p, "TOOL") == 0 ||

+           stricmp (p, "UEFI_APPLICATION") == 0 ||

+           stricmp (p, "USER_DEFINED") == 0 ||

+           stricmp (p, "UEFI_DRIVER") == 0 ||

+           stricmp (p, "DXE_CORE") == 0

+          ) {

+    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;

+    Ext   = ".pei";

+  } else {

+  	printf ("%s", p);

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // open source file

+  //

+  fpIn = fopen (argv[2], "rb");

+  if (!fpIn) {

+    Error (NULL, 0, 0, argv[2], "failed to open input file for reading");

+    return STATUS_ERROR;

+  }

+

+  FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);

+

+  //

+  // Read the dos & pe hdrs of the image

+  //

+  DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;

+  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");

+    fclose (fpIn);

+    return STATUS_ERROR;

+  }

+

+  PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);

+  if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {

+    Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");

+    fclose (fpIn);

+    return STATUS_ERROR;

+  }

+

+  //

+  // open output file

+  //

+  strcpy (outname, argv[2]);

+  pe = NULL;

+  for (p = outname; *p; p++) {

+    if (*p == '.') {

+      pe = p;

+    }

+  }

+

+  if (!pe) {

+    pe = p;

+  }

+

+  strcpy (pe, Ext);

+

+  if (!OutImageName) {

+    OutImageName = outname;

+  }

+

+  fpOut = fopen (OutImageName, "w+b");

+  if (!fpOut) {

+    Error (NULL, 0, 0, OutImageName, "could not open output file for writing");

+    fclose (fpIn);

+    return STATUS_ERROR;

+  }

+

+  //

+  // Zero all unused fields of the DOS header

+  //

+  memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));

+  memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));

+  DosHdr->e_magic  = BackupDosHdr.e_magic;

+  DosHdr->e_lfanew = BackupDosHdr.e_lfanew;

+

+  for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {

+    FileBuffer[Index] = DosHdr->e_cp;

+  }

+

+  //

+  // Path the PE header

+  //

+  PeHdr->OptionalHeader.Subsystem = (USHORT) Type;

+  if (TimeStampPresent) {

+    PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;

+  }

+

+  if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;

+    Optional32->MajorLinkerVersion          = 0;

+    Optional32->MinorLinkerVersion          = 0;

+    Optional32->MajorOperatingSystemVersion = 0;

+    Optional32->MinorOperatingSystemVersion = 0;

+    Optional32->MajorImageVersion           = 0;

+    Optional32->MinorImageVersion           = 0;

+    Optional32->MajorSubsystemVersion       = 0;

+    Optional32->MinorSubsystemVersion       = 0;

+    Optional32->Win32VersionValue           = 0;

+    Optional32->CheckSum                    = 0;

+    Optional32->SizeOfStackReserve = 0;

+    Optional32->SizeOfStackCommit  = 0;

+    Optional32->SizeOfHeapReserve  = 0;

+    Optional32->SizeOfHeapCommit   = 0;

+

+    //

+    // Strip zero padding at the end of the .reloc section 

+    //

+    if (Optional32->NumberOfRvaAndSizes >= 6) {

+      if (Optional32->DataDirectory[5].Size != 0) {

+        SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);

+        for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {

+          //

+          // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory

+          //

+          if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {

+            SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;

+            AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));

+            //

+            // Check to see if there is zero padding at the end of the base relocations

+            //

+            if (AllignedRelocSize < SectionHeader->SizeOfRawData) {

+              //

+              // Check to see if the base relocations are at the end of the file

+              //

+              if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {

+                //

+                // All the required conditions are met to strip the zero padding of the end of the base relocations section

+                //

+                Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);

+                Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);

+                SectionHeader->SizeOfRawData = AllignedRelocSize;

+                FileLength = Optional32->SizeOfImage;

+              }

+            }

+          }

+        }

+      }

+    }

+  } 

+  if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {

+    Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;

+    Optional64->MajorLinkerVersion          = 0;

+    Optional64->MinorLinkerVersion          = 0;

+    Optional64->MajorOperatingSystemVersion = 0;

+    Optional64->MinorOperatingSystemVersion = 0;

+    Optional64->MajorImageVersion           = 0;

+    Optional64->MinorImageVersion           = 0;

+    Optional64->MajorSubsystemVersion       = 0;

+    Optional64->MinorSubsystemVersion       = 0;

+    Optional64->Win32VersionValue           = 0;

+    Optional64->CheckSum                    = 0;

+    Optional64->SizeOfStackReserve = 0;

+    Optional64->SizeOfStackCommit  = 0;

+    Optional64->SizeOfHeapReserve  = 0;

+    Optional64->SizeOfHeapCommit   = 0;

+

+    //

+    // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty

+    //

+    if (PeHdr->FileHeader.Machine == 0x8664) { // X64

+      if (Optional64->NumberOfRvaAndSizes >= 4) {

+        if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {

+          SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);

+          for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {

+            if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {

+              RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);

+              for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {

+                SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);

+                for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {

+                  if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {

+                    UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));

+                    if (UnwindInfo->Version == 1) {

+                      memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));

+                      memset (UnwindInfo, 0, sizeof (UNWIND_INFO));

+                    }

+                  }

+                }

+                memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));

+              }

+            }

+          }

+          Optional64->DataDirectory[3].Size = 0;

+          Optional64->DataDirectory[3].VirtualAddress = 0;

+        }

+      }

+    }

+

+    //

+    // Strip zero padding at the end of the .reloc section 

+    //

+    if (Optional64->NumberOfRvaAndSizes >= 6) {

+      if (Optional64->DataDirectory[5].Size != 0) {

+        SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);

+        for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {

+          //

+          // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory

+          //

+          if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {

+            SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;

+            AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));

+            //

+            // Check to see if there is zero padding at the end of the base relocations

+            //

+            if (AllignedRelocSize < SectionHeader->SizeOfRawData) {

+              //

+              // Check to see if the base relocations are at the end of the file

+              //

+              if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {

+                //

+                // All the required conditions are met to strip the zero padding of the end of the base relocations section

+                //

+                Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);

+                Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);

+                SectionHeader->SizeOfRawData = AllignedRelocSize;

+                FileLength = Optional64->SizeOfImage;

+              }

+            }

+          }

+        }

+      }

+    }

+  }

+

+  FWriteFile (fpOut, FileBuffer, FileLength);

+

+  //

+  // Done

+  //

+  fclose (fpIn);

+  fclose (fpOut);

+  //

+  // printf ("Created %s\n", OutImageName);

+  //

+  return STATUS_SUCCESS;

+}

diff --git a/Source/GenAcpiTable/GenAcpiTable.c b/Source/GenAcpiTable/GenAcpiTable.c
new file mode 100644
index 0000000..7a413ea
--- /dev/null
+++ b/Source/GenAcpiTable/GenAcpiTable.c
@@ -0,0 +1,544 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  GenAcpiTable.c

+  

+Abstract:

+

+  A utility that extracts the .DATA section from a PE/COFF image.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h> // for PE32 structure definitions

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+

+//

+// Version of this utility

+//

+#define UTILITY_NAME    "GenAcpiTable"

+#define UTILITY_VERSION "v0.11"

+

+//

+// Define the max length of a filename

+//

+#define MAX_PATH                  256

+#define DEFAULT_OUTPUT_EXTENSION  ".acpi"

+

+//

+// Use this to track our command-line options and globals

+//

+struct {

+  INT8  OutFileName[MAX_PATH];

+  INT8  InFileName[MAX_PATH];

+} mOptions;

+

+//

+// Use these to convert from machine type value to a named type

+//

+typedef struct {

+  UINT16  Value;

+  INT8    *Name;

+} STRING_LOOKUP;

+

+static STRING_LOOKUP  mMachineTypes[] = {

+  EFI_IMAGE_MACHINE_IA32,

+  "IA32",

+  EFI_IMAGE_MACHINE_IA64,

+  "IA64",

+  EFI_IMAGE_MACHINE_EBC,

+  "EBC",

+  0,

+  NULL

+};

+

+static STRING_LOOKUP  mSubsystemTypes[] = {

+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,

+  "EFI application",

+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,

+  "EFI boot service driver",

+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,

+  "EFI runtime driver",

+  0,

+  NULL

+};

+//

+//  Function prototypes

+//

+static

+void

+Usage (

+  VOID

+  );

+

+static

+STATUS

+ParseCommandLine (

+  int       Argc,

+  char      *Argv[]

+  );

+

+static

+STATUS

+CheckPE32File (

+  INT8      *FileName,

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  );

+

+static

+STATUS

+ProcessFile (

+  INT8      *InFileName,

+  INT8      *OutFileName

+  );

+

+static

+void

+DumpImage (

+  INT8      *FileName

+  );

+

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+

+Arguments:

+

+  Argc            - standard C main() argument count

+

+  Argv            - standard C main() argument list

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  UINT32  Status;

+

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Parse the command line arguments

+  //

+  if (ParseCommandLine (Argc, Argv)) {

+    return STATUS_ERROR;

+  }

+  //

+  // Make sure we don't have the same filename for input and output files

+  //

+  if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {

+    Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");

+    goto Finish;

+  }

+  //

+  // Process the file

+  //

+  ProcessFile (mOptions.InFileName, mOptions.OutFileName);

+Finish:

+  Status = GetUtilityStatus ();

+  return Status;

+}

+

+static

+STATUS

+ProcessFile (

+  INT8      *InFileName,

+  INT8      *OutFileName

+  )

+/*++

+

+Routine Description:

+  

+  Process a PE32 EFI file.

+

+Arguments:

+

+  InFileName - Name of the PE32 EFI file to process.

+  OutFileName - Name of the output file for the processed data.

+

+Returns:

+

+  0 - successful

+

+--*/

+{

+  STATUS                      Status;

+  UINTN                       Index;

+  FILE                        *InFptr;

+  FILE                        *OutFptr;

+  UINT16                      MachineType;

+  UINT16                      SubSystem;

+  UINT32                      PESigOffset;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;

+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;

+  EFI_IMAGE_SECTION_HEADER    SectionHeader;

+  UINT8                       *Buffer;

+  long                        SaveFilePosition;

+

+  InFptr  = NULL;

+  OutFptr = NULL;

+  Buffer  = NULL;

+  Status  = STATUS_ERROR;

+  //

+  // Try to open the input file

+  //

+  if ((InFptr = fopen (InFileName, "rb")) == NULL) {

+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Double-check the file to make sure it's what we expect it to be

+  //

+  if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {

+    goto Finish;

+  }

+  //

+  // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit

+  // offset (from the start of the file) to the PE signature, which always

+  // follows the MSDOS stub. The PE signature is immediately followed by the

+  // COFF file header.

+  //

+  //

+  if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {

+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);

+    goto Finish;

+  }

+

+  if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");

+    goto Finish;

+  }

+

+  if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {

+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");

+    goto Finish;

+  }

+  //

+  // We should now be at the COFF file header. Read it in and verify it's

+  // of an image type we support.

+  //

+  if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read file header from image");

+    goto Finish;

+  }

+

+  if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {

+    Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);

+    goto Finish;

+  }

+  //

+  // Read in the optional header. Assume PE32, and if not, then re-read as PE32+

+  //

+  SaveFilePosition = ftell (InFptr);

+  if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");

+    goto Finish;

+  }

+

+  if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {

+    if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {

+      Error (NULL, 0, 0, InFileName, "failed to seek to .data section");

+      goto Finish;

+    }

+

+    if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {

+      Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");

+      goto Finish;

+    }

+  }

+  //

+  // Search for the ".data" section

+  //

+  for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {

+    if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {

+      Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");

+      goto Finish;

+    }

+

+    if (strcmp (SectionHeader.Name, ".data") == 0) {

+      if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {

+        Error (NULL, 0, 0, InFileName, "failed to seek to .data section");

+        goto Finish;

+      }

+

+      Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);

+      if (Buffer == NULL) {

+        Status = EFI_OUT_OF_RESOURCES;

+        goto Finish;

+      }

+      if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {

+        Error (NULL, 0, 0, InFileName, "failed to .data section");

+        goto Finish;

+      }

+      //

+      // Now open our output file

+      //

+      if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {

+        Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");

+        goto Finish;

+      }

+

+      if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, OutFileName, "failed to write .data section");

+        goto Finish;

+      }

+

+      Status = STATUS_SUCCESS;

+      goto Finish;

+    }

+  }

+

+  Status = STATUS_ERROR;

+

+Finish:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+  //

+  // Close the output file. If there was an error, delete the output file so

+  // that a subsequent build will rebuild it.

+  //

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+    if (GetUtilityStatus () == STATUS_ERROR) {

+      remove (OutFileName);

+    }

+  }

+

+  //

+  // Free up our buffer

+  //

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  return Status;

+}

+

+static

+STATUS

+CheckPE32File (

+  INT8      *FileName,

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileName    - GC_TODO: add argument description

+  Fptr        - GC_TODO: add argument description

+  MachineType - GC_TODO: add argument description

+  SubSystem   - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  /*++

+

+Routine Description:

+  

+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a

+  PE32 image file, and then return the machine type in the supplied pointer.

+

+Arguments:

+

+  Fptr          File pointer to the already-opened PE32 file

+  MachineType   Location to stuff the machine type of the PE32 file. This is needed

+                because the image may be Itanium-based, IA32, or EBC.

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+  EFI_IMAGE_DOS_HEADER      DosHeader;

+  EFI_IMAGE_FILE_HEADER     FileHdr;

+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;

+  UINT32                    PESig;

+  STATUS                    Status;

+

+  Status = STATUS_ERROR;

+  //

+  // Position to the start of the file

+  //

+  fseek (Fptr, 0, SEEK_SET);

+  //

+  // Read the DOS header

+  //

+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");

+    goto Finish;

+  }

+  //

+  // Check the magic number (0x5A4D)

+  //

+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");

+    goto Finish;

+  }

+  //

+  // Position into the file and check the PE signature

+  //

+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);

+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");

+    goto Finish;

+  }

+  //

+  // Check the PE signature in the header "PE\0\0"

+  //

+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");

+    goto Finish;

+  }

+  //

+  // Read the file header

+  //

+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");

+    goto Finish;

+  }

+  //

+  // Read the optional header so we can get the subsystem

+  //

+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");

+    goto Finish;

+  }

+

+  *SubSystem = OptionalHdr.Subsystem;

+  //

+  // Good to go

+  //

+  Status = STATUS_SUCCESS;

+Finish:

+  fseek (Fptr, 0, SEEK_SET);

+  return Status;

+}

+

+static

+int

+ParseCommandLine (

+  int         Argc,

+  char        *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+  Given the Argc/Argv program arguments, and a pointer to an options structure,

+  parse the command-line options and check their validity.

+

+

+Arguments:

+

+  Argc            - standard C main() argument count

+  Argv            - standard C main() argument list

+

+Returns:

+

+  STATUS_SUCCESS    success

+  non-zero          otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  //

+  // Clear out the options

+  //

+  memset ((char *) &mOptions, 0, sizeof (mOptions));

+  //

+  // Skip over the program name

+  //

+  Argc--;

+  Argv++;

+

+  if (Argc != 2) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  strcpy (mOptions.InFileName, Argv[0]);

+  //

+  // Next argument

+  //

+  Argv++;

+  Argc--;

+

+  strcpy (mOptions.OutFileName, Argv[0]);

+

+  return STATUS_SUCCESS;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+  

+  Print usage information for this utility.

+

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+

+--*/

+{

+  int               Index;

+  static const char *Msg[] = {

+    UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",

+    "  Generate an ACPI Table image from an EFI PE32 image",

+    "  Usage: "UTILITY_NAME " InFileName OutFileName",

+    "    where:",

+    "      InFileName     - name of the input PE32 file",

+    "      OutFileName    - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,

+    "",

+    NULL

+  };

+  for (Index = 0; Msg[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Msg[Index]);

+  }

+}

diff --git a/Source/GenAcpiTable/build.xml b/Source/GenAcpiTable/build.xml
new file mode 100644
index 0000000..a60871b
--- /dev/null
+++ b/Source/GenAcpiTable/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenAcpiTable Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenAcpiTable"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenBsfFixup/GenBsfFixup.c b/Source/GenBsfFixup/GenBsfFixup.c
new file mode 100644
index 0000000..462f97f
--- /dev/null
+++ b/Source/GenBsfFixup/GenBsfFixup.c
@@ -0,0 +1,490 @@
+/*++

+

+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved

+This software and associated documentation (if any) is furnished

+under a license and may only be used or copied in accordance

+with the terms of the license. Except as permitted by such

+license, no part of this software or documentation may be

+reproduced, stored in a retrieval system, or transmitted in any

+form or by any means without the express written consent of

+Intel Corporation.

+

+

+Module Name:

+

+  GenBsfFixup.c

+

+Abstract:

+

+  Utility to Fixup the SEC component for IA32.  This is an 

+  interim tool in place of the full GenBsfImage support for 

+  IA32.

+  This tool supports the Synch3 update

+

+--*/

+

+#include "BaseTypes.h"

+#include "UefiBaseTypes.h"

+#include "EfiImage.h"

+#include "FirmwareVolumeHeader.h"

+#include "FirmwareVolumeImageFormat.h"

+#include "ParseInf.h"

+#include "CommonLib.h"

+#include "FirmwareFileSystem.h"

+#include "FvLib.h"

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <assert.h>

+

+//

+// BugBug -- this port to the new FFS is really weird.

+//           A lot of the file-header stuff has been ported, but

+//           not the section information.

+//

+#define TOOLVERSION "0.1"

+

+UINT32  gFixup;

+

+UINT32

+GetOccupiedSize (

+  IN UINT32  ActualSize,

+  IN UINT32  Alignment

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  ActualSize  - GC_TODO: add argument description

+  Alignment   - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  UINT32  OccupiedSize;

+

+  OccupiedSize = ActualSize;

+  while ((OccupiedSize & (Alignment - 1)) != 0) {

+    OccupiedSize++;

+  }

+

+  return OccupiedSize;

+}

+

+int

+ReadHeader (

+  FILE    *In,

+  UINT32  *FvSize

+  )

+/*++

+

+Routine Description:

+

+  Reads in Firmware Volume information from the volume header file.

+

+Arguments:

+

+  In: Firmware Volume header file to read from

+  FvSize: Size of Firmware Volume

+

+Returns:

+

+  int: Number of bytes read

+

+--*/

+{

+  EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;

+  EFI_FV_BLOCK_MAP_ENTRY      BlockMap;

+  INT32                       SigTemp[2];

+  INT32                       Invert;

+  INT32                       bytesread;

+  UINT32                      size;

+

+  size      = 0;

+  Invert    = 0;

+  bytesread = 0;

+

+  if (In == NULL) {

+    printf ("Error: Input file is NULL.\n");

+    return -1;

+  }

+

+  fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);

+  bytesread   = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);

+  SigTemp[0]  = VolumeHeader.Signature;

+  SigTemp[1]  = 0;

+

+  if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {

+    Invert = 1;

+  }

+

+  do {

+    fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);

+    bytesread += sizeof (EFI_FV_BLOCK_MAP_ENTRY);

+

+    if (BlockMap.NumBlocks != 0) {

+      size += BlockMap.NumBlocks * BlockMap.BlockLength;

+    }

+

+  } while (BlockMap.NumBlocks != 0);

+

+  *FvSize = size;

+  rewind (In);

+

+  if (Invert == 1) {

+    bytesread *= -1;

+  }

+

+  return bytesread;

+}

+

+UINT32

+GetSectionLength (

+  IN  UINT32  *Length

+  )

+/*++

+

+Routine Description:

+

+  Converts a UINT8[3] array to a UINT32

+

+Arguments:

+

+  Length        A pointer to a 3 byte array

+

+Returns:

+

+  UINT32:       The length.

+

+--*/

+{

+  return *Length & 0x00FFFFFF;

+}

+

+int

+Readfile (

+  UINT8   *FvImage,

+  int     bytes,

+  int     Invert

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FvImage - GC_TODO: add argument description

+  bytes   - GC_TODO: add argument description

+  Invert  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  UINT32                    FileLength;

+  UINT32                    OccupiedFileLength;

+  EFI_FFS_FILE_HEADER       *FileHeader;

+  UINT8                     FileState;

+  UINT8                     Checksum;

+  UINT8                     *Ptr;

+  UINT32                    SectionLength;

+  EFI_COMMON_SECTION_HEADER *SectionHeader;

+  EFI_IMAGE_NT_HEADERS      *PeHeader;

+  UINT32                    PeiCoreOffset;

+

+  Ptr         = FvImage + bytes;

+

+  FileHeader  = (EFI_FFS_FILE_HEADER *) Ptr;

+

+  FileState   = GetFileState ((UINT8) Invert, FileHeader);

+

+  switch (FileState) {

+  case EFI_FILE_HEADER_CONSTRUCTION:

+  case EFI_FILE_HEADER_INVALID:

+    return sizeof (EFI_FFS_FILE_HEADER);

+

+  case EFI_FILE_HEADER_VALID:

+    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+    Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);

+    Checksum  = (UINT8) (Checksum - FileHeader->State);

+    if (Checksum != 0) {

+      return -1;

+    }

+    //

+    // Now do the fixup stuff - begin

+    //

+    if (FileHeader->Type == EFI_FV_FILETYPE_PEI_CORE) {

+      SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);

+      SectionLength = GetSectionLength ((UINT32 *) &SectionHeader->Size[0]);

+

+      printf ("Section length is 0x%X\n", SectionLength);

+

+      if (SectionHeader->Type == EFI_SECTION_PE32) {

+

+        gFixup    = bytes + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);

+

+        PeHeader  = (EFI_IMAGE_NT_HEADERS *) Ptr + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);

+

+        if (((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_magic == EFI_IMAGE_DOS_SIGNATURE) {

+          //

+          // DOS image header is present, so read the PE header after the DOS image header

+          //

+          PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) PeHeader + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_lfanew) & 0x0ffff));

+

+        }

+

+        PeiCoreOffset = (UINTN) ((UINTN) (PeHeader->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));

+

+        gFixup += PeiCoreOffset;

+      }

+    }

+

+    FileLength          = GetLength (FileHeader->Size);

+    OccupiedFileLength  = GetOccupiedSize (FileLength, 8);

+    return OccupiedFileLength;

+

+  case EFI_FILE_DATA_VALID:

+    //

+    // Calculate header checksum

+    //

+    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+    Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);

+    Checksum  = (UINT8) (Checksum - FileHeader->State);

+    if (Checksum != 0) {

+      return -1;

+    }

+    //

+    // Determine file length

+    //

+    FileLength          = GetLength (FileHeader->Size);

+    OccupiedFileLength  = GetOccupiedSize (FileLength, 8);

+

+    //

+    // Determine if file checksum is valid or fixed

+    //

+    if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {

+      Checksum  = CalculateSum8 (Ptr, FileLength);

+      Checksum  = (UINT8) (Checksum - FileHeader->State);

+      if (Checksum != 0) {

+        return -1;

+      }

+    } else {

+      if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {

+        return -1;

+      }

+    }

+    break;

+

+  case EFI_FILE_MARKED_FOR_UPDATE:

+  case EFI_FILE_DELETED:

+    //

+    // Calculate header checksum

+    //

+    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+    Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);

+    Checksum  = (UINT8) (Checksum - FileHeader->State);

+    if (Checksum != 0) {

+      return -1;

+    }

+    //

+    // Determine file length

+    //

+    FileLength          = GetLength (FileHeader->Size);

+    OccupiedFileLength  = GetOccupiedSize (FileLength, 8);

+

+    //

+    // Determine if file checksum is valid or fixed

+    //

+    if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {

+      Checksum  = CalculateSum8 (Ptr, FileLength);

+      Checksum  = (UINT8) (Checksum - FileHeader->State);

+      if (Checksum != 0) {

+        return -1;

+      }

+    } else {

+      if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {

+        return -1;

+      }

+    }

+

+    return OccupiedFileLength;

+

+  default:

+    return sizeof (EFI_FFS_FILE_HEADER);

+  }

+

+  return OccupiedFileLength;

+}

+

+int

+main (

+  int argc,

+  char*argv[]

+  )

+/*++

+

+Routine Description:

+

+  Runs GenBsfFixup

+

+Arguments:

+

+  argc: number of command line arguments

+

+  arg[0] = This file name

+  arg[1] = Firmware Volume Name

+  arg[2] = Base Address to relocate

+  arg[3] = Relative offset of the fixup to perform

+  arg[4] = Output File Name

+

+Returns:

+    

+  int: 0 code success, -1 code failure

+

+--*/

+{

+  FILE        *In;

+  FILE        *Out;

+  int         ByteStart;

+  int         Invert;

+  int         Index;

+  int         cnt;

+  UINT8       *FvImage;

+  int         ByteRead;

+  UINT32      FvSize;

+  UINT64      delta;

+  UINT32      Idx;

+  UINT64      FvOffset;

+  EFI_STATUS  Status;

+

+  Index   = 0;

+  Invert  = 0;

+  printf (

+    "GenBsfFixup EFI 2.0.  Version %s, %s\n""Copyright (c) 2000-2001, Intel Corporation\n\n",

+    TOOLVERSION,

+    __DATE__

+    );

+

+  if (argc != 5) {

+    printf ("Usage:\n""  GenBsfFixup FvVolumeImageFile AddressOfFvInMemory OffsetOfFixup OutputFileName\n");

+    return -1;

+  }

+

+  In = fopen (argv[1], "rb");

+

+  if (In == NULL) {

+    printf ("Unable to open FV image file \"%s\"\n", argv[1]);

+    return -1;

+  }

+

+  ByteStart = ReadHeader (In, &FvSize);

+

+  if (ByteStart < 0) {

+    Invert = 1;

+    ByteStart *= -1;

+  }

+

+  FvImage = malloc (FvSize);

+  if (FvImage == NULL) {

+    printf ("Cannot allocate memory\n");

+    fclose (In);

+    return -1;

+  }

+

+  ByteRead = fread (FvImage, 1, FvSize, In);

+

+  if ((unsigned int) ByteRead != FvSize) {

+    printf ("Read File error\n");

+    fclose (In);

+    return -1;

+  }

+

+  cnt = 0;

+  while ((unsigned int) ByteStart < FvSize && cnt != -1) {

+    cnt = Readfile (FvImage, ByteStart, Invert);

+

+    if (cnt != -1) {

+      ByteStart += cnt;

+    }

+

+    if (cnt != sizeof (EFI_FFS_FILE_HEADER)) {

+      Index++;

+    }

+  }

+

+  if (cnt == -1) {

+    printf ("Firmware Volume image corrupted\n");

+    return -1;

+  }

+

+  fclose (In);

+

+  Out = fopen (argv[4], "wb");

+

+  if (Out == NULL) {

+    printf ("Unable to open FV image file \"%s\"\n", argv[4]);

+    return -1;

+  }

+

+  In = fopen (argv[1], "rb");

+

+  if (In == NULL) {

+    printf ("Unable to open FV image file \"%s\"\n", argv[1]);

+    return -1;

+  }

+

+  if (gFixup != 0) {

+

+    printf ("Fixup of 0x%X\n", gFixup);

+

+    Status = AsciiStringToUint64 (argv[2], TRUE, &FvOffset);

+

+    gFixup += (UINT32) FvOffset;

+

+    ByteStart = ReadHeader (In, &FvSize);

+

+    Readfile (FvImage, ByteStart, Invert);

+

+    cnt     = 0;

+    Status  = AsciiStringToUint64 (argv[3], TRUE, &delta);

+

+    fclose (In);

+    In = fopen (argv[1], "rb");

+

+    if (In == NULL) {

+      printf ("Unable to open FV image file \"%s\"\n", argv[1]);

+      return -1;

+    }

+

+    for (Idx = 0; Idx < delta - FvOffset; Idx++) {

+      fputc (fgetc (In), Out);

+    }

+

+    fwrite (&gFixup, sizeof (UINT32), 1, Out);

+    fseek (In, sizeof (UINT32), SEEK_CUR);

+

+    for (Idx = 0; Idx < FvSize - (delta - FvOffset) - sizeof (UINT32); Idx++) {

+      fputc (fgetc (In), Out);

+    }

+

+    fclose (In);

+    fclose (Out);

+  } else {

+    printf ("There was no fixup to perform\n");

+  }

+

+  free (FvImage);

+

+  return 0;

+}

diff --git a/Source/GenBsfFixup/build.xml b/Source/GenBsfFixup/build.xml
new file mode 100644
index 0000000..1f35cf2
--- /dev/null
+++ b/Source/GenBsfFixup/build.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenFvImage Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenBsfFixup"/>

+  <property name="FileSet" value="GenBsfFixup.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+    <if>

+      <istrue value="${OSX}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value=""/>

+      </then>

+    </if>

+

+    <if>

+      <istrue value="${cygwin}"/>

+      <then>

+        <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${msft}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${linux}"/>

+      <then>

+        <if>

+          <istrue value="${x86_64_linux}"/>

+          <then>

+            <property name="syslibdirs" value="/lib64"/>

+          </then>

+          <else>

+            <property name="syslibdirs" value="/usr/lib"/>

+          </else>

+        </if>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    <echo message="syslibdirs set to: ${syslibdirs}"/>

+  </target>

+

+  <target name="Tool" depends="init, GenBsfFixup"/>

+

+  <target name="GenBsfFixup" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_IA32_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/${ToolName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Common"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+

+      <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>

+      <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>

+      <syslibset libs="RpcRT4" if="msft"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenBsfImage/GenBsfImage.c b/Source/GenBsfImage/GenBsfImage.c
new file mode 100644
index 0000000..59d20d0
--- /dev/null
+++ b/Source/GenBsfImage/GenBsfImage.c
@@ -0,0 +1,3519 @@
+/*++

+

+Copyright (c)  1999 - 2006, Intel Corporation. All rights reserved

+This software and associated documentation (if any) is furnished

+under a license and may only be used or copied in accordance

+with the terms of the license. Except as permitted by such

+license, no part of this software or documentation may be

+reproduced, stored in a retrieval system, or transmitted in any

+form or by any means without the express written consent of

+Intel Corporation.

+

+

+Module Name:

+

+  GenBsfImage.c

+

+Abstract:

+

+  This file contains functions required to generate a boot strap file (BSF) 

+  also known as the Volume Top File (VTF)

+

+--*/

+

+//

+// Module Coded to EFI 2.0 Coding Conventions

+//

+#include <FvLib.h>

+#include <Common/UefiBaseTypes.h>

+#include "GenBsfImage.h"

+#include <Guid/FirmwareFileSystem.h>

+#include "CommonLib.h"

+

+//

+// Global variables

+//

+EFI_GUID      Bsf1NameGuid = EFI_IPF_VTF1_GUID

+EFI_GUID      Bsf2NameGuid = EFI_IPF_VTF2_GUID

+

+CHAR8           **TokenStr;

+CHAR8           **OrgStrTokPtr;

+

+PARSED_BSF_INFO *FileListPtr;

+PARSED_BSF_INFO *FileListHeadPtr;

+

+VOID            *Bsf1Buffer;

+VOID            *Bsf1EndBuffer;

+VOID            *Bsf2Buffer;

+VOID            *Bsf2EndBuffer;

+

+UINTN           ValidLineNum        = 0;

+UINTN           ValidFFDFileListNum = 0;

+

+//

+// Section Description and their number of occurences in *.INF file

+//

+UINTN           NumFvFiles        = 0;

+UINTN           SectionOptionNum  = 0;

+

+//

+// Global flag which will check for BSF Present, if yes then will be used

+// to decide about adding FFS header to pad data

+//

+BOOLEAN         BSFPresent = FALSE;

+

+//

+// Address related information

+//

+UINT64          Fv1BaseAddress        = 0;

+UINT64          Fv2BaseAddress        = 0;

+UINT64          Fv1EndAddress         = 0;

+UINT64          Fv2EndAddress         = 0;

+UINT32          Bsf1TotalSize         = SIZE_TO_OFFSET_PAL_A_END;

+UINT64          Bsf1LastStartAddress  = 0;

+UINT32          Bsf2TotalSize         = 0;

+UINT64          Bsf2LastStartAddress  = 0;

+

+UINT32          BufferToTop           = 0;

+

+//

+// IA32 Reset Vector Bin name

+//

+CHAR8           IA32BinFile[FILE_NAME_SIZE];

+

+//

+// Function Implementations

+//

+VOID

+BuildTokenList (

+  IN  CHAR8 *Token

+  )

+/*++

+Routine Description:

+

+  This function builds the token list in an array which will be parsed later

+

+Arguments:

+

+  Token    - The pointer of string

+

+Returns:

+

+  None

+

+--*/

+{

+  strcpy (*TokenStr, Token);

+  TokenStr++;

+}

+

+EFI_STATUS

+ConvertVersionInfo (

+  IN      CHAR8     *Str,

+  IN OUT  UINT8     *MajorVer,

+  IN OUT  UINT8     *MinorVer

+  )

+/*++

+Routine Description:

+

+  This function converts GUID string to GUID

+

+Arguments:

+

+  Str      - String representing in form XX.XX

+  MajorVer - The major vertion

+  MinorVer - The minor vertion

+

+Returns:

+

+  EFI_SUCCESS  - The fuction completed successfully.

+

+--*/

+{

+  CHAR8 StrPtr[40];

+  CHAR8 *Token;

+  UINTN Length;

+  UINTN Major;

+  UINTN Minor;

+

+  Major = 0;

+  Minor = 0;

+  memset (StrPtr, 0, 40);

+  Token = strtok (Str, ".");

+

+  while (Token != NULL) {

+    strcat (StrPtr, Token);

+    Token = strtok (NULL, ".");

+  }

+

+  Length = strlen (StrPtr);

+  sscanf (

+    StrPtr,

+    "%01x%02x",

+    &Major,

+    &Minor

+    );

+

+  *MajorVer = (UINT8) Major;

+  *MinorVer = (UINT8) Minor;

+  return EFI_SUCCESS;

+}

+

+VOID

+TrimLine (

+  IN  CHAR8 *Line

+  )

+/*++

+Routine Description:

+

+  This function cleans up the line by removing all whitespace and 

+  comments

+

+Arguments:

+

+  Line   - The pointer of the string

+

+Returns:

+

+  None

+

+--*/

+{

+  CHAR8 TmpLine[FILE_NAME_SIZE];

+  CHAR8 Char;

+  CHAR8 *Ptr0;

+  UINTN Index;

+  UINTN Index2;

+

+  //

+  // Change '#' to '//' for Comment style

+  //

+  if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {

+    Line[Ptr0 - Line] = 0;

+  }

+

+  //

+  // Initialize counters

+  //

+  Index   = 0;

+  Index2  = 0;

+

+  while ((Char = Line[Index]) != 0) {

+    if ((Char != ' ') && (Char != '\t') && (Char != '\n')) {

+      TmpLine[Index2++] = Char;

+    }

+    Index++;

+  }

+

+  TmpLine[Index2] = 0;

+  strcpy (Line, TmpLine);

+}

+

+VOID

+ValidLineCount (

+  IN  FILE *Fp

+  )

+/*++

+

+Routine Description:

+

+  This function calculated number of valid lines in a input file.

+  

+Arguments:

+

+  Fp    - Pointer to a file handle which has been opened.

+

+Returns:

+

+  None

+

+--*/

+{

+  CHAR8 Buff[FILE_NAME_SIZE];

+

+  while (fgets (Buff, sizeof (Buff), Fp)) {

+    TrimLine (Buff);

+    if (Buff[0] == 0) {

+      continue;

+    }

+

+    ValidLineNum++;

+  }

+}

+

+VOID

+ParseInputFile (

+  IN  FILE *Fp

+  )

+/*++

+  

+Routine Description:

+

+  This function parses the input file and tokenize the string

+  

+Arguments:

+

+  Fp    - Pointer to a file handle which has been opened.

+  

+Returns:

+

+  None

+

+--*/

+{

+  CHAR8 *Token;

+  CHAR8 Buff[FILE_NAME_SIZE];

+  CHAR8 OrgLine[FILE_NAME_SIZE];

+  CHAR8 Str[FILE_NAME_SIZE];

+  CHAR8 Delimit[] = "=";

+

+  while (fgets (Buff, sizeof (Buff), Fp) != NULL) {

+    strcpy (OrgLine, Buff);

+    TrimLine (Buff);

+    if (Buff[0] == 0) {

+      continue;

+    }

+

+    Token = strtok (Buff, Delimit);

+

+    while (Token != NULL) {

+      strcpy (Str, Token);

+      BuildTokenList (Str);

+      Token = strtok (NULL, Delimit);

+    }

+  }

+}

+

+EFI_STATUS

+InitializeComps (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from INF file.  This also initializes

+  the BSF symbol file.

+  

+Arguments:

+

+  None

+

+Returns:

+

+  EFI_SUCCESS            - The function completed successfully

+  EFI_OUT_OF_RESOURCES   - Malloc failed.

+

+--*/

+{

+

+  FileListPtr = malloc (sizeof (PARSED_BSF_INFO));

+

+  if (FileListPtr == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  FileListHeadPtr = FileListPtr;

+  memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));

+  FileListPtr->NextBsfInfo = NULL;

+

+  remove (BSF_SYM_FILE);

+  return EFI_SUCCESS;

+}

+

+VOID

+ParseAndUpdateComponents (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from INF file.

+  

+Arguments:

+

+  BsfInfo  - A pointer to the BSF Info Structure

+  

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT64  StringValue;

+

+  while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {

+

+    if (_stricmp (*TokenStr, "COMP_LOC") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "F") == 0) {

+        BsfInfo->LocationType = FIRST_VTF;

+      } else if (_stricmp (*TokenStr, "S") == 0) {

+        BsfInfo->LocationType = SECOND_VTF;

+      } else {

+        BsfInfo->LocationType = NONE;

+        printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);

+      }

+    } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {

+      TokenStr++;

+      if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {

+        printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);

+        return ;

+      }

+

+      BsfInfo->CompType = (UINT8) StringValue;

+    } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "-") == 0) {

+        BsfInfo->VersionPresent = FALSE;

+        BsfInfo->MajorVer       = 0;

+        BsfInfo->MinorVer       = 0;

+      } else {

+        BsfInfo->VersionPresent = TRUE;

+        ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);

+      }

+    } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {

+      TokenStr++;

+      strcpy (BsfInfo->CompBinName, *TokenStr);

+    } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {

+      TokenStr++;

+      strcpy (BsfInfo->CompSymName, *TokenStr);

+    } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "-") == 0) {

+        BsfInfo->PreferredSize  = FALSE;

+        BsfInfo->CompSize       = 0;

+      } else {

+        BsfInfo->PreferredSize = TRUE;

+        if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {

+          printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);

+          return ;

+        }

+

+        BsfInfo->CompSize = (UINTN) StringValue;

+      }

+

+    } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "1") == 0) {

+        BsfInfo->CheckSumRequired = 1;

+      } else if (_stricmp (*TokenStr, "0") == 0) {

+        BsfInfo->CheckSumRequired = 0;

+      } else {

+        printf ("\nERROR: Bad information in INF file about Checksum required field");

+      }

+    }

+

+    TokenStr++;

+    if (*TokenStr == NULL) {

+      break;

+    }

+  }

+}

+

+VOID

+InitializeInFileInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from INF file.

+

+Arguments:

+

+  NONE

+

+Returns:

+

+  NONE

+

+--*/

+{

+  UINTN SectionOptionFlag;

+  UINTN SectionCompFlag;

+

+  SectionOptionFlag = 0;

+  SectionCompFlag   = 0;

+  TokenStr          = OrgStrTokPtr;

+  while (*TokenStr != NULL) {

+    if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {

+      SectionOptionFlag = 1;

+      SectionCompFlag   = 0;

+    }

+

+    if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {

+      if (FileListPtr == NULL) {

+        FileListPtr = FileListHeadPtr;

+      }

+

+      SectionCompFlag   = 1;

+      SectionOptionFlag = 0;

+      TokenStr++;

+    }

+

+    if (SectionOptionFlag) {

+      if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {

+        *TokenStr++;

+        strcpy (IA32BinFile, *TokenStr);

+      }

+    }

+

+    if (SectionCompFlag) {

+      if (_stricmp (*TokenStr, "COMP_NAME") == 0) {

+        TokenStr++;

+        strcpy (FileListPtr->CompName, *TokenStr);

+        TokenStr++;

+        ParseAndUpdateComponents (FileListPtr);

+      }

+

+      if (*TokenStr != NULL) {

+        FileListPtr->NextBsfInfo  = malloc (sizeof (PARSED_BSF_INFO));

+        if (FileListPtr->NextBsfInfo == NULL) {

+          printf ("Error: Out of memory resources.\n");

+          break;

+        }

+        FileListPtr = FileListPtr->NextBsfInfo;

+        memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));

+        FileListPtr->NextBsfInfo = NULL;

+        continue;

+      } else {

+        break;

+      }

+    }

+

+    TokenStr++;

+  }

+}

+

+EFI_STATUS

+GetBsfRelatedInfoFromInfFile (

+  IN  CHAR8 *FileName

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the input file, parse it and create a list of tokens

+  which is parsed and used, to intialize the data related to BSF

+  

+Arguments:

+

+  FileName  - FileName which needed to be read to parse data

+

+Returns:

+   

+  EFI_ABORTED           - Error in opening file

+  EFI_INVALID_PARAMETER - File doesn't contain any valid informations

+  EFI_OUT_OF_RESOURCES  - Malloc Failed

+  EFI_SUCCESS           - The function completed successfully 

+

+--*/

+{

+  FILE        *Fp;

+  UINTN       Index;

+  EFI_STATUS  Status;

+

+  Fp = fopen (FileName, "r");

+  if (Fp == NULL) {

+    printf ("\nERROR: Error in opening %s file\n", FileName);

+    return EFI_ABORTED;

+  }

+

+  ValidLineCount (Fp);

+

+  if (ValidLineNum == 0) {

+    printf ("\nERROR: File doesn't contain any valid informations");

+    return EFI_INVALID_PARAMETER;

+  }

+

+  TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));

+

+  if (TokenStr == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));

+  OrgStrTokPtr = TokenStr;

+

+  for (Index = 0; Index < (2 * ValidLineNum); Index++) {

+    *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);

+

+    if (*TokenStr == NULL) {

+      free (OrgStrTokPtr);

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    memset (*TokenStr, 0, FILE_NAME_SIZE);

+//    free (*TokenStr);

+    TokenStr++;

+  }

+

+  TokenStr  = NULL;

+  TokenStr  = OrgStrTokPtr;

+  fseek (Fp, 0L, SEEK_SET);

+

+  Status = InitializeComps ();

+

+  if (Status != EFI_SUCCESS) {

+    free (OrgStrTokPtr);

+    return Status;

+  }

+

+  ParseInputFile (Fp);

+  InitializeInFileInfo ();

+

+  if (Fp) {

+    fclose (Fp);

+  }

+  free (OrgStrTokPtr);

+  return EFI_SUCCESS;

+}

+

+VOID

+GetRelativeAddressInBsfBuffer (

+  IN      UINT64     Address,

+  IN OUT  UINTN      *RelativeAddress,

+  IN      LOC_TYPE   LocType

+  )

+/*++

+  

+Routine Description:

+

+  This function checks for the address alignmnet for specified data boundary. In

+  case the address is not aligned, it returns FALSE and the amount of data in 

+  terms of byte needed to adjust to get the boundary alignmnet. If data is 

+  aligned, TRUE will be returned.

+  

+Arguments:

+

+  Address             - The address of the flash map space

+  RelativeAddress     - The relative address of the Buffer

+  LocType             - The type of the BSF

+

+

+Returns:

+

+    

+--*/

+{

+  UINT64  TempAddress;

+  UINT8   *LocalBuff;

+

+  if (LocType == FIRST_VTF) {

+    LocalBuff         = (UINT8 *) Bsf1EndBuffer;

+    TempAddress       = Fv1EndAddress - Address;

+    *RelativeAddress  = (UINTN) LocalBuff - (UINTN) TempAddress;

+  } else {

+    LocalBuff         = (UINT8 *) Bsf2EndBuffer;

+    TempAddress       = Fv2EndAddress - Address;

+    *RelativeAddress  = (UINTN) LocalBuff - (UINTN) TempAddress;

+  }

+}

+

+EFI_STATUS

+GetComponentVersionInfo (

+  IN  OUT PARSED_BSF_INFO   *BsfInfo,

+  IN      UINT8             *Buffer

+  )

+/*++

+Routine Description:

+

+  This function will extract the version information from File

+  

+Arguments:

+

+  BsfInfo  - A Pointer to the BSF Info Structure

+  Buffer   - A Pointer to type UINT8 

+

+Returns:

+ 

+   EFI_SUCCESS           - The function completed successfully

+   EFI_INVALID_PARAMETER - The parameter is invalid

+    

+--*/

+{

+  UINT16      VersionInfo;

+  EFI_STATUS  Status;

+

+  switch (BsfInfo->CompType) {

+

+  case COMP_TYPE_FIT_PAL_A:

+  case COMP_TYPE_FIT_PAL_B:

+    memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));

+    BsfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);

+    BsfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);

+    Status            = EFI_SUCCESS;

+    break;

+

+  default:

+    Status = EFI_INVALID_PARAMETER;

+    break;

+  }

+

+  return Status;

+}

+

+BOOLEAN

+CheckAddressAlignment (

+  IN      UINT64  Address,

+  IN      UINT64  AlignmentData,

+  IN OUT  UINT64  *AlignAdjustByte

+  )

+/*++

+  

+Routine Description:

+

+  This function checks for the address alignmnet for specified data boundary. In

+  case the address is not aligned, it returns FALSE and the amount of data in 

+  terms of byte needed to adjust to get the boundary alignmnet. If data is 

+  aligned, TRUE will be returned.

+  

+Arguments:

+

+  Address              - Pointer to buffer containing byte data of component.

+  AlignmentData        - DataSize for which address needed to be aligned

+  AlignAdjustByte      - Number of bytes needed to adjust alignment.

+

+Returns:

+

+  TRUE                 - Address is aligned to specific data size boundary

+  FALSE                - Address in not aligned to specified data size boundary

+                       - Add/Subtract AlignAdjustByte to aling the address.

+    

+--*/

+{

+  //

+  // Check if the assigned address is on address boundary. If not, it will

+  // return the remaining byte required to adjust the address for specified

+  // address boundary

+  //

+  *AlignAdjustByte = (Address % AlignmentData);

+

+  if (*AlignAdjustByte == 0) {

+    return TRUE;

+  } else {

+    return FALSE;

+  }

+}

+

+EFI_STATUS

+GetFitTableStartAddress (

+  IN OUT  FIT_TABLE   **FitTable

+  )

+/*++

+  

+Routine Description:

+

+  Get the FIT table start address in BSF Buffer

+  

+Arguments:

+

+  FitTable    - Pointer to available fit table where new component can be added

+  

+Returns:

+

+  EFI_SUCCESS - The function completed successfully

+    

+--*/

+{

+  UINT64  FitTableAdd;

+  UINT64  FitTableAddOffset;

+  UINTN   RelativeAddress;

+

+  //

+  // Read the Fit Table address from Itanium-based address map.

+  //

+  FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);

+

+  //

+  // Translate this Itanium-based address in terms of local buffer address which

+  // contains the image for Boot Strapped File. The relative address will be

+  // the address of fit table BSF buffer.

+  //

+  GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);

+  FitTableAdd = *(UINTN *) RelativeAddress;

+

+  //

+  // The FitTableAdd is the extracted Itanium based address pointing to FIT

+  // table. The relative address will return its actual location in BSF

+  // Buffer.

+  //

+  GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);

+

+  *FitTable = (FIT_TABLE *) RelativeAddress;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetNextAvailableFitPtr (

+  IN  FIT_TABLE   **FitPtr

+  )

+/*++

+  

+Routine Description:

+

+  Get the FIT table address and locate the free space in fit where we can add

+  new component. In this process, this function locates the fit table using

+  Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec) 

+  and locate the available location in FIT table to be used by new components. 

+  If there are any Fit table which areg not being used contains ComponentType 

+  field as 0x7F. If needed we can change this and spec this out.

+  

+Arguments:

+

+  FitPtr    - Pointer to available fit table where new component can be added

+  

+Returns:

+

+  EFI_SUCCESS  - The function completed successfully

+    

+--*/

+{

+  FIT_TABLE *TmpFitPtr;

+  UINT64    FitTableAdd;

+  UINT64    FitTableAddOffset;

+  UINTN     Index;

+  UINTN     NumFitComponents;

+  UINTN     RelativeAddress;

+

+  //

+  // Read the Fit Table address from Itanium-based address map.

+  //

+  FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);

+

+  //

+  // Translate this Itanium-based address in terms of local buffer address which

+  // contains the image for Boot Strapped File. The relative address will be

+  // the address of fit table BSF buffer.

+  //

+  GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);

+  FitTableAdd = *(UINTN *) RelativeAddress;

+

+  //

+  // The FitTableAdd is the extracted Itanium based address pointing to FIT

+  // table. The relative address will return its actual location in BSF

+  // Buffer.

+  //

+  GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);

+

+  TmpFitPtr         = (FIT_TABLE *) RelativeAddress;

+  NumFitComponents  = TmpFitPtr->CompSize;

+

+  for (Index = 0; Index < NumFitComponents; Index++) {

+    if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {

+      *FitPtr = TmpFitPtr;

+      break;

+    }

+

+    TmpFitPtr++;

+  }

+

+  return EFI_SUCCESS;

+}

+

+INTN

+CompareItems (

+  IN const VOID  *Arg1,

+  IN const VOID  *Arg2

+  )

+/*++

+

+Routine Description:

+

+    This function is used by qsort to sort the FIT table based upon Component

+    Type in their incresing order.

+

+Arguments:

+    

+    Arg1  -   Pointer to Arg1

+    Arg2  -   Pointer to Arg2

+    

+Returns:

+

+    None

+

+--*/

+{

+  if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {

+    return 1;

+  } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {

+    return -1;

+  } else {

+    return 0;

+  }

+}

+

+VOID

+SortFitTable (

+  IN  VOID

+  )

+/*++

+

+Routine Description:

+

+    This function is used by qsort to sort the FIT table based upon Component

+    Type in their incresing order.

+

+Arguments:

+    

+    VOID

+

+Returns:

+

+    None

+

+--*/

+{

+  FIT_TABLE *FitTable;

+  FIT_TABLE *TmpFitPtr;

+  UINTN     NumFitComponents;

+  UINTN     Index;

+

+  GetFitTableStartAddress (&FitTable);

+  TmpFitPtr         = FitTable;

+  NumFitComponents  = 0;

+  for (Index = 0; Index < FitTable->CompSize; Index++) {

+    if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {

+      NumFitComponents += 1;

+    }

+

+    TmpFitPtr++;

+  }

+

+  qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);

+}

+

+VOID

+UpdateFitEntryForFwVolume (

+  IN  UINT64  Size

+  )

+/*++

+  

+Routine Description:

+

+  This function updates the information about Firmware Volume  in FIT TABLE.

+  This FIT table has to be immediately below the PAL_A Start and it contains

+  component type and address information. Other informations can't be

+  created this time so we would need to fix it up..

+  

+  

+Arguments:

+

+  Size   - Firmware Volume Size

+  

+Returns:

+

+  VOID

+

+--*/

+{

+  FIT_TABLE *CompFitPtr;

+  UINTN     RelativeAddress;

+

+  //

+  // FV Fit table will be located at PAL_A Startaddress - 16 byte location

+  //

+  Bsf1LastStartAddress -= 0x10;

+  Bsf1TotalSize += 0x10;

+

+  GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);

+

+  CompFitPtr              = (FIT_TABLE *) RelativeAddress;

+  CompFitPtr->CompAddress = Fv1BaseAddress;

+

+  //

+  // Since we don't have any information about its location in Firmware Volume,

+  // initialize address to 0. This will be updated once Firmware Volume is

+  // being build and its current address will be fixed in FIT table. Currently

+  // we haven't implemented it so far and working on architectural clarafication

+  //

+  //

+  // Firmware Volume Size in 16 byte block

+  //

+  CompFitPtr->CompSize = ((UINT32) Size) / 16;

+

+  //

+  // Since Firmware Volume does not exist by the time we create this FIT info

+  // this should be fixedup from Firmware Volume creation tool. We haven't

+  // worked out a method so far.

+  //

+  CompFitPtr->CompVersion = MAKE_VERSION (0, 0);

+

+  //

+  // Since we don't have any info about this file, we are making sure that

+  // checksum is not needed.

+  //

+  CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);

+

+  //

+  // Since non BSF component will reside outside the BSF, we will not have its

+  // binary image while creating BSF, hence we will not perform checksum at

+  // this time. Once Firmware Volume is being created which will contain this

+  // BSF, it will fix the FIT table for all the non BSF component and hence

+  // checksum

+  //

+  CompFitPtr->CheckSum = 0;

+}

+

+EFI_STATUS

+UpdateFitEntryForNonBSFComp (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function updates the information about non BSF component in FIT TABLE.

+  Since non BSF componets binaries are not part of BSF binary, we would still

+  be required to update its location information in Firmware Volume, inside

+  FIT table.

+  

+Arguments:

+

+  BsfInfo    - Pointer to BSF Info Structure

+  

+Returns:

+

+  EFI_ABORTED  - The function fails to update the component in FIT  

+  EFI_SUCCESS  - The function completed successfully

+

+--*/

+{

+  FIT_TABLE *CompFitPtr;

+

+  //

+  // Scan the FIT table for available space

+  //

+  GetNextAvailableFitPtr (&CompFitPtr);

+  if (CompFitPtr == NULL) {

+    printf ("\nERROR: Can't update this component in FIT");

+    return EFI_ABORTED;

+  }

+

+  //

+  // Since we don't have any information about its location in Firmware Volume,

+  // initialize address to 0. This will be updated once Firmware Volume is

+  // being build and its current address will be fixed in FIT table

+  //

+  CompFitPtr->CompAddress = 0;

+  CompFitPtr->CompSize    = BsfInfo->CompSize;

+  CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);

+  CompFitPtr->CvAndType   = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);

+

+  //

+  // Since non BSF component will reside outside the BSF, we will not have its

+  // binary image while creating BSF, hence we will not perform checksum at

+  // this time. Once Firmware Volume is being created which will contain this

+  // BSF, it will fix the FIT table for all the non BSF component and hence

+  // checksum

+  //

+  CompFitPtr->CheckSum = 0;

+

+  //

+  // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base

+  // address of Firmware Volume in which this BSF will be attached.

+  //

+  if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {

+    CompFitPtr->CompAddress = Fv1BaseAddress;

+  }

+

+  return EFI_SUCCESS;

+}

+

+//

+// !!!WARNING

+// This function is updating the SALE_ENTRY in Itanium address space as per SAL

+// spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI

+// CORE moves in Firmware Volume, we would need to modify this function to be

+// used with a API which will detect PEICORE component while building Firmware

+// Volume and update its entry in FIT table as well as in Itanium address space

+// as per Intel?Itanium(TM) SAL address space

+//

+EFI_STATUS

+UpdateEntryPoint (

+  IN  PARSED_BSF_INFO   *BsfInfo,

+  IN  UINT64            *CompStartAddress

+  )

+/*++

+  

+Routine Description:

+

+  This function updated the architectural entry point in IPF, SALE_ENTRY.

+  

+Arguments:

+

+  BsfInfo            - Pointer to BSF Info Structure 

+  CompStartAddress   - Pointer to Component Start Address

+  

+Returns:

+

+  EFI_INVALID_PARAMETER  - The parameter is invalid

+  EFI_SUCCESS            - The function completed successfully

+

+--*/

+{

+  UINTN   RelativeAddress;

+  UINT64  SalEntryAdd;

+  FILE    *Fp;

+  UINTN   Offset;

+

+  CHAR8   Buff[FILE_NAME_SIZE];

+  CHAR8   Buff1[10];

+  CHAR8   Buff2[10];

+  CHAR8   OffsetStr[30];

+  CHAR8   Buff3[10];

+  CHAR8   Buff4[10];

+  CHAR8   Buff5[10];

+  CHAR8   Token[50];

+

+  Fp = fopen (BsfInfo->CompSymName, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Error in opening file");

+    return EFI_INVALID_PARAMETER;

+  }

+

+  while (fgets (Buff, sizeof (Buff), Fp) != NULL) {

+    fscanf (

+      Fp,

+      "%s %s %s %s %s %s %s",

+      &Buff1,

+      &Buff2,

+      &OffsetStr,

+      &Buff3,

+      &Buff4,

+      &Buff5,

+      &Token

+      );

+    if (_stricmp (Token, "SALE_ENTRY") == 0) {

+      break;

+    }

+  }

+

+  Offset = strtoul (OffsetStr, NULL, 16);

+

+  *CompStartAddress += Offset;

+  SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);

+

+  GetRelativeAddressInBsfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);

+

+  memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+CreateAndUpdateComponent (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for each components and update them

+  in BSF Buffer as well as in FIT table. If the component is located in non

+  BSF area, only the FIT table address will be updated

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_SUCCESS      - The function completed successful

+  EFI_ABORTED      - Aborted due to one of the many reasons like:

+                      (a) Component Size greater than the specified size.

+                      (b) Error opening files.

+            

+  EFI_INVALID_PARAMETER     Value returned from call to UpdateEntryPoint()

+  EFI_OUT_OF_RESOURCES      Memory allocation failure.

+  

+--*/

+{

+  EFI_STATUS  Status;

+  UINT64      CompStartAddress;

+  UINT64      FileSize;

+  UINT64      NumByteRead;

+  UINT64      NumAdjustByte;

+  UINT8       *Buffer;

+  FILE        *Fp;

+  FIT_TABLE   *CompFitPtr;

+  BOOLEAN     Aligncheck;

+

+  if (BsfInfo->LocationType == NONE) {

+    UpdateFitEntryForNonBSFComp (BsfInfo);

+    return EFI_SUCCESS;

+  }

+

+  Fp = fopen (BsfInfo->CompBinName, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);

+    return EFI_ABORTED;

+  }

+

+  FileSize = _filelength (_fileno (Fp));

+

+  if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {

+

+    //

+    // BUGBUG: Satish to correct

+    //

+    FileSize -= SIZE_OF_PAL_HEADER;

+  }

+

+  if (BsfInfo->PreferredSize) {

+    if (FileSize > BsfInfo->CompSize) {

+      printf ("\nERROR: The component size is more than specified size");

+      return EFI_ABORTED;

+    }

+

+    FileSize = BsfInfo->CompSize;

+  }

+

+  Buffer = malloc ((UINTN) FileSize);

+  if (Buffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (Buffer, 0, (UINTN) FileSize);

+

+  if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {

+

+    //

+    // Read first 64 bytes of PAL header and use it to find version info

+    //

+    NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);

+

+    //

+    // PAL header contains the version info. Currently, we will use the header

+    // to read version info and then discard.

+    //

+    if (!BsfInfo->VersionPresent) {

+      GetComponentVersionInfo (BsfInfo, Buffer);

+    }

+  }

+

+  NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);

+  fclose (Fp);

+

+  //

+  // If it is non PAL_B component, pass the entire buffer to get the version

+  // info and implement any specific case inside GetComponentVersionInfo.

+  //

+  if (BsfInfo->CompType != COMP_TYPE_FIT_PAL_B) {

+    if (!BsfInfo->VersionPresent) {

+      GetComponentVersionInfo (BsfInfo, Buffer);

+    }

+  }

+

+  if (BsfInfo->LocationType == SECOND_VTF) {

+

+    CompStartAddress = (Bsf2LastStartAddress - FileSize);

+  } else {

+    CompStartAddress = (Bsf1LastStartAddress - FileSize);

+  }

+

+  if (BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) {

+    Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);

+  } else {

+    Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);

+  }

+

+  if (!Aligncheck) {

+    CompStartAddress -= NumAdjustByte;

+  }

+

+  if (BsfInfo->LocationType == SECOND_VTF) {

+    Bsf2LastStartAddress = CompStartAddress;

+    Bsf2TotalSize += (UINT32) (FileSize + NumAdjustByte);

+    Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);

+  } else {

+    Bsf1LastStartAddress = CompStartAddress;

+    Bsf1TotalSize += (UINT32) (FileSize + NumAdjustByte);

+    Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);

+  }

+

+  if (EFI_ERROR (Status)) {

+    return EFI_ABORTED;

+  }

+

+  GetNextAvailableFitPtr (&CompFitPtr);

+

+  CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;

+  assert ((FileSize % 16) == 0);

+  CompFitPtr->CompSize    = (UINT32) (FileSize / 16);

+  CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);

+  CompFitPtr->CvAndType   = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);

+  if (BsfInfo->CheckSumRequired) {

+    CompFitPtr->CheckSum  = 0;

+    CompFitPtr->CheckSum  = CalculateChecksum8 (Buffer, (UINTN) FileSize);

+  }

+

+  //

+  // Free the buffer

+  //

+  if (Buffer) {

+    free (Buffer);

+  }

+

+  //

+  // Update the SYM file for this component based on it's start address.

+  //

+  Status = UpdateSymFile (CompStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);

+  if (EFI_ERROR (Status)) {

+

+    //

+    // At this time, SYM files are not required, so continue on error.

+    //

+  }

+

+  // !!!!!!!!!!!!!!!!!!!!!

+  // BUGBUG:

+  // This part of the code is a temporary line since PEICORE is going to be inside

+  // BSF till we work out how to determine the SALE_ENTRY through it. We will need

+  // to clarify so many related questions

+  // !!!!!!!!!!!!!!!!!!!!!!!

+  if (BsfInfo->CompType == COMP_TYPE_FIT_PEICORE) {

+    Status = UpdateEntryPoint (BsfInfo, &CompStartAddress);

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+CreateAndUpdatePAL_A (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for each components and update them

+  in BSF Buffer as well as FIT table

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_ABORTED           - Due to one of the following reasons:

+                           (a)Error Opening File

+                           (b)The PAL_A Size is more than specified size status

+                              One of the values mentioned below returned from 

+                              call to UpdateSymFile

+  EFI_SUCCESS           - The function completed successfully.

+  EFI_INVALID_PARAMETER - One of the input parameters was invalid.

+  EFI_ABORTED           - An error occurred.UpdateSymFile

+  EFI_OUT_OF_RESOURCES  - Memory allocation failed.

+   

+--*/

+{

+  EFI_STATUS  Status;

+  UINT64      PalStartAddress;

+  UINT64      AbsAddress;

+  UINTN       RelativeAddress;

+  UINT64      FileSize;

+  UINT64      NumByteRead;

+  UINT8       *Buffer;

+  FILE        *Fp;

+  FIT_TABLE   *PalFitPtr;

+

+  Fp = fopen (BsfInfo->CompBinName, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);

+    return EFI_ABORTED;

+  }

+

+  FileSize = _filelength (_fileno (Fp));

+  FileSize -= SIZE_OF_PAL_HEADER;

+

+  if (BsfInfo->PreferredSize) {

+    if (FileSize > BsfInfo->CompSize) {

+      printf ("\nERROR: The PAL_A Size is more than specified size");

+      return EFI_ABORTED;

+    }

+

+    FileSize = BsfInfo->CompSize;

+  }

+

+  Buffer = malloc ((UINTN) FileSize);

+  if (Buffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (Buffer, 0, (UINTN) FileSize);

+

+  //

+  // Read, Get version Info and discard the PAL header.

+  //

+  NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);

+

+  //

+  // Extract the version info from header of PAL_A. Once done, discrad this buffer

+  //

+  if (!BsfInfo->VersionPresent) {

+    GetComponentVersionInfo (BsfInfo, Buffer);

+  }

+

+  //

+  // Read PAL_A file in a buffer

+  //

+  NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);

+  fclose (Fp);

+

+  PalStartAddress       = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);

+  Bsf1LastStartAddress  = PalStartAddress;

+  Bsf1TotalSize += (UINT32) FileSize;

+  Status      = UpdateBsfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);

+

+  AbsAddress  = Fv1EndAddress - SIZE_TO_PAL_A_FIT;

+  GetRelativeAddressInBsfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);

+  PalFitPtr               = (FIT_TABLE *) RelativeAddress;

+  PalFitPtr->CompAddress  = PalStartAddress | IPF_CACHE_BIT;

+  assert ((FileSize % 16) == 0);

+  PalFitPtr->CompSize     = (UINT32) (FileSize / 16);

+  PalFitPtr->CompVersion  = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);

+  PalFitPtr->CvAndType    = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);

+  if (BsfInfo->CheckSumRequired) {

+    PalFitPtr->CheckSum = 0;

+    PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);

+  }

+

+  if (Buffer) {

+    free (Buffer);

+  }

+

+  //

+  // Update the SYM file for this component based on it's start address.

+  //

+  Status = UpdateSymFile (PalStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);

+  if (EFI_ERROR (Status)) {

+

+    //

+    // At this time, SYM files are not required, so continue on error.

+    //

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+CreateFitTableAndInitialize (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function creates and intializes FIT table which would be used to

+  add component info inside this

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_ABORTED  - Aborted due to no size information

+  EFI_SUCCESS  - The function completed successfully

+

+--*/

+{

+  UINT64    PalFitTableAdd;

+  UINT64    FitTableAdd;

+  UINT64    FitTableAddressOffset;

+  FIT_TABLE *PalFitPtr;

+  FIT_TABLE *FitStartPtr;

+  UINTN     NumFitComp;

+  UINTN     RelativeAddress;

+  UINTN     Index;

+

+  if (!BsfInfo->PreferredSize) {

+    printf ("\nERROR: FIT could not be allocated becuase there are no size information");

+    return EFI_ABORTED;

+  }

+

+  if ((BsfInfo->CompSize % 16) != 0) {

+    printf ("\nERROR: Invalid Fit Table Size, not multiple of 16 bytes. Please correct the size");

+  }

+

+  PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;

+  GetRelativeAddressInBsfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);

+  PalFitPtr             = (FIT_TABLE *) RelativeAddress;

+  PalFitTableAdd        = (PalFitPtr->CompAddress - BsfInfo->CompSize);

+

+  FitTableAdd           = (PalFitPtr->CompAddress - 0x10) - BsfInfo->CompSize;

+  FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);

+  GetRelativeAddressInBsfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);

+  *(UINT64 *) RelativeAddress = FitTableAdd;

+

+  GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);

+

+  //

+  // Update Fit Table with FIT Signature and FIT info in first 16 bytes.

+  //

+  FitStartPtr = (FIT_TABLE *) RelativeAddress;

+

+  strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8);  // "_FIT_   "

+  assert (((BsfInfo->CompSize & 0x00FFFFFF) % 16) == 0);

+  FitStartPtr->CompSize     = (BsfInfo->CompSize & 0x00FFFFFF) / 16;

+  FitStartPtr->CompVersion  = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);

+

+  //

+  // BUGBUG: If a checksum is required, add code to checksum the FIT table.  Also

+  // determine what to do for things like the FV component that aren't easily checksummed.

+  // The checksum will be done once we are done with all the componet update in the FIT

+  // table

+  //

+  FitStartPtr->CvAndType  = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);

+

+  NumFitComp              = FitStartPtr->CompSize;

+

+  FitStartPtr++;

+

+  //

+  // Intialize remaining FIT table space to UNUSED fit component type

+  // so that when we need to create a FIT entry for a component, we can

+  // locate a free one and use it.

+  //

+  for (Index = 0; Index < (NumFitComp - 1); Index++) {

+    FitStartPtr->CvAndType = 0x7F;  // Initialize all with UNUSED

+    FitStartPtr++;

+  }

+

+  Bsf1TotalSize += BsfInfo->CompSize;

+  Bsf1LastStartAddress -= BsfInfo->CompSize;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+WriteBsfBinary (

+  IN CHAR8     *FileName,

+  IN UINT32    BsfSize,

+  IN LOC_TYPE  LocType

+  )

+/*++

+

+Routine Description:

+

+  Write Firmware Volume from memory to a file.

+  

+Arguments:

+

+  FileName     - Output File Name which needed to be created/

+  BsfSize      - FileSize

+  LocType      - The type of the BSF

+  

+Returns:

+

+  EFI_ABORTED - Returned due to one of the following resons:

+                 (a) Error Opening File

+                 (b) Failing to copy buffers

+  EFI_SUCCESS - The fuction completes successfully

+

+--*/

+{

+  FILE  *Fp;

+  UINTN NumByte;

+  VOID  *BsfBuffer;

+  UINTN RelativeAddress;

+

+  if (LocType == FIRST_VTF) {

+    GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);

+    BsfBuffer = (VOID *) RelativeAddress;

+  } else {

+    GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);

+    BsfBuffer = (VOID *) RelativeAddress;

+  }

+

+  Fp = fopen (FileName, "w+b");

+  if (Fp == NULL) {

+    printf ("Error in opening file %s\n", FileName);

+    return EFI_ABORTED;

+  }

+

+  NumByte = fwrite (BsfBuffer, sizeof (UINT8), (UINTN) BsfSize, Fp);

+

+  if (Fp) {

+    fclose (Fp);

+  }

+

+  if (NumByte != (sizeof (UINT8) * BsfSize)) {

+    printf ("\nERROR: Could not copy buffer into file %s ", FileName);

+    return EFI_ABORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+UpdateBsfBuffer (

+  IN  UINT64   StartAddress,

+  IN  UINT8    *Buffer,

+  IN  UINT64   DataSize,

+  IN LOC_TYPE  LocType

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+  

+Arguments:

+

+  StartAddress   - StartAddress in buffer. This number will automatically

+                  point to right address in buffer where data needed 

+                  to be updated.

+  Buffer         - Buffer pointer from data will be copied to memory mapped buffer.

+  DataSize       - Size of the data needed to be copied.

+  LocType        - The type of the BSF

+

+Returns:

+  

+  EFI_ABORTED  - The input parameter is error

+  EFI_SUCCESS  - The function completed successfully

+

+--*/

+{

+  UINT8 *LocalBufferPtrToWrite;

+

+  if (LocType == FIRST_VTF) {

+    if ((StartAddress | IPF_CACHE_BIT) < (Bsf1LastStartAddress | IPF_CACHE_BIT)) {

+      printf ("ERROR: Start Address is less then the BSF start address\n");

+      return EFI_ABORTED;

+    }

+

+    LocalBufferPtrToWrite = (UINT8 *) Bsf1EndBuffer;

+    LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);

+  } else {

+    if ((StartAddress | IPF_CACHE_BIT) < (Bsf2LastStartAddress | IPF_CACHE_BIT)) {

+      printf ("ERROR: Start Address is less then the BSF start address\n");

+      return EFI_ABORTED;

+    }

+    LocalBufferPtrToWrite = (UINT8 *) Bsf2EndBuffer;

+    LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);

+  }

+

+  memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+UpdateFfsHeader (

+  IN UINT32         TotalBsfSize,

+  IN LOC_TYPE       LocType  

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+  

+Arguments:

+

+  TotalBsfSize     - Size of the BSF

+  Fileoffset       - The start of the file relative to the start of the FV.

+  LocType          - The type of the BSF

+

+Returns:

+  

+  EFI_SUCCESS            - The function completed successfully

+  EFI_INVALID_PARAMETER  - The Ffs File Header Pointer is NULL

+

+--*/

+{

+  EFI_FFS_FILE_HEADER *FileHeader;

+  UINTN               RelativeAddress;

+  EFI_GUID            EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;

+

+  //

+  // Find the BSF file header location

+  //

+  if (LocType == FIRST_VTF) {

+    GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);

+    FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;

+  } else {

+    GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);

+    FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;

+  }

+

+  if (FileHeader == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // write header

+  //

+  memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));

+  memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));

+  FileHeader->Type        = EFI_FV_FILETYPE_FREEFORM;

+  FileHeader->Attributes  = FFS_ATTRIB_CHECKSUM;

+

+  //

+  // Now FileSize includes the EFI_FFS_FILE_HEADER

+  //

+  FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);

+  FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);

+  FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);

+

+  //

+  // Fill in checksums and state, all three must be zero for the checksums.

+  //

+  FileHeader->IntegrityCheck.Checksum.Header  = 0;

+  FileHeader->IntegrityCheck.Checksum.File    = 0;

+  FileHeader->State                           = 0;

+  FileHeader->IntegrityCheck.Checksum.Header  = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+  FileHeader->IntegrityCheck.Checksum.File    = CalculateChecksum8 ((UINT8 *) FileHeader, TotalBsfSize);

+  FileHeader->State                           = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+ValidateAddressAndSize (

+  IN  UINT64  BaseAddress,

+  IN  UINT64  FwVolSize

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+  

+Arguments:

+

+  BaseAddress    - Base address for the Fw Volume.

+  

+  FwVolSize      - Total Size of the FwVolume to which BSF will be attached..

+

+Returns:

+  

+  EFI_SUCCESS     - The function completed successfully

+  EFI_UNSUPPORTED - The input parameter is error

+

+--*/

+{

+  if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {

+    return EFI_SUCCESS;

+  }

+

+  return EFI_UNSUPPORTED;

+}

+

+EFI_STATUS

+UpdateIA32ResetVector (

+  IN  CHAR8   *FileName,

+  IN  UINT64  FirstFwVSize

+  )

+/*++

+

+Routine Description:

+

+  Update the 16 byte IA32 Reset vector to maintain the compatibility

+  

+Arguments:

+

+  FileName     - Binary file name which contains the IA32 Reset vector info..

+  FirstFwVSize - Total Size of the FwVolume to which BSF will be attached..

+

+Returns:

+  

+  EFI_SUCCESS            - The function completed successfully

+  EFI_ABORTED            - Invalid File Size

+  EFI_INVALID_PARAMETER  - Bad File Name

+  EFI_OUT_OF_RESOURCES   - Memory allocation failed.

+

+--*/

+{

+  UINT8 *Buffer;

+  UINT8 *LocalBsfBuffer;

+  UINTN FileSize;

+  UINTN NumByteRead;

+  FILE  *Fp;

+

+  if (!strcmp (FileName, "")) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Fp = fopen (FileName, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Unable to open the file %s", FileName);

+  }

+

+  FileSize = _filelength (_fileno (Fp));

+

+  if (FileSize > 16) {

+    return EFI_ABORTED;

+  }

+

+  Buffer = malloc (FileSize);

+  if (Buffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  NumByteRead     = fread (Buffer, sizeof (UINT8), FileSize, Fp);

+

+  LocalBsfBuffer  = (UINT8 *) Bsf1EndBuffer - SIZE_IA32_RESET_VECT;

+  memcpy (LocalBsfBuffer, Buffer, FileSize);

+

+  if (Buffer) {

+    free (Buffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+CleanUpMemory (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  This function cleans up any allocated buffer

+  

+Arguments:

+

+  NONE

+

+Returns:

+  

+  NONE

+

+--*/

+{

+  PARSED_BSF_INFO *TempFileListPtr;

+

+  if (Bsf1Buffer) {

+    free (Bsf1Buffer);

+  }

+

+  if (Bsf2Buffer) {

+    free (Bsf2Buffer);

+  }

+

+  //

+  // Cleanup the buffer which was allocated to read the file names from FV.INF

+  //

+  FileListPtr = FileListHeadPtr;

+  while (FileListPtr != NULL) {

+    TempFileListPtr = FileListPtr->NextBsfInfo;

+    free (FileListPtr);

+    FileListPtr = TempFileListPtr;

+  }

+}

+

+EFI_STATUS

+ProcessAndCreateBsf (

+  IN  UINT64  Size

+  )

+/*++

+

+Routine Description:

+

+  This function process the link list created during INF file parsing

+  and create component in BSF and updates its info in FIT table

+  

+Arguments:

+

+  Size   - Size of the Firmware Volume of which, this BSF belongs to.

+

+Returns:

+  

+  EFI_UNSUPPORTED - Unknown FIT type

+  EFI_SUCCESS     - The function completed successfully                 

+

+--*/

+{

+  EFI_STATUS      Status;

+  PARSED_BSF_INFO *ParsedInfoPtr;

+

+  Status        = EFI_SUCCESS;

+

+  ParsedInfoPtr = FileListHeadPtr;

+

+  while (ParsedInfoPtr != NULL) {

+

+    switch (ParsedInfoPtr->CompType) {

+    //

+    // COMP_TYPE_FIT_HEADER is a special case, hence handle it here

+    //

+    case COMP_TYPE_FIT_HEADER:

+      Status = CreateFitTableAndInitialize (ParsedInfoPtr);

+      break;

+

+    //

+    // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here

+    //

+    case COMP_TYPE_FIT_PAL_A:

+      Status = CreateAndUpdatePAL_A (ParsedInfoPtr);

+

+      //

+      // Based on BSF specification, once the PAL_A component has been written,

+      // update the Firmware Volume info as FIT table. This will be utilized

+      // to extract the Firmware Volume Start address where this BSF will be

+      // of part.

+      //

+      if (Status == EFI_SUCCESS) {

+        UpdateFitEntryForFwVolume (Size);

+      }

+      break;

+

+    case COMP_TYPE_FIT_FV_BOOT:

+      //

+      // Since FIT entry for Firmware Volume has been created and it is

+      // located at (PAL_A start - 16 byte). So we will not process any

+      // Firmware Volume related entry from INF file

+      //

+      Status = EFI_SUCCESS;

+      break;

+

+    default:

+      //

+      // Any other component type should be handled here. This will create the

+      // image in specified BSF and create appropriate entry about this

+      // component in FIT Entry.

+      //

+      Status = CreateAndUpdateComponent (ParsedInfoPtr);

+      if (EFI_ERROR (Status)) {

+        printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);

+      }

+      break;

+    }

+

+    ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+GenerateBsfImage (

+  IN  UINT64  StartAddress1,

+  IN  UINT64  Size1,

+  IN  UINT64  StartAddress2,

+  IN  UINT64  Size2

+  )

+/*++

+

+Routine Description:

+

+  This is the main function which will be called from application.

+

+Arguments:

+

+  StartAddress1  - The start address of the first BSF      

+  Size1          - The size of the first BSF

+  StartAddress2  - The start address of the second BSF      

+  Size2          - The size of the second BSF

+

+Returns:

+ 

+  EFI_OUT_OF_RESOURCES - Can not allocate memory

+  The return value can be any of the values 

+  returned by the calls to following functions:

+      GetBsfRelatedInfoFromInfFile

+      ProcessAndCreateBsf

+      UpdateIA32ResetVector

+      UpdateFfsHeader

+      WriteBsfBinary

+  

+--*/

+{

+  EFI_STATUS  Status;

+  CHAR8       OutFileName1[FILE_NAME_SIZE];

+  CHAR8       OutFileName2[FILE_NAME_SIZE];

+  BOOLEAN     SecondBSF;

+

+  Status          = EFI_UNSUPPORTED;

+  

+  if (StartAddress2 == 0) {

+    SecondBSF = FALSE;

+  } else {

+    SecondBSF = TRUE;

+  }

+  Fv1BaseAddress        = StartAddress1;

+  Fv1EndAddress         = Fv1BaseAddress + Size1;

+  

+  memset (OutFileName1, 0, FILE_NAME_SIZE);

+  sprintf (

+    OutFileName1,

+    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",

+    Bsf1NameGuid.Data1,

+    Bsf1NameGuid.Data2,

+    Bsf1NameGuid.Data3,

+    Bsf1NameGuid.Data4[0],

+    Bsf1NameGuid.Data4[1],

+    Bsf1NameGuid.Data4[2],

+    Bsf1NameGuid.Data4[3],

+    Bsf1NameGuid.Data4[4],

+    Bsf1NameGuid.Data4[5],

+    Bsf1NameGuid.Data4[6],

+    Bsf1NameGuid.Data4[7],

+    BSF_OUTPUT_FILE

+    );

+    

+  //

+  // The image buffer for the First BSF

+  //

+  Bsf1Buffer = malloc ((UINTN) Size1);

+  if (Bsf1Buffer == NULL) {

+    printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (Bsf1Buffer, 0x00, (UINTN) Size1);

+  Bsf1EndBuffer         = (UINT8 *) Bsf1Buffer + Size1;

+  Bsf1LastStartAddress  = Fv1EndAddress | IPF_CACHE_BIT;

+  

+  if (SecondBSF) {

+    Fv2BaseAddress        = StartAddress2;

+    Fv2EndAddress         = Fv2BaseAddress + Size2;

+    

+    memset (OutFileName2, 0, FILE_NAME_SIZE);

+    sprintf (

+      OutFileName2,

+      "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",

+      Bsf2NameGuid.Data1,

+      Bsf2NameGuid.Data2,

+      Bsf2NameGuid.Data3,

+      Bsf2NameGuid.Data4[0],

+      Bsf2NameGuid.Data4[1],

+      Bsf2NameGuid.Data4[2],

+      Bsf2NameGuid.Data4[3],

+      Bsf2NameGuid.Data4[4],

+      Bsf2NameGuid.Data4[5],

+      Bsf2NameGuid.Data4[6],

+      Bsf2NameGuid.Data4[7],

+      BSF_OUTPUT_FILE

+      );

+    

+    //

+    // The image buffer for the second BSF

+    //

+    Bsf2Buffer = malloc ((UINTN) Size2);

+    if (Bsf2Buffer == NULL) {

+      printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");

+      return EFI_OUT_OF_RESOURCES;

+    }

+    memset (Bsf2Buffer, 0x00, (UINTN) Size2);

+    Bsf2EndBuffer         = (UINT8 *) Bsf2Buffer + Size2;

+    Bsf2LastStartAddress  = Fv2EndAddress | IPF_CACHE_BIT;

+  }

+  

+  Status = GetBsfRelatedInfoFromInfFile (BSF_INPUT_FILE);

+  if (Status != EFI_SUCCESS) {

+    printf ("\nERROR: Error in parsing input file");

+    CleanUpMemory ();

+    return Status;

+  }

+

+  Status = ProcessAndCreateBsf (Size1);

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory ();

+    return Status;

+  }

+

+  Status = UpdateIA32ResetVector (IA32BinFile, Bsf1TotalSize);

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory ();

+    return Status;

+  }

+

+  //

+  // Re arrange the FIT Table for Ascending order of their FIT Type..

+  //

+  SortFitTable ();

+

+  //

+  // All components have been updated in FIT table. Now perform the FIT table

+  // checksum. The following function will check if Checksum is required,

+  // if yes, then it will perform the checksum otherwise not.

+  //

+  CalculateFitTableChecksum ();

+

+  //

+  // Write the FFS header

+  //

+  Bsf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);

+  Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);

+  Status = UpdateFfsHeader (Bsf1TotalSize, FIRST_VTF);

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory ();

+    return Status;

+  }

+  //

+  // Update the BSF buffer into specified BSF binary file

+  //

+  Status  = WriteBsfBinary (OutFileName1, Bsf1TotalSize, FIRST_VTF);

+

+  if (SecondBSF) {

+    Bsf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);

+    Bsf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);

+    Status = UpdateFfsHeader (Bsf2TotalSize, SECOND_VTF);

+    if (Status != EFI_SUCCESS) {

+      CleanUpMemory ();

+      return Status;

+    }

+    

+    //

+    // Update the BSF buffer into specified BSF binary file

+    //

+    Status  = WriteBsfBinary (OutFileName2, Bsf2TotalSize, SECOND_VTF);

+  }

+  

+  CleanUpMemory ();

+  printf ("\n");

+

+  return Status;

+}

+

+EFI_STATUS

+PeimFixupInFitTable (

+  IN  UINT64  StartAddress

+  )

+/*++

+

+Routine Description:

+

+  This function is an entry point to fixup SAL-E entry point.

+

+Arguments:

+

+  StartAddress - StartAddress for PEIM.....

+    

+Returns:

+ 

+  EFI_SUCCESS          - The function completed successfully

+  EFI_ABORTED          - Error Opening File

+  EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.

+

+--*/

+{

+  EFI_STATUS  Status;

+  FILE        *Fp;

+  UINT64      *StartAddressPtr;

+  UINTN       FirstFwVSize;

+  UINTN       NumByte;

+  CHAR8       OutFileName1[FILE_NAME_SIZE];

+

+  StartAddressPtr   = malloc (sizeof (UINT64));

+  if (StartAddressPtr == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  *StartAddressPtr = StartAddress;

+

+  memset (OutFileName1, 0, FILE_NAME_SIZE);

+

+  sprintf (

+    OutFileName1,

+    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",

+    Bsf1NameGuid.Data1,

+    Bsf1NameGuid.Data2,

+    Bsf1NameGuid.Data3,

+    Bsf1NameGuid.Data4[0],

+    Bsf1NameGuid.Data4[1],

+    Bsf1NameGuid.Data4[2],

+    Bsf1NameGuid.Data4[3],

+    Bsf1NameGuid.Data4[4],

+    Bsf1NameGuid.Data4[5],

+    Bsf1NameGuid.Data4[6],

+    Bsf1NameGuid.Data4[7],

+    BSF_OUTPUT_FILE

+    );

+

+  Fp = fopen (OutFileName1, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Error opening file ");

+    if (StartAddressPtr) {

+      free (StartAddressPtr);

+    }

+

+    return EFI_ABORTED;

+  }

+

+  FirstFwVSize = _filelength (_fileno (Fp));

+  fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);

+  NumByte = fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);

+

+  if (Fp) {

+    fclose (Fp);

+  }

+

+  if (StartAddressPtr) {

+    free (StartAddressPtr);

+  }

+

+  printf ("\n");

+  Status = EFI_SUCCESS;

+  return Status;

+}

+

+EFI_STATUS

+UpdateSymFile (

+  IN UINT64 BaseAddress,

+  IN CHAR8  *DestFileName,

+  IN CHAR8  *SourceFileName

+  )

+/*++

+

+Routine Description:

+

+  This function adds the SYM tokens in the source file to the destination file.

+  The SYM tokens are updated to reflect the base address.

+

+Arguments:

+

+  BaseAddress    - The base address for the new SYM tokens.

+  DestFileName   - The destination file.

+  SourceFileName - The source file.

+

+Returns:

+

+  EFI_SUCCESS             - The function completed successfully.

+  EFI_INVALID_PARAMETER   - One of the input parameters was invalid.

+  EFI_ABORTED             - An error occurred.

+

+--*/

+{

+  FILE    *SourceFile;

+  FILE    *DestFile;

+  CHAR8   Buffer[_MAX_PATH];

+  CHAR8   Type[_MAX_PATH];

+  CHAR8   Address[_MAX_PATH];

+  CHAR8   Section[_MAX_PATH];

+  CHAR8   Token[_MAX_PATH];

+  CHAR8   BaseToken[_MAX_PATH];

+  UINT64  TokenAddress;

+  long    StartLocation;

+

+  //

+  // Verify input parameters.

+  //

+  if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Open the source file

+  //

+  SourceFile = fopen (SourceFileName, "r");

+  if (SourceFile == NULL) {

+

+    //

+    // SYM files are not required.

+    //

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Use the file name minus extension as the base for tokens

+  //

+  strcpy (BaseToken, SourceFileName);

+  strtok (BaseToken, ". \t\n");

+  strcat (BaseToken, "__");

+

+  //

+  // Open the destination file

+  //

+  DestFile = fopen (DestFileName, "a+");

+  if (DestFile == NULL) {

+    fclose (SourceFile);

+    return EFI_ABORTED;

+  }

+

+  //

+  // If this is the beginning of the output file, write the symbol format info.

+  //

+  if (fseek (DestFile, 0, SEEK_END) != 0) {

+    fclose (SourceFile);

+    fclose (DestFile);

+    return EFI_ABORTED;

+  }

+

+  StartLocation = ftell (DestFile);

+

+  if (StartLocation == 0) {

+    fprintf (DestFile, "TEXTSYM format | V1.0\n");

+  } else if (StartLocation == -1) {

+    fclose (SourceFile);

+    fclose (DestFile);

+    return EFI_ABORTED;

+  }

+

+  //

+  // Read the first line

+  //

+  if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {

+    Buffer[0] = 0;

+  }

+

+  //

+  // Make sure it matches the expected sym format

+  //

+  if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {

+    fclose (SourceFile);

+    fclose (DestFile);

+    return EFI_ABORTED;

+  }

+

+  //

+  // Read in the file

+  //

+  while (feof (SourceFile) == 0) {

+

+    //

+    // Read a line

+    //

+    if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {

+

+      //

+      // Get the token address

+      //

+      AsciiStringToUint64 (Address, TRUE, &TokenAddress);

+

+      //

+      // Add the base address, the size of the FFS file header and the size of the peim header.

+      //

+      TokenAddress += BaseAddress &~IPF_CACHE_BIT;

+

+      fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);

+    }

+  }

+

+  fclose (SourceFile);

+  fclose (DestFile);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+CalculateFitTableChecksum (

+  VOID

+  )

+/*++

+  

+Routine Description:

+

+  This function will perform byte checksum on the FIT table, if the the checksum required

+  field is set to CheckSum required. If the checksum is not required then checksum byte

+  will have value as 0;.

+  

+Arguments:

+

+  NONE

+  

+Returns:

+

+  Status       - Value returned by call to CalculateChecksum8 ()

+  EFI_SUCCESS  - The function completed successfully

+    

+--*/

+{

+  FIT_TABLE *TmpFitPtr;

+  UINT64    FitTableAdd;

+  UINT64    FitTableAddOffset;

+  UINTN     RelativeAddress;

+  UINTN     Size;

+

+  //

+  // Read the Fit Table address from Itanium-based address map.

+  //

+  FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);

+

+  //

+  // Translate this Itanium-based address in terms of local buffer address which

+  // contains the image for Boot Strapped File

+  //

+  GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);

+  FitTableAdd = *(UINTN *) RelativeAddress;

+

+  GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);

+

+  TmpFitPtr = (FIT_TABLE *) RelativeAddress;

+

+  Size      = TmpFitPtr->CompSize * 16;

+

+  if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {

+    TmpFitPtr->CheckSum = 0;

+    TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);

+  } else {

+    TmpFitPtr->CheckSum = 0;

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s, EFI 2.0 BootStrap File Generation Utility. Version %i.%i, %s.\n\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION,

+    UTILITY_DATE

+    );

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "Usage: %s -B BaseAddress -S FwVolumeSize\n",

+    UTILITY_NAME

+    );

+  printf ("  Where:\n");

+  printf ("\tBaseAddress is the starting address of Firmware Volume where\n\tBoot Strapped Image will reside.\n\n");

+  printf ("\tFwVolumeSize is the size of Firmware Volume.\n\n");

+}

+

+EFI_STATUS

+main (

+  IN UINTN  argc,

+  IN  CHAR8 **argv

+  )

+/*++

+

+Routine Description:

+

+  This utility uses GenBsfImage.dll to build a Boot Strap File Image which will be

+  part of firmware volume image.

+

+Arguments:

+

+  argc   - The count of the parameters

+  argv   - The parameters

+

+

+Returns:

+

+  0   - No error conditions detected.

+  1   - One or more of the input parameters is invalid.

+  2   - A resource required by the utility was unavailable.  

+      - Most commonly this will be memory allocation or file creation.

+  3   - GenFvImage.dll could not be loaded.

+  4   - Error executing the GenFvImage dll.

+  5   - Now this tool does not support the IA32 platform

+

+--*/

+{

+  UINT8       Index;

+  UINT64      StartAddress1;

+  UINT64      StartAddress2;

+  UINT64      FwVolSize1;

+  UINT64      FwVolSize2;

+  BOOLEAN     FirstRoundB;

+  BOOLEAN     FirstRoundS;

+  EFI_STATUS  Status;

+  BOOLEAN     IsIA32;

+

+  //

+  // Display utility information

+  //

+  PrintUtilityInfo ();

+

+  //

+  // Verify the correct number of IA32 arguments

+  //

+  IsIA32 = FALSE;

+  if (argc == IA32_ARGS) {

+    //

+    //  Now this tool is not used for IA32 platform, if it will be used in future,

+    //  the IA32-specific functions need to be updated and verified, the updating can  

+    //  refer to IPF relevant functions)

+    //

+    printf ("ERROR: Now this tool does not support the IA32 platform!\n");

+    printf ("ERROR: And the IA32-specific functions need to be updated and verified!\n");

+    return 5;

+    

+    /*

+    StartAddress1 = 0;

+    IsIA32        = TRUE;

+

+    //

+    // Parse the command line arguments

+    //

+    for (Index = 1; Index < IA32_ARGS; Index += 2) {

+

+      //

+      // Make sure argument pair begin with - or /

+      //

+      if (argv[Index][0] != '-' && argv[Index][0] != '/') {

+        PrintUsage ();

+        printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");

+        return 1;

+      }

+

+      //

+      // Make sure argument specifier is only one letter

+      //

+      if (argv[Index][2] != 0) {

+        PrintUsage ();

+        printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);

+        return 1;

+      }

+

+      //

+      // Determine argument to read

+      //

+      switch (argv[Index][1]) {

+

+      case 't':

+      case 'T':

+        Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);

+        if (Status != EFI_SUCCESS) {

+          printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);

+          return 1;

+        }

+        break;

+

+      default:

+        PrintUsage ();

+        printf ("Unrecognized IA32 argument \"%s\".\n", argv[Index]);

+        IsIA32 = FALSE;

+        break;

+      }

+    }

+

+    if (IsIA32) {

+      //

+      // Call the GenBsfImage 

+      //

+      Status = Generate32BsfImage (StartAddress1);

+

+      if (EFI_ERROR(Status)) {

+        switch (Status) {

+

+        case EFI_INVALID_PARAMETER:

+          printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");

+          break;

+

+        case EFI_ABORTED:

+          printf ("\nERROR: Error detected while creating the file image.\n");

+          break;

+

+        case EFI_OUT_OF_RESOURCES:

+          printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");

+          break;

+

+        case EFI_VOLUME_CORRUPTED:

+          printf ("\nERROR: No base address was specified \n");

+          break;

+

+        default:

+          printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);

+          break;

+        }

+        return 2;

+      }

+

+      return 0;

+    }

+    */

+  } 

+

+  //

+  // Verify the correct number of arguments

+  //

+  if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {

+    PrintUsage ();

+    return 1;

+  }

+

+  //

+  // Initialize variables

+  //

+  StartAddress1 = 0;

+  StartAddress2 = 0;

+  FwVolSize1    = 0;

+  FwVolSize2    = 0;

+  FirstRoundB   = TRUE;

+  FirstRoundS   = TRUE;

+

+  //

+  // Parse the command line arguments

+  //

+  for (Index = 1; Index < argc; Index += 2) {

+

+    //

+    // Make sure argument pair begin with - or /

+    //

+    if (argv[Index][0] != '-' && argv[Index][0] != '/') {

+      PrintUsage ();

+      printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");

+      return 1;

+    }

+

+    //

+    // Make sure argument specifier is only one letter

+    //

+    if (argv[Index][2] != 0) {

+      PrintUsage ();

+      printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);

+      return 1;

+    }

+

+    //

+    // Determine argument to read

+    //

+    switch (argv[Index][1]) {

+

+    case 'B':

+    case 'b':

+      if (FirstRoundB) {

+        Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);

+        FirstRoundB = FALSE;

+      } else {

+        Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);

+      }

+

+      if (Status != EFI_SUCCESS) {

+        printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);

+        return 1;

+      }

+      break;

+

+    case 'S':

+    case 's':

+      if (FirstRoundS) {

+        Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);

+        FirstRoundS = FALSE;

+      } else {

+        Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);

+      }

+

+      if (Status != EFI_SUCCESS) {

+        printf ("\nERROR: Bad size \"%s\"\n", argv[Index + 1]);

+        return 1;

+      }

+      break;

+

+    default:

+      PrintUsage ();

+      printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);

+      return 1;

+      break;

+    }

+  }

+

+  //

+  // Call the GenBsfImage

+  //

+  Status = GenerateBsfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2);

+

+  if (EFI_ERROR (Status)) {

+    switch (Status) {

+

+    case EFI_INVALID_PARAMETER:

+      printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");

+      break;

+

+    case EFI_ABORTED:

+      printf ("\nERROR: Error detected while creating the file image.\n");

+      break;

+

+    case EFI_OUT_OF_RESOURCES:

+      printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");

+      break;

+

+    case EFI_VOLUME_CORRUPTED:

+      printf ("\nERROR: No base address was specified \n");

+      break;

+

+    default:

+      printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);

+      break;

+    }

+    return 2;

+  }

+  return 0;

+}

+

+EFI_STATUS

+Generate32BsfImage (

+IN  UINT64  BootFileStartAddress

+  )

+/*++

+

+Routine Description:

+

+  This is the main IA32 function which will be called from application.

+  (Now this tool is not used for IA32 platform, if it will be used in future,

+  the relative functions need to be updated, the updating can refer to IPF 

+  functions)

+

+Arguments:

+

+  BootFileStartAddress   - Top Address of Boot File

+

+Returns:

+ 

+  The return value can be any of the values 

+  returned by the calls to following functions:

+      Get32BsfRelatedInfoFromInfFile

+      CreateBsfBuffer

+      ProcessAndCreate32Bsf

+      Update32FfsHeader

+      WriteBsfBinary

+  

+--*/

+{

+  EFI_STATUS    Status;

+  UINT32        BsfSize;

+  CHAR8         OutFileName[FILE_NAME_SIZE];

+

+  EFI_GUID      BsfNameGuid = EFI_IA32_BOOT_STRAP_GUID;

+

+  Status = EFI_UNSUPPORTED;

+

+  memset (OutFileName, 0, FILE_NAME_SIZE);

+

+  sprintf (

+    OutFileName, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",

+    BsfNameGuid.Data1,

+    BsfNameGuid.Data2,

+    BsfNameGuid.Data3,

+    BsfNameGuid.Data4[0],

+    BsfNameGuid.Data4[1],

+    BsfNameGuid.Data4[2],

+    BsfNameGuid.Data4[3],

+    BsfNameGuid.Data4[4],

+    BsfNameGuid.Data4[5],

+    BsfNameGuid.Data4[6],

+    BsfNameGuid.Data4[7],

+    BSF_OUTPUT_FILE

+    );

+

+

+  Status = Get32BsfRelatedInfoFromInfFile (BSF_INPUT_FILE);

+

+  if (Status != EFI_SUCCESS) {

+    printf ("\nERROR: Error in parsing input file");

+    CleanUpMemory ();

+    return Status;

+  }

+

+  if (GetTotal32BsfSize (&BsfSize) == EFI_SUCCESS) {

+    Bsf1Buffer = malloc ((UINTN) BsfSize);

+    if (Bsf1Buffer == NULL) {

+      printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");

+      CleanUpMemory ();

+      return EFI_OUT_OF_RESOURCES;

+    }

+    memset (Bsf1Buffer, 0x00, (UINTN) BsfSize);

+  } else {

+    printf ("\nERROR: Could not get BSF size.");

+    CleanUpMemory ();

+    return EFI_ABORTED;

+  }

+

+  //

+  //VTF must align properly

+  //

+  Bsf1LastStartAddress = BootFileStartAddress - BsfSize;

+  Bsf1LastStartAddress = Bsf1LastStartAddress & -8;

+  BsfSize          = (UINT32)BootFileStartAddress - (UINT32)Bsf1LastStartAddress;

+  Bsf1LastStartAddress = BsfSize;

+  BufferToTop      = (UINT32)BootFileStartAddress - BsfSize;

+

+  Status = ProcessAndCreate32Bsf (BsfSize);

+

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory();

+    return Status;

+  }

+

+  //

+  // Write the FFS header

+  //

+  Status = Update32FfsHeader (BsfSize);

+

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory();

+    return Status;

+  }

+

+  // 

+  // Calculate the Start address of this BSF

+  //

+  Bsf1Buffer = (UINT8 *)Bsf1Buffer + Bsf1LastStartAddress;

+

+  //

+  // Update the BSF buffer into specified BSF binary file

+  //

+  Status = WriteBsfBinary (OutFileName, BsfSize - (UINT32)Bsf1LastStartAddress, FIRST_VTF);

+

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory();

+    return Status;

+  }

+

+  Status = Write32SoftFit (IA32_SOFT_FIT, FileListHeadPtr);

+

+  if (Status != EFI_SUCCESS) {

+    CleanUpMemory();

+    return Status;

+  }

+  

+  CleanUpMemory ();

+  printf ("\n");  

+

+  return Status;

+}

+

+EFI_STATUS

+GetTotal32BsfSize(

+  IN  UINT32  *BsfSize 

+  )

+/*++

+

+Routine Description:

+

+  This function calculates total size for IA32 BSF which would be needed to create

+  the buffer. This will be done using Passed Info link list and looking for the

+  size of the components which belong to BSF. The addtional file header is accounted.

+

+Arguments:

+

+  BSFSize     - Pointer to the size of IA32 BSF 

+

+Returns:

+

+  EFI_ABORTED - Returned due to one of the following resons:

+                (a) Error Opening File

+  EFI_SUCCESS - The fuction completes successfully

+

+--*/

+{

+  PARSED_BSF_INFO     *BsfInfo;

+  FILE                *Fp;

+  UINT32              Alignment;

+

+  *BsfSize = 0;

+  Alignment = 0;

+  

+  BsfInfo = FileListHeadPtr;

+

+  while (BsfInfo != NULL) {

+    if (BsfInfo->LocationType != SECOND_VTF) {

+

+      if ( BsfInfo->Align ) {

+        //

+        // Create additional align to compensate for component boundary requirements

+        //

+        Alignment = 1 << BsfInfo->Align;

+        *BsfSize += Alignment;

+      }

+      

+      if (BsfInfo->PreferredSize) {

+        *BsfSize += BsfInfo->CompSize;

+      } else {

+        Fp = fopen (BsfInfo->CompBinName,"r+b");

+

+        if (Fp == NULL) {

+          printf ("\nERROR: Error in opening file %s", BsfInfo->CompBinName);

+          return EFI_ABORTED;

+        }

+        

+        *BsfSize += _filelength (_fileno (Fp));

+        

+        if (Fp) {

+          fclose (Fp);

+        }

+      }    

+    }

+    BsfInfo = BsfInfo->NextBsfInfo;

+  }

+

+  //

+  // Add file header space

+  //

+  *BsfSize += sizeof (EFI_FFS_FILE_HEADER);

+

+  //

+  // Create additional to IA32 Seccore section header

+  //

+  *BsfSize += sizeof (EFI_COMMON_SECTION_HEADER);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+ProcessAndCreate32Bsf (

+  IN  UINT64  Size

+  )

+/*++

+

+Routine Description:

+

+  This function process the link list created during INF file parsing

+  and create component in IA32 BSF

+  

+Arguments:

+

+  Size   - Size of the Firmware Volume of which, this BSF belongs to.

+

+Returns:

+  

+  EFI_UNSUPPORTED - Unknown component type

+  EFI_SUCCESS     - The function completed successfully                 

+

+--*/

+{

+  EFI_STATUS          Status;

+  PARSED_BSF_INFO     *ParsedInfoPtr;

+

+  Status = EFI_SUCCESS;

+

+  ParsedInfoPtr = FileListHeadPtr;

+

+  while (ParsedInfoPtr != NULL) {

+    

+    switch (ParsedInfoPtr->CompType) {

+

+    case COMP_TYPE_SECCORE:

+      Status = CreateAndUpdateSeccore (ParsedInfoPtr);

+      break;

+

+    default:

+      //

+      // Any other component type should be handled here. This will create the

+      // image in specified BSF

+      //

+      Status = CreateAndUpdate32Component (ParsedInfoPtr);

+      if (EFI_ERROR(Status)) {

+        printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);

+      }

+      break;

+    }

+

+    ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+CreateAndUpdateSeccore (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for seccore and update them

+  in IA32 BSF Buffer

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_ABORTED           - Due to one of the following reasons:

+                           (a)Error Opening File

+                           (b)The PAL_A Size is more than specified size status

+                              One of the values mentioned below returned from 

+                              call to UpdateSymFile

+  EFI_SUCCESS           - The function completed successfully.

+  EFI_INVALID_PARAMETER - One of the input parameters was invalid.

+  EFI_ABORTED           - An error occurred.UpdateSymFile

+  EFI_OUT_OF_RESOURCES  - Memory allocation failed.

+   

+--*/

+{

+  UINT8                      *SecbinStartAddress;

+  UINT8                      *SecfileStartAddress;

+  UINT32                     FileSize;

+  UINT64                     NumByteRead;

+  UINT8                      *Buffer;

+  FILE                       *Fp;

+  UINT64                     TotalLength;

+  EFI_COMMON_SECTION_HEADER  *SecHeader;

+

+  Fp = fopen (BsfInfo->CompBinName, "r+b");

+

+  if (Fp == NULL) {

+    printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);

+    return EFI_ABORTED;

+  }

+

+  FileSize = _filelength (_fileno (Fp));

+

+  if (BsfInfo->PreferredSize) {

+    if (FileSize > BsfInfo->CompSize) {

+      printf("\nERROR: The Seccore Size is more than specified size");

+      return EFI_ABORTED;

+    }

+

+    FileSize = BsfInfo->CompSize;

+  }

+

+  BsfInfo->CompSize = FileSize;

+

+  Buffer = malloc ((UINTN) FileSize);

+  if (Buffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (Buffer, 0, (UINTN) FileSize);

+

+  //

+  // Read seccore in a buffer

+  //

+  NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);

+  fclose (Fp);

+

+  SecfileStartAddress = (UINT8 *) Bsf1Buffer + Bsf1LastStartAddress - FileSize - sizeof (EFI_COMMON_SECTION_HEADER); 

+  if (SecfileStartAddress == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  SecbinStartAddress = SecfileStartAddress + sizeof (EFI_COMMON_SECTION_HEADER);

+

+  BsfInfo->CompPreferredAddress = Bsf1LastStartAddress - FileSize + BufferToTop;

+

+  //

+  // write section header

+  //

+  memset (SecfileStartAddress, 0, sizeof (EFI_COMMON_SECTION_HEADER));

+  SecHeader = (EFI_COMMON_SECTION_HEADER *) SecfileStartAddress;

+  SecHeader->Type = EFI_SECTION_RAW;

+  TotalLength     = sizeof (EFI_COMMON_SECTION_HEADER) + (UINT64) FileSize;

+  memcpy (SecHeader->Size, &TotalLength, 3);

+

+  //

+  // write seccore

+  //

+  memcpy (SecbinStartAddress, Buffer, (UINTN) FileSize);

+

+  if (Buffer) {

+    free (Buffer);

+  }

+

+  Bsf1LastStartAddress = SecfileStartAddress - (UINT8 *) Bsf1Buffer;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+CreateAndUpdate32Component (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for each components. Add it at aligned address.

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_SUCCESS              - The function completed successful

+  EFI_ABORTED              - Aborted due to one of the many reasons like:

+                              (a) Component Size greater than the specified size.

+                              (b) Error opening files.

+  EFI_INVALID_PARAMETER    - Value returned from call to UpdateEntryPoint()

+  EFI_OUT_OF_RESOURCES     - Memory allocation failed.

+  

+--*/

+{

+  UINT64      CompStartAddress;

+  UINT32      FileSize;

+  UINT64      NumByteRead;

+  UINT8       *Buffer;

+  FILE        *Fp;

+  UINT8       *LocalBufferPtrToWrite;

+  UINT64      Alignment;

+

+  Fp = fopen (BsfInfo->CompBinName, "r+b");

+

+  if (Fp == NULL) {

+    printf("\nERROR: Opening file %s", BsfInfo->CompBinName);

+    return EFI_ABORTED;

+  }

+

+  FileSize = _filelength (_fileno (Fp));

+

+  if (BsfInfo->PreferredSize) {

+    if (FileSize > BsfInfo->CompSize) {

+      printf("\nERROR: The component size is more than specified size");

+      return EFI_ABORTED;

+    }

+    FileSize = BsfInfo->CompSize;

+  }

+  BsfInfo->CompSize = FileSize;

+

+  Buffer = malloc ((UINTN) FileSize);

+  if (Buffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (Buffer,0, (UINTN) FileSize);

+

+  NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);

+  fclose (Fp);

+

+  CompStartAddress = Bsf1LastStartAddress - FileSize + BufferToTop;

+

+  if (BsfInfo->Align) {

+    //

+    // Create additional align to compensate for component boundary requirements

+    //

+    Alignment = 0 - (1 << BsfInfo->Align);

+    CompStartAddress = CompStartAddress & Alignment;    

+  }

+

+  BsfInfo->CompPreferredAddress = CompStartAddress;

+

+  //

+  // write bin

+  //

+  LocalBufferPtrToWrite = (UINT8 *) Bsf1Buffer;

+  Bsf1LastStartAddress  = CompStartAddress - BufferToTop;

+  LocalBufferPtrToWrite += Bsf1LastStartAddress;

+  memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) FileSize);  

+  Bsf1LastStartAddress = CompStartAddress - BufferToTop;

+

+  //

+  // Free the buffer

+  //

+  if (Buffer) {

+    free (Buffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+Update32FfsHeader(

+  IN UINT32     BsfSize

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+

+Arguments:

+

+  BsfSize     - Size of the IA32 BSF

+

+Returns:

+  

+  EFI_SUCCESS            - The function completed successfully

+  EFI_INVALID_PARAMETER  - The Ffs File Header Pointer is NULL

+

+--*/

+{

+  EFI_FFS_FILE_HEADER     *FileHeader;

+  UINT32                  TotalBsfSize;

+  EFI_GUID                EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;

+

+  

+  //

+  // Find the BSF file header location, the bsf file must be 8 bytes aligned

+  //

+  Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);

+  Bsf1LastStartAddress += BufferToTop;

+  Bsf1LastStartAddress = Bsf1LastStartAddress & -8;

+  Bsf1LastStartAddress -= BufferToTop;

+  FileHeader = (EFI_FFS_FILE_HEADER*)((UINT8*)Bsf1Buffer + Bsf1LastStartAddress);

+

+  if (FileHeader == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // write header

+  //

+  memset (FileHeader, 0, sizeof(EFI_FFS_FILE_HEADER));

+  memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));

+

+  FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;

+  FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;

+

+  //

+  // Now FileSize includes the EFI_FFS_FILE_HEADER

+  //

+  TotalBsfSize = BsfSize - (UINT32)Bsf1LastStartAddress;

+  FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);

+  FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);

+  FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);

+

+  //

+  // Fill in checksums and state, all three must be zero for the checksums.

+  //

+  FileHeader->IntegrityCheck.Checksum.Header = 0;

+  FileHeader->IntegrityCheck.Checksum.File = 0;

+  FileHeader->State = 0;

+  FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8*) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+  FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8*) FileHeader, TotalBsfSize);

+  FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+Get32BsfRelatedInfoFromInfFile (

+  IN  CHAR8 *FileName

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the input file, parse it and create a list of tokens

+  which is parsed and used, to intialize the data related to IA32 BSF

+  

+Arguments:

+

+  FileName  FileName which needed to be read to parse data

+

+Returns:

+   

+  EFI_ABORTED            Error in opening file

+  EFI_INVALID_PARAMETER  File doesn't contain any valid informations

+  EFI_OUT_OF_RESOURCES   Malloc Failed

+  EFI_SUCCESS            The function completed successfully 

+

+--*/

+{

+  FILE          *Fp;

+  UINTN         Index;

+  EFI_STATUS    Status;

+  

+  Fp = fopen (FileName, "r");

+  if (Fp == NULL) {

+    printf ("\nERROR: Error in opening %s file\n", FileName);

+    return EFI_ABORTED;

+  }

+  

+  ValidLineCount (Fp);

+  

+  if (ValidLineNum == 0) {

+    printf ("\nERROR: File doesn't contain any valid informations");

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  TokenStr = (CHAR8 **)malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));

+

+  if (TokenStr == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));

+  OrgStrTokPtr = TokenStr;

+  

+  for (Index = 0; Index < (2 * ValidLineNum); Index++) {

+    *TokenStr = (CHAR8 *)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);

+

+    if (*TokenStr == NULL) {

+      free (OrgStrTokPtr);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    

+    memset (*TokenStr, 0, FILE_NAME_SIZE);

+//    free (*TokenStr);

+    TokenStr++;

+  }

+  

+  TokenStr = NULL;

+  TokenStr = OrgStrTokPtr;

+  fseek (Fp, 0L, SEEK_SET);

+  

+  Status = InitializeComps();

+

+  if (Status != EFI_SUCCESS) {

+    free (TokenStr);

+    return Status;

+  }

+  ParseInputFile (Fp);

+  Initialize32InFileInfo ();

+  

+  if (Fp) {

+    fclose (Fp);

+  }

+  free (TokenStr);

+  return EFI_SUCCESS;

+}

+

+VOID

+Initialize32InFileInfo (

+  VOID                     

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from IA32 INF file.

+

+Arguments:

+

+  NONE

+

+Returns:

+

+  NONE

+

+--*/

+{

+  UINTN   SectionOptionFlag;

+  UINTN   SectionCompFlag;

+

+  SectionOptionFlag =0 ;

+  SectionCompFlag = 0;  

+  TokenStr = OrgStrTokPtr;

+  while (*TokenStr != NULL) {

+    if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {

+      SectionOptionFlag = 1;

+      SectionCompFlag = 0;

+    }

+    

+    if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {

+      if (FileListPtr == NULL) {

+        FileListPtr = FileListHeadPtr;

+      }

+      

+      SectionCompFlag = 1;

+      SectionOptionFlag = 0;

+      TokenStr++;

+    }

+    

+    if (SectionOptionFlag) {

+      if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {

+        *TokenStr++;

+        strcpy (IA32BinFile, *TokenStr);

+      }

+    }

+    

+    if (SectionCompFlag) {

+      if (_stricmp (*TokenStr, "COMP_NAME") == 0) {

+        TokenStr++;

+        strcpy (FileListPtr->CompName, *TokenStr);

+        TokenStr++;

+        ParseAndUpdate32Components (FileListPtr);

+      }

+      

+      if (*TokenStr != NULL) {

+        FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));

+        if (FileListPtr->NextBsfInfo == NULL) {

+          printf ("Error: Out of memory resources.\n");

+          break;

+        }

+        FileListPtr = FileListPtr->NextBsfInfo;

+        memset (FileListPtr, 0, sizeof(PARSED_BSF_INFO));

+        FileListPtr->NextBsfInfo = NULL;

+        continue;

+      } else {

+        break;

+      }

+    }

+    

+    TokenStr++;

+  }

+}

+

+VOID 

+ParseAndUpdate32Components (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from INF file.

+  

+Arguments:

+

+  BsfInfo   - A pointer to the BSF Info Structure

+  

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT64  StringValue;

+  UINT64  AlignStringValue;

+

+  while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {

+

+    if (_stricmp (*TokenStr, "COMP_LOC") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "B") == 0) {

+        BsfInfo->LocationType = FIRST_VTF;

+      } else if (_stricmp (*TokenStr, "N") == 0) {

+        BsfInfo->LocationType = SECOND_VTF;

+      } else {

+        BsfInfo->LocationType = NONE;

+        printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);

+      }

+    } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {

+      TokenStr++;

+      if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {

+        printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); 

+        return;

+      }

+      BsfInfo->CompType = (UINT8) StringValue;

+    } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "-") == 0) {

+        BsfInfo->VersionPresent = FALSE;

+        BsfInfo->MajorVer = 0;

+        BsfInfo->MinorVer = 0;

+      } else {

+        BsfInfo->VersionPresent = TRUE;

+        ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);

+      }

+    } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {

+      TokenStr++;

+      strcpy (BsfInfo->CompBinName, *TokenStr);

+    } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {

+      TokenStr++;

+      strcpy (BsfInfo->CompSymName, *TokenStr);

+    } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "-") == 0) {

+        BsfInfo->PreferredSize = FALSE;

+        BsfInfo->CompSize = 0;

+      } else {

+        BsfInfo->PreferredSize = TRUE;

+        if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {

+          printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); 

+          return;

+        }

+        BsfInfo->CompSize = (UINTN) StringValue;

+      }

+

+    } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {

+      TokenStr++;

+      if (_stricmp (*TokenStr, "1") == 0) {

+        BsfInfo->CheckSumRequired = 1;

+      } else if (_stricmp (*TokenStr, "0") == 0) {

+        BsfInfo->CheckSumRequired = 0;

+      } else {

+        printf ("\nERROR: Bad information in INF file about Checksum required field");

+      }

+    } else if (_stricmp (*TokenStr, "COMP_ALIGN") == 0) {

+      TokenStr++;

+      if (AsciiStringToUint64 (*TokenStr, FALSE, &AlignStringValue) != EFI_SUCCESS) {

+        printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); 

+        return;

+      }

+      if (AlignStringValue >= 0) {

+        BsfInfo->Align = (UINT32) AlignStringValue;

+      } else {

+        printf ("\nERROR: invalid align \"%s\".", AlignStringValue); 

+        return;

+      }

+    }

+    TokenStr++;

+    if (*TokenStr == NULL) {

+      break;

+    }

+  }

+}

+

+EFI_STATUS

+Write32SoftFit(

+  IN CHAR8              *FileName,

+  IN PARSED_BSF_INFO    *BsfInfo

+  )

+/*++

+

+Routine Description:

+

+  Write IA32 Firmware Volume component address from memory to a file.

+  

+Arguments:

+

+  FileName      Output File Name which needed to be created/

+  BsfInfo       Parsed info link

+  

+Returns:

+

+  EFI_ABORTED  - Returned due to one of the following resons:

+                  (a) Error Opening File

+                  (b) Failing to copy buffers

+  EFI_SUCCESS  - The function completes successfully

+

+--*/

+{

+  FILE    *Fp;

+

+  Fp = fopen (FileName, "w+t");

+  if (Fp == NULL) {

+    printf ("Error in opening file %s\n", FileName);

+    return EFI_ABORTED;

+  }

+

+  while (BsfInfo != NULL) {

+    if (strlen (BsfInfo->CompName) != 0) {

+      fprintf (Fp, "\n%s\n", BsfInfo->CompName);

+    } else {

+      fprintf (Fp, "\n%s\n", "Name not available");    

+    }

+    

+    fprintf (Fp, "%d\n", BsfInfo->CompPreferredAddress);

+    fprintf (Fp, "%d\n", BsfInfo->CompSize);

+    fprintf (Fp, "%d\n", BsfInfo->Align);

+    

+    BsfInfo = BsfInfo->NextBsfInfo;

+  }

+

+  if (Fp) {

+    fclose (Fp);

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/Source/GenBsfImage/GenBsfImage.h b/Source/GenBsfImage/GenBsfImage.h
new file mode 100644
index 0000000..1efbebc
--- /dev/null
+++ b/Source/GenBsfImage/GenBsfImage.h
@@ -0,0 +1,633 @@
+/*++

+

+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved

+This software and associated documentation (if any) is furnished

+under a license and may only be used or copied in accordance

+with the terms of the license. Except as permitted by such

+license, no part of this software or documentation may be

+reproduced, stored in a retrieval system, or transmitted in any

+form or by any means without the express written consent of

+Intel Corporation.

+

+

+Module Name:  

+

+  GenBsfImage.h

+

+Abstract:

+

+  This file contains the relevant declarations required

+  to generate Boot Strap File

+

+--*/

+

+//

+// Module Coded to EFI 2.0 Coding Conventions

+//

+#ifndef   _EFI_GEN_BSF_IMAGE_H

+#define   _EFI_GEN_BSF_IMAGE_H

+

+//

+// External Files Referenced

+//

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <io.h>

+#include "assert.h"

+// #include "TianoCommon.h"

+#include "Common/FirmwareFileSystem.h"

+#include "Common/FirmwareVolumeHeader.h"

+#include "ParseInf.h"

+

+//

+// Internal Constants

+//

+#define EFI_IPF_VTF1_GUID \

+  { \

+    0xfa371c9b, 0x5a86, 0x4198, 0xab, 0xc2, 0xed, 0x3f, 0xaa, 0xce, 0xb0, 0x8b \

+  };

+

+#define EFI_IPF_VTF2_GUID \

+  { \

+    0x624a0d5a, 0x315f, 0x40b6, 0xa6, 0x33, 0xe5, 0xf7, 0xde, 0x58, 0x20, 0xa0 \

+  };

+

+#define EFI_IA32_BOOT_STRAP_GUID \

+  { \

+    0xd4260a8d, 0x356, 0x4f45, 0x85, 0xe9, 0xad, 0x1d, 0x79, 0x22, 0x79, 0xf0 \

+  };

+

+#define CV_N_TYPE(a,b)            (UINT8)(((UINT8)a << 7) + (UINT8)b)  // Keeps the CV and Type in same byte field

+#define MAKE_VERSION(a,b)         (UINT16)(((UINT16)a << 8) + (UINT16)b)

+

+#define   FILE_NAME_SIZE          256

+#define   COMPONENT_NAME_SIZE     128

+#define   BSF_INPUT_FILE          "BSF.INF"

+#define   BSF_OUTPUT_FILE         "Bsf.RAW"

+#define   BSF_SYM_FILE            "Bsf.SYM"

+#define   FIT_SIGNATURE           "_FIT_   "

+

+//

+// This is IA32 seccore

+//

+#define   COMP_TYPE_SECCORE             0x0F

+

+//

+//Fit Type Definition

+//

+#define   COMP_TYPE_FIT_HEADER          0x00

+#define   COMP_TYPE_FIT_PAL_B           0x01

+

+//

+// This is generic PAL_A

+//

+#define   COMP_TYPE_FIT_PAL_A           0x0F

+#define   COMP_TYPE_FIT_PEICORE         0x10

+#define   COMP_TYPE_FIT_AUTOSCAN        0x30

+#define   COMP_TYPE_FIT_FV_BOOT         0x7E

+

+//

+//This is processor Specific PAL_A

+//

+#define   COMP_TYPE_FIT_PAL_A_SPECIFIC  0x0E

+#define   COMP_TYPE_FIT_UNUSED    0x7F

+

+#define   FIT_TYPE_MASK           0x7F

+#define   CHECKSUM_BIT_MASK       0x80

+

+//

+// IPF processor address is cached bit

+//

+#define IPF_CACHE_BIT 0x8000000000000000

+

+//

+// Size definition to calculate the location from top of address for

+// each component

+//

+#define SIZE_IA32_RESET_VECT      0x10        // 16 Bytes

+#define SIZE_SALE_ENTRY_POINT     0x08        // 8 Byte

+#define SIZE_FIT_TABLE_ADD        0x08        // 8 Byte

+#define SIZE_FIT_TABLE_PAL_A      0x10     

+#define SIZE_RESERVED             0x10

+

+

+#define SIZE_TO_OFFSET_PAL_A_END  (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \

+                                  SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A + \

+                                  SIZE_RESERVED)

+#define SIZE_TO_PAL_A_FIT         (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \

+                                  SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A)

+

+#define SIZE_OF_PAL_HEADER        0x40        //PAL has 64 byte header

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "GenBsfImage"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION   0

+#define UTILITY_MINOR_VERSION   0

+#define UTILITY_DATE            __DATE__

+

+//

+// The maximum number of arguments accepted from the command line.

+//

+#define ONE_BSF_ARGS  5

+#define TWO_BSF_ARGS  9

+

+//

+// The number of IA32 bsf arguments accepted from the command line.

+//

+#define IA32_ARGS  3

+

+#define IA32_SOFT_FIT "IA32BsfAddress.inf"

+

+//

+// Internal Data Structure

+//

+typedef enum _LOC_TYPE 

+{

+  NONE,                   // In case there is - INF file

+  FIRST_VTF,              // First VTF

+  SECOND_VTF,             // Outside BSF

+} LOC_TYPE;

+

+typedef struct _PARSED_BSF_INFO {

+  CHAR8       CompName[COMPONENT_NAME_SIZE];

+  LOC_TYPE    LocationType;

+  UINT8       CompType;

+  UINT8       MajorVer;

+  UINT8       MinorVer;

+  UINT8       CheckSumRequired;

+  BOOLEAN     VersionPresent;                // If it is TRUE, then, Version is in INF file

+  BOOLEAN     PreferredSize;

+  BOOLEAN     PreferredAddress;

+  CHAR8       CompBinName[FILE_NAME_SIZE];

+  CHAR8       CompSymName[FILE_NAME_SIZE];

+  UINTN       CompSize;

+  UINT64      CompPreferredAddress;

+  UINT32      Align;

+

+  //

+  //  Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'

+  //  Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'

+  //  Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'

+  //  Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'

+  //

+  struct      _PARSED_BSF_INFO   *NextBsfInfo;

+} PARSED_BSF_INFO;

+

+#pragma pack (1)

+typedef struct {

+  UINT64      CompAddress;

+  UINT32      CompSize;

+  UINT16      CompVersion;

+  UINT8       CvAndType;

+  UINT8       CheckSum;

+} FIT_TABLE;

+#pragma pack ()

+

+//

+// The function that displays general utility information

+//

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+;

+

+//

+// The function that displays the utility usage message.

+//

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+;

+

+//

+// Other Function Prototype Declarations

+//

+

+EFI_STATUS

+UpdateBsfBuffer(

+  IN  UINT64    StartAddress,

+  IN  UINT8     *Buffer,

+  IN  UINT64    DataSize,

+  IN  LOC_TYPE  LocType

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+  

+Arguments:

+

+  StartAddress   - StartAddress in buffer. This number will automatically

+                  point to right address in buffer where data needed 

+                  to be updated.

+  Buffer         - Buffer pointer from data will be copied to memory mapped buffer.

+  DataSize       - Size of the data needed to be copied.

+  LocType        - The type of the BSF

+

+Returns:

+  

+  EFI_ABORTED  - The input parameter is error

+  EFI_SUCCESS  - The function completed successfully

+

+--*/

+;

+

+EFI_STATUS

+UpdateSymFile (

+  IN UINT64 BaseAddress,

+  IN CHAR8  *DestFileName,

+  IN CHAR8  *SourceFileName

+  )

+/*++

+

+Routine Description:

+

+  This function adds the SYM tokens in the source file to the destination file.

+  The SYM tokens are updated to reflect the base address.

+

+Arguments:

+

+  BaseAddress    - The base address for the new SYM tokens.

+  DestFileName   - The destination file.

+  SourceFileName - The source file.

+

+Returns:

+

+  EFI_SUCCESS             - The function completed successfully.

+  EFI_INVALID_PARAMETER   - One of the input parameters was invalid.

+  EFI_ABORTED             - An error occurred.

+

+--*/

+;

+

+EFI_STATUS

+CalculateFitTableChecksum (

+  VOID

+  )

+/*++

+  

+Routine Description:

+

+  This function will perform byte checksum on the FIT table, if the the checksum required

+  field is set to CheckSum required. If the checksum is not required then checksum byte

+  will have value as 0;.

+  

+Arguments:

+

+  NONE

+  

+Returns:

+

+  Status       - Value returned by call to CalculateChecksum8 ()

+  EFI_SUCCESS  - The function completed successfully

+    

+--*/

+;

+

+EFI_STATUS

+GenerateBsfImage (

+  IN  UINT64  StartAddress1,

+  IN  UINT64  Size1,

+  IN  UINT64  StartAddress2,

+  IN  UINT64  Size2

+  )

+/*++

+

+Routine Description:

+

+  This is the main function which will be called from application.

+

+Arguments:

+

+  StartAddress1  - The start address of the first BSF      

+  Size1          - The size of the first BSF

+  StartAddress2  - The start address of the second BSF      

+  Size2          - The size of the second BSF

+

+Returns:

+ 

+  EFI_OUT_OF_RESOURCES - Can not allocate memory

+  The return value can be any of the values 

+  returned by the calls to following functions:

+      GetBsfRelatedInfoFromInfFile

+      ProcessAndCreateBsf

+      UpdateIA32ResetVector

+      UpdateFfsHeader

+      WriteBsfBinary

+  

+--*/

+;

+

+EFI_STATUS

+PeimFixupInFitTable (

+  IN  UINT64  StartAddress

+  )

+/*++

+

+Routine Description:

+

+  This function is an entry point to fixup SAL-E entry point.

+

+Arguments:

+

+  StartAddress - StartAddress for PEIM.....

+    

+Returns:

+ 

+  EFI_SUCCESS   - The function completed successfully

+  EFI_ABORTED   - Error Opening File 

+

+--*/

+;

+

+EFI_STATUS

+Generate32BsfImage (

+IN  UINT64  BootFileStartAddress

+  )

+/*++

+

+Routine Description:

+

+  This is the main IA32 function which will be called from application.

+  (Now this tool is not used for IA32 platform, if it will be used in future,

+  the relative functions need to be updated, the updating can refer to IPF 

+  functions)

+

+Arguments:

+

+  BootFileStartAddress   - Top Address of Boot File

+

+Returns:

+ 

+  The return value can be any of the values 

+  returned by the calls to following functions:

+      Get32BsfRelatedInfoFromInfFile

+      CreateBsfBuffer

+      ProcessAndCreate32Bsf

+      Update32FfsHeader

+      WriteBsfBinary

+  

+--*/

+;

+

+EFI_STATUS

+GetTotal32BsfSize(

+  IN  UINT32  *BsfSize 

+  )

+/*++

+

+Routine Description:

+

+  This function calculates total size for IA32 BSF which would be needed to create

+  the buffer. This will be done using Passed Info link list and looking for the

+  size of the components which belong to BSF. The addtional file header is accounted.

+

+Arguments:

+

+  BSFSize     - Pointer to the size of IA32 BSF 

+

+Returns:

+

+  EFI_ABORTED - Returned due to one of the following resons:

+                (a) Error Opening File

+  EFI_SUCCESS - The fuction completes successfully

+

+--*/

+;

+

+EFI_STATUS

+ProcessAndCreate32Bsf (

+  IN  UINT64  Size

+  )

+/*++

+

+Routine Description:

+

+  This function process the link list created during INF file parsing

+  and create component in IA32 BSF

+  

+Arguments:

+

+  Size   - Size of the Firmware Volume of which, this BSF belongs to.

+

+Returns:

+  

+  EFI_UNSUPPORTED - Unknown component type

+  EFI_SUCCESS     - The function completed successfully                 

+

+--*/

+;

+

+EFI_STATUS

+CreateAndUpdateSeccore (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for seccore and update them

+  in IA32 BSF Buffer

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_ABORTED           - Due to one of the following reasons:

+                           (a)Error Opening File

+                           (b)The PAL_A Size is more than specified size status

+                              One of the values mentioned below returned from 

+                              call to UpdateSymFile

+  EFI_SUCCESS           - The function completed successfully.

+  EFI_INVALID_PARAMETER - One of the input parameters was invalid.

+  EFI_ABORTED           - An error occurred.UpdateSymFile

+   

+--*/

+;

+

+EFI_STATUS

+CreateAndUpdate32Component (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the binary file for each components. Add it at aligned address.

+  

+Arguments:

+

+  BsfInfo    - Pointer to Parsed Info

+  

+Returns:

+

+  EFI_SUCCESS              - The function completed successful

+  EFI_ABORTED              - Aborted due to one of the many reasons like:

+                              (a) Component Size greater than the specified size.

+                              (b) Error opening files.

+  EFI_INVALID_PARAMETER    - Value returned from call to UpdateEntryPoint()

+  

+--*/

+;

+

+EFI_STATUS

+Update32FfsHeader(

+  IN      UINT32 BsfSize

+  )

+/*++

+

+Routine Description:

+

+  Update the Firmware Volume Buffer with requested buffer data

+

+Arguments:

+

+  BsfSize     - Size of the IA32 BSF

+

+Returns:

+  

+  EFI_SUCCESS            - The function completed successfully

+  EFI_INVALID_PARAMETER  - The Ffs File Header Pointer is NULL

+

+--*/

+;

+

+EFI_STATUS

+Get32BsfRelatedInfoFromInfFile (

+  IN  CHAR8 *FileName

+  )

+/*++

+  

+Routine Description:

+

+  This function reads the input file, parse it and create a list of tokens

+  which is parsed and used, to intialize the data related to IA32 BSF

+  

+Arguments:

+

+  FileName  FileName which needed to be read to parse data

+

+Returns:

+   

+  EFI_ABORTED            Error in opening file

+  EFI_INVALID_PARAMETER  File doesn't contain any valid informations

+  EFI_OUT_OF_RESOURCES   Malloc Failed

+  EFI_SUCCESS            The function completed successfully 

+

+--*/

+;

+

+VOID

+Initialize32InFileInfo (

+  VOID                     

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from IA32 INF file.

+

+Arguments:

+

+  NONE

+

+Returns:

+

+  NONE

+

+--*/

+;

+

+VOID 

+ParseAndUpdate32Components (

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+

+Routine Description:

+

+  This function intializes the relevant global variable which is being

+  used to store the information retrieved from INF file.

+  

+Arguments:

+

+  BsfInfo   - A pointer to the BSF Info Structure

+  

+

+Returns:

+

+  None

+

+--*/

+;

+

+EFI_STATUS

+Write32SoftFit(

+  IN CHAR8              *FileName,

+  IN  PARSED_BSF_INFO   *BsfInfo

+  )

+/*++

+

+Routine Description:

+

+  Write IA32 Firmware Volume component address from memory to a file.

+  

+Arguments:

+

+  FileName      Output File Name which needed to be created/

+  BsfInfo       Parsed info link

+  

+Returns:

+

+  EFI_ABORTED  - Returned due to one of the following resons:

+                  (a) Error Opening File

+                  (b) Failing to copy buffers

+  EFI_SUCCESS  - The fuction completes successfully

+

+--*/

+;

+

+#endif

diff --git a/Source/GenBsfImage/build.xml b/Source/GenBsfImage/build.xml
new file mode 100644
index 0000000..fe8f202
--- /dev/null
+++ b/Source/GenBsfImage/build.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenFvImage Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenBsfImage"/>

+  <property name="FileSet" value="GenBsfImage.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+    <if>

+      <istrue value="${OSX}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value=""/>

+      </then>

+    </if>

+

+    <if>

+      <istrue value="${cygwin}"/>

+      <then>

+        <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${msft}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${linux}"/>

+      <then>

+        <if>

+          <istrue value="${x86_64_linux}"/>

+          <then>

+            <property name="syslibdirs" value="/lib64"/>

+          </then>

+          <else>

+            <property name="syslibdirs" value="/usr/lib"/>

+          </else>

+        </if>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    <echo message="syslibdirs set to: ${syslibdirs}"/>

+  </target>

+

+  <target name="Tool" depends="init, GenBsfImage"/>

+

+  <target name="GenBsfImage" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_IA32_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/${ToolName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+

+      <!-- <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>

+      <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>

+      <syslibset libs="RpcRT4" if="msft"/> -->

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenCRC32Section/GenCRC32Section.c b/Source/GenCRC32Section/GenCRC32Section.c
new file mode 100644
index 0000000..b99cf2f
--- /dev/null
+++ b/Source/GenCRC32Section/GenCRC32Section.c
@@ -0,0 +1,286 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+    GenCRC32Section.c

+

+Abstract:

+

+  This file contains functions required to generate a Firmware File System 

+  file. The code is compliant with the Tiano C Coding standards.

+

+--*/

+

+#include "GenCRC32Section.h"

+

+#define TOOLVERSION   "0.2"

+

+#define UTILITY_NAME  "GenCrc32Section"

+

+EFI_GUID  gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;

+

+EFI_STATUS

+SignSectionWithCrc32 (

+  IN OUT UINT8  *FileBuffer,

+  IN OUT UINT32 *BufferSize,

+  IN UINT32     DataSize

+  )

+/*++

+        

+Routine Description:

+           

+  Signs the section with CRC32 and add GUIDed section header for the 

+  signed data. data stays in same location (overwrites source data).

+            

+Arguments:

+               

+  FileBuffer  - Buffer containing data to sign

+                

+  BufferSize  - On input, the size of FileBuffer. On output, the size of 

+                actual section data (including added section header).              

+

+  DataSize    - Length of data to Sign

+

+  Key         - Key to use when signing. Currently only CRC32 is supported.

+                                       

+Returns:

+                       

+  EFI_SUCCESS           - Successful

+  EFI_OUT_OF_RESOURCES  - Not enough resource to complete the operation.

+                        

+--*/

+{

+

+  UINT32                Crc32Checksum;

+  EFI_STATUS            Status;

+  UINT32                TotalSize;

+  CRC32_SECTION_HEADER  Crc32Header;

+  UINT8                 *SwapBuffer;

+

+  Crc32Checksum = 0;

+  SwapBuffer    = NULL;

+

+  if (DataSize == 0) {

+    *BufferSize = 0;

+

+    return EFI_SUCCESS;

+  }

+

+  Status = CalculateCrc32 (FileBuffer, DataSize, &Crc32Checksum);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  TotalSize = DataSize + CRC32_SECTION_HEADER_SIZE;

+  Crc32Header.GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;

+  Crc32Header.GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalSize & 0xff);

+  Crc32Header.GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalSize & 0xff00) >> 8);

+  Crc32Header.GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalSize & 0xff0000) >> 16);

+  memcpy (&(Crc32Header.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));

+  Crc32Header.GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;

+  Crc32Header.GuidSectionHeader.DataOffset  = CRC32_SECTION_HEADER_SIZE;

+  Crc32Header.CRC32Checksum                 = Crc32Checksum;

+

+  SwapBuffer = (UINT8 *) malloc (DataSize);

+  if (SwapBuffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  memcpy (SwapBuffer, FileBuffer, DataSize);

+  memcpy (FileBuffer, &Crc32Header, CRC32_SECTION_HEADER_SIZE);

+  memcpy (FileBuffer + CRC32_SECTION_HEADER_SIZE, SwapBuffer, DataSize);

+

+  //

+  // Make sure section ends on a DWORD boundary

+  //

+  while ((TotalSize & 0x03) != 0) {

+    FileBuffer[TotalSize] = 0;

+    TotalSize++;

+  }

+

+  *BufferSize = TotalSize;

+

+  if (SwapBuffer != NULL) {

+    free (SwapBuffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+{

+  printf ("Usage:\n");

+  printf (UTILITY_NAME " -i \"inputfile1\" \"inputfile2\" -o \"outputfile\" \n");

+  printf ("   -i \"inputfile\":\n ");

+  printf ("       specifies the input files that would be signed to CRC32 Guided section.\n");

+  printf ("   -o \"outputfile\":\n");

+  printf ("       specifies the output file that is a CRC32 Guided section.\n");

+}

+

+INT32

+ReadFilesContentsIntoBuffer (

+  IN      CHAR8   *argv[],

+  IN      INT32   Start,

+  IN OUT  UINT8   **FileBuffer,

+  IN OUT  UINT32  *BufferSize,

+  OUT     UINT32  *ContentSize,

+  IN      INT32   MaximumArguments

+  )

+{

+  INT32   Index;

+  CHAR8   *FileName;

+  FILE    *InputFile;

+  UINT8   Temp;

+  UINT32  Size;

+

+  FileName  = NULL;

+  InputFile = NULL;

+  Size      = 0;

+  Index     = 0;

+

+  //

+  // read all input files into one file buffer

+  //

+  while (argv[Start + Index][0] != '-') {

+

+    FileName  = argv[Start + Index];

+    InputFile = fopen (FileName, "rb");

+    if (InputFile == NULL) {

+      Error (NULL, 0, 0, FileName, "failed to open input binary file");

+      return -1;

+    }

+

+    fread (&Temp, sizeof (UINT8), 1, InputFile);

+    while (!feof (InputFile)) {

+      (*FileBuffer)[Size++] = Temp;

+      fread (&Temp, sizeof (UINT8), 1, InputFile);

+    }

+

+    fclose (InputFile);

+    InputFile = NULL;

+

+    //

+    // Make sure section ends on a DWORD boundary

+    //

+    while ((Size & 0x03) != 0) {

+      (*FileBuffer)[Size] = 0;

+      Size++;

+    }

+

+    Index++;

+    if (Index == MaximumArguments) {

+      break;

+    }

+  }

+

+  *ContentSize = Size;

+  return Index;

+}

+

+int

+main (

+  INT32 argc,

+  CHAR8 *argv[]

+  )

+{

+  FILE        *OutputFile;

+  UINT8       *FileBuffer;

+  UINT32      BufferSize;

+  EFI_STATUS  Status;

+  UINT32      ContentSize;

+  CHAR8       *OutputFileName;

+  INT32       ReturnValue;

+  INT32       Index;

+

+  OutputFile      = NULL;

+  FileBuffer      = NULL;

+  ContentSize     = 0;

+  OutputFileName  = NULL;

+

+  SetUtilityName (UTILITY_NAME);

+

+  if (argc == 1) {

+    PrintUsage ();

+    return -1;

+  }

+

+  BufferSize  = 1024 * 1024 * 16;

+  FileBuffer  = (UINT8 *) malloc (BufferSize * sizeof (UINT8));

+  if (FileBuffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failed", NULL);

+    return -1;

+  }

+

+  ZeroMem (FileBuffer, BufferSize);

+

+  for (Index = 0; Index < argc; Index++) {

+    if (strcmpi (argv[Index], "-i") == 0) {

+      ReturnValue = ReadFilesContentsIntoBuffer (

+                      argv,

+                      (Index + 1),

+                      &FileBuffer,

+                      &BufferSize,

+                      &ContentSize,

+                      (argc - (Index + 1))

+                      );

+      if (ReturnValue == -1) {

+        Error (NULL, 0, 0, "failed to read file contents", NULL);

+        return -1;

+      }

+

+      Index += ReturnValue;

+    }

+

+    if (strcmpi (argv[Index], "-o") == 0) {

+      OutputFileName = argv[Index + 1];

+    }

+  }

+

+  OutputFile = fopen (OutputFileName, "wb");

+  if (OutputFile == NULL) {

+    Error (NULL, 0, 0, OutputFileName, "failed to open output binary file");

+    free (FileBuffer);

+    return -1;

+  }

+

+  /*  

+  //

+  // make sure section ends on a DWORD boundary ??

+  //

+  while ( (Size & 0x03) != 0 ) {

+    FileBuffer[Size] = 0;

+    Size ++;

+  }

+*/

+  Status = SignSectionWithCrc32 (FileBuffer, &BufferSize, ContentSize);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "failed to sign section", NULL);

+    free (FileBuffer);

+    fclose (OutputFile);

+    return -1;

+  }

+

+  ContentSize = fwrite (FileBuffer, sizeof (UINT8), BufferSize, OutputFile);

+  if (ContentSize != BufferSize) {

+    Error (NULL, 0, 0, "failed to write output buffer", NULL);

+    ReturnValue = -1;

+  } else {

+    ReturnValue = 0;

+  }

+

+  free (FileBuffer);

+  fclose (OutputFile);

+  return ReturnValue;

+}

diff --git a/Source/GenCRC32Section/GenCRC32Section.h b/Source/GenCRC32Section/GenCRC32Section.h
new file mode 100644
index 0000000..1cf976b
--- /dev/null
+++ b/Source/GenCRC32Section/GenCRC32Section.h
@@ -0,0 +1,63 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenCRC32Section.h 

+

+Abstract:

+

+  Header file for GenFfsFile. Mainly defines the header of section

+  header for CRC32 GUID defined sections. Share with GenSection.c

+

+--*/

+

+//

+// External Files Referenced

+//

+

+/* Standard Headers */

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <assert.h>

+

+/* MDE Headers */

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Protocol/GuidedSectionExtraction.h>

+

+/* Tool Headers */

+#include "CommonLib.h"

+#include "Crc32.h"

+#include "EfiCompress.h"

+#include "EfiUtilityMsgs.h"

+#include "ParseInf.h"

+

+//

+// Module Coded to Tiano Coding Conventions

+//

+#ifndef _EFI_GEN_CRC32_SECTION_H

+#define _EFI_GEN_CRC32_SECTION_H

+

+

+typedef struct {

+  EFI_GUID_DEFINED_SECTION  GuidSectionHeader;

+  UINT32                    CRC32Checksum;

+} CRC32_SECTION_HEADER;

+

+#define EFI_SECTION_CRC32_GUID_DEFINED  0

+#define CRC32_SECTION_HEADER_SIZE       (sizeof (CRC32_SECTION_HEADER))

+

+#endif

diff --git a/Source/GenCRC32Section/build.xml b/Source/GenCRC32Section/build.xml
new file mode 100644
index 0000000..3ec9ce5
--- /dev/null
+++ b/Source/GenCRC32Section/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenCRC32Section Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenCRC32Section"/>

+  <property name="FileSet" value="GenCRC32Section.c GenCRC32Section.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenCapsuleHdr/CreateGuid.c b/Source/GenCapsuleHdr/CreateGuid.c
new file mode 100644
index 0000000..2a984fa
--- /dev/null
+++ b/Source/GenCapsuleHdr/CreateGuid.c
@@ -0,0 +1,50 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  CreateGuid.c  

+

+Abstract:

+

+  Library routine to create a GUID

+

+--*/

+

+#include <windows.h>

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+void

+CreateGuid (

+  GUID *Guid

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Guid  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  CoCreateGuid (Guid);

+}

diff --git a/Source/GenCapsuleHdr/GenCapsuleHdr.c b/Source/GenCapsuleHdr/GenCapsuleHdr.c
new file mode 100644
index 0000000..d1f55b9
--- /dev/null
+++ b/Source/GenCapsuleHdr/GenCapsuleHdr.c
@@ -0,0 +1,2674 @@
+/*++

+

+Copyright (c)  2002-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  GenCapsuleHdr.c  

+

+Abstract:

+

+  Generate a capsule header for a file, and optionally prepend the

+  header to a file or list of files.

+

+--*/

+

+#define _UNICODE

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/MultiPhase.h>

+#include <Common/Capsule.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Common/FirmwareFileSystem.h>  // for FV header GUID

+#include <Guid/Capsule.h>

+#include <Guid/FirmwareFileSystem.h>  // for FV header GUID

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+

+#define MAX_PATH                  256

+#define PROGRAM_NAME              "GenCapsuleHdr"

+

+#define UNICODE_BACKSLASH         L'\\'

+#define UNICODE_FILE_START        0xFEFF

+#define UNICODE_CR                0x000D

+#define UNICODE_LF                0x000A

+#define UNICODE_NULL              0x0000

+#define UNICODE_SPACE             L' '

+#define UNICODE_SLASH             L'/'

+#define UNICODE_DOUBLE_QUOTE      L'"'

+#define UNICODE_A                 L'A'

+#define UNICODE_F                 L'F'

+#define UNICODE_Z                 L'Z'

+#define UNICODE_a                 L'a'

+#define UNICODE_f                 L'f'

+#define UNICODE_z                 L'z'

+#define UNICODE_0                 L'0'

+#define UNICODE_9                 L'9'

+#define UNICODE_TAB               L'\t'

+

+#define OEM_HEADER_STRING         L"OemHeader"

+#define AUTHOR_INFO_STRING        L"AuthorInfo"

+#define REVISION_INFO_STRING      L"RevisionInfo"

+#define SHORT_DESCRIPTION_STRING  L"ShortDescription"

+#define LONG_DESCRIPTION_STRING   L"LongDescription"

+#define EQUAL_STRING              L"="

+#define OPEN_BRACE_STRING         L"{"

+#define CLOSE_BRACE_STRING        L"}"

+#define GUID_STRING               L"GUID"

+#define DATA_STRING               L"DATA"

+

+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)

+#define UEFI_CAPSULE_HEADER_NO_FALAGS      0

+#define UEFI_CAPSULE_HEADER_RESET_FALAGS   CAPSULE_FLAGS_PERSIST_ACROSS_RESET

+#define UEFI_CAPSULE_HEADER_ALL_FALAGS     (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)

+#endif

+

+typedef wchar_t WCHAR;

+

+typedef struct _FILE_LIST {

+  struct _FILE_LIST *Next;

+  INT8              FileName[MAX_PATH];

+} FILE_LIST;

+

+typedef struct _SIZE_LIST {

+  struct _SIZE_LIST *Next;

+  UINT32            Size;

+} SIZE_LIST;

+

+typedef struct {

+  INT8    FileName[MAX_PATH];

+  WCHAR   *FileBuffer;

+  WCHAR   *FileBufferPtr;

+  UINT32  FileSize;

+  FILE    *FilePtr;

+  BOOLEAN EndOfFile;

+  UINT32  LineNum;

+} SOURCE_FILE;

+

+//

+// Here's all our globals.

+//

+static struct {

+  BOOLEAN   Dump;

+  BOOLEAN   Verbose;

+  BOOLEAN   JoinMode;

+  INT8      ScriptFileName[MAX_PATH];

+  INT8      OutputFileName[MAX_PATH];

+  FILE_LIST *FileList;

+  FILE      *OutFptr;

+  SIZE_LIST *SizeList;

+  SIZE_LIST *LastSize;

+  SIZE_LIST *CurrentSize;

+} mOptions;

+

+static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;

+

+void

+CreateGuid (

+  EFI_GUID *Guid

+  );

+

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  );

+

+static

+void

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+STATUS

+GetHexValue (

+  SOURCE_FILE  *SourceFile,

+  UINT32       *Value,

+  UINT32       NumDigits

+  );

+

+static

+BOOLEAN

+GetSplitFileName (

+  INT8    *BaseFileName,

+  INT8    *NewFileName,

+  UINT32  SequenceNumber

+  );

+

+static

+STATUS

+SplitCapsule (

+  INT8 *CapsuleFileName

+  );

+

+static

+void

+Usage (

+  VOID

+  );

+

+static

+void

+DumpCapsule (

+  VOID

+  );

+

+static

+STATUS

+JoinCapsule (

+  VOID

+  );

+

+static

+STATUS

+DumpCapsuleHeaderStrings (

+  UINT8   *SectionName,

+  WCHAR   *Buffer

+  );

+

+static

+STATUS

+CheckFirmwareVolumeHeader (

+  INT8    *FileName,

+  INT8    *Buffer,

+  UINT32  BufferSize

+  );

+

+static

+BOOLEAN

+IsToken (

+  SOURCE_FILE *File,

+  WCHAR       *Token

+  );

+

+static

+BOOLEAN

+GetNumber (

+  INT8    *Str,

+  UINT32  *Value

+  );

+

+static

+STATUS

+ProcessScriptFile (

+  INT8                *ScriptFileName,

+  FILE                *OutFptr,

+  EFI_CAPSULE_HEADER  *CapsuleHeader

+  );

+

+static

+STATUS

+ParseCapsuleInfo (

+  SOURCE_FILE       *SourceFile,

+  FILE              *OutFptr,

+  WCHAR             *SectionName

+  );

+

+static

+STATUS

+CreateCapsule (

+  VOID

+  );

+

+static

+STATUS

+ParseOemInfo (

+  SOURCE_FILE       *SourceFile,

+  FILE              *OutFptr

+  );

+

+static

+BOOLEAN

+IsWhiteSpace (

+  WCHAR Char

+  );

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *File

+  );

+

+int

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+  Call the routine to process the command-line arguments, then

+  dispatch to the appropriate function.

+  

+Arguments:

+  Standard C main() argc and argv.

+

+Returns:

+  0      if successful

+  nonzero otherwise

+  

+--*/

+// GC_TODO:    Argc - add argument and description to function comment

+// GC_TODO:    ] - add argument and description to function comment

+{

+  STATUS    Status;

+  FILE_LIST *NextFile;

+  //

+  // Specify our program name to the error printing routines.

+  //

+  SetUtilityName (PROGRAM_NAME);

+  //

+  // Process the command-line arguments

+  //

+  Status = ProcessArgs (Argc, Argv);

+  if (Status == STATUS_SUCCESS) {

+    if (mOptions.Dump) {

+      DumpCapsule ();

+    } else if (mOptions.JoinMode) {

+      JoinCapsule ();

+    } else {

+      CreateCapsule ();

+    }

+  }

+  //

+  // Cleanup

+  //

+  while (mOptions.FileList != NULL) {

+    NextFile = mOptions.FileList->Next;

+    free (mOptions.FileList);

+    mOptions.FileList = NextFile;

+  }

+

+  while (mOptions.SizeList != NULL) {

+    mOptions.CurrentSize = mOptions.SizeList->Next;

+    free (mOptions.SizeList);

+    mOptions.SizeList = mOptions.CurrentSize;

+  }

+

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+CreateCapsule (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  FILE                        *InFptr;

+  FILE_LIST                   *FileList;

+  INT8                        *Buffer;

+  UINT32                      Size;

+  EFI_CAPSULE_HEADER          CapsuleHeader;

+  UINT8                       Zero;

+  UINT8                       FirstFile;

+  UINT32                      CapsuleHeaderSize;

+  long                        InsertedBlockMapEntryOffset;

+  EFI_FV_BLOCK_MAP_ENTRY      InsertedBlockMapEntry;

+  UINT64                      FirmwareVolumeSize;

+  long                        FileSize;

+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;

+

+  Buffer                      = NULL;

+  InFptr                      = NULL;

+  FirmwareVolumeSize          = 0;

+  CapsuleHeaderSize           = 0;

+  InsertedBlockMapEntryOffset = 0;

+  memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY));

+  memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER));

+

+  if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader));

+  memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID));

+  CapsuleHeader.HeaderSize        = sizeof (EFI_CAPSULE_HEADER);

+  CapsuleHeader.CapsuleImageSize  = sizeof (EFI_CAPSULE_HEADER);

+  if (mOptions.ScriptFileName[0] != 0) {

+    if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) {

+      goto Done;

+    }

+  } else {

+    //

+    // Insert a default capsule header

+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)

+    CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);

+    CapsuleHeader.Flags   = UEFI_CAPSULE_HEADER_ALL_FALAGS;

+#endif

+    CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER);

+

+   if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {

+     Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+     goto Done;

+   }

+ }

+

+  CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody;

+  //

+  // Now copy the contents of any other files specified on the command

+  // line to the output file. Files must be FFS files, which are aligned

+  // on 8-byte boundaries. Don't align the first file, since it's the start

+  // of the image once the capsule header has been removed.

+  //

+  FileList  = mOptions.FileList;

+  FirstFile = 1;

+  Zero      = 0;

+  while (FileList != NULL) {

+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");

+      goto Done;

+    }

+    //

+    // Allocate a buffer into which we can read the file.

+    //

+    fseek (InFptr, 0, SEEK_END);

+    Size = ftell (InFptr);

+    rewind (InFptr);

+    Buffer = (char *) malloc (Size);

+    if (Buffer == NULL) {

+      Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");

+      goto Done;

+    }

+

+    if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");

+      goto Done;

+    }

+

+    if (Size > 0) {

+      //

+      // Align the write of the first bytes from the file if not the first file

+      //

+      if (FirstFile) {

+        //

+        // First file must be a firmware volume. Double-check, and then insert

+        // an additional block map entry so we can add more files from the command line

+        //

+        if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) {

+          goto Done;

+        }

+        //

+        // Save a copy of the firmware volume header for later

+        //

+        memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER));

+        FirmwareVolumeSize = FVHeader.FvLength;

+        if (FileList->Next != NULL) {

+          //

+          // Copy the firmware volume header

+          //

+          InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength;

+          if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) {

+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+            goto Done;

+          }

+

+          if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) {

+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+            goto Done;

+          }

+

+          if (fwrite (

+                Buffer + FVHeader.HeaderLength,

+                Size - FVHeader.HeaderLength,

+                1,

+                mOptions.OutFptr

+                ) != 1) {

+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+            goto Done;

+          }

+        } else {

+          //

+          // Copy the file contents as-is

+          //

+          if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {

+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+            goto Done;

+          }

+        }

+      } else {

+        while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) {

+          if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) {

+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+            goto Done;

+          }

+        }

+

+        if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {

+          Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+          goto Done;

+        }

+      }

+

+      FirstFile = 0;

+    }

+

+    free (Buffer);

+    Buffer = NULL;

+    fclose (InFptr);

+    InFptr    = NULL;

+    FileList  = FileList->Next;

+  }

+

+Done:

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+  //

+  // If we inserted an additional block map entry, then fix it up. Fix up the

+  // FV header as well to reflect our new size.

+  //

+  if (InsertedBlockMapEntryOffset != 0) {

+    FileSize                        = ftell (mOptions.OutFptr);

+    InsertedBlockMapEntry.NumBlocks = 1;

+    InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY));

+    fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET);

+    fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);

+    //

+    // Fix up the firmware volume header and write it out

+    //

+    fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET);

+    FVHeader.FvLength = FileSize - CapsuleHeaderSize;

+    FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY);

+    fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);

+    //

+    // Reposition to the end of the file

+    //

+  }

+  //

+  // Close files and free the global string lists we allocated memory for

+  //

+  if (mOptions.OutFptr != NULL) {

+    //

+    // We should now know the full capsule image size. Update the header and write it again.

+    //

+    fseek (mOptions.OutFptr, 0, SEEK_END);

+    Size  = ftell (mOptions.OutFptr);

+    CapsuleHeader.CapsuleImageSize = Size;

+    fseek (mOptions.OutFptr, 0, SEEK_SET);

+    if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {

+      Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+    }

+

+    fseek (mOptions.OutFptr, 0, SEEK_END);

+    fclose (mOptions.OutFptr);

+    mOptions.OutFptr = NULL;

+  }

+  //

+  // If they are doing split capsule output, then split it up now.

+  //

+  if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) {

+    SplitCapsule (mOptions.OutputFileName);

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+ProcessScriptFile (

+  INT8                *ScriptFileName,

+  FILE                *OutFptr,

+  EFI_CAPSULE_HEADER  *CapsuleHeader

+  )

+/*++

+

+Routine Description:

+  Parse a capsule header script file.

+

+Arguments:

+  ScriptFileName    - name of script file to parse

+  OutFptr           - output to dump binary data

+  CapsuleHeader     - capsule header to update with size info

+                      of parsed fields in the script file

+

+Returns:

+  STATUS_SUCCESS - if all went well

+

+--*/

+{

+#if 0

+  STATUS      Status;

+  SOURCE_FILE SourceFile;

+  WCHAR       *WScriptFileName;

+  BOOLEAN     InComment;

+

+  if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write capsule header to output file", NULL);

+    return STATUS_ERROR;

+  }

+

+  memset (&SourceFile, 0, sizeof (SOURCE_FILE));

+  strcpy (SourceFile.FileName, ScriptFileName);

+

+  Status = STATUS_ERROR;

+  //

+  // Open the input unicode script file and read it into a buffer

+  //

+  WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR));

+  if (WScriptFileName == NULL) {

+    Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);

+    return STATUS_ERROR;

+  }

+

+  swprintf (WScriptFileName, L"%S", ScriptFileName);

+  if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) {

+    free (WScriptFileName);

+    Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading");

+    goto Done;

+  }

+

+  free (WScriptFileName);

+  fseek (SourceFile.FilePtr, 0, SEEK_END);

+  SourceFile.FileSize = ftell (SourceFile.FilePtr);

+  rewind (SourceFile.FilePtr);

+  SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR));

+  if (SourceFile.FileBuffer == NULL) {

+    Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents");

+    goto Done;

+  }

+

+  if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) {

+    Error (NULL, 0, 0, ScriptFileName, "failed to read file contents");

+    goto Done;

+  }

+

+  SourceFile.FileBufferPtr  = SourceFile.FileBuffer;

+  SourceFile.LineNum        = 1;

+  if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) {

+    Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL);

+    goto Done;

+  }

+

+  SourceFile.FileBufferPtr++;

+  SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0;

+  //

+  // Walk the source file buffer and replace all carriage returns with 0 so

+  // we can print from the file contents on parse errors.

+  //

+  InComment = 0;

+  while (!EndOfFile (&SourceFile)) {

+    if (SourceFile.FileBufferPtr[0] == UNICODE_CR) {

+      SourceFile.FileBufferPtr[0] = 0;

+      InComment                   = 0;

+    } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) {

+      InComment = 0;

+    } else if (InComment) {

+      SourceFile.FileBufferPtr[0] = UNICODE_SPACE;

+    } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) {

+      InComment                   = 1;

+      SourceFile.FileBufferPtr[0] = UNICODE_SPACE;

+    }

+

+    SourceFile.FileBufferPtr++;

+  }

+  //

+  // Reposition to the start of the file, but skip over the unicode file start

+  //

+  SourceFile.FileBufferPtr = SourceFile.FileBuffer;

+  SourceFile.FileBufferPtr++;

+  SourceFile.EndOfFile                    = 0;

+  CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr);

+  //

+  // Parse the OEM bytes

+  //

+  if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) {

+    goto Done;

+  }

+  //

+  // Parse the author information

+  //

+  CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr);

+  if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) {

+    goto Done;

+  }

+  //

+  // Parse the revision information

+  //

+  CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr);

+  if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) {

+    goto Done;

+  }

+  //

+  // Parse the short description

+  //

+  CapsuleHeader->OffsetToShortDescription = ftell (OutFptr);

+  if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) {

+    goto Done;

+  }

+  //

+  // Parse the long description

+  //

+  CapsuleHeader->OffsetToLongDescription = ftell (OutFptr);

+  if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) {

+    goto Done;

+  }

+  //

+  // Better be end of contents

+  //

+  SkipWhiteSpace (&SourceFile);

+  if (!EndOfFile (&SourceFile)) {

+    Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr);

+    goto Done;

+  }

+

+  CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr);

+  rewind (OutFptr);

+  fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr);

+  fseek (OutFptr, 0, SEEK_END);

+  Status = STATUS_SUCCESS;

+Done:

+  if (SourceFile.FilePtr != NULL) {

+    fclose (SourceFile.FilePtr);

+  }

+

+  if (SourceFile.FileBuffer != NULL) {

+    free (SourceFile.FileBuffer);

+  }

+

+  return Status;

+

+#endif

+  return STATUS_SUCCESS;

+}

+//

+// Parse the OEM data of format:

+//      OemInfo {

+//            GUID = 12345676-1234-1234-123456789ABC

+//            DATA = 0x01, 0x02, 0x03...

+//      }

+//

+static

+STATUS

+ParseOemInfo (

+  SOURCE_FILE       *SourceFile,

+  FILE              *OutFptr

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  SourceFile  - GC_TODO: add argument description

+  OutFptr     - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  long                    OemHeaderOffset;

+  UINT32                  Data;

+  EFI_CAPSULE_OEM_HEADER  OemHeader;

+  STATUS                  Status;

+  UINT32                  DigitCount;

+  WCHAR                   *SaveFilePos;

+  UINT8                   ByteData;

+

+  Status = STATUS_ERROR;

+  memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER));

+  OemHeaderOffset       = ftell (OutFptr);

+  OemHeader.HeaderSize  = sizeof (EFI_CAPSULE_OEM_HEADER);

+  if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, OEM_HEADER_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      OEM_HEADER_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, EQUAL_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      EQUAL_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      OPEN_BRACE_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+  //

+  // Look for:  GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx

+  //

+  if (!IsToken (SourceFile, GUID_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      GUID_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, EQUAL_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      EQUAL_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+  //

+  // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID

+  //

+  SkipWhiteSpace (SourceFile);

+  if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);

+    goto Done;

+  }

+

+  OemHeader.OemGuid.Data1 = Data;

+  if (!IsToken (SourceFile, L"-")) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected dash in GUID, not %S",

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+  //

+  // Get 3 word values

+  //

+  for (DigitCount = 0; DigitCount < 3; DigitCount++) {

+    if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);

+      goto Done;

+    }

+

+    switch (DigitCount) {

+    case 0:

+      OemHeader.OemGuid.Data2 = (UINT16) Data;

+      break;

+

+    case 1:

+      OemHeader.OemGuid.Data3 = (UINT16) Data;

+      break;

+

+    case 2:

+      OemHeader.OemGuid.Data4[1]  = (UINT8) Data;

+      OemHeader.OemGuid.Data4[0]  = (UINT8) (Data >> 8);

+      break;

+    }

+

+    if (!IsToken (SourceFile, L"-")) {

+      Error (

+        SourceFile->FileName,

+        SourceFile->LineNum,

+        0,

+        NULL,

+        "expected dash in GUID, not %S",

+        SourceFile->FileBufferPtr

+        );

+      goto Done;

+    }

+  }

+  //

+  // Pick up the last 6 bytes of the GUID

+  //

+  SaveFilePos = SourceFile->FileBufferPtr;

+  for (DigitCount = 0; DigitCount < 6; DigitCount++) {

+    if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);

+      goto Done;

+    }

+

+    OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data;

+  }

+  //

+  // Now read raw OEM data bytes. May or may not be present.

+  //    DATA = 0x01, 0x02, 0x02...

+  //

+  if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {

+    Status = STATUS_SUCCESS;

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, DATA_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      DATA_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, EQUAL_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      EQUAL_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  while (!EndOfFile (SourceFile)) {

+    if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {

+      Status = STATUS_SUCCESS;

+      goto Done;

+    }

+

+    if (IsToken (SourceFile, L"0x")) {

+      if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) {

+        Error (

+          SourceFile->FileName,

+          SourceFile->LineNum,

+          0,

+          NULL,

+          "expected hex byte value, not %.20S",

+          SourceFile->FileBufferPtr

+          );

+        goto Done;

+      }

+

+      if (Data &~0xFF) {

+        Error (

+          SourceFile->FileName,

+          SourceFile->LineNum,

+          0,

+          NULL,

+          "expected byte hex byte value at %.20S",

+          SourceFile->FileBufferPtr

+          );

+        goto Done;

+      }

+      //

+      // Skip over the hex digits, then write the data

+      //

+      while (iswxdigit (SourceFile->FileBufferPtr[0])) {

+        SourceFile->FileBufferPtr++;

+      }

+

+      ByteData = (UINT8) Data;

+      if (fwrite (&ByteData, 1, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, "failed to write OEM data to output file", NULL);

+        goto Done;

+      }

+

+      OemHeader.HeaderSize++;

+      //

+      // Optional comma

+      //

+      IsToken (SourceFile, L",");

+    } else {

+      Error (

+        SourceFile->FileName,

+        SourceFile->LineNum,

+        0,

+        NULL,

+        "expected hex OEM data, not %.20S",

+        SourceFile->FileBufferPtr

+        );

+      goto Done;

+    }

+  }

+

+  if (EndOfFile (SourceFile)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S close to OEM header data",

+      CLOSE_BRACE_STRING

+      );

+    goto Done;

+  }

+

+  Status = STATUS_SUCCESS;

+Done:

+  //

+  // re-write the oem header if no errors

+  //

+  if (Status == STATUS_SUCCESS) {

+    fseek (OutFptr, OemHeaderOffset, SEEK_SET);

+    if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {

+      Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);

+      goto Done;

+    }

+

+    fseek (OutFptr, 0, SEEK_END);

+  }

+

+  return Status;

+}

+

+static

+STATUS

+ParseCapsuleInfo (

+  SOURCE_FILE       *SourceFile,

+  FILE              *OutFptr,

+  WCHAR             *SectionName

+  )

+// GC_TODO: function comment should start with '/*++'

+//

+// GC_TODO: function comment is missing 'Routine Description:'

+// GC_TODO: function comment is missing 'Arguments:'

+// GC_TODO: function comment is missing 'Returns:'

+// GC_TODO:    SourceFile - add argument and description to function comment

+// GC_TODO:    OutFptr - add argument and description to function comment

+// GC_TODO:    SectionName - add argument and description to function comment

+// Parse:  eng "string " "parts"

+//          spa "string " "parts"

+// Write out: "eng string parts\0spa string parts\0\0

+//

+{

+  STATUS  Status;

+  int     StringCount;

+  WCHAR   Zero;

+  WCHAR   Spacebar;

+

+  Status    = STATUS_ERROR;

+  Zero      = 0;

+  Spacebar  = UNICODE_SPACE;

+

+  if (!IsToken (SourceFile, SectionName)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      SectionName,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, EQUAL_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      EQUAL_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      NULL,

+      "expected %S, not %.20S",

+      OPEN_BRACE_STRING,

+      SourceFile->FileBufferPtr

+      );

+    goto Done;

+  }

+

+  while (!EndOfFile (SourceFile)) {

+    if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {

+      break;

+    }

+    //

+    // Look for language identifier (3 lowercase chars)

+    //

+    if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) &&

+        (SourceFile->FileBufferPtr[0] <= UNICODE_z) &&

+        (SourceFile->FileBufferPtr[1] >= UNICODE_a) &&

+        (SourceFile->FileBufferPtr[1] <= UNICODE_z) &&

+        (SourceFile->FileBufferPtr[2] >= UNICODE_a) &&

+        (SourceFile->FileBufferPtr[2] <= UNICODE_z) &&

+        IsWhiteSpace (SourceFile->FileBufferPtr[3])

+          ) {

+      //

+      // Write the 3 chars followed by a spacebar, and then look for opening quote

+      //

+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);

+      SourceFile->FileBufferPtr++;

+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);

+      SourceFile->FileBufferPtr++;

+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);

+      SourceFile->FileBufferPtr++;

+      fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr);

+      StringCount = 0;

+      while (IsToken (SourceFile, L"\"")) {

+        StringCount++;

+        while (!EndOfFile (SourceFile)) {

+          if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {

+            SourceFile->FileBufferPtr++;

+            break;

+          } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) {

+            Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL);

+            goto Done;

+          } else {

+            fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);

+            SourceFile->FileBufferPtr++;

+          }

+        }

+      }

+

+      if (StringCount == 0) {

+        Error (

+          SourceFile->FileName,

+          SourceFile->LineNum,

+          0,

+          NULL,

+          "expected quoted string, not %.20S",

+          SourceFile->FileBufferPtr

+          );

+        goto Done;

+      }

+      //

+      // This string's null terminator

+      //

+      fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);

+    } else {

+      Error (

+        SourceFile->FileName,

+        SourceFile->LineNum,

+        0,

+        NULL,

+        "expected valid language identifer, not %.20S",

+        SourceFile->FileBufferPtr

+        );

+      goto Done;

+    }

+  }

+  //

+  // Double null terminator

+  //

+  fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);

+  Status = STATUS_SUCCESS;

+Done:

+  return Status;

+}

+

+static

+STATUS

+SplitCapsule (

+  INT8    *CapsuleFileName

+  )

+/*++

+

+Routine Description:

+  We've created an entire capsule image. Now split it up into the 

+  size pieces they requested.

+

+Arguments:

+  CapsuleFileName  - name of an existing capsule file on disk

+

+Returns:

+  STATUS_SUCCESS - if no problems

+

+Notes:

+  This implementation reads in the entire capsule image from

+  disk, then overwrites the original file with the first

+  in the series.

+

+--*/

+{

+#if 0

+  EFI_CAPSULE_HEADER  *CapHdr;

+

+  EFI_CAPSULE_HEADER  Hdr;

+  FILE                *CapFptr;

+  FILE                *OutFptr;

+  UINT32              SizeLeft;

+  UINT32              CurrentSize;

+  UINT32              DataSize;

+  UINT32              SequenceNumber;

+  INT8                *Buffer;

+  INT8                FileName[MAX_PATH];

+  STATUS              Status;

+  UINT32              FileSize;

+  //

+  // Figure out the total size, then rewind the input file and

+  // read the entire thing in

+  //

+  if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) {

+    Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading");

+    return STATUS_ERROR;

+  }

+

+  OutFptr = NULL;

+  Status  = STATUS_SUCCESS;

+  fseek (CapFptr, 0, SEEK_END);

+  SizeLeft = ftell (CapFptr);

+  fseek (CapFptr, 0, SEEK_SET);

+  CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft);

+  if (CapHdr == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    goto FailDone;

+  }

+

+  if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read capsule contents", "split failed");

+    goto FailDone;

+  }

+

+  fclose (CapFptr);

+  CapFptr = NULL;

+  //

+  // Get a GUID to fill in the InstanceId GUID in the header

+  //

+  CreateGuid (&CapHdr->InstanceId);

+  SequenceNumber = 0;

+  //

+  // If the split size is larger than the original capsule image, then

+  // we're done.

+  //

+  if (mOptions.SizeList->Size >= SizeLeft) {

+    mOptions.SizeList->Size = SizeLeft;

+    goto Done;

+  }

+  //

+  // First size has to be big enough for the original header

+  //

+  if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) {

+    Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL);

+    goto FailDone;

+  }

+  //

+  // Initialize the header we'll use on all but the first part

+  //

+  memset (&Hdr, 0, sizeof (Hdr));

+  Hdr.CapsuleGuid         = CapHdr->CapsuleGuid;

+  Hdr.HeaderSize          = sizeof (Hdr);

+  Hdr.Flags               = CapHdr->Flags;

+  Hdr.InstanceId          = CapHdr->InstanceId;

+  Hdr.CapsuleImageSize    = CapHdr->CapsuleImageSize;

+  Hdr.OffsetToCapsuleBody = Hdr.HeaderSize;

+  Hdr.SequenceNumber      = 1;

+  //

+  // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size);

+  //

+  Buffer = (UINT8 *) CapHdr;

+  //

+  // Walk the list of sizes and write out a capsule header, and

+  // then the raw capsule data.

+  //

+  //  SizeLeft -= mOptions.SizeList->Size;

+  //

+  mOptions.CurrentSize = mOptions.SizeList;

+  while (SizeLeft) {

+    CurrentSize = mOptions.CurrentSize->Size;

+    GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber);

+    if ((OutFptr = fopen (FileName, "wb")) == NULL) {

+      Error (NULL, 0, 0, FileName, "failed to open split file for writing");

+      goto FailDone;

+    }

+

+    if (Buffer == (UINT8 *) CapHdr) {

+      //

+      // First part -- write out original header and data

+      //

+      if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, FileName, "failed to write to split image file");

+        goto FailDone;

+      }

+

+      SizeLeft -= CurrentSize;

+      Buffer += CurrentSize;

+      DataSize  = CurrentSize;

+      FileSize  = CurrentSize;

+    } else {

+      //

+      // Not the first part. Write the default header, and then the raw bytes from the

+      // original image.

+      //

+      if (CurrentSize <= sizeof (Hdr)) {

+        Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize);

+        goto FailDone;

+      }

+

+      DataSize = CurrentSize - sizeof (Hdr);

+      if (DataSize > SizeLeft) {

+        DataSize = SizeLeft;

+      }

+

+      if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, FileName, "failed to write capsule header to output file");

+        fclose (OutFptr);

+        goto FailDone;

+      }

+

+      if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, FileName, "failed to write capsule data to output file");

+        fclose (OutFptr);

+        goto FailDone;

+      }

+

+      Hdr.SequenceNumber++;

+      Buffer += DataSize;

+      SizeLeft -= DataSize;

+      FileSize = DataSize + sizeof (Hdr);

+    }

+    //

+    // Next size in list if there is one

+    //

+    if (mOptions.CurrentSize->Next != NULL) {

+      mOptions.CurrentSize = mOptions.CurrentSize->Next;

+    }

+

+    SequenceNumber++;

+    fclose (OutFptr);

+    OutFptr = NULL;

+    printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize);

+  }

+

+  goto Done;

+FailDone:

+  Status = STATUS_ERROR;

+Done:

+  if (CapHdr != NULL) {

+    free (CapHdr);

+  }

+

+  if (CapFptr != NULL) {

+    fclose (CapFptr);

+  }

+

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+  }

+

+  return Status;

+

+#endif

+   return STATUS_SUCCESS;

+}

+

+static

+BOOLEAN

+GetSplitFileName (

+  INT8    *BaseFileName,

+  INT8    *NewFileName,

+  UINT32  SequenceNumber

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  BaseFileName    - GC_TODO: add argument description

+  NewFileName     - GC_TODO: add argument description

+  SequenceNumber  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  /*++

+

+Routine Description:

+  Given an initial split capsule file name and a sequence number,

+  create an appropriate file name for this split of a capsule image.

+

+Arguments:

+  BaseFileName   - name of of the first split file in the series

+  NewFileName    - output name of the split file

+  SequenceNumber - 0-based sequence number of split images

+

+Returns:

+  TRUE   - name created successfully

+  FALSE  - otherwise

+

+--*/

+  INT8    *Ptr;

+  INT8    *Part2Start;

+  UINT32  Digits;

+  UINT32  Len;

+  UINT32  BaseOffset;

+  //

+  // Work back from the end of the file name and see if there is a number somewhere

+  //

+  for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--)

+    ;

+  if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) {

+    //

+    // Found no number, so just add it to the end

+    //

+    sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber);

+    return TRUE;

+  } else {

+    //

+    // Found a number. Look back to find the first digit.

+    //

+    Part2Start = Ptr + 1;

+    for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++)

+      ;

+    if (!isdigit (*Ptr)) {

+      Ptr++;

+      Digits--;

+    }

+

+    BaseOffset      = atoi (Ptr);

+    SequenceNumber  = SequenceNumber + BaseOffset;

+    if (Digits > 1) {

+      //

+      // Copy the first part of the original file name to the new filename

+      // This is the path for filenames with format path\name001.cap

+      //

+      Len = (UINT32) Ptr - (UINT32) BaseFileName;

+      strncpy (NewFileName, BaseFileName, Len);

+      sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber);

+      strcat (NewFileName, Part2Start);

+      return TRUE;

+    } else {

+      //

+      // Only one digit found. This is the path for filenames with

+      // format path\name1.cap

+      //

+      Len = (UINT32) Ptr - (UINT32) BaseFileName + 1;

+      strncpy (NewFileName, BaseFileName, Len);

+      sprintf (NewFileName + Len - 1, "%d", SequenceNumber);

+      strcat (NewFileName, Part2Start);

+      return TRUE;

+    }

+  }

+}

+

+static

+BOOLEAN

+IsWhiteSpace (

+  WCHAR  Char

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Char  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  switch (Char) {

+  case UNICODE_SPACE:

+  case UNICODE_TAB:

+  case UNICODE_NULL:

+  case UNICODE_CR:

+  case UNICODE_LF:

+    return TRUE;

+

+  default:

+    return FALSE;

+  }

+}

+

+static

+BOOLEAN

+IsToken (

+  SOURCE_FILE *File,

+  WCHAR       *Token

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  File  - GC_TODO: add argument description

+  Token - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  SkipWhiteSpace (File);

+  if (EndOfFile (File)) {

+    return FALSE;

+  }

+

+  if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) {

+    File->FileBufferPtr += wcslen (Token);

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+static

+STATUS

+CheckFirmwareVolumeHeader (

+  INT8    *FileName,

+  INT8    *Buffer,

+  UINT32  BufferSize

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileName    - GC_TODO: add argument description

+  Buffer      - GC_TODO: add argument description

+  BufferSize  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  EFI_FIRMWARE_VOLUME_HEADER  *Hdr;

+  EFI_GUID                    FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;

+

+  Hdr           = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;

+  if (Hdr->Signature != EFI_FVH_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)");

+    return STATUS_ERROR;

+  }

+

+  if (Hdr->Revision != EFI_FVH_REVISION) {

+    Error (NULL, 0, 0, FileName, "unsupported firmware volume header version");

+    return STATUS_ERROR;

+  }

+

+  if (Hdr->FvLength > BufferSize) {

+    Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size");

+    return STATUS_ERROR;

+  }

+

+  if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) {

+    Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header");

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+void

+DumpCapsule (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+#if 0

+  FILE                        *InFptr;

+  FILE_LIST                   *FileList;

+  EFI_CAPSULE_HEADER          CapsuleHeader;

+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;

+  EFI_CAPSULE_OEM_HEADER      *OemHeader;

+  UINT8                       *BPtr;

+  UINT32                      FileSize;

+  UINT32                      CapsuleHeaderDataSize;

+  UINT8                       ByteCount;

+  UINT8                       *CapsuleHeaderData;

+  BOOLEAN                     SplitImage;

+

+  InFptr            = NULL;

+  CapsuleHeaderData = NULL;

+  FileList          = mOptions.FileList;

+  while (FileList != NULL) {

+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");

+      goto Done;

+    }

+

+    if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header");

+      goto Done;

+    }

+

+    fseek (InFptr, 0, SEEK_END);

+    FileSize = ftell (InFptr);

+    if (CapsuleHeader.CapsuleImageSize > FileSize) {

+      SplitImage = TRUE;

+    } else {

+      SplitImage = FALSE;

+    }

+

+    printf (

+      "Capsule %s Size=0x%X CargoSize=0x%X\n",

+      FileList->FileName,

+      FileSize,

+      FileSize - CapsuleHeader.OffsetToCapsuleBody

+      );

+    printf (

+      "  GUID                  %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",

+      CapsuleHeader.CapsuleGuid.Data1,

+      (UINT32) CapsuleHeader.CapsuleGuid.Data2,

+      (UINT32) CapsuleHeader.CapsuleGuid.Data3,

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[0],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[1],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[2],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[3],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[4],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[5],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[6],

+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[7]

+      );

+    if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {

+      printf ("  INVALID GUID");

+    }

+

+    printf ("\n");

+    printf ("  Header size           0x%08X\n", CapsuleHeader.HeaderSize);

+    printf ("  Flags                 0x%08X\n", CapsuleHeader.Flags);

+    if (!SplitImage) {

+      printf ("  Capsule image size    0x%08X\n", CapsuleHeader.CapsuleImageSize);

+    } else {

+      printf ("  Capsule image size    0x%08X (split)\n", CapsuleHeader.CapsuleImageSize);

+    }

+

+    printf ("  Sequence number       %d\n", CapsuleHeader.SequenceNumber);

+    printf (

+      "  InstanceId            %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",

+      CapsuleHeader.InstanceId.Data1,

+      (UINT32) CapsuleHeader.InstanceId.Data2,

+      (UINT32) CapsuleHeader.InstanceId.Data3,

+      (UINT32) CapsuleHeader.InstanceId.Data4[0],

+      (UINT32) CapsuleHeader.InstanceId.Data4[1],

+      (UINT32) CapsuleHeader.InstanceId.Data4[2],

+      (UINT32) CapsuleHeader.InstanceId.Data4[3],

+      (UINT32) CapsuleHeader.InstanceId.Data4[4],

+      (UINT32) CapsuleHeader.InstanceId.Data4[5],

+      (UINT32) CapsuleHeader.InstanceId.Data4[6],

+      (UINT32) CapsuleHeader.InstanceId.Data4[7]

+      );

+    printf ("  Offset to capsule     0x%X\n", CapsuleHeader.OffsetToCapsuleBody);

+    //

+    // Dump header data if there

+    //

+    CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize;

+    if (CapsuleHeaderDataSize != 0) {

+      CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize);

+      if (CapsuleHeaderData == NULL) {

+        Error (

+          NULL,

+          0,

+          0,

+          "failed to allocate memory to read in capsule header data",

+          "0x%X bytes",

+          CapsuleHeaderDataSize

+          );

+        goto Done;

+      }

+

+      fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET);

+      if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) {

+        Error (

+          NULL,

+          0,

+          0,

+          "failed to read capsule header data contents from file",

+          "0x%X bytes",

+          CapsuleHeaderDataSize

+          );

+        goto Done;

+      }

+      //

+      // ************************************************************************

+      //

+      // OEM HEADER

+      //

+      // ************************************************************************

+      //

+      if (CapsuleHeader.OffsetToOemDefinedHeader != 0) {

+        OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize);

+        printf ("  OEM Header\n");

+        printf (

+          "    GUID                %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",

+          OemHeader->OemGuid.Data1,

+          (UINT32) OemHeader->OemGuid.Data2,

+          (UINT32) OemHeader->OemGuid.Data3,

+          (UINT32) OemHeader->OemGuid.Data4[0],

+          (UINT32) OemHeader->OemGuid.Data4[1],

+          (UINT32) OemHeader->OemGuid.Data4[2],

+          (UINT32) OemHeader->OemGuid.Data4[3],

+          (UINT32) OemHeader->OemGuid.Data4[4],

+          (UINT32) OemHeader->OemGuid.Data4[5],

+          (UINT32) OemHeader->OemGuid.Data4[6],

+          (UINT32) OemHeader->OemGuid.Data4[7]

+          );

+        printf ("    Header size:        0x%X\n", OemHeader->HeaderSize);

+        printf ("    OEM data");

+        BPtr = (UINT8 *) (OemHeader + 1);

+        for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) {

+          if ((ByteCount & 0x7) == 0) {

+            printf ("\n      ");

+          }

+

+          printf ("%02X ", (UINT32) *BPtr);

+          BPtr++;

+        }

+

+        printf ("\n");

+      }

+      //

+      // ************************************************************************

+      //

+      // Author, revision, short description, and long description information

+      //

+      // ************************************************************************

+      //

+      if (CapsuleHeader.OffsetToAuthorInformation != 0) {

+        if (DumpCapsuleHeaderStrings (

+              "Author information",

+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize)

+              ) != STATUS_SUCCESS) {

+          goto Done;

+        }

+      }

+

+      if (CapsuleHeader.OffsetToRevisionInformation != 0) {

+        if (DumpCapsuleHeaderStrings (

+              "Revision information",

+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize)

+              ) != STATUS_SUCCESS) {

+          goto Done;

+        }

+      }

+

+      if (CapsuleHeader.OffsetToShortDescription != 0) {

+        if (DumpCapsuleHeaderStrings (

+              "Short description",

+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize)

+              ) != STATUS_SUCCESS) {

+          goto Done;

+        }

+      }

+

+      if (CapsuleHeader.OffsetToLongDescription != 0) {

+        if (DumpCapsuleHeaderStrings (

+              "Long description",

+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize)

+              ) != STATUS_SUCCESS) {

+          goto Done;

+        }

+      }

+    }

+    //

+    // If it's not a split image, or it is a split image and this is the first in the series, then

+    // dump the cargo volume.

+    //

+    if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) {

+      printf ("  Cargo FV dump\n");

+      fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET);

+      if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) {

+        Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header");

+        goto Done;

+      }

+

+      printf ("    FV length           0x%X", FVHeader.FvLength);

+      if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) {

+        if (!SplitImage) {

+          printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody);

+        }

+      }

+

+      printf ("\n");

+      printf ("    Signature           0x%X ", FVHeader.Signature);

+      if (FVHeader.Signature == EFI_FVH_SIGNATURE) {

+        printf ("_FVH\n");

+      } else {

+        printf ("INVALID\n");

+      }

+

+      printf ("    FV header length    0x%X\n", (UINT32) FVHeader.HeaderLength);

+      printf ("    Revision            0x%X\n", (UINT32) FVHeader.Revision);

+      printf ("\n");

+    }

+

+    FileList = FileList->Next;

+  }

+

+Done:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  if (CapsuleHeaderData != NULL) {

+    free (CapsuleHeaderData);

+  }

+#endif

+}

+

+static

+STATUS

+JoinCapsule (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Join split capsule images into a single image. This is the

+  support function for the -j command-line option.

+

+Arguments:

+  None.

+

+Returns:

+  STATUS_SUCCESS - no problems encountered

+

+--*/

+{

+#if 0

+  UINT32              Size;

+  FILE                *InFptr;

+  FILE                *OutFptr;

+  INT8                *Buffer;

+  FILE_LIST           *FileList;

+  STATUS              Status;

+  EFI_CAPSULE_HEADER  CapHdr;

+  EFI_CAPSULE_HEADER  *CapHdrPtr;

+  UINT32              SizeLeft;

+  UINT32              SequenceNumber;

+  //

+  // Must have at least two files for join mode

+  //

+  if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) {

+    Error (NULL, 0, 0, "must specify at least two file names to join", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Open the output file

+  //

+  if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+

+  FileList        = mOptions.FileList;

+  Buffer          = NULL;

+  SequenceNumber  = 0;

+  InFptr          = NULL;

+  SizeLeft        = 0;

+  while (FileList != NULL) {

+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");

+      goto FailDone;

+    }

+    //

+    // Allocate a buffer into which we can read the file.

+    //

+    fseek (InFptr, 0, SEEK_END);

+    Size = ftell (InFptr);

+    rewind (InFptr);

+    Buffer = (char *) malloc (Size);

+    if (Buffer == NULL) {

+      Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");

+      goto FailDone;

+    }

+

+    CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer;

+    if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {

+      Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");

+      goto FailDone;

+    }

+    //

+    // Check the header for validity. Check size first.

+    //

+    if (Size < sizeof (EFI_CAPSULE_HEADER)) {

+      Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header");

+      goto FailDone;

+    }

+    //

+    // Check GUID

+    //

+    if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {

+      Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID");

+      goto FailDone;

+    }

+    //

+    // Check sequence number

+    //

+    if (CapHdrPtr->SequenceNumber != SequenceNumber) {

+      Error (

+        NULL,

+        0,

+        0,

+        FileList->FileName,

+        "invalid sequence number %d (expected %d)",

+        CapHdrPtr->SequenceNumber,

+        SequenceNumber

+        );

+      goto FailDone;

+    }

+    //

+    // If the first file, read save the capsule header

+    //

+    if (SequenceNumber == 0) {

+      memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER));

+      //

+      // Erase the InstanceId GUID

+      //

+      memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID));

+      if (fwrite (Buffer, Size, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file");

+        goto FailDone;

+      }

+

+      if (CapHdr.CapsuleImageSize < Size) {

+        Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size");

+        goto FailDone;

+      }

+

+      SizeLeft = CapHdr.CapsuleImageSize - Size;

+    } else {

+      //

+      // Check the GUID against the first file's GUID

+      //

+      if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) {

+        Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID");

+        goto FailDone;

+      }

+      //

+      // Make sure we're not throwing out any header info

+      //

+      if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) {

+        //

+        // Could be the split information, so just emit a warning

+        //

+        Warning (

+          NULL,

+          0,

+          0,

+          FileList->FileName,

+          "image appears to have additional capsule header information -- ignoring"

+          );

+      } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) {

+        Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient");

+        goto FailDone;

+      }

+

+      if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) {

+        Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");

+        goto FailDone;

+      }

+

+      if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) {

+        Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL);

+        goto FailDone;

+      }

+      //

+      // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody);

+      //

+      SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody);

+    }

+    //

+    // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft);

+    //

+    fclose (InFptr);

+    InFptr = NULL;

+    free (Buffer);

+    Buffer    = NULL;

+    FileList  = FileList->Next;

+    SequenceNumber++;

+  }

+

+  if (SizeLeft) {

+    Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft);

+    goto FailDone;

+  }

+

+  Status = STATUS_SUCCESS;

+  goto Done;

+FailDone:

+  Status = STATUS_ERROR;

+Done:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+  }

+

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  return Status;

+

+#endif

+return STATUS_SUCCESS;

+}

+

+static

+STATUS

+DumpCapsuleHeaderStrings (

+  UINT8   *SectionName,

+  WCHAR   *Buffer

+  )

+/*++

+

+Routine Description:

+  Given a pointer to string data from a capsule header, dump

+  the strings.

+

+Arguments:

+  SectionName  - name of the capsule header section to which

+                 the string data pertains

+  Buffer       - pointer to string data from a capsule header

+

+Returns:

+  STATUS_SUCCESS - all went well

+

+--*/

+{

+  printf ("  %s\n", SectionName);

+  while (*Buffer) {

+    printf ("    Language: %S\n", Buffer);

+    while (*Buffer) {

+      Buffer++;

+    }

+

+    Buffer++;

+    while (*Buffer) {

+      if (wcslen (Buffer) > 60) {

+        printf ("      %.60S\n", Buffer);

+        Buffer += 60;

+      } else {

+        printf ("      %S\n", Buffer);

+        Buffer += wcslen (Buffer);

+      }

+    }

+

+    Buffer++;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+GetHexValue (

+  SOURCE_FILE  *SourceFile,

+  UINT32       *Value,

+  UINT32       NumDigits

+  )

+/*++

+

+Routine Description:

+  Scan a hex value from the input stream.

+  

+Arguments:

+  SourceFile   - input file contents

+  Value        - returned value

+  NumDigits    - number of digits to read

+

+Returns:

+  STATUS_SUCCESS - if NumDigits were read from the file

+  STATUS_ERROR   - otherwise

+

+  

+--*/

+{

+  WCHAR   *SaveFilePos;

+  UINT32  Digits;

+  WCHAR   Nibble;

+

+  SaveFilePos = SourceFile->FileBufferPtr;

+  *Value      = 0;

+  Digits      = NumDigits;

+  while (Digits > 0) {

+    Nibble = SourceFile->FileBufferPtr[0];

+    if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) {

+      *Value = (*Value << 4) | (Nibble - UNICODE_0);

+    } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) {

+      *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10);

+    } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) {

+      *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10);

+    } else {

+      Error (

+        SourceFile->FileName,

+        SourceFile->LineNum,

+        0,

+        NULL,

+        "expected %d valid hex nibbles at %.20S",

+        NumDigits,

+        SaveFilePos

+        );

+      return STATUS_ERROR;

+    }

+

+    SourceFile->FileBufferPtr++;

+    Digits--;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *File

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  File  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) {

+    File->EndOfFile = TRUE;

+  }

+  //

+  // Reposition to the end of the file if we went beyond

+  //

+  if (File->EndOfFile) {

+    File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR);

+  }

+

+  return File->EndOfFile;

+}

+

+static

+void

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  SourceFile  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  while (!EndOfFile (SourceFile)) {

+    switch (*SourceFile->FileBufferPtr) {

+    case UNICODE_NULL:

+    case UNICODE_CR:

+    case UNICODE_SPACE:

+    case UNICODE_TAB:

+      SourceFile->FileBufferPtr++;

+      break;

+

+    case UNICODE_LF:

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      break;

+

+    default:

+      return ;

+    }

+  }

+}

+//

+// Parse a number. Possible format:

+//   1234

+//   1234k

+//   1234K

+//   1M

+//   1m

+//   0x100

+//

+static

+BOOLEAN

+GetNumber (

+  INT8    *Str,

+  UINT32  *Value

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Str   - GC_TODO: add argument description

+  Value - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  UINT32  LValue;

+

+  *Value  = 0;

+  LValue  = 0;

+  if (!isdigit (Str[0])) {

+    return FALSE;

+  }

+  //

+  // Look for hex number

+  //

+  if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) {

+    Str += 2;

+    if (Str[0] == 0) {

+      return FALSE;

+    }

+

+    while (Str[0]) {

+      if ((Str[0] >= '0') && (Str[0] <= '9')) {

+        LValue = (LValue << 4) | (Str[0] - '0');

+      } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) {

+        LValue = (LValue << 4) | (Str[0] - 'A' + 0x10);

+      } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) {

+        LValue = (LValue << 4) | (Str[0] - 'a' + 0x10);

+      } else {

+        break;

+      }

+

+      Str++;

+    }

+  } else {

+    LValue = atoi (Str);

+    while (isdigit (*Str)) {

+      Str++;

+    }

+  }

+  //

+  // If string left over, better be one character we recognize

+  //

+  if (Str[0]) {

+    if (Str[1]) {

+      return FALSE;

+    }

+

+    switch (Str[0]) {

+    case 'k':

+    case 'K':

+      LValue *= 1024;

+      break;

+

+    case 'm':

+    case 'M':

+      LValue *= 1024 * 1024;

+      break;

+

+    default:

+      return FALSE;

+    }

+  }

+

+  *Value = LValue;

+  return TRUE;

+}

+//

+// Process the command-line arguments

+//

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+

+  Processes command line arguments.

+

+Arguments:

+

+  Argc   - Number of command line arguments

+  Argv[] - Array of files input on command line  

+

+Returns:

+

+  STATUS_ERROR    - Function exited with an error

+  STATUS_SUCCESS  - Function executed successfully

+

+--*/

+{

+  FILE_LIST *NewFile;

+

+  FILE_LIST *LastFile;

+  SIZE_LIST *NewSize;

+  

+  NewFile = NULL;

+  NewSize = NULL;

+  

+  //

+  // Clear our globals

+  //

+  memset ((char *) &mOptions, 0, sizeof (mOptions));

+

+  //

+  // Skip program name

+  //

+  Argc--;

+  Argv++;

+

+  if (Argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Process until no more options

+  //

+  while ((Argc > 0) && (Argv[0][0] == '-')) {

+    if (stricmp (Argv[0], "-script") == 0) {

+      //

+      // Check for one more arg

+      //

+      if (Argc > 1) {

+        //

+        // Save the file name

+        //

+        if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) {

+          Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size");

+          

+          if (NewFile != NULL) {

+            free (NewFile);

+          }

+          if (NewSize != NULL) {

+            free (NewSize);

+          }

+          

+          return STATUS_ERROR;

+        }

+

+        strcpy (mOptions.ScriptFileName, Argv[1]);

+      } else {

+        Error (NULL, 0, 0, Argv[0], "missing script file name with option");

+        Usage ();

+        

+        if (NewFile != NULL) {

+          free (NewFile);

+        }

+        if (NewSize != NULL) {

+          free (NewSize);

+        }       

+

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+      //

+      // -o outfilename -- specify output file name (required)

+      //

+    } else if (stricmp (Argv[0], "-o") == 0) {

+      //

+      // check for one more arg

+      //

+      if (Argc > 1) {

+        //

+        // Try to open the file

+        //

+        // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) {

+        //  Error (NULL, 0, 0, Argv[1], "failed to open output file for writing");

+        //  return STATUS_ERROR;

+        // }

+        //

+        strcpy (mOptions.OutputFileName, Argv[1]);

+      } else {

+        Error (NULL, 0, 0, Argv[0], "missing output filename with option");

+        Usage ();

+        

+        if (NewFile != NULL) {

+          free (NewFile);

+        }

+        if (NewSize != NULL) {

+          free (NewSize);

+        }

+                

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-j") == 0) {

+      mOptions.JoinMode = TRUE;

+      //

+      // -split <size> option (multiple allowed)

+      //

+    } else if (stricmp (Argv[0], "-split") == 0) {

+      if (Argc > 1) {

+        NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST));

+        if (NewSize == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+

+          if (NewFile != NULL) {

+            free (NewFile);

+          }

+          if (NewSize != NULL) {

+            free (NewSize);

+          }

+          

+          return STATUS_ERROR;

+        }

+

+        memset (NewSize, 0, sizeof (SIZE_LIST));

+        //

+        // Get the size from the next arg, and then add this size

+        // to our size list

+        //

+        if (!GetNumber (Argv[1], &NewSize->Size)) {

+          Error (NULL, 0, 0, Argv[1], "invalid split size argument");

+

+          if (NewFile != NULL) {

+            free (NewFile);

+          }

+          if (NewSize != NULL) {

+            free (NewSize);

+          }       

+          

+          return STATUS_ERROR;

+        }

+

+        if (mOptions.SizeList == NULL) {

+          mOptions.SizeList     = NewSize;

+          mOptions.CurrentSize  = NewSize;

+        } else {

+          mOptions.LastSize->Next = NewSize;

+        }

+

+        mOptions.LastSize = NewSize;

+        free (NewSize);

+      } else {

+        Error (NULL, 0, 0, Argv[0], "missing size parameter with option");

+        Usage ();

+

+        if (NewFile != NULL) {

+          free (NewFile);

+        }

+        if (NewSize != NULL) {

+          free (NewSize);

+        }

+        

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;      

+    } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {

+      Usage ();

+      

+      if (NewFile != NULL) {

+        free (NewFile);

+      }

+      if (NewSize != NULL) {

+        free (NewSize);

+      }

+      

+      return STATUS_ERROR;

+      //

+      // Default minimum header

+      //

+    } else if (stricmp (Argv[0], "-dump") == 0) {

+      mOptions.Dump = TRUE;

+    } else if (stricmp (Argv[0], "-v") == 0) {

+      mOptions.Verbose = TRUE;

+    } else {

+      Error (NULL, 0, 0, Argv[0], "unrecognized option");

+      Usage ();

+      

+      if (NewFile != NULL) {

+        free (NewFile);

+      }

+      if (NewSize != NULL) {

+        free (NewSize);

+      }

+      

+      return STATUS_ERROR;

+    }

+

+    Argc--;

+    Argv++;

+  }

+  //

+  // Can't -j join files and -s split output capsule

+  //

+  if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) {

+    Error (NULL, 0, 0, "cannot specify both -j and -size", NULL);

+    

+    if (NewFile != NULL) {

+      free (NewFile);

+    }

+    if (NewSize != NULL) {

+      free (NewSize);

+    }

+    

+    return STATUS_ERROR;

+  }

+  //

+  // Must have specified an output file name if not -dump

+  //

+  if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) {

+    Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified");

+    Usage ();

+    

+    if (NewFile != NULL) {

+      free (NewFile);

+    }

+    if (NewSize != NULL) {

+      free (NewSize);

+    }

+    

+    return STATUS_ERROR;

+  }

+  //

+  // Rest of arguments are input files. The first one is a firmware

+  // volume image, and the rest are FFS files that are to be inserted

+  // into the firmware volume.

+  //

+  LastFile = NULL;

+  while (Argc > 0) {

+    NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST));

+    if (NewFile == NULL) {

+      Error (NULL, 0, 0, "memory allocation failure", NULL);

+

+      if (NewFile != NULL) {

+        free (NewFile);

+      }

+      if (NewSize != NULL) {

+        free (NewSize);

+      }

+    

+      return STATUS_ERROR;

+    }

+

+    memset ((char *) NewFile, 0, sizeof (FILE_LIST));

+    strcpy (NewFile->FileName, Argv[0]);

+    if (mOptions.FileList == NULL) {

+      mOptions.FileList = NewFile;

+    } else {

+      if (LastFile == NULL) {

+        LastFile = NewFile;

+      } else {

+        LastFile->Next = NewFile;

+      }      

+    }

+

+    LastFile = NewFile;

+    Argc--;

+    Argv++;

+  }

+

+  //

+  // Must have provided at least one file name

+  //

+  if (mOptions.FileList == NULL) {

+    Error (NULL, 0, 0, "must specify at least one file name", NULL);

+    Usage ();

+    

+    if (NewFile != NULL) {

+      free (NewFile);

+    }

+    if (NewSize != NULL) {

+      free (NewSize);

+    }

+    

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Print usage information for this utility.

+  

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+  

+--*/

+{

+  int               Index;

+  static const char *Str[] = {

+    PROGRAM_NAME " -- create a capsule header",

+    "  Usage: "PROGRAM_NAME " {options} [CapsuleFV]",

+    //

+    // {FfsFileNames}",

+    //

+    "    Options include:",

+    "      -h or -?         for this help information",

+    "      -script fname    to take capsule header info from unicode script",

+    "                       file fname",

+    "      -o fname         write output to file fname (required)",

+    "      -split size      split capsule image into multiple output files",

+    "      -dump            to dump a capsule header",

+    "      -v               for verbose output\n",

+    "      -j               to join split capsule images into a single image",

+    "",

+    "    CapsuleFV is the name of an existing well-formed Tiano firmware",

+    "    volume file.",

+    //

+    // FfsFileNames are the names of one or more Tiano FFS files to",

+    // "    insert into the output capsule image.",

+    //

+    NULL

+  };

+  for (Index = 0; Str[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Str[Index]);

+  }

+}

diff --git a/Source/GenCapsuleHdr/build.xml b/Source/GenCapsuleHdr/build.xml
new file mode 100644
index 0000000..db72d16
--- /dev/null
+++ b/Source/GenCapsuleHdr/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenCapsuleHdr Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenCapsuleHdr"/>

+  <property name="FileSet" value="GenCapsuleHdr.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+      <syslibset dir="${env.CYGWIN_HOME}/lib/mingw" libs="msvcr71" if="cygwin"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenDepex/DepexParser.c b/Source/GenDepex/DepexParser.c
new file mode 100644
index 0000000..9f0a0cb
--- /dev/null
+++ b/Source/GenDepex/DepexParser.c
@@ -0,0 +1,903 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  DepexParser.c

+

+Abstract:

+

+  Validate Dependency Expression syntax

+  recursive descent Algorithm

+

+  The original BNF grammar(taken from "Pre EFI Initialization Core Interface Specification 

+  draft review 0.9") is thus:

+       <depex>    ::= BEFORE <guid> END

+                    | AFTER <guid> END

+                    | SOR <bool> END

+                    | <bool> END    

+       <bool>     ::= <bool> AND <term> 

+                    | <bool> OR <term>  

+                    | <term>            

+       <term>     ::= NOT <factor>      

+                    | <factor>          

+       <factor>   ::= <bool>            

+                    | TRUE 

+                    | FALSE 

+                    | GUID

+

+       <guid>     ::= '{' <hex32> ',' <hex16> ',' <hex16> ','

+                      <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ',' 

+                      <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'

+       <hex32>    ::= <hexprefix> <hexvalue>

+       <hex16>    ::= <hexprefix> <hexvalue>

+       <hex8>     ::= <hexprefix> <hexvalue>

+       <hexprefix>::= '0' 'x'

+                    | '0' 'X'

+       <hexvalue> ::= <hexdigit> <hexvalue>

+                    | <hexdigit>

+       <hexdigit> ::= [0-9]

+                    | [a-f]

+                    | [A-F]

+

+  After cleaning left recursive and parentheses supported, the BNF grammar used in this module is thus:

+       <depex>    ::= BEFORE <guid>

+                    | AFTER <guid>

+                    | SOR <bool>

+                    | <bool>

+       <bool>     ::= <term><rightbool>

+       <rightbool>::= AND <term><rightbool>

+                    | OR <term><rightbool>

+                    | ''

+       <term>     ::= NOT <factor>

+                    | <factor>

+       <factor>   ::= '('<bool>')'<rightfactor>

+                    | NOT <factor> <rightbool> <rightfactor>

+                    | TRUE <rightfactor>

+                    | FALSE <rightfactor>

+                    | END <rightfactor>

+                    | <guid> <rightfactor>                    

+       <rightfactor> ::=AND <term><rightbool> <rightfactor>   

+                    | OR <term><rightbool> <rightfactor>                 

+                    | ''

+       <guid>     ::= '{' <hex32> ',' <hex16> ',' <hex16> ','

+                      <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ',' 

+                      <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'

+       <hex32>    ::= <hexprefix> <hexvalue>

+       <hex16>    ::= <hexprefix> <hexvalue>

+       <hex8>     ::= <hexprefix> <hexvalue>

+       <hexprefix>::= '0' 'x'

+                    | '0' 'X'

+       <hexvalue> ::= <hexdigit> <hexvalue>

+                    | <hexdigit>

+       <hexdigit> ::= [0-9]

+                    | [a-f]

+                    | [A-F]

+ 

+  Note: 1. There's no precedence in operators except parentheses;

+        2. For hex32, less and equal than 8 bits is valid, more than 8 bits is invalid.

+           Same constraint for hex16 is 4, hex8 is 2. All hex should contains at least 1 bit.

+        3. "<factor>   ::= '('<bool>')'<rightfactor>" is added to support parentheses;

+        4. "<factor>   ::= GUID" is changed to "<factor>   ::= <guid>";

+        5. "DEPENDENCY_END" is the terminal of the expression. But it has been filtered by caller. 

+           During parsing, "DEPENDENCY_END" will be treated as illegal factor;

+    

+  This code should build in any environment that supports a standard C-library w/ string

+  operations and File I/O services.

+

+  As an example of usage, consider the following:

+

+  The input string could be something like: 

+    

+      NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,

+        0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,

+        0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,

+        0x3f, 0xc1, 0x4d } AND

+

+  It's invalid for an extra "AND" in the end.

+

+  Complies with Tiano C Coding Standards Document, version 0.33, 16 Aug 2001.

+

+--*/

+

+#include "DepexParser.h"

+

+BOOLEAN

+ParseBool (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  );

+

+BOOLEAN

+ParseTerm (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  );

+

+BOOLEAN

+ParseRightBool (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  );

+

+BOOLEAN

+ParseFactor (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  );

+

+VOID

+LeftTrim (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Left trim the space, '\n' and '\r' character in string.

+  The space at the end does not need trim.

+

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  None

+

+

+--*/

+{

+  while

+  (

+    ((*Pindex) < (Pbegin + length)) &&

+    ((strncmp (*Pindex, " ", 1) == 0) || (strncmp (*Pindex, "\n", 1) == 0) || (strncmp (*Pindex, "\r", 1) == 0))

+  ) {

+    (*Pindex)++;

+  }

+}

+

+BOOLEAN

+ParseHexdigit (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse Hex bit in dependency expression.  

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    Length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If parses a valid hex bit, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  //

+  // <hexdigit> ::= [0-9] | [a-f] | [A-F]

+  //

+  if (((**Pindex) >= '0' && (**Pindex) <= '9') ||

+      ((**Pindex) >= 'a' && (**Pindex) <= 'f') ||

+      ((**Pindex) >= 'A' && (**Pindex) <= 'F')

+      ) {

+    (*Pindex)++;

+    return TRUE;

+  } else {

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseHex32 (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse Hex32 in dependency expression.  

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    Length of the string

+  Pindex    The pointer of point to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If parses a valid hex32, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT32 Index;

+  INT8  *Pin;

+

+  Index = 0;

+  Pin   = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {

+    return FALSE;

+  }

+  (*Pindex) += 2;

+

+  while (ParseHexdigit (Pbegin, length, Pindex)) {

+    Index++;

+  }

+

+  if (Index > 0 && Index <= 8) {

+    return TRUE;

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseHex16 (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse Hex16 in dependency expression.  

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    Length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If parses a valid hex16, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  int   Index;

+  INT8  *Pin;

+

+  Index = 0;

+  Pin   = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {

+    return FALSE;

+  }

+  (*Pindex) += 2;

+

+  while (ParseHexdigit (Pbegin, length, Pindex)) {

+    Index++;

+  }

+

+  if (Index > 0 && Index <= 4) {

+    return TRUE;

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseHex8 (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse Hex8 in dependency expression.  

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    Length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If parses a valid hex8, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  int   Index;

+  INT8  *Pin;

+

+  Index = 0;

+  Pin   = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {

+    return FALSE;

+  }

+  (*Pindex) += 2;

+

+  while (ParseHexdigit (Pbegin, length, Pindex)) {

+    Index++;

+  }

+

+  if (Index > 0 && Index <= 2) {

+    return TRUE;

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseGuid (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse guid in dependency expression.

+  There can be any number of spaces between '{' and hexword, ',' and hexword, 

+  hexword and ',', hexword and '}'. The hexword include hex32, hex16 and hex8.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If parses a valid guid, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT32 Index;

+  INT8  *Pin;

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, "{", 1) != 0) {

+    return FALSE;

+  }

+  (*Pindex)++;

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (!ParseHex32 (Pbegin, length, Pindex)) {

+    *Pindex = Pin;

+    return FALSE;

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, ",", 1) != 0) {

+    return FALSE;

+  } else {

+    (*Pindex)++;

+  }

+

+  for (Index = 0; Index < 2; Index++) {

+    LeftTrim (Pbegin, length, Pindex);

+    if (!ParseHex16 (Pbegin, length, Pindex)) {

+      *Pindex = Pin;

+      return FALSE;

+    }

+

+    LeftTrim (Pbegin, length, Pindex);

+    if (strncmp (*Pindex, ",", 1) != 0) {

+      return FALSE;

+    } else {

+      (*Pindex)++;

+    }

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, "{", 1) != 0) {

+    return FALSE;

+  }

+  (*Pindex)++;

+

+  for (Index = 0; Index < 7; Index++) {

+    LeftTrim (Pbegin, length, Pindex);

+    if (!ParseHex8 (Pbegin, length, Pindex)) {

+      *Pindex = Pin;

+      return FALSE;

+    }

+

+    LeftTrim (Pbegin, length, Pindex);

+    if (strncmp (*Pindex, ",", 1) != 0) {

+      return FALSE;

+    } else {

+      (*Pindex)++;

+    }

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (!ParseHex8 (Pbegin, length, Pindex)) {

+    *Pindex = Pin;

+    return FALSE;

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, "}", 1) != 0) {

+    return FALSE;

+  } else {

+    (*Pindex)++;

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, "}", 1) != 0) {

+    return FALSE;

+  } else {

+    (*Pindex)++;

+  }

+

+  return TRUE;

+}

+

+BOOLEAN

+ParseRightFactor (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse rightfactor in bool expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If string is a valid rightfactor expression, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT8  *Pin;

+

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  //

+  // <rightfactor> ::=AND <term> <rightbool> <rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {

+    *Pindex += strlen (OPERATOR_AND);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseTerm (Pbegin, length, Pindex)) {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (ParseRightBool (Pbegin, length, Pindex)) {

+        LeftTrim (Pbegin, length, Pindex);

+        if (ParseRightFactor (Pbegin, length, Pindex)) {

+          return TRUE;

+        } else {

+          *Pindex = Pin;

+        }

+      } else {

+        *Pindex = Pin;

+      }

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <rightfactor> ::=OR <term> <rightbool> <rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {

+    *Pindex += strlen (OPERATOR_OR);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseTerm (Pbegin, length, Pindex)) {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (ParseRightBool (Pbegin, length, Pindex)) {

+        LeftTrim (Pbegin, length, Pindex);

+        if (ParseRightFactor (Pbegin, length, Pindex)) {

+          return TRUE;

+        } else {

+          *Pindex = Pin;

+        }

+      } else {

+        *Pindex = Pin;

+      }

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <rightfactor> ::= ''

+  //

+  *Pindex = Pin;

+  return TRUE;

+}

+

+BOOLEAN

+ParseRightBool (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse rightbool in bool expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If string is a valid rightbool expression, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT8  *Pin;

+

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  //

+  // <rightbool>::= AND <term><rightbool>

+  //

+  if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {

+    *Pindex += strlen (OPERATOR_AND);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseTerm (Pbegin, length, Pindex)) {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (ParseRightBool (Pbegin, length, Pindex)) {

+        return TRUE;

+      } else {

+        *Pindex = Pin;

+      }

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <rightbool>::=  OR <term><rightbool>

+  //

+  if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {

+    *Pindex += strlen (OPERATOR_OR);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseTerm (Pbegin, length, Pindex)) {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (ParseRightBool (Pbegin, length, Pindex)) {

+        return TRUE;

+      } else {

+        *Pindex = Pin;

+      }

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <rightbool>::= ''

+  //

+  *Pindex = Pin;

+  return TRUE;

+}

+

+BOOLEAN

+ParseFactor (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse factor in bool expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If string is a valid factor, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT8  *Pin;

+

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  //

+  // <factor>   ::= '('<bool>')'<rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) {

+    *Pindex += strlen (OPERATOR_LEFT_PARENTHESIS);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (!ParseBool (Pbegin, length, Pindex)) {

+      *Pindex = Pin;

+    } else {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (strncmp (*Pindex, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) {

+        *Pindex += strlen (OPERATOR_RIGHT_PARENTHESIS);

+        LeftTrim (Pbegin, length, Pindex);

+

+        if (ParseRightFactor (Pbegin, length, Pindex)) {

+          return TRUE;

+        } else {

+          *Pindex = Pin;

+        }

+      }

+    }

+  }

+  //

+  // <factor>   ::= NOT <factor> <rightbool> <rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {

+    *Pindex += strlen (OPERATOR_NOT);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseFactor (Pbegin, length, Pindex)) {

+      LeftTrim (Pbegin, length, Pindex);

+

+      if (ParseRightBool (Pbegin, length, Pindex)) {

+        LeftTrim (Pbegin, length, Pindex);

+

+        if (ParseRightFactor (Pbegin, length, Pindex)) {

+          return TRUE;

+        } else {

+          *Pindex = Pin;

+        }

+      } else {

+        *Pindex = Pin;

+      }

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <factor>   ::= TRUE <rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) {

+    *Pindex += strlen (OPERATOR_TRUE);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseRightFactor (Pbegin, length, Pindex)) {

+      return TRUE;

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <factor>   ::= FALSE <rightfactor>

+  //

+  if (strncmp (*Pindex, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) {

+    *Pindex += strlen (OPERATOR_FALSE);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseRightFactor (Pbegin, length, Pindex)) {

+      return TRUE;

+    } else {

+      *Pindex = Pin;

+    }

+  }

+  //

+  // <factor>   ::= <guid> <rightfactor>

+  //

+  if (ParseGuid (Pbegin, length, Pindex)) {

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (ParseRightFactor (Pbegin, length, Pindex)) {

+      return TRUE;

+    } else {

+      *Pindex = Pin;

+      return FALSE;

+    }

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseTerm (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse term in bool expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If string is a valid term, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT8  *Pin;

+

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  //

+  // <term>     ::= NOT <factor>

+  //

+  if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {

+    *Pindex += strlen (OPERATOR_NOT);

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (!ParseFactor (Pbegin, length, Pindex)) {

+      *Pindex = Pin;

+    } else {

+      return TRUE;

+    }

+  }

+  //

+  // <term>     ::=<factor>

+  //

+  if (ParseFactor (Pbegin, length, Pindex)) {

+    return TRUE;

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseBool (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length,

+  IN OUT  INT8      **Pindex

+  )

+/*++

+

+Routine Description:

+

+  Parse bool expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+  Pindex    The pointer of pointer to the next parse character in the string

+

+Returns:

+

+  BOOLEAN   If string is a valid bool expression, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  INT8  *Pin;

+  Pin = *Pindex;

+  LeftTrim (Pbegin, length, Pindex);

+

+  if (ParseTerm (Pbegin, length, Pindex)) {

+    LeftTrim (Pbegin, length, Pindex);

+

+    if (!ParseRightBool (Pbegin, length, Pindex)) {

+      *Pindex = Pin;

+      return FALSE;

+    } else {

+      return TRUE;

+    }

+  } else {

+    *Pindex = Pin;

+    return FALSE;

+  }

+}

+

+BOOLEAN

+ParseDepex (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length

+  )

+/*++

+

+Routine Description:

+

+  Parse whole dependency expression.

+

+Arguments:

+

+  Pbegin    The pointer to the string  

+  length    length of the string

+

+Returns:

+

+  BOOLEAN   If string is a valid dependency expression, return TRUE, otherwise FALSE

+

+

+--*/

+{

+  BOOLEAN Result;

+  INT8    **Pindex;

+  INT8    *temp;

+

+  Result  = FALSE;

+  temp    = Pbegin;

+  Pindex  = &temp;

+

+  LeftTrim (Pbegin, length, Pindex);

+  if (strncmp (*Pindex, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) {

+    (*Pindex) += strlen (OPERATOR_BEFORE);

+    Result = ParseGuid (Pbegin, length, Pindex);

+

+  } else if (strncmp (*Pindex, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) {

+    (*Pindex) += strlen (OPERATOR_AFTER);

+    Result = ParseGuid (Pbegin, length, Pindex);

+

+  } else if (strncmp (*Pindex, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) {

+    (*Pindex) += strlen (OPERATOR_SOR);

+    Result = ParseBool (Pbegin, length, Pindex);

+

+  } else {

+    Result = ParseBool (Pbegin, length, Pindex);

+

+  }

+

+  LeftTrim (Pbegin, length, Pindex);

+  return (BOOLEAN) (Result && (*Pindex) >= (Pbegin + length));

+}

diff --git a/Source/GenDepex/DepexParser.h b/Source/GenDepex/DepexParser.h
new file mode 100644
index 0000000..29e0884
--- /dev/null
+++ b/Source/GenDepex/DepexParser.h
@@ -0,0 +1,26 @@
+/*++

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  

+          GenDepex.h

+

+  Abstract:

+          This file contains the relevant declarations required

+          to generate a binary Dependency File

+

+  Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.

+

+--*/

+

+// TODO: fix comment to set correct module name: DepexParser.h

+#ifndef _EFI_DEPEX_PARSER_H_

+#define _EFI_DEPEX_PARSER_H_

+#include "GenDepex.h"

+#endif

diff --git a/Source/GenDepex/GenDepex.c b/Source/GenDepex/GenDepex.c
new file mode 100644
index 0000000..3818649
--- /dev/null
+++ b/Source/GenDepex/GenDepex.c
@@ -0,0 +1,919 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenDepex.c

+

+Abstract:

+

+  Generate Dependency Expression ("GenDepex")

+

+  Infix to Postfix Algorithm

+

+  This code has been scrubbed to be free of having any EFI core tree dependencies.

+  It should build in any environment that supports a standard C-library w/ string

+  operations and File I/O services.

+

+  As an example of usage, consider the following:

+

+  The input user file could be something like "Sample.DXS" whose contents are

+

+    #include "Tiano.h"

+

+    DEPENDENCY_START

+      NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL) 

+        OR EFI_PXE_BASE_CODE_PROTOCOL

+    DEPENDENCY_END

+

+  This file is then washed through the C-preprocessor, viz.,

+

+    cl /EP Sample.DXS > Sample.TMP1

+

+  This yields the following file "Sample.TMP1" whose contents are

+

+    DEPENDENCY_START

+      NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,

+        0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,

+        0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,

+        0x3f, 0xc1, 0x4d }

+    DEPENDENCY_END

+

+  This file, in turn, will be fed into the utility, viz.,

+

+    GenDepex Sample.TMP1 Sample.TMP2

+

+  With a file that is 55 bytes long:

+

+     55 bytes for the grammar binary

+        PUSH opcode         - 1  byte

+        GUID Instance       - 16 bytes

+        PUSH opcode         - 1  byte

+        GUID Instance       - 16 bytes

+        AND opcode          - 1  byte

+        NOT opcode          - 1  byte

+        PUSH opcode         - 1  byte

+        GUID Instance       - 16 bytes

+        OR opcode           - 1  byte

+        END opcode          - 1  byte

+

+  The file "Sample.TMP2" could be fed via a Section-builder utility 

+  (GenSection) that would be used for the creation of a dependency

+  section file (.DPX) which in turn would be used by a generate FFS

+  utility (GenFfsFile) to produce a DXE driver/core (.DXE) or 

+  a DXE application (.APP) file.

+

+  Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.

+

+--*/

+

+#include "GenDepex.h"

+

+#define TOOL_NAME "GenDepex"

+

+extern

+ParseDepex (

+  IN      INT8      *Pbegin,

+  IN      UINT32    length

+  );

+

+VOID

+PrintGenDepexUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT.

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s, Tiano Dependency Expression Generation Utility. Version %d.%d.\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION

+    );

+  printf ("Copyright (C) 1996-2002 Intel Corporation.  All rights reserved.\n\n");

+}

+

+VOID

+PrintGenDepexUsageInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT.

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "Usage: %s -I <INFILE> -O <OUTFILE> [-P <Optional Boundary for padding up>] \n",

+    UTILITY_NAME

+    );

+  printf (" Where:\n");

+  printf ("  <INFILE> is the input pre-processed dependency text files name.\n");

+  printf ("  <OUTFILE> is the output binary dependency files name.\n");

+  printf ("  <Optional Boundary for padding up> is the padding integer value.\n");

+  printf ("    This is the boundary to align the output file size to.\n");

+}

+

+DEPENDENCY_OPCODE

+PopOpCode (

+  IN OUT VOID **Stack

+  )

+/*++

+

+Routine Description:

+

+  Pop an element from the Opcode stack.

+

+Arguments:

+

+  Stack               Current top of the OpCode stack location

+

+Returns:

+

+  DEPENDENCY_OPCODE   OpCode at the top of the OpCode stack.

+  Stack               New top of the OpCode stack location

+

+

+--*/

+{

+  DEPENDENCY_OPCODE *OpCodePtr;

+

+  OpCodePtr = *Stack;

+  OpCodePtr--;

+  *Stack = OpCodePtr;

+  return *OpCodePtr;

+}

+

+VOID

+PushOpCode (

+  IN OUT  VOID                **Stack,

+  IN      DEPENDENCY_OPCODE   OpCode

+  )

+/*++

+

+Routine Description:

+

+  Push an element onto the Opcode Stack

+

+Arguments:

+

+  Stack     Current top of the OpCode stack location

+  OpCode    OpCode to push onto the stack

+

+Returns:

+

+  Stack     New top of the OpCode stack location

+

+--*/

+{

+  DEPENDENCY_OPCODE *OpCodePtr;

+

+  OpCodePtr   = *Stack;

+  *OpCodePtr  = OpCode;

+  OpCodePtr++;

+  *Stack = OpCodePtr;

+}

+

+EFI_STATUS

+GenerateDependencyExpression (

+  IN     FILE           *InFile,

+  IN OUT FILE           *OutFile,

+  IN     INT8           Padding  OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  This takes the pre-compiled dependency text file and 

+  converts it into a binary dependency file.

+

+  The BNF for the dependency expression is as follows 

+  (from the DXE 1.0 Draft specification).

+

+  The inputted BNF grammar is thus:

+    <depex> ::= sor <dep> | 

+                before GUID <dep> | 

+                after GUID <dep> | 

+                <bool>

+

+    <dep> ::=   <bool> |

+

+    <bool> ::=  <bool> and <term> | 

+                <bool> or <term> | 

+                <term>

+

+    <term> ::=  not <factor> | 

+                <factor>

+

+    <factor> ::= ( <bool> ) | 

+                 <term> <term> | 

+                 GUID | 

+                 <boolval>

+

+    <boolval> ::= true | 

+                  false

+

+  The outputed binary grammer is thus:

+    <depex> ::= sor <dep> | 

+                before <depinst> <dep> | 

+                after <depinst> <dep> | 

+                <bool>

+

+    <dep> ::=   <bool> |

+

+    <bool> ::=  <bool> and <term> | 

+                <bool> or <term> | <term>

+

+    <term> ::=  not <factor> | 

+                <factor>

+

+    <factor> ::= ( <bool> ) | 

+                 <term> <term> | 

+                 <boolval> | 

+                 <depinst> | 

+                 <termval>

+

+    <boolval> ::= true | 

+                  false

+

+    <depinst> ::= push GUID

+

+    <termval> ::= end

+

+  BugBug: A correct grammer is parsed correctly. A file that violates the

+          grammer may parse when it should generate an error. There is some

+          error checking and it covers most of the case when it's an include

+          of definition issue. An ill formed expresion may not be detected.

+

+Arguments:

+

+  InFile -  Input pre-compiled text file of the dependency expression.

+            This needs to be in ASCII.

+            The file pointer can not be NULL.

+

+  OutFile - Binary dependency file.

+            The file pointer can not be NULL.

+

+  Padding - OPTIONAL integer value to pad the output file to.

+

+

+Returns:

+

+  EFI_SUCCESS             The function completed successfully.

+  EFI_INVALID_PARAMETER   One of the parameters in the text file was invalid.

+  EFI_OUT_OF_RESOURCES    Unable to allocate memory.

+  EFI_ABORTED             An misc error occurred.

+

+--*/

+{

+  INT8              *Ptrx;

+  INT8              *Pend;

+  INT8              *EvaluationStack;

+  INT8              *StackPtr;

+  INT8              *Buffer;

+  INT8              Line[LINESIZE];

+  UINTN             Index;

+  UINTN             OutFileSize;

+  UINTN             FileSize;

+  UINTN             Results;

+  BOOLEAN           NotDone;

+  BOOLEAN           Before_Flag;

+  BOOLEAN           After_Flag;

+  BOOLEAN           Dep_Flag;

+  BOOLEAN           SOR_Flag;

+  EFI_GUID          Guid;

+  UINTN             ArgCountParsed;

+  DEPENDENCY_OPCODE Opcode;

+

+  Before_Flag = FALSE;

+  After_Flag  = FALSE;

+  Dep_Flag    = FALSE;

+  SOR_Flag    = FALSE;

+

+  memset (Line, 0, LINESIZE);

+

+  OutFileSize     = 0;

+

+  EvaluationStack = (INT8 *) malloc (EVAL_STACK_SIZE);

+

+  if (EvaluationStack != NULL) {

+    StackPtr = EvaluationStack;

+  } else {

+    printf ("Unable to allocate memory to EvaluationStack - Out of resources\n");

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Results = (UINTN) fseek (InFile, 0, SEEK_END);

+

+  if (Results != 0) {

+    printf ("FSEEK failed - Aborted\n");

+    return EFI_ABORTED;

+  }

+

+  FileSize = ftell (InFile);

+

+  if (FileSize == -1L) {

+    printf ("FTELL failed - Aborted\n");

+    return EFI_ABORTED;

+  }

+

+  Buffer = (INT8 *) malloc (FileSize + BUFFER_SIZE);

+

+  if (Buffer == NULL) {

+    printf ("Unable to allocate memory to Buffer - Out of resources\n");

+    free (EvaluationStack);

+

+    Results = (UINTN) fclose (InFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    Results = (UINTN) fclose (OutFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Results = (UINTN) fseek (InFile, 0, SEEK_SET);

+

+  if (Results != 0) {

+    printf ("FSEEK failed - Aborted\n");

+    return EFI_ABORTED;

+  }

+

+  memset (Buffer, 0, FileSize + BUFFER_SIZE);

+  fread (Buffer, FileSize, 1, InFile);

+

+  Ptrx    = Buffer;

+  Pend    = Ptrx + FileSize - strlen (DEPENDENCY_END);

+  Index   = FileSize;

+

+  NotDone = TRUE;

+  while ((Index--) && NotDone) {

+

+    if (strncmp (Pend, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {

+      NotDone = FALSE;

+    } else {

+      Pend--;

+    }

+  }

+

+  if (NotDone) {

+    printf ("Couldn't find end string %s\n", DEPENDENCY_END);

+

+    Results = (UINTN) fclose (InFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    Results = (UINTN) fclose (OutFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    free (Buffer);

+    free (EvaluationStack);

+

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Index   = FileSize;

+

+  NotDone = TRUE;

+  while ((Index--) && NotDone) {

+

+    if (strncmp (Ptrx, DEPENDENCY_START, strlen (DEPENDENCY_START)) == 0) {

+      Ptrx += sizeof (DEPENDENCY_START);

+      NotDone = FALSE;

+      //

+      // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)?

+      //

+    } else {

+      Ptrx++;

+    }

+  }

+

+  if (NotDone) {

+    printf ("Couldn't find start string %s\n", DEPENDENCY_START);

+

+    Results = (UINTN) fclose (InFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    Results = (UINTN) fclose (OutFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    free (Buffer);

+    free (EvaluationStack);

+

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  //  validate the syntax of expression

+  //

+  if (!ParseDepex (Ptrx, Pend - Ptrx - 1)) {

+    printf ("The syntax of expression is wrong\n");

+

+    Results = (UINTN) fclose (InFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    Results = (UINTN) fclose (OutFile);

+    if (Results != 0) {

+      printf ("FCLOSE failed\n");

+    }

+

+    free (Buffer);

+    free (EvaluationStack);

+

+    return EFI_INVALID_PARAMETER;

+  }

+

+  NotDone = TRUE;

+

+  while ((Index--) && NotDone) {

+

+    if (*Ptrx == ' ') {

+      Ptrx++;

+    } else if (*Ptrx == '\n' || *Ptrx == '\r') {

+      Ptrx++;

+    } else if (strncmp (Ptrx, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) {

+      //

+      //  Checks for some invalid dependencies

+      //

+      if (Before_Flag) {

+

+        printf ("A BEFORE operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (After_Flag) {

+

+        printf ("An AFTER operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (SOR_Flag) {

+

+        printf ("Another SOR operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (Dep_Flag) {

+

+        printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else {

+        //

+        //  BUGBUG - This was not in the spec but is in the CORE code

+        //  An OPERATOR_SOR has to be first - following the DEPENDENCY_START

+        //

+        fputc (EFI_DEP_SOR, OutFile);

+        OutFileSize++;

+        Ptrx += sizeof (OPERATOR_SOR);

+        SOR_Flag = TRUE;

+

+      }

+    } else if (strncmp (Ptrx, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) {

+      //

+      //  Checks for some invalid dependencies

+      //

+      if (Before_Flag) {

+

+        printf ("Another BEFORE operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (After_Flag) {

+

+        printf ("An AFTER operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (SOR_Flag) {

+

+        printf ("A SOR operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (Dep_Flag) {

+

+        printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else {

+        fputc (EFI_DEP_BEFORE, OutFile);

+        OutFileSize++;

+        Ptrx += sizeof (OPERATOR_BEFORE);

+        Before_Flag = TRUE;

+      }

+    } else if (strncmp (Ptrx, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) {

+      //

+      //  Checks for some invalid dependencies

+      //

+      if (Before_Flag) {

+

+        printf ("A BEFORE operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (After_Flag) {

+

+        printf ("Another AFTER operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (SOR_Flag) {

+

+        printf ("A SOR operator was detected.\n");

+        printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else if (Dep_Flag) {

+

+        printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n");

+        return EFI_INVALID_PARAMETER;

+

+      } else {

+        fputc (EFI_DEP_AFTER, OutFile);

+        OutFileSize++;

+        Ptrx += sizeof (OPERATOR_AFTER);

+        Dep_Flag    = TRUE;

+        After_Flag  = TRUE;

+      }

+    } else if (strncmp (Ptrx, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {

+      while (StackPtr != EvaluationStack) {

+        Opcode = PopOpCode ((VOID **) &StackPtr);

+        if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {

+          fputc (Opcode, OutFile);

+          OutFileSize++;

+        } else {

+          PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);

+          break;

+        }

+      }

+

+      PushOpCode ((VOID **) &StackPtr, EFI_DEP_AND);

+      Ptrx += sizeof (OPERATOR_AND);

+      Dep_Flag = TRUE;

+

+    } else if (strncmp (Ptrx, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {

+      while (StackPtr != EvaluationStack) {

+        Opcode = PopOpCode ((VOID **) &StackPtr);

+        if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {

+          fputc (Opcode, OutFile);

+          OutFileSize++;

+        } else {

+          PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);

+          break;

+        }

+      }

+

+      PushOpCode ((VOID **) &StackPtr, EFI_DEP_OR);

+      Ptrx += sizeof (OPERATOR_OR);

+      Dep_Flag = TRUE;

+

+    } else if (strncmp (Ptrx, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {

+      while (StackPtr != EvaluationStack) {

+        Opcode = PopOpCode ((VOID **) &StackPtr);

+        if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {

+          fputc (Opcode, OutFile);

+          OutFileSize++;

+        } else {

+          PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);

+          break;

+        }

+      }

+

+      PushOpCode ((VOID **) &StackPtr, EFI_DEP_NOT);

+      Ptrx += sizeof (OPERATOR_NOT);

+      Dep_Flag = TRUE;

+

+    } else if (*Ptrx == '\t') {

+

+      printf ("File contains tabs. This violates the coding standard\n");

+      return EFI_INVALID_PARAMETER;

+

+    } else if (*Ptrx == '\n') {

+      //

+      // Skip the newline character in the file

+      //

+      Ptrx++;

+

+    } else if (strncmp (Ptrx, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) {

+      PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);

+

+      Ptrx += strlen (OPERATOR_LEFT_PARENTHESIS);

+      Dep_Flag = TRUE;

+

+    } else if (strncmp (Ptrx, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) {

+      while (StackPtr != EvaluationStack) {

+        Opcode = PopOpCode ((VOID **) &StackPtr);

+        if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {

+          fputc (Opcode, OutFile);

+          OutFileSize++;

+        } else {

+          break;

+        }

+      }

+

+      Ptrx += strlen (OPERATOR_RIGHT_PARENTHESIS);

+      Dep_Flag = TRUE;

+

+    } else if (strncmp (Ptrx, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) {

+

+      fputc (EFI_DEP_TRUE, OutFile);

+

+      OutFileSize++;

+

+      //

+      // OutFileSize += sizeof (EFI_DEP_TRUE);

+      //

+      Dep_Flag = TRUE;

+

+      Ptrx += strlen (OPERATOR_TRUE);

+

+    } else if (strncmp (Ptrx, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) {

+

+      fputc (EFI_DEP_FALSE, OutFile);

+

+      OutFileSize++;

+

+      //

+      // OutFileSize += sizeof (EFI_DEP_FALSE);

+      //

+      Dep_Flag = TRUE;

+

+      Ptrx += strlen (OPERATOR_FALSE);

+

+    } else if (*Ptrx == '{') {

+      Ptrx++;

+

+      if (*Ptrx == ' ') {

+        Ptrx++;

+      }

+

+      {

+        int byte_index;

+        // This is an array of UINT32s. sscanf will trash memory

+        // if you try to read into a UINT8 with a %x formatter.

+        UINT32 Guid_Data4[8];

+

+        ArgCountParsed = sscanf (

+                         Ptrx,

+            "%x, %x, %x, { %x, %x, %x, %x, %x, %x, %x, %x }",

+                         &Guid.Data1,

+                         &Guid.Data2,

+                         &Guid.Data3,

+                         &Guid_Data4[0],

+                         &Guid_Data4[1],

+                         &Guid_Data4[2],

+                         &Guid_Data4[3],

+                         &Guid_Data4[4],

+                         &Guid_Data4[5],

+                         &Guid_Data4[6],

+                         &Guid_Data4[7]

+                         );

+        

+        // Now we can copy the 32 bit ints into the GUID.

+        for (byte_index=0; byte_index<8; byte_index++) {

+          Guid.Data4[byte_index] = (UINT8) Guid_Data4[byte_index];

+        }

+      }

+

+      if (ArgCountParsed != 11) {

+        printf ("We have found an illegal GUID\n");

+        printf ("Fix your depex\n");

+        exit (-1);

+      }

+

+      while (*Ptrx != '}') {

+        Ptrx++;

+      }

+

+    Ptrx++;

+      while (*Ptrx != '}') {

+        Ptrx++;

+      }

+    //

+      // Absorb the closing }

+      //

+      Ptrx++;

+

+      //

+      // Don't provide a PUSH Opcode for the Before and After case

+      //

+      if ((!Before_Flag) && (!After_Flag)) {

+        fputc (EFI_DEP_PUSH, OutFile);

+        OutFileSize++;

+      }

+

+      fwrite (&Guid, sizeof (EFI_GUID), 1, OutFile);

+

+      OutFileSize += sizeof (EFI_GUID);

+      Dep_Flag = TRUE;

+

+    } else if (strncmp (Ptrx, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {

+      NotDone = FALSE;

+    } else {

+      //

+      // Not a valid construct. Null terminate somewhere out there and

+      // print an error message.

+      //

+      *(Ptrx + 20) = 0;

+      printf (TOOL_NAME " ERROR: Unrecognized input at: \"%s\"...\n", Ptrx);

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  //  DRAIN();

+  //

+  while (StackPtr != EvaluationStack) {

+    fputc (PopOpCode ((VOID **) &StackPtr), OutFile);

+    OutFileSize++;

+  }

+

+  if (OutFileSize == 0) {

+    printf ("Grammer contains no operators or constants\n");

+    return EFI_INVALID_PARAMETER;

+  }

+

+  fputc (EFI_DEP_END, OutFile);

+

+  OutFileSize++;

+

+  //

+  //  Checks for invalid padding values

+  //

+  if (Padding < 0) {

+

+    printf ("The inputted padding value was %d\n", Padding);

+    printf ("The optional padding value can not be less than ZERO\n");

+    return EFI_INVALID_PARAMETER;

+

+  } else if (Padding > 0) {

+

+    while ((OutFileSize % Padding) != 0) {

+

+      fputc (' ', OutFile);

+      OutFileSize++;

+    }

+  }

+

+  Results = (UINTN) fclose (InFile);

+  if (Results != 0) {

+    printf ("FCLOSE failed\n");

+  }

+

+  Results = (UINTN) fclose (OutFile);

+  if (Results != 0) {

+    printf ("FCLOSE failed\n");

+  }

+

+  free (Buffer);

+  free (EvaluationStack);

+

+  return EFI_SUCCESS;

+} // End GenerateDependencyExpression function

+

+int

+main (

+  IN UINTN argc,

+  IN CHAR8 *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Parse user entries.  Print some rudimentary help

+

+Arguments:

+

+  argc    The count of input arguments

+  argv    The input arguments string array

+

+Returns:

+

+  EFI_SUCCESS             The function completed successfully.

+  EFI_INVALID_PARAMETER   One of the input parameters was invalid or one of the parameters in the text file was invalid.

+  EFI_OUT_OF_RESOURCES    Unable to allocate memory.

+  EFI_ABORTED             Unable to open/create a file or a misc error.

+

+--*/

+// TODO:    ] - add argument and description to function comment

+{

+  FILE    *OutFile;

+  FILE    *InFile;

+  UINT8   Padding;

+  UINTN   Index;

+  BOOLEAN Input_Flag;

+  BOOLEAN Output_Flag;

+  BOOLEAN Pad_Flag;

+

+  InFile      = NULL;

+  OutFile     = NULL;

+  Padding     = 0;

+  Input_Flag  = FALSE;

+  Output_Flag = FALSE;

+  Pad_Flag    = FALSE;

+

+  if (argc < 5) {

+    printf ("Not enough arguments\n");

+    PrintGenDepexUsageInfo ();

+    return EFI_INVALID_PARAMETER;

+  }

+

+  for (Index = 1; Index < argc - 1; Index++) {

+

+    if ((strcmp (argv[Index], "-I") == 0) || (strcmp (argv[Index], "-i") == 0)) {

+

+      if (!Input_Flag) {

+

+        InFile      = fopen (argv[Index + 1], "rb");

+        Input_Flag  = TRUE;

+

+      } else {

+        printf ("GenDepex only allows one INPUT (-I) argument\n");

+        return EFI_INVALID_PARAMETER;

+      }

+

+    } else if ((strcmp (argv[Index], "-O") == 0) || (strcmp (argv[Index], "-o") == 0)) {

+

+      if (!Output_Flag) {

+

+        OutFile     = fopen (argv[Index + 1], "wb");

+        Output_Flag = TRUE;

+

+      } else {

+        printf ("GenDepex only allows one OUTPUT (-O) argument\n");

+        return EFI_INVALID_PARAMETER;

+      }

+

+    } else if ((strcmp (argv[Index], "-P") == 0) || (strcmp (argv[Index], "-p") == 0)) {

+

+      if (!Pad_Flag) {

+

+        Padding   = (UINT8) atoi (argv[Index + 1]);

+        Pad_Flag  = TRUE;

+

+      } else {

+        printf ("GenDepex only allows one PADDING (-P) argument\n");

+        return EFI_INVALID_PARAMETER;

+      }

+    }

+  }

+

+  PrintGenDepexUtilityInfo ();

+

+  if (InFile == NULL) {

+    printf ("Can not open <INFILE> for reading.\n");

+    PrintGenDepexUsageInfo ();

+    return EFI_ABORTED;

+  }

+

+  if (OutFile == NULL) {

+    printf ("Can not open <OUTFILE> for writting.\n");

+    PrintGenDepexUsageInfo ();

+    return EFI_ABORTED;

+  }

+

+  return GenerateDependencyExpression (InFile, OutFile, Padding);

+}

diff --git a/Source/GenDepex/GenDepex.h b/Source/GenDepex/GenDepex.h
new file mode 100644
index 0000000..b198156
--- /dev/null
+++ b/Source/GenDepex/GenDepex.h
@@ -0,0 +1,71 @@
+/*++

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  

+          GenDepex.h

+

+  Abstract:

+          This file contains the relevant declarations required

+          to generate a binary Dependency File

+

+  Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.

+

+--*/

+

+#ifndef _EFI_GEN_DEPEX_H

+#define _EFI_GEN_DEPEX_H

+

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <memory.h>

+#include <string.h>

+#ifndef __GNUC__

+#include <malloc.h>

+#endif

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/Dependency.h>

+

+#define DEPENDENCY_START            "DEPENDENCY_START"

+#define OPERATOR_BEFORE             "BEFORE"

+#define OPERATOR_AFTER              "AFTER"

+#define OPERATOR_AND                "AND"

+#define OPERATOR_OR                 "OR"

+#define OPERATOR_NOT                "NOT"

+#define OPERATOR_TRUE               "TRUE"

+#define OPERATOR_FALSE              "FALSE"

+#define OPERATOR_SOR                "SOR"

+#define OPERATOR_END                "END"

+#define OPERATOR_LEFT_PARENTHESIS   "("

+#define OPERATOR_RIGHT_PARENTHESIS  ")"

+#define DEPENDENCY_END              "DEPENDENCY_END"

+

+#define DXE_DEP_LEFT_PARENTHESIS    0x0a

+#define DXE_DEP_RIGHT_PARENTHESIS   0x0b

+

+#define LINESIZE                    320

+#define SIZE_A_SYMBOL               60

+#define DEPENDENCY_OPCODE           UINT8

+#define EVAL_STACK_SIZE             0x1024

+#define BUFFER_SIZE                 0x100

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "GenDepex"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION 0

+#define UTILITY_MINOR_VERSION 5

+

+#endif

diff --git a/Source/GenDepex/build.xml b/Source/GenDepex/build.xml
new file mode 100644
index 0000000..e749431
--- /dev/null
+++ b/Source/GenDepex/build.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenDepex Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenDepex"/>

+  <property name="FileSet" value="DepexParser.c GenDepex.c GenDepex.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" />

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenFfsFile/GenFfsFile.c b/Source/GenFfsFile/GenFfsFile.c
new file mode 100644
index 0000000..1eea09f
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.c
@@ -0,0 +1,2646 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenFfsFile.c

+

+Abstract:

+

+  This file contains functions required to generate a Firmware File System

+  file.

+

+--*/

+

+#include <stdio.h>

+#include <ctype.h>  // for isalpha()

+//

+// include file for _spawnv

+//

+#ifndef __GNUC__

+#include <process.h>

+#endif

+#include <stdlib.h>

+#include <string.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+

+#include "ParseInf.h"

+#include "EfiCompress.h"

+#include "EfiCustomizedCompress.h"

+#include "Crc32.h"

+#include "GenFfsFile.h"

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+#include "SimpleFileParsing.h"

+

+#define UTILITY_NAME    "GenFfsFile"

+#define TOOLVERSION     "0.32"

+#define MAX_ARRAY_SIZE  100

+

+static

+INT32

+GetNextLine (

+  OUT CHAR8       *Destination,

+  IN FILE         *Package,

+  IN OUT UINT32   *LineNumber

+  );

+

+static

+void

+CheckSlash (

+  IN OUT CHAR8  *String,

+  IN FILE       *In,

+  IN OUT UINT32 *LineNumber

+  );

+

+static

+INT32

+FindSectionInPackage (

+  IN CHAR8        *BuildDirectory,

+  IN FILE         *OverridePackage,

+  IN OUT UINT32   *LineNumber

+  );

+

+static

+STATUS

+ProcessCommandLineArgs (

+  int     Argc,

+  char    *Argv[]

+  );

+

+static

+void

+PrintUsage (

+  void

+  );

+

+//

+// Keep globals in this structure

+//

+static struct {

+  UINT8   BuildDirectory[_MAX_PATH];

+  UINT8   PrimaryPackagePath[_MAX_PATH];

+  UINT8   OverridePackagePath[_MAX_PATH];

+  BOOLEAN Verbose;

+} mGlobals;

+

+static EFI_GUID mZeroGuid = { 0 };

+

+static

+void

+StripQuotes (

+  IN OUT CHAR8 *String

+  )

+/*++

+

+Routine Description:

+

+  Removes quotes and/or whitespace from around a string

+

+Arguments:

+

+ String    - String to remove quotes from

+

+Returns:

+

+  None

+

+--*/

+{

+  UINTN Index;

+  UINTN Index2;

+  UINTN StrLen;

+

+  Index2  = strspn (String, "\" \t\n");

+  StrLen  = strlen (String);

+

+  for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) {

+    String[Index - Index2] = String[Index];

+  }

+

+  String[Index - Index2] = 0;

+}

+

+static

+void

+PrintUsage (

+  void

+  )

+/*++

+

+Routine Description:

+

+  Print Error / Help message.

+

+Arguments:

+

+  void

+

+Returns:

+

+  None

+

+--*/

+{

+  printf ("Usage:\n");

+  printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");

+  printf ("   -b \"build directory\":\n ");

+  printf ("       specifies the full path to the component build directory.\n");

+  printf ("   -p1 \"P1_path\":\n");

+  printf ("       specifies fully qualified file name to the primary package file.\n");

+  printf ("       This file will normally exist in the same directory as the makefile\n");

+  printf ("       for the component. Required.\n");

+  printf ("   -p2 \"P2_path\":\n");

+  printf ("       specifies fully qualified file name to the override package file.\n");

+  printf ("       This file will normally exist in the build tip. Optional.\n");

+}

+

+static

+INT32

+TestComment (

+  IN CHAR8  *String,

+  IN FILE   *In

+  )

+/*++

+

+Routine Description:

+

+  Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment

+

+Arguments:

+

+  String      - String to test

+

+  In          - Open file to move pointer within

+

+Returns:

+

+  -1          - End of file reached

+   0          - Not a comment

+   1          - Comment bypassed

+

+--*/

+{

+  CHAR8 CharBuffer;

+

+  CharBuffer = 0;

+  if ((String[0] == '/') && (String[1] == '/')) {

+    while (CharBuffer != '\n') {

+      fscanf (In, "%c", &CharBuffer);

+      if (feof (In)) {

+        return -1;

+      }

+    }

+  } else {

+    return 0;

+  }

+

+  return 1;

+}

+

+static

+void

+BreakString (

+  IN CONST CHAR8 *Source,

+  OUT CHAR8      *Destination,

+  IN INTN        Direction

+  )

+/*++

+

+Routine Description:

+

+  Takes an input string and returns either the part before the =, or the part after the =, depending on direction

+

+Arguments:

+

+  Source      - String to break

+

+  Destination - Buffer to place new string in

+

+  Direction   - 0 to return all of source string before =

+                1 to return all of source string after =

+

+Returns:

+

+  None

+

+--*/

+{

+  UINTN Index;

+  UINTN Index2;

+

+  Index   = 0;

+  Index2  = 0;

+

+  if (strchr (Source, '=') == NULL) {

+    strcpy (Destination, Source);

+

+    return ;

+  }

+

+  if (Direction == 0) {

+    //

+    // return part of string before =

+    //

+    while (Source[Index] != '=') {

+      Destination[Index] = Source[Index++];

+    }

+

+    Destination[Index] = 0;

+  } else {

+    //

+    // return part of string after =

+    //

+    strcpy (Destination, strchr (Source, '=') + 1);

+  }

+}

+

+static

+INT32

+GetNextLine (

+  OUT CHAR8       *Destination,

+  IN FILE         *Package,

+  IN OUT UINT32   *LineNumber

+  )

+/*++

+

+Routine Description:

+

+  Gets the next non-commented line from the file

+

+Arguments:

+

+  Destination - Where to put string

+

+  Package     - Package to get string from

+  

+  LineNumber  - The actual line number.

+

+Returns:

+

+  -1          - End of file reached

+   0          - Success

+

+--*/

+{

+  CHAR8 String[_MAX_PATH];

+  fscanf (Package, "%s", &String);

+  if (feof (Package)) {

+    return -1;

+  }

+

+  while (TestComment (String, Package) == 1) {

+    fscanf (Package, "%s", &String);

+    if (feof (Package)) {

+      return -1;

+    }

+  }

+

+  strcpy (Destination, String);

+  return 0;

+}

+

+static

+VOID

+CheckSlash (

+  IN OUT CHAR8  *String,

+  IN FILE       *In,

+  IN OUT UINT32 *LineNumber

+  )

+/*++

+

+Routine Description:

+

+  Checks to see if string is line continuation character, if so goes to next valid line

+

+Arguments:

+

+  String      - String to test

+

+  In          - Open file to move pointer within

+  

+  LineNumber  - The line number.

+

+Returns:

+

+  None

+

+--*/

+{

+  CHAR8 ByteBuffer;

+  ByteBuffer = 0;

+

+  switch (String[0]) {

+

+  case '\\':

+    while (String[0] == '\\') {

+      while (ByteBuffer != '\n') {

+        fscanf (In, "%c", &ByteBuffer);

+      }

+      (*LineNumber)++;

+      if (GetNextLine (String, In, LineNumber) == -1) {

+        return ;

+      }

+    }

+    break;

+

+  case '\n':

+    (*LineNumber)++;

+    while (String[0] == '\n') {

+      if (GetNextLine (String, In, LineNumber) == -1) {

+        return ;

+      }

+    }

+    break;

+

+  default:

+    break;

+

+  }

+

+}

+

+static

+INT32

+FindSectionInPackage (

+  IN CHAR8        *BuildDirectory,

+  IN FILE         *OverridePackage,

+  IN OUT UINT32   *LineNumber

+  )

+/*++

+

+Routine Description:

+

+  Finds the matching section within the package

+

+Arguments:

+

+  BuildDirectory  - name of section to find

+

+  OverridePackage - Package file to search within

+  

+  LineNumber      - The line number.

+

+Returns:

+

+  -1          - End of file reached

+   0          - Success

+

+--*/

+{

+  CHAR8 String[_MAX_PATH];

+  CHAR8 NewString[_MAX_PATH];

+  String[0] = 0;

+

+  while (strcmp (BuildDirectory, String) != 0) {

+    if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) {

+      return -1;

+    }

+

+    if (NewString[0] == '[') {

+      if (NewString[strlen (NewString) - 1] != ']') {

+        //

+        // have to construct string.

+        //

+        strcpy (String, NewString + 1);

+

+        while (1) {

+          fscanf (OverridePackage, "%s", &NewString);

+          if (feof (OverridePackage)) {

+            return -1;

+          }

+

+          if (NewString[0] != ']') {

+            if (strlen (String) != 0) {

+              strcat (String, " ");

+            }

+

+            strcat (String, NewString);

+            if (String[strlen (String) - 1] == ']') {

+              String[strlen (String) - 1] = 0;

+              break;

+            }

+          } else {

+            break;

+          }

+        }

+      } else {

+        NewString[strlen (NewString) - 1] = 0;

+        strcpy (String, NewString + 1);

+      }

+    }

+  }

+

+  return 0;

+}

+

+static

+EFI_STATUS

+GenSimpleGuidSection (

+  IN OUT UINT8  *FileBuffer,

+  IN OUT UINT32 *BufferSize,

+  IN UINT32     DataSize,

+  IN EFI_GUID   SignGuid,

+  IN UINT16     GuidedSectionAttributes

+  )

+/*++

+

+Routine Description:

+

+  add GUIDed section header for the data buffer.

+  data stays in same location (overwrites source data).

+

+Arguments:

+

+  FileBuffer  - Buffer containing data to sign

+

+  BufferSize  - On input, the size of FileBuffer. On output, the size of

+                actual section data (including added section header).

+

+  DataSize    - Length of data to Sign

+

+  SignGuid    - Guid to be add.

+  

+  GuidedSectionAttributes - The section attribute.

+

+Returns:

+

+  EFI_SUCCESS           - Successful

+  EFI_OUT_OF_RESOURCES  - Not enough resource.

+

+--*/

+{

+  UINT32                    TotalSize;

+

+  EFI_GUID_DEFINED_SECTION  GuidSectionHeader;

+  UINT8                     *SwapBuffer;

+

+  SwapBuffer = NULL;

+

+  if (DataSize == 0) {

+    *BufferSize = 0;

+

+    return EFI_SUCCESS;

+  }

+

+  TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION);

+  GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;

+  GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalSize & 0xff);

+  GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalSize & 0xff00) >> 8);

+  GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalSize & 0xff0000) >> 16);

+  memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID));

+  GuidSectionHeader.Attributes  = GuidedSectionAttributes;

+  GuidSectionHeader.DataOffset  = sizeof (EFI_GUID_DEFINED_SECTION);

+

+  SwapBuffer                    = (UINT8 *) malloc (DataSize);

+  if (SwapBuffer == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  memcpy (SwapBuffer, FileBuffer, DataSize);

+  memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION));

+  memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize);

+

+  //

+  // Make sure section ends on a DWORD boundary

+  //

+  while ((TotalSize & 0x03) != 0) {

+    FileBuffer[TotalSize] = 0;

+    TotalSize++;

+  }

+

+  *BufferSize = TotalSize;

+

+  if (SwapBuffer != NULL) {

+    free (SwapBuffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+static

+EFI_STATUS

+CompressSection (

+  UINT8  *FileBuffer,

+  UINT32 *BufferSize,

+  UINT32 DataSize,

+  CHAR8  *Type

+  )

+/*++

+

+Routine Description:

+

+  Compress the data and add section header for the compressed data.

+  Compressed data (with section header) stays in same location as the source

+  (overwrites source data).

+

+Arguments:

+

+  FileBuffer  - Buffer containing data to Compress

+

+  BufferSize  - On input, the size of FileBuffer. On output, the size of

+                actual compressed data (including added section header).

+                When buffer is too small, this value indicates the size needed.

+

+  DataSize    - The size of data to compress

+

+  Type        - The compression type (not used currently).

+                Assume EFI_HEAVY_COMPRESSION.

+

+Returns:

+

+  EFI_BUFFER_TOO_SMALL - Buffer size is too small.

+  EFI_UNSUPPORTED      - Compress type can not be supported.

+  EFI_SUCCESS          - Successful

+  EFI_OUT_OF_RESOURCES - Not enough resource.

+

+--*/

+{

+  EFI_STATUS              Status;

+  UINT8                   *CompData;

+  UINT32                  CompSize;

+  UINT32                  TotalSize;

+  EFI_COMPRESSION_SECTION CompressionSet;

+  UINT8                   CompressionType;

+  COMPRESS_FUNCTION       CompressFunction;

+

+  Status            = EFI_SUCCESS;

+  CompData          = NULL;

+  CompSize          = 0;

+  TotalSize         = 0;

+  CompressFunction  = NULL;

+

+  //

+  // Get the compress type

+  //

+  if (strcmpi (Type, "Dummy") == 0) {

+    //

+    // Added "Dummy" to keep backward compatibility.

+    //

+    CompressionType   = EFI_STANDARD_COMPRESSION;

+    CompressFunction  = (COMPRESS_FUNCTION) Compress;

+

+  } else if (strcmpi (Type, "LZH") == 0) {

+    //

+    // EFI stardard compression (LZH)

+    //

+    CompressionType   = EFI_STANDARD_COMPRESSION;

+    CompressFunction  = (COMPRESS_FUNCTION) Compress;

+

+  } else {

+    //

+    // Customized compression

+    //

+    Status = SetCustomizedCompressionType (Type);

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    CompressionType   = EFI_CUSTOMIZED_COMPRESSION;

+    CompressFunction  = (COMPRESS_FUNCTION) CustomizedCompress;

+  }

+  //

+  // Compress the raw data

+  //

+  Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);

+  if (Status == EFI_BUFFER_TOO_SMALL) {

+    CompData = malloc (CompSize);

+    if (!CompData) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);

+  }

+

+  if (EFI_ERROR (Status)) {

+    if (CompData != NULL) {

+      free (CompData);

+    }

+

+    return Status;

+  }

+

+  TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION);

+

+  //

+  // Buffer too small?

+  //

+  if (TotalSize > *BufferSize) {

+    *BufferSize = TotalSize;

+    if (CompData != NULL) {

+      free (CompData);

+    }

+

+    return EFI_BUFFER_TOO_SMALL;

+  }

+  //

+  // Add the section header for the compressed data

+  //

+  CompressionSet.CommonHeader.Type    = EFI_SECTION_COMPRESSION;

+  CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);

+  CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);

+  CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);

+  CompressionSet.CompressionType      = CompressionType;

+  CompressionSet.UncompressedLength   = DataSize;

+

+  //

+  // Copy header and data to the buffer

+  //

+  memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION));

+  memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize);

+

+  //

+  // Make sure section ends on a DWORD boundary

+  //

+  while ((TotalSize & 0x03) != 0) {

+    FileBuffer[TotalSize] = 0;

+    TotalSize++;

+  }

+

+  *BufferSize = TotalSize;

+

+  if (CompData != NULL) {

+    free (CompData);

+  }

+

+  return EFI_SUCCESS;

+}

+

+static

+void

+StripParens (

+  IN OUT CHAR8 *String

+  )

+/*++

+

+Routine Description:

+

+  Removes Parenthesis from around a string

+

+Arguments:

+

+ String    - String to remove parens from

+

+Returns:

+

+  None

+

+--*/

+{

+  INT32 Index;

+

+  if (String[0] != '(') {

+    return ;

+  }

+

+  for (Index = 1; String[Index] != ')'; Index++) {

+    String[Index - 1] = String[Index];

+    if (String[Index] == 0) {

+      return ;

+    }

+  }

+

+  String[Index - 1] = 0;

+

+  return ;

+}

+

+static

+void

+StripEqualMark (

+  IN OUT CHAR8 *String

+  )

+/*++

+

+Routine Description:

+

+  Removes Equal Mark from around a string

+

+Arguments:

+

+ String    - String to remove equal mark from

+

+Returns:

+

+  None

+

+--*/

+{

+  INT32 Index;

+

+  if (String[0] != '=' && String[strlen (String) - 1] != '=') {

+    return ;

+  }

+

+  if (String[0] == '=') {

+

+    for (Index = 1; String[Index] != 0; Index++) {

+      String[Index - 1] = String[Index];

+    }

+

+    String[Index - 1] = 0;

+  }

+

+  if (String[strlen (String) - 1] == '=') {

+    String[strlen (String) - 1] = 0;

+  }

+

+  return ;

+}

+

+static

+INT32

+ProcessEnvironmentVariable (

+  IN CHAR8  *Buffer,

+  OUT CHAR8 *NewBuffer

+  )

+/*++

+

+Routine Description:

+

+  Converts environment variables to values

+

+Arguments:

+

+  Buffer      - Buffer containing Environment Variable String

+

+  NewBuffer   - Buffer containing value of environment variable

+

+

+Returns:

+

+  Number of characters from Buffer used

+

+--*/

+{

+  INT32 Index;

+  INT32 Index2;

+  CHAR8 VariableBuffer[_MAX_PATH];

+

+  Index   = 2;

+  Index2  = 0;

+

+  while (Buffer[Index] != ')') {

+    VariableBuffer[Index - 2] = Buffer[Index++];

+  }

+

+  VariableBuffer[Index - 2] = 0;

+  Index++;

+

+  if (getenv (VariableBuffer) != NULL) {

+    strcpy (NewBuffer, getenv (VariableBuffer));

+  } else {

+    printf ("Environment variable %s not found!\n", VariableBuffer);

+  }

+

+  return Index;

+}

+

+static

+void

+SplitAttributesField (

+  IN CHAR8       *Buffer,

+  IN CHAR8       *AttributesArray[],

+  IN OUT UINT32  *NumberOfAttributes

+  )

+/*

+  NumberOfAttributes: on input, it specifies the current number of attributes

+                      stored in AttributeArray.

+                      on output, it is updated to the latest number of attributes

+                      stored in AttributesArray.

+*/

+{

+  UINT32  Index;

+  UINT32  Index2;

+  UINT32  z;

+  CHAR8   *CharBuffer;

+

+  CharBuffer  = NULL;

+  CharBuffer  = (CHAR8 *) malloc (_MAX_PATH);

+  ZeroMem (CharBuffer, _MAX_PATH);

+

+  for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) {

+

+    if (Buffer[Index] != '|') {

+      CharBuffer[z] = Buffer[Index];

+      z++;

+    } else {

+

+      CharBuffer[z] = 0;

+      AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;

+      Index2++;

+

+      //

+      // allocate new char buffer for the next attributes string

+      //

+      CharBuffer = (CHAR8 *) malloc (_MAX_PATH);

+      ZeroMem (CharBuffer, _MAX_PATH);

+      z = 0;

+    }

+  }

+

+  CharBuffer[z] = 0;

+  //

+  // record the last attributes string in the Buffer

+  //

+  AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;

+  Index2++;

+

+  *NumberOfAttributes += Index2;

+

+  return ;

+}

+

+static

+INT32

+GetToolArguments (

+  CHAR8       *ToolArgumentsArray[],

+  FILE        *Package,

+  CHAR8       **PtrInputFileName,

+  CHAR8       **PtrOutputFileName,

+  EFI_GUID    *Guid,

+  UINT16      *GuidedSectionAttributes

+  )

+{

+  CHAR8       Buffer[_MAX_PATH];

+  BOOLEAN     ArgumentsFlag;

+  BOOLEAN     InputFlag;

+  BOOLEAN     OutputFlag;

+  BOOLEAN     GuidFlag;

+  BOOLEAN     AttributesFlag;

+  UINT32      argc;

+  UINT32      Index2;

+  UINT32      z;

+  CHAR8       *CharBuffer;

+  INT32       Index;

+  INT32       ReturnValue;

+  EFI_STATUS  Status;

+

+  CHAR8       *AttributesArray[MAX_ARRAY_SIZE];

+  UINT32      NumberOfAttributes;

+  CHAR8       *InputFileName;

+  CHAR8       *OutputFileName;

+  UINT32      LineNumber;

+  Buffer[_MAX_PATH];

+

+  ArgumentsFlag   = FALSE;

+  InputFlag       = FALSE;

+  OutputFlag      = FALSE;

+  GuidFlag        = FALSE;

+  AttributesFlag  = FALSE;

+  //

+  // Start at 1, since ToolArgumentsArray[0]

+  // is the program name.

+  //

+  argc            = 1;

+  Index2              = 0;

+

+  z                   = 0;

+  ReturnValue         = 0;

+  NumberOfAttributes  = 0;

+  InputFileName       = NULL;

+  OutputFileName      = NULL;

+

+  ZeroMem (Buffer, _MAX_PATH);

+  ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);

+  LineNumber = 0;

+  while (Buffer[0] != ')') {

+

+    if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+      CheckSlash (Buffer, Package, &LineNumber);

+      StripEqualMark (Buffer);

+    } else {

+      Error (NULL, 0, 0, "failed to get next line from package file", NULL);

+      return -1;

+    }

+

+    if (Buffer[0] == ')') {

+      break;

+    } else if (strcmpi (Buffer, "ARGS") == 0) {

+

+      ArgumentsFlag   = TRUE;

+      AttributesFlag  = FALSE;

+      continue;

+

+    } else if (strcmpi (Buffer, "INPUT") == 0) {

+

+      InputFlag       = TRUE;

+      ArgumentsFlag   = FALSE;

+      AttributesFlag  = FALSE;

+      continue;

+

+    } else if (strcmpi (Buffer, "OUTPUT") == 0) {

+

+      OutputFlag      = TRUE;

+      ArgumentsFlag   = FALSE;

+      AttributesFlag  = FALSE;

+      continue;

+

+    } else if (strcmpi (Buffer, "GUID") == 0) {

+

+      GuidFlag        = TRUE;

+      ArgumentsFlag   = FALSE;

+      AttributesFlag  = FALSE;

+      //

+      // fetch the GUID for the section

+      //

+      continue;

+

+    } else if (strcmpi (Buffer, "ATTRIBUTES") == 0) {

+

+      AttributesFlag  = TRUE;

+      ArgumentsFlag   = FALSE;

+      //

+      // fetch the GUIDed Section's Attributes

+      //

+      continue;

+

+    } else if (strcmpi (Buffer, "") == 0) {

+      continue;

+    }

+    //

+    // get all command arguments into ToolArgumentsArray

+    //

+    if (ArgumentsFlag) {

+

+      StripEqualMark (Buffer);

+

+      CharBuffer = (CHAR8 *) malloc (_MAX_PATH);

+      if (CharBuffer == NULL) {

+        goto ErrorExit;

+      }

+

+      ZeroMem (CharBuffer, sizeof (_MAX_PATH));

+

+      ToolArgumentsArray[argc] = CharBuffer;

+

+      if (Buffer[0] == '$') {

+        Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]);

+        //

+        // if there is string after the environment variable, cat it.

+        //

+        if ((UINT32) Index < strlen (Buffer)) {

+          strcat (ToolArgumentsArray[argc], &Buffer[Index]);

+        }

+      } else {

+        strcpy (ToolArgumentsArray[argc], Buffer);

+      }

+

+      argc += 1;

+      ToolArgumentsArray[argc] = NULL;

+      continue;

+    }

+

+    if (InputFlag) {

+

+      StripEqualMark (Buffer);

+

+      InputFileName = (CHAR8 *) malloc (_MAX_PATH);

+      if (InputFileName == NULL) {

+        goto ErrorExit;

+      }

+

+      ZeroMem (InputFileName, sizeof (_MAX_PATH));

+

+      if (Buffer[0] == '$') {

+        Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName);

+        //

+        // if there is string after the environment variable, cat it.

+        //

+        if ((UINT32) Index < strlen (Buffer)) {

+          strcat (InputFileName, &Buffer[Index]);

+        }

+      } else {

+        strcpy (InputFileName, Buffer);

+      }

+

+      InputFlag = FALSE;

+      continue;

+    }

+

+    if (OutputFlag) {

+

+      StripEqualMark (Buffer);

+

+      OutputFileName = (CHAR8 *) malloc (_MAX_PATH);

+      if (OutputFileName == NULL) {

+        goto ErrorExit;

+      }

+

+      ZeroMem (OutputFileName, sizeof (_MAX_PATH));

+

+      if (Buffer[0] == '$') {

+        Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName);

+        //

+        // if there is string after the environment variable, cat it.

+        //

+        if ((UINT32) Index < strlen (Buffer)) {

+          strcat (OutputFileName, &Buffer[Index]);

+        }

+      } else {

+        strcpy (OutputFileName, Buffer);

+      }

+

+      OutputFlag = FALSE;

+      continue;

+    }

+

+    if (GuidFlag) {

+

+      StripEqualMark (Buffer);

+

+      Status = StringToGuid (Buffer, Guid);

+      if (EFI_ERROR (Status)) {

+        ReturnValue = -1;

+        goto ErrorExit;

+      }

+

+      GuidFlag = FALSE;

+    }

+

+    if (AttributesFlag) {

+

+      StripEqualMark (Buffer);

+

+      //

+      // there might be no space between each attribute in the statement,

+      // split them aside and return each attribute string

+      // in the AttributesArray

+      //

+      SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes);

+    }

+  }

+  //

+  // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);

+  // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);

+  //

+  for (z = 0; z < NumberOfAttributes; z++) {

+    if (strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) {

+      *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;

+    } else if (strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) {

+      *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;

+    }

+  }

+

+ErrorExit:

+

+  for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) {

+    if (AttributesArray[Index2] == NULL) {

+      break;

+    }

+

+    free (AttributesArray[Index2]);

+  }

+

+  *PtrInputFileName   = InputFileName;

+  *PtrOutputFileName  = OutputFileName;

+

+  return ReturnValue;

+}

+

+static

+INT32

+ProcessScript (

+  IN OUT UINT8   *FileBuffer,

+  IN FILE        *Package,

+  IN CHAR8       *BuildDirectory,

+  IN BOOLEAN     ForceUncompress

+  )

+/*++

+

+Routine Description:

+

+  Signs the section, data stays in same location

+

+Arguments:

+

+  FileBuffer  - Data Buffer

+

+  Package     - Points to curly brace in Image Script

+

+  BuildDirectory     - Name of the source directory parameter

+  

+  ForceUncompress   - Whether to force uncompress.

+

+Returns:

+

+  Number of bytes added to file buffer

+  -1 on error

+

+--*/

+{

+  EFI_STATUS  Status;

+  UINT32      Size;

+  CHAR8       Buffer[_MAX_PATH];

+  CHAR8       Type[_MAX_PATH];

+  CHAR8       FileName[_MAX_PATH];

+  CHAR8       NewBuffer[_MAX_PATH];

+  INT32       Index3;

+  INT32       Index2;

+  UINT32      ReturnValue;

+  UINT8       ByteBuffer;

+  FILE        *InFile;

+  UINT32      SourceDataSize;

+  CHAR8       *ToolArgumentsArray[MAX_ARRAY_SIZE];

+  CHAR8       *OutputFileName;

+  CHAR8       *InputFileName;

+  CHAR8       ToolName[_MAX_PATH];

+  FILE        *OutputFile;

+  FILE        *InputFile;

+  UINT8       Temp;

+  int         returnint;

+  INT32       Index;

+  UINT32      LineNumber;

+  BOOLEAN     IsError;

+  EFI_GUID    SignGuid;

+  UINT16      GuidedSectionAttributes;

+  UINT8       *TargetFileBuffer;

+

+  OutputFileName          = NULL;

+  InputFileName           = NULL;

+  OutputFile              = NULL;

+  InputFile               = NULL;

+  IsError                 = FALSE;

+  GuidedSectionAttributes = 0;

+  TargetFileBuffer        = NULL;

+

+  Size                    = 0;

+  LineNumber              = 0;

+  Buffer[0]               = 0;

+  for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) {

+    ToolArgumentsArray[Index3] = NULL;

+  }

+

+  while (Buffer[0] != '}') {

+    if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+      CheckSlash (Buffer, Package, &LineNumber);

+    } else {

+      printf ("ERROR in IMAGE SCRIPT!\n");

+      IsError = TRUE;

+      goto Done;

+    }

+

+    if (strcmpi (Buffer, "Compress") == 0) {

+      //

+      // Handle compress

+      //

+      //

+      // read compression type

+      //

+      if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+        CheckSlash (Buffer, Package, &LineNumber);

+      }

+

+      StripParens (Buffer);

+      if (Buffer[0] == '$') {

+        ProcessEnvironmentVariable (&Buffer[0], Type);

+      } else {

+        strcpy (Type, Buffer);

+      }

+      //

+      // build buffer

+      //

+      while (Buffer[0] != '{') {

+        if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+          CheckSlash (Buffer, Package, &LineNumber);

+        }

+      }

+

+      ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress);

+      if (ReturnValue == -1) {

+        IsError = TRUE;

+        goto Done;

+      }

+      //

+      // Call compress routine on buffer.

+      // Occasionally, compressed data + section header would

+      // be largere than the source and EFI_BUFFER_TOO_SMALL is

+      // returned from CompressSection()

+      //

+      SourceDataSize = ReturnValue;

+

+      if (!ForceUncompress) {

+

+        Status = CompressSection (

+                  &FileBuffer[Size],

+                  &ReturnValue,

+                  SourceDataSize,

+                  Type

+                  );

+

+        if (Status == EFI_BUFFER_TOO_SMALL) {

+          Status = CompressSection (

+                    &FileBuffer[Size],

+                    &ReturnValue,

+                    SourceDataSize,

+                    Type

+                    );

+        }

+

+        if (EFI_ERROR (Status)) {

+          IsError = TRUE;

+          goto Done;

+        }

+      }

+

+      Size += ReturnValue;

+

+    } else if (strcmpi (Buffer, "Tool") == 0) {

+

+      ZeroMem (ToolName, _MAX_PATH);

+      ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);

+      ZeroMem (&SignGuid, sizeof (EFI_GUID));

+

+      //

+      // handle signing Tool

+      //

+      while (Buffer[0] != '(') {

+        if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+          CheckSlash (Buffer, Package, &LineNumber);

+        }

+      }

+

+      if (strcmpi (Buffer, "(") == 0) {

+        if (GetNextLine (Buffer, Package, &LineNumber) != -1) {

+          CheckSlash (Buffer, Package, &LineNumber);

+        }

+      }

+

+      StripParens (Buffer);

+

+      if (Buffer[0] == '$') {

+        Index = ProcessEnvironmentVariable (&Buffer[0], ToolName);

+        //

+        // if there is string after the environment variable, cat it.

+        //

+        if ((UINT32) Index < strlen (Buffer)) {

+          strcat (ToolName, &Buffer[Index]);

+        }

+      } else {

+        strcpy (ToolName, Buffer);

+      }

+

+      ToolArgumentsArray[0] = ToolName;

+

+      //

+      // read ARGS

+      //

+      if (GetToolArguments (

+            ToolArgumentsArray,

+            Package,

+            &InputFileName,

+            &OutputFileName,

+            &SignGuid,

+            &GuidedSectionAttributes

+            ) == -1) {

+        IsError = TRUE;

+        goto Done;

+      }

+      //

+      // if the tool need input file,

+      // dump the file buffer to the specified input file.

+      //

+      if (InputFileName != NULL) {

+        InputFile = fopen (InputFileName, "wb");

+        if (InputFile == NULL) {

+          Error (NULL, 0, 0, InputFileName, "failed to open output file for writing");

+          IsError = TRUE;

+          goto Done;

+        }

+

+        fwrite (FileBuffer, sizeof (UINT8), Size, InputFile);

+        fclose (InputFile);

+        InputFile = NULL;

+        free (InputFileName);

+        InputFileName = NULL;

+      }

+      //

+      // dispatch signing tool

+      //

+#ifdef __GNUC__

+      {

+        char CommandLine[1000];

+        sprintf(CommandLine, "%s %s", ToolName, ToolArgumentsArray);

+        returnint = system(CommandLine);

+      }

+#else

+      returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray);

+#endif

+      if (returnint != 0) {

+        Error (NULL, 0, 0, ToolName, "external tool failed");

+        IsError = TRUE;

+        goto Done;

+      }

+      //

+      // if the tool has output file,

+      // dump the output file to the file buffer

+      //

+      if (OutputFileName != NULL) {

+

+        OutputFile = fopen (OutputFileName, "rb");

+        if (OutputFile == NULL) {

+          Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");

+          IsError = TRUE;

+          goto Done;

+        }

+

+        TargetFileBuffer  = &FileBuffer[Size];

+        SourceDataSize    = Size;

+

+        fread (&Temp, sizeof (UINT8), 1, OutputFile);

+        while (!feof (OutputFile)) {

+          FileBuffer[Size++] = Temp;

+          fread (&Temp, sizeof (UINT8), 1, OutputFile);

+        }

+

+        while ((Size & 0x03) != 0) {

+          FileBuffer[Size] = 0;

+          Size++;

+        }

+

+        SourceDataSize = Size - SourceDataSize;

+

+        fclose (OutputFile);

+        OutputFile = NULL;

+        free (OutputFileName);

+        OutputFileName = NULL;

+

+        if (CompareGuid (&SignGuid, &mZeroGuid) != 0) {

+          ReturnValue = SourceDataSize;

+          Status = GenSimpleGuidSection (

+                    TargetFileBuffer,

+                    &ReturnValue,

+                    SourceDataSize,

+                    SignGuid,

+                    GuidedSectionAttributes

+                    );

+          if (EFI_ERROR (Status)) {

+            IsError = TRUE;

+            goto Done;

+          }

+

+          Size = ReturnValue;

+        }

+      }

+

+    } else if (Buffer[0] != '}') {

+      //

+      // if we are here, we should see either a file name,

+      // or a }.

+      //

+      Index3      = 0;

+      FileName[0] = 0;

+      //

+      // Prepend the build directory to the file name if the

+      // file name does not already contain a full path.

+      //

+      if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) {

+        sprintf (FileName, "%s\\", BuildDirectory);

+      }

+

+      while (Buffer[Index3] != '\n') {

+        if (Buffer[Index3] == '$') {

+          Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer);

+          strcat (FileName, NewBuffer);

+        }

+

+        if (Buffer[Index3] == 0) {

+          break;

+        } else {

+          Index2              = strlen (FileName);

+          FileName[Index2++]  = Buffer[Index3++];

+          FileName[Index2]    = 0;

+        }

+      }

+

+      InFile = fopen (FileName, "rb");

+      if (InFile == NULL) {

+        Error (NULL, 0, 0, FileName, "failed to open file for reading");

+        IsError = TRUE;

+        goto Done;

+      }

+

+      fread (&ByteBuffer, sizeof (UINT8), 1, InFile);

+      while (!feof (InFile)) {

+        FileBuffer[Size++] = ByteBuffer;

+        fread (&ByteBuffer, sizeof (UINT8), 1, InFile);

+      }

+

+      fclose (InFile);

+      InFile = NULL;

+

+      //

+      // Make sure section ends on a DWORD boundary

+      //

+      while ((Size & 0x03) != 0) {

+        FileBuffer[Size] = 0;

+        Size++;

+      }

+

+    }

+  }

+

+Done:

+  for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) {

+    if (ToolArgumentsArray[Index3] == NULL) {

+      break;

+    }

+

+    free (ToolArgumentsArray[Index3]);

+  }

+

+  if (IsError) {

+    return -1;

+  }

+

+  return Size;

+

+}

+

+static

+UINT8

+StringToType (

+  IN CHAR8 *String

+  )

+/*++

+

+Routine Description:

+

+  Converts File Type String to value.  EFI_FV_FILETYPE_ALL indicates that an

+  unrecognized file type was specified.

+

+Arguments:

+

+  String    - File type string

+

+Returns:

+

+  File Type Value

+

+--*/

+{

+  if (strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) {

+    return EFI_FV_FILETYPE_RAW;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) {

+    return EFI_FV_FILETYPE_FREEFORM;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {

+    return EFI_FV_FILETYPE_SECURITY_CORE;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) {

+    return EFI_FV_FILETYPE_PEI_CORE;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) {

+    return EFI_FV_FILETYPE_DXE_CORE;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) {

+    return EFI_FV_FILETYPE_PEIM;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) {

+    return EFI_FV_FILETYPE_DRIVER;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {

+    return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) {

+    return EFI_FV_FILETYPE_APPLICATION;

+  }

+

+  if (strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {

+    return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;

+  }

+

+  return EFI_FV_FILETYPE_ALL;

+}

+

+static

+UINT32

+AdjustFileSize (

+  IN UINT8  *FileBuffer,

+  IN UINT32 FileSize

+  )

+/*++

+

+Routine Description:

+  Adjusts file size to insure sectioned file is exactly the right length such

+  that it ends on exactly the last byte of the last section.  ProcessScript()

+  may have padded beyond the end of the last section out to a 4 byte boundary.

+  This padding is stripped.

+

+Arguments:

+  FileBuffer  - Data Buffer - contains a section stream

+  FileSize    - Size of FileBuffer as returned from ProcessScript()

+

+Returns:

+  Corrected size of file.

+

+--*/

+{

+  UINT32                    TotalLength;

+  UINT32                    CurrentLength;

+  UINT32                    SectionLength;

+  UINT32                    SectionStreamLength;

+  EFI_COMMON_SECTION_HEADER *SectionHeader;

+  EFI_COMMON_SECTION_HEADER *NextSectionHeader;

+

+  TotalLength         = 0;

+  CurrentLength       = 0;

+  SectionStreamLength = FileSize;

+

+  SectionHeader       = (EFI_COMMON_SECTION_HEADER *) FileBuffer;

+

+  while (TotalLength < SectionStreamLength) {

+    SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff;

+    TotalLength += SectionLength;

+

+    if (TotalLength == SectionStreamLength) {

+      return TotalLength;

+    }

+    //

+    // Move to the next byte following the section...

+    //

+    SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);

+    CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer;

+

+    //

+    // Figure out where the next section begins

+    //

+    NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3);

+    NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3);

+    TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;

+    SectionHeader = NextSectionHeader;

+  }

+

+  return CurrentLength;

+}

+

+static

+INT32

+MainEntry (

+  INT32     argc,

+  CHAR8     *argv[],

+  BOOLEAN   ForceUncompress

+  )

+/*++

+

+Routine Description:

+

+  MainEntry function.

+

+Arguments:

+

+  argc            - Number of command line parameters.

+  argv            - Array of pointers to command line parameter strings.

+  ForceUncompress - If TRUE, force to do not compress the sections even if compression

+                    is specified in the script. Otherwise, FALSE.

+

+Returns:

+  STATUS_SUCCESS  - Function exits successfully.

+  STATUS_ERROR    - Some error occurred during execution.

+

+--*/

+{

+  FILE                    *PrimaryPackage;

+  FILE                    *OverridePackage;

+  FILE                    *Out;

+  CHAR8                   BaseName[_MAX_PATH];

+  EFI_GUID                FfsGuid;

+  CHAR8                   GuidString[_MAX_PATH];

+  EFI_FFS_FILE_HEADER     FileHeader;

+  CHAR8                   FileType[_MAX_PATH];

+  EFI_FFS_FILE_ATTRIBUTES FfsAttrib;

+  EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined;

+  UINT64                  FfsAlignment;

+  UINT32                  FfsAlignment32;

+  CHAR8                   InputString[_MAX_PATH];

+  BOOLEAN                 ImageScriptInOveride;

+  UINT32                  FileSize;

+  UINT8                   *FileBuffer;

+  EFI_STATUS              Status;

+  UINT32                  LineNumber;

+  EFI_FFS_FILE_TAIL       TailValue;

+

+  BaseName[0]       = 0;

+  FileType[0]       = 0;

+  FfsAttrib         = 0;

+  FfsAttribDefined  = 0;

+  FfsAlignment      = 0;

+  FfsAlignment32    = 0;

+  PrimaryPackage    = NULL;

+  Out               = NULL;

+  OverridePackage   = NULL;

+  FileBuffer        = NULL;

+

+  strcpy (GuidString, "00000000-0000-0000-0000-000000000000");

+  Status = StringToGuid (GuidString, &FfsGuid);

+  if (Status != 0) {

+    Error (NULL, 0, 0, GuidString, "error parsing GUID string");

+    return STATUS_ERROR;

+  }

+

+  GuidString[0]         = 0;

+  ImageScriptInOveride  = FALSE;

+  //

+  // Initialize the simple file parsing routines. Then open

+  // the primary package file for parsing.

+  //

+  SFPInit ();

+  if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) {

+    Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");

+    goto Done;

+  }

+  //

+  // First token in the file must be "PACKAGE.INF"

+  //

+  if (!SFPIsToken ("PACKAGE.INF")) {

+    Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL);

+    goto Done;

+  }

+  //

+  // Find the [.] section

+  //

+  if (!SFPSkipToToken ("[.]")) {

+    Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL);

+    goto Done;

+  }

+  //

+  // Start parsing the data. The algorithm is essentially the same for each keyword:

+  //   1. Identify the keyword

+  //   2. Verify that the keyword/value pair has not already been defined

+  //   3. Set some flag indicating that the keyword/value pair has been defined

+  //   4. Skip over the "="

+  //   5. Get the value, which may be a number, TRUE, FALSE, or a string.

+  //

+  while (1) {

+    if (SFPIsToken ("BASE_NAME")) {

+      //

+      // Found BASE_NAME, format:

+      //   BASE_NAME = MyBaseName

+      //

+      if (BaseName[0] != 0) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL);

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (!SFPGetNextToken (BaseName, sizeof (BaseName))) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("IMAGE_SCRIPT")) {

+      //

+      // Found IMAGE_SCRIPT. Break out and process below.

+      //

+      break;

+    } else if (SFPIsToken ("FFS_FILEGUID")) {

+      //

+      // found FILEGUID, format:

+      //   FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A

+      //

+      if (GuidString[0] != 0) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL);

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL);

+        goto Done;

+      }

+

+      Status = StringToGuid (GuidString, &FfsGuid);

+      if (Status != 0) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_FILETYPE")) {

+      //

+      // ***********************************************************************

+      //

+      // Found FFS_FILETYPE, format:

+      //  FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION

+      //

+      if (FileType[0] != 0) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL);

+        goto Done;

+      }

+

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (!SFPGetNextToken (FileType, sizeof (FileType))) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {

+      //

+      // ***********************************************************************

+      //

+      // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE

+      // Spec says the bit is for future expansion, and must be false.

+      //

+      if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) {

+        Error (

+          mGlobals.PrimaryPackagePath,

+          SFPGetLineNumber (),

+          0,

+          "FFS_ATTRIB_HEADER_EXTENSION previously defined",

+          NULL

+          );

+        goto Done;

+      }

+

+      FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION;

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (SFPIsToken ("TRUE")) {

+        Error (

+          mGlobals.PrimaryPackagePath,

+          SFPGetLineNumber (),

+          0,

+          "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",

+          NULL

+          );

+        goto Done;

+      } else if (SFPIsToken ("FALSE")) {

+        //

+        // Default is FALSE

+        //

+      } else {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {

+      //

+      // ***********************************************************************

+      //

+      // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE

+      //

+      if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL);

+        goto Done;

+      }

+

+      FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT;

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (SFPIsToken ("TRUE")) {

+        FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT;

+      } else if (SFPIsToken ("FALSE")) {

+        //

+        // Default is FALSE

+        //

+      } else {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {

+      //

+      // ***********************************************************************

+      //

+      // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE

+      //

+      if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL);

+        goto Done;

+      }

+

+      FfsAttribDefined |= FFS_ATTRIB_RECOVERY;

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (SFPIsToken ("TRUE")) {

+        FfsAttrib |= FFS_ATTRIB_RECOVERY;

+      } else if (SFPIsToken ("FALSE")) {

+        //

+        // Default is FALSE

+        //

+      } else {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {

+      //

+      // ***********************************************************************

+      //

+      // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE

+      //

+      if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL);

+        goto Done;

+      }

+

+      FfsAttribDefined |= FFS_ATTRIB_CHECKSUM;

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (SFPIsToken ("TRUE")) {

+        FfsAttrib |= FFS_ATTRIB_CHECKSUM;

+      } else if (SFPIsToken ("FALSE")) {

+        //

+        // Default is FALSE

+        //

+      } else {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);

+        goto Done;

+      }

+    } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {

+      //

+      // ***********************************************************************

+      //

+      // Found FFS_ALIGNMENT, formats:

+      //   FFS_ALIGNMENT = 0-7

+      //   FFS_ATTRIB_DATA_ALIGNMENT = 0-7

+      //

+      if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) {

+        Error (

+          mGlobals.PrimaryPackagePath,

+          SFPGetLineNumber (),

+          0,

+          "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",

+          NULL

+          );

+        goto Done;

+      }

+

+      FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT;

+      if (!SFPIsToken ("=")) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);

+        goto Done;

+      }

+

+      if (!SFPGetNumber (&FfsAlignment32)) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL);

+        goto Done;

+      }

+

+      if (FfsAlignment32 > 7) {

+        Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL);

+        goto Done;

+      }

+

+      FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3);

+    } else {

+      SFPGetNextToken (InputString, sizeof (InputString));

+      Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token");

+      goto Done;

+    }

+  }

+  //

+  // Close the primary package file

+  //

+  SFPCloseFile ();

+  //

+  // TODO: replace code below with basically a copy of the code above. Don't

+  // forget to reset the FfsAttribDefined variable first. Also, you'll need

+  // to somehow keep track of whether or not the basename is defined multiple

+  // times in the override package. Ditto on the file GUID.

+  //

+  if (mGlobals.OverridePackagePath[0] != 0) {

+    OverridePackage = fopen (mGlobals.OverridePackagePath, "r");

+    //

+    // NOTE: For package override to work correctly, the code below must be modified to

+    //       SET or CLEAR bits properly. For example, if the primary package set

+    //       FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then

+    //       we'd need to clear the bit below. Since this is not happening, I'm guessing that

+    //       the override functionality is not being used, so should be made obsolete. If I'm

+    //       wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is

+    //       used, and we'll address it then.  4/10/2003

+    //

+    Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL);

+    goto Done;

+  } else {

+    OverridePackage = NULL;

+  }

+

+#ifdef OVERRIDE_SUPPORTED

+  if (OverridePackage != NULL) {

+    //

+    // Parse override package file

+    //

+    fscanf (OverridePackage, "%s", &InputString);

+    if (strcmpi (InputString, "PACKAGE.INF") != 0) {

+      Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");

+      goto Done;

+    }

+    //

+    // Match [dir] to Build Directory

+    //

+    if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) {

+      Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file");

+      goto Done;

+    }

+

+    InputString[0] = 0;

+    while ((InputString[0] != '[') && (!feof (OverridePackage))) {

+      if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) {

+        if (InputString[0] != '[') {

+here:

+          if (strcmpi (InputString, "BASE_NAME") == 0) {

+            //

+            // found BASE_NAME, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+              strcpy (BaseName, InputString);

+            } else {

+              BreakString (InputString, InputString, 1);

+              strcpy (BaseName, InputString);

+            }

+          } else if (strcmpi (InputString, "IMAGE_SCRIPT") == 0) {

+            //

+            // found IMAGE_SCRIPT, come back later to process it

+            //

+            ImageScriptInOveride = TRUE;

+            fscanf (OverridePackage, "%s", &InputString);

+          } else if (strcmpi (InputString, "FFS_FILEGUID") == 0) {

+            //

+            // found FILEGUID, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+              Status = StringToGuid (InputString, &FfsGuid);

+              if (Status != 0) {

+                Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");

+                goto Done;

+              }

+            } else {

+              BreakString (InputString, InputString, 1);

+              Status = StringToGuid (InputString, &FfsGuid);

+              if (Status != 0) {

+                Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");

+                goto Done;

+              }

+            }

+          } else if (strcmpi (InputString, "FFS_FILETYPE") == 0) {

+            //

+            // found FILETYPE, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+              strcpy (FileType, InputString);

+            } else {

+              BreakString (InputString, InputString, 1);

+              strcpy (FileType, InputString);

+            }

+

+          } else if (strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) {

+            //

+            // found FFS_ATTRIB_RECOVERY, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+              if (strcmpi (InputString, "TRUE") == 0) {

+                FfsAttrib |= FFS_ATTRIB_RECOVERY;

+              }

+            } else {

+              BreakString (InputString, InputString, 1);

+              if (strcmpi (InputString, "TRUE") == 0) {

+                FfsAttrib |= FFS_ATTRIB_RECOVERY;

+              }

+            }

+          } else if (strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) {

+            //

+            // found FFS_ATTRIB_CHECKSUM, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+              if (strcmpi (InputString, "TRUE") == 0) {

+                FfsAttrib |= FFS_ATTRIB_CHECKSUM;

+              }

+            } else {

+              BreakString (InputString, InputString, 1);

+              if (strcmpi (InputString, "TRUE") == 0) {

+                FfsAttrib |= FFS_ATTRIB_CHECKSUM;

+              }

+            }

+          } else if (strcmpi (InputString, "FFS_ALIGNMENT") == 0) {

+            //

+            // found FFS_ALIGNMENT, next is = and string.

+            //

+            fscanf (OverridePackage, "%s", &InputString);

+            CheckSlash (InputString, OverridePackage, &LineNumber);

+            if (strlen (InputString) == 1) {

+              //

+              // string is just =

+              //

+              fscanf (OverridePackage, "%s", &InputString);

+              CheckSlash (InputString, OverridePackage, &LineNumber);

+            } else {

+              BreakString (InputString, InputString, 1);

+            }

+

+            AsciiStringToUint64 (InputString, FALSE, &FfsAlignment);

+            if (FfsAlignment > 7) {

+              Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value");

+              goto Done;

+            }

+

+            FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3);

+          } else if (strchr (InputString, '=') != NULL) {

+            BreakString (InputString, String, 1);

+            fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR);

+            BreakString (InputString, InputString, 0);

+            goto here;

+          }

+        }

+      }

+    }

+  }

+#endif // #ifdef OVERRIDE_SUPPORTED

+  //

+  // Require that they specified a file GUID at least, since that's how we're

+  // naming the file.

+  //

+  if (GuidString[0] == 0) {

+    Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Build Header and process image script

+  //

+  FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8));

+  if (FileBuffer == NULL) {

+    Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);

+    goto Done;

+  }

+

+  FileSize = 0;

+  if (ImageScriptInOveride) {

+#ifdef OVERRIDE_SUPORTED

+    rewind (OverridePackage);

+    LineNumber = 0;

+    FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber);

+    while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {

+      GetNextLine (InputString, OverridePackage, &LineNumber);

+      CheckSlash (InputString, OverridePackage, &LineNumber);

+      if (strchr (InputString, '=') != NULL) {

+        BreakString (InputString, InputString, 0);

+      }

+    }

+

+    while (InputString[0] != '{') {

+      GetNextLine (InputString, OverridePackage, &LineNumber);

+      CheckSlash (InputString, OverridePackage, &LineNumber);

+    }

+    //

+    // Found start of image script, process it

+    //

+    FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress);

+    if (FileSize == -1) {

+      return -1;

+    }

+

+    if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {

+      FileSize = AdjustFileSize (FileBuffer, FileSize);

+    }

+

+    if (BaseName[0] == '\"') {

+      StripQuotes (BaseName);

+    }

+

+    if (BaseName[0] != 0) {

+      sprintf (InputString, "%s-%s", GuidString, BaseName);

+    } else {

+      strcpy (InputString, GuidString);

+    }

+

+    switch (StringToType (FileType)) {

+

+    case EFI_FV_FILETYPE_SECURITY_CORE:

+      strcat (InputString, ".SEC");

+      break;

+

+    case EFI_FV_FILETYPE_PEIM:

+    case EFI_FV_FILETYPE_PEI_CORE:

+    case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:

+      strcat (InputString, ".PEI");

+      break;

+

+    case EFI_FV_FILETYPE_DRIVER:

+    case EFI_FV_FILETYPE_DXE_CORE:

+      strcat (InputString, ".DXE");

+      break;

+

+    case EFI_FV_FILETYPE_APPLICATION:

+      strcat (InputString, ".APP");

+      break;

+

+    case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:

+      strcat (InputString, ".FVI");

+      break;

+

+    case EFI_FV_FILETYPE_ALL:

+      Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL);

+      goto Done;

+

+    default:

+      strcat (InputString, ".FFS");

+      break;

+    }

+

+    if (ForceUncompress) {

+      strcat (InputString, ".ORG");

+    }

+

+    Out = fopen (InputString, "wb");

+    if (Out == NULL) {

+      Error (NULL, 0, 0, InputString, "could not open output file for writing");

+      goto Done;

+    }

+    //

+    // create ffs header

+    //

+    memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));

+    memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));

+    FileHeader.Type       = StringToType (FileType);

+    FileHeader.Attributes = FfsAttrib;

+    //

+    // Now FileSize includes the EFI_FFS_FILE_HEADER

+    //

+    FileSize += sizeof (EFI_FFS_FILE_HEADER);

+    FileHeader.Size[0]  = (UINT8) (FileSize & 0xFF);

+    FileHeader.Size[1]  = (UINT8) ((FileSize & 0xFF00) >> 8);

+    FileHeader.Size[2]  = (UINT8) ((FileSize & 0xFF0000) >> 16);

+    //

+    // Fill in checksums and state, these must be zero for checksumming

+    //

+    // FileHeader.IntegrityCheck.Checksum.Header = 0;

+    // FileHeader.IntegrityCheck.Checksum.File = 0;

+    // FileHeader.State = 0;

+    //

+    FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (

+                                                  (UINT8 *) &FileHeader,

+                                                  sizeof (EFI_FFS_FILE_HEADER)

+                                                  );

+    if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {

+      FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize);

+    } else {

+      FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+    }

+

+    FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+    //

+    // write header

+    //

+    if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {

+      Error (NULL, 0, 0, "failed to write file header to output file", NULL);

+      goto Done;

+    }

+    //

+    // write data

+    //

+    if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {

+      Error (NULL, 0, 0, "failed to write all bytes to output file", NULL);

+      goto Done;

+    }

+

+    fclose (Out);

+    Out = NULL;

+#endif // #ifdef OVERRIDE_SUPPORTED

+  } else {

+    //

+    // Open primary package file and process the IMAGE_SCRIPT section

+    //

+    PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r");

+    if (PrimaryPackage == NULL) {

+      Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");

+      goto Done;

+    }

+

+    LineNumber = 1;

+    FindSectionInPackage (".", PrimaryPackage, &LineNumber);

+    while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {

+      GetNextLine (InputString, PrimaryPackage, &LineNumber);

+      CheckSlash (InputString, PrimaryPackage, &LineNumber);

+      if (strchr (InputString, '=') != NULL) {

+        BreakString (InputString, InputString, 0);

+      }

+    }

+

+    while (InputString[0] != '{') {

+      GetNextLine (InputString, PrimaryPackage, &LineNumber);

+      CheckSlash (InputString, PrimaryPackage, &LineNumber);

+    }

+    //

+    // Found start of image script, process it

+    //

+    FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress);

+    if (FileSize == -1) {

+      goto Done;

+    }

+

+    if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {

+      FileSize = AdjustFileSize (FileBuffer, FileSize);

+    }

+

+    if (BaseName[0] == '\"') {

+      StripQuotes (BaseName);

+    }

+

+    if (BaseName[0] != 0) {

+      sprintf (InputString, "%s-%s", GuidString, BaseName);

+    } else {

+      strcpy (InputString, GuidString);

+    }

+

+    switch (StringToType (FileType)) {

+

+    case EFI_FV_FILETYPE_SECURITY_CORE:

+      strcat (InputString, ".SEC");

+      break;

+

+    case EFI_FV_FILETYPE_PEIM:

+    case EFI_FV_FILETYPE_PEI_CORE:

+    case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:

+      strcat (InputString, ".PEI");

+      break;

+

+    case EFI_FV_FILETYPE_DRIVER:

+    case EFI_FV_FILETYPE_DXE_CORE:

+      strcat (InputString, ".DXE");

+      break;

+

+    case EFI_FV_FILETYPE_APPLICATION:

+      strcat (InputString, ".APP");

+      break;

+

+    case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:

+      strcat (InputString, ".FVI");

+      break;

+

+    case EFI_FV_FILETYPE_ALL:

+      Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL);

+      goto Done;

+

+    default:

+      strcat (InputString, ".FFS");

+      break;

+    }

+

+    if (ForceUncompress) {

+      strcat (InputString, ".ORG");

+    }

+

+    Out = fopen (InputString, "wb");

+    if (Out == NULL) {

+      Error (NULL, 0, 0, InputString, "failed to open output file for writing");

+      goto Done;

+    }

+    //

+    // Initialize the FFS file header

+    //

+    memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));

+    memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));

+    FileHeader.Type       = StringToType (FileType);

+    FileHeader.Attributes = FfsAttrib;

+    //

+    // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER

+    //

+    FileSize += sizeof (EFI_FFS_FILE_HEADER);

+    //

+    // If using a tail, then it adds two bytes

+    //

+    if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      //

+      // Tail is not allowed for pad and 0-length files

+      //

+      if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) {

+        Error (

+          mGlobals.PrimaryPackagePath,

+          1,

+          0,

+          "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",

+          NULL

+          );

+        goto Done;

+      }

+

+      FileSize += sizeof (EFI_FFS_FILE_TAIL);

+    }

+

+    FileHeader.Size[0]  = (UINT8) (FileSize & 0xFF);

+    FileHeader.Size[1]  = (UINT8) ((FileSize & 0xFF00) >> 8);

+    FileHeader.Size[2]  = (UINT8) ((FileSize & 0xFF0000) >> 16);

+    //

+    // Fill in checksums and state, they must be 0 for checksumming.

+    //

+    // FileHeader.IntegrityCheck.Checksum.Header = 0;

+    // FileHeader.IntegrityCheck.Checksum.File = 0;

+    // FileHeader.State = 0;

+    //

+    FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (

+                                                  (UINT8 *) &FileHeader,

+                                                  sizeof (EFI_FFS_FILE_HEADER)

+                                                  );

+    if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {

+      //

+      // Cheating here.  Since the header checksums, just calculate the checksum of the body.

+      // Checksum does not include the tail

+      //

+      if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+        FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (

+                                                    FileBuffer,

+                                                    FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL)

+                                                    );

+      } else {

+        FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (

+                                                    FileBuffer,

+                                                    FileSize - sizeof (EFI_FFS_FILE_HEADER)

+                                                    );

+      }

+    } else {

+      FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+    }

+    //

+    // Set the state now. Spec says the checksum assumes the state is 0

+    //

+    FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+    //

+    // If there is a tail, then set it

+    //

+    if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      TailValue = FileHeader.IntegrityCheck.TailReference;

+      TailValue = (UINT16) (~TailValue);

+      memcpy (

+        (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL),

+        &TailValue,

+        sizeof (TailValue)

+        );

+    }

+    //

+    // Write the FFS file header

+    //

+    if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {

+      Error (NULL, 0, 0, "failed to write file header contents", NULL);

+      goto Done;

+    }

+    //

+    // Write data

+    //

+    if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {

+      Error (NULL, 0, 0, "failed to write file contents", NULL);

+      goto Done;

+    }

+  }

+

+Done:

+  SFPCloseFile ();

+  if (Out != NULL) {

+    fclose (Out);

+  }

+

+  if (PrimaryPackage != NULL) {

+    fclose (PrimaryPackage);

+  }

+

+  if (FileBuffer != NULL) {

+    free (FileBuffer);

+  }

+

+  if (OverridePackage != NULL) {

+    fclose (OverridePackage);

+  }

+

+  return GetUtilityStatus ();

+}

+

+int

+main (

+  INT32 argc,

+  CHAR8 *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Main function.

+

+Arguments:

+

+  argc - Number of command line parameters.

+  argv - Array of pointers to parameter strings.

+

+Returns:

+  STATUS_SUCCESS - Utility exits successfully.

+  STATUS_ERROR   - Some error occurred during execution.

+

+--*/

+{

+  STATUS  Status;

+  //

+  // Set the name of our utility for error reporting purposes.

+  //

+  SetUtilityName (UTILITY_NAME);

+  Status = ProcessCommandLineArgs (argc, argv);

+  if (Status != STATUS_SUCCESS) {

+    return Status;

+  }

+

+  Status = MainEntry (argc, argv, TRUE);

+  if (Status == STATUS_SUCCESS) {

+    MainEntry (argc, argv, FALSE);

+  }

+  //

+  // If any errors were reported via the standard error reporting

+  // routines, then the status has been saved. Get the value and

+  // return it to the caller.

+  //

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+ProcessCommandLineArgs (

+  int     Argc,

+  char    *Argv[]

+  )

+/*++

+

+Routine Description:

+  Process the command line arguments.

+

+Arguments:

+  Argc - as passed in to main()

+  Argv - as passed in to main()

+

+Returns:

+  STATUS_SUCCESS    - arguments all ok

+  STATUS_ERROR      - problem with args, so caller should exit

+

+--*/

+{

+  //

+  // If no args, then print usage instructions and return an error

+  //

+  if (Argc == 1) {

+    PrintUsage ();

+    return STATUS_ERROR;

+  }

+

+  memset (&mGlobals, 0, sizeof (mGlobals));

+  Argc--;

+  Argv++;

+  while (Argc > 0) {

+    if (strcmpi (Argv[0], "-b") == 0) {

+      //

+      // OPTION: -b BuildDirectory

+      // Make sure there is another argument, then save it to our globals.

+      //

+      if (Argc < 2) {

+        Error (NULL, 0, 0, "-b option requires the build directory name", NULL);

+        return STATUS_ERROR;

+      }

+

+      if (mGlobals.BuildDirectory[0]) {

+        Error (NULL, 0, 0, Argv[0], "option can only be specified once");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.BuildDirectory, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (strcmpi (Argv[0], "-p1") == 0) {

+      //

+      // OPTION: -p1 PrimaryPackageFile

+      // Make sure there is another argument, then save it to our globals.

+      //

+      if (Argc < 2) {

+        Error (NULL, 0, 0, Argv[0], "option requires the primary package file name");

+        return STATUS_ERROR;

+      }

+

+      if (mGlobals.PrimaryPackagePath[0]) {

+        Error (NULL, 0, 0, Argv[0], "option can only be specified once");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.PrimaryPackagePath, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (strcmpi (Argv[0], "-p2") == 0) {

+      //

+      // OPTION: -p2 OverridePackageFile

+      // Make sure there is another argument, then save it to our globals.

+      //

+      if (Argc < 2) {

+        Error (NULL, 0, 0, Argv[0], "option requires the override package file name");

+        return STATUS_ERROR;

+      }

+

+      if (mGlobals.OverridePackagePath[0]) {

+        Error (NULL, 0, 0, Argv[0], "option can only be specified once");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.OverridePackagePath, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (strcmpi (Argv[0], "-v") == 0) {

+      //

+      // OPTION: -v       verbose

+      //

+      mGlobals.Verbose = TRUE;

+    } else if (strcmpi (Argv[0], "-h") == 0) {

+      //

+      // OPTION: -h      help

+      //

+      PrintUsage ();

+      return STATUS_ERROR;

+    } else if (strcmpi (Argv[0], "-?") == 0) {

+      //

+      // OPTION:  -?      help

+      //

+      PrintUsage ();

+      return STATUS_ERROR;

+    } else {

+      Error (NULL, 0, 0, Argv[0], "unrecognized option");

+      PrintUsage ();

+      return STATUS_ERROR;

+    }

+

+    Argv++;

+    Argc--;

+  }

+  //

+  // Must have at least specified the package file name

+  //

+  if (mGlobals.PrimaryPackagePath[0] == 0) {

+    Error (NULL, 0, 0, "must specify primary package file", NULL);

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

diff --git a/Source/GenFfsFile/GenFfsFile.h b/Source/GenFfsFile/GenFfsFile.h
new file mode 100644
index 0000000..f5bc718
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.h
@@ -0,0 +1,36 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenFfsFile.h 

+

+Abstract:

+

+  Header file for GenFfsFile.

+

+--*/

+

+//

+// Module Coded to Tiano Coding Conventions

+//

+#ifndef _EFI_GEN_FFSFILE_H

+#define _EFI_GEN_FFSFILE_H

+

+//

+// External Files Referenced

+//

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+

+#include "MyAlloc.h"

+

+#endif

diff --git a/Source/GenFfsFile/SimpleFileParsing.c b/Source/GenFfsFile/SimpleFileParsing.c
new file mode 100644
index 0000000..5fa5a22
--- /dev/null
+++ b/Source/GenFfsFile/SimpleFileParsing.c
@@ -0,0 +1,969 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  SimpleFileParsing.c  

+

+Abstract:

+

+  Generic but simple file parsing routines.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "EfiUtilityMsgs.h"

+#include "SimpleFileParsing.h"

+

+#define MAX_PATH                    255

+#define MAX_NEST_DEPTH              20  // just in case we get in an endless loop.

+#define MAX_STRING_IDENTIFIER_NAME  100 // number of wchars

+#define MAX_LINE_LEN                400

+

+#define T_CHAR_SPACE                ' '

+#define T_CHAR_NULL                 0

+#define T_CHAR_CR                   '\r'

+#define T_CHAR_TAB                  '\t'

+#define T_CHAR_LF                   '\n'

+#define T_CHAR_SLASH                '/'

+#define T_CHAR_BACKSLASH            '\\'

+#define T_CHAR_DOUBLE_QUOTE         '"'

+#define T_CHAR_LC_X                 'x'

+#define T_CHAR_0                    '0'

+

+//

+// We keep a linked list of these for the source files we process

+//

+typedef struct _SOURCE_FILE {

+  FILE                *Fptr;

+  T_CHAR              *FileBuffer;

+  T_CHAR              *FileBufferPtr;

+  UINT32              FileSize;

+  INT8                FileName[MAX_PATH];

+  UINT32              LineNum;

+  BOOLEAN             EndOfFile;

+  BOOLEAN             SkipToHash;

+  struct _SOURCE_FILE *Previous;

+  struct _SOURCE_FILE *Next;

+  T_CHAR              ControlCharacter;

+} SOURCE_FILE;

+

+//

+// Here's all our module globals.

+//

+static struct {

+  SOURCE_FILE SourceFile;

+  BOOLEAN     Verbose;

+} mGlobals;

+

+static

+UINT32

+t_strcmp (

+  T_CHAR *Buffer,

+  T_CHAR *Str

+  );

+

+static

+UINT32

+t_strncmp (

+  T_CHAR *Str1,

+  T_CHAR *Str2,

+  UINT32 Len

+  );

+

+static

+UINT32

+t_strlen (

+  T_CHAR *Str

+  );

+

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+SkipTo (

+  SOURCE_FILE *SourceFile,

+  T_CHAR      TChar,

+  BOOLEAN     StopAfterNewline

+  );

+

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+UINT32

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+//

+// static

+// T_CHAR *

+// GetQuotedString (

+//  SOURCE_FILE *SourceFile,

+//  BOOLEAN     Optional

+//  );

+//

+static

+T_CHAR  *

+t_strcpy (

+  T_CHAR *Dest,

+  T_CHAR *Src

+  );

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  );

+

+static

+STATUS

+ParseFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+FILE    *

+FindFile (

+  IN INT8     *FileName,

+  OUT INT8    *FoundFileName,

+  IN UINT32   FoundFileNameLen

+  );

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+STATUS

+SFPInit (

+  VOID

+  )

+{

+  memset ((void *) &mGlobals, 0, sizeof (mGlobals));

+  return STATUS_SUCCESS;

+}

+

+UINT32

+SFPGetLineNumber (

+  VOID

+  )

+{

+  return mGlobals.SourceFile.LineNum;

+}

+

+/*++

+

+Routine Description:

+  Return the line number of the file we're parsing. Used

+  for error reporting purposes.

+

+Arguments:

+  None.

+

+Returns:

+  The line number, or 0 if no file is being processed

+

+--*/

+T_CHAR *

+SFPGetFileName (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Return the name of the file we're parsing. Used

+  for error reporting purposes.

+

+Arguments:

+  None.

+

+Returns:

+  A pointer to the file name. Null if no file is being

+  processed.

+

+--*/

+{

+  if (mGlobals.SourceFile.FileName[0]) {

+    return mGlobals.SourceFile.FileName;

+  }

+

+  return NULL;

+}

+

+STATUS

+SFPOpenFile (

+  IN INT8   *FileName

+  )

+/*++

+

+Routine Description:

+  Open a file for parsing.

+

+Arguments:

+  FileName  - name of the file to parse

+

+Returns:

+  

+

+--*/

+{

+  STATUS  Status;

+  t_strcpy (mGlobals.SourceFile.FileName, FileName);

+  Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);

+  return Status;

+}

+

+BOOLEAN

+SFPIsToken (

+  T_CHAR *Str

+  )

+/*++

+

+Routine Description:

+  Check to see if the specified token is found at

+  the current position in the input file.

+

+Arguments:

+  Str - the token to look for

+

+Returns:

+  TRUE - the token is next

+  FALSE - the token is not next

+

+Notes:

+  We do a simple string comparison on this function. It is

+  the responsibility of the caller to ensure that the token

+  is not a subset of some other token.

+

+  The file pointer is advanced past the token in the input file.

+

+--*/

+{

+  UINT32  Len;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+

+  if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {

+    mGlobals.SourceFile.FileBufferPtr += Len;

+    return TRUE;

+  }

+

+  return FALSE;

+

+}

+

+BOOLEAN

+SFPGetNextToken (

+  T_CHAR *Str,

+  UINT32 Len

+  )

+{

+  UINT32  Index;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  Index = 0;

+  while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {

+    if (IsWhiteSpace (&mGlobals.SourceFile)) {

+      if (Index > 0) {

+        Str[Index] = 0;

+        return TRUE;

+      }

+

+      return FALSE;

+    } else {

+      Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];

+      mGlobals.SourceFile.FileBufferPtr++;

+      Index++;

+    }

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+SFPSkipToToken (

+  T_CHAR *Str

+  )

+{

+  UINT32  Len;

+  T_CHAR  *SavePos;

+  Len     = t_strlen (Str);

+  SavePos = mGlobals.SourceFile.FileBufferPtr;

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  while (!EndOfFile (&mGlobals.SourceFile)) {

+    if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {

+      mGlobals.SourceFile.FileBufferPtr += Len;

+      return TRUE;

+    }

+

+    mGlobals.SourceFile.FileBufferPtr++;

+    SkipWhiteSpace (&mGlobals.SourceFile);

+  }

+

+  mGlobals.SourceFile.FileBufferPtr = SavePos;

+  return FALSE;

+}

+

+BOOLEAN

+SFPGetNumber (

+  UINT32   *Value

+  )

+/*++

+

+Routine Description:

+  Check the token at the current file position for a numeric value.

+  May be either decimal or hex.

+

+Arguments:

+  Value  - pointer where to store the value

+

+Returns:

+  FALSE    - current token is not a number

+  TRUE     - current token is a number

+

+--*/

+{

+  //

+  //  UINT32 Len;

+  //

+  SkipWhiteSpace (&mGlobals.SourceFile);

+  if (EndOfFile (&mGlobals.SourceFile)) {

+    return FALSE;

+  }

+

+  if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+    //

+    // Check for hex value

+    //

+    if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {

+      if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {

+        return FALSE;

+      }

+

+      mGlobals.SourceFile.FileBufferPtr += 2;

+      sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);

+      while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+        mGlobals.SourceFile.FileBufferPtr++;

+      }

+

+      return TRUE;

+    } else {

+      *Value = atoi (mGlobals.SourceFile.FileBufferPtr);

+      while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {

+        mGlobals.SourceFile.FileBufferPtr++;

+      }

+

+      return TRUE;

+    }

+  } else {

+    return FALSE;

+  }

+}

+

+STATUS

+SFPCloseFile (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Close the file being parsed.

+

+Arguments:

+  None.

+

+Returns:

+  STATUS_SUCCESS - the file was closed 

+  STATUS_ERROR   - no file is currently open

+

+--*/

+{

+  if (mGlobals.SourceFile.FileBuffer != NULL) {

+    free (mGlobals.SourceFile.FileBuffer);

+    memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));

+    return STATUS_SUCCESS;

+  }

+

+  return STATUS_ERROR;

+}

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  )

+/*++

+

+Routine Description:

+

+  Given a source file, open the file and parse it

+  

+Arguments:

+

+  SourceFile        - name of file to parse

+  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.

+

+Returns:

+

+  Standard status.

+  

+--*/

+{

+  static UINT32 NestDepth = 0;

+  INT8          FoundFileName[MAX_PATH];

+  STATUS        Status;

+

+  Status = STATUS_SUCCESS;

+  NestDepth++;

+  //

+  // Print the file being processed. Indent so you can tell the include nesting

+  // depth.

+  //

+  if (mGlobals.Verbose) {

+    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);

+  }

+

+  //

+  // Make sure we didn't exceed our maximum nesting depth

+  //

+  if (NestDepth > MAX_NEST_DEPTH) {

+    Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+  //

+  // Try to open the file locally, and if that fails try along our include paths.

+  //

+  strcpy (FoundFileName, SourceFile->FileName);

+  if ((SourceFile->Fptr = fopen (FoundFileName, "r")) == NULL) {

+    //

+    // Try to find it among the paths if it has a parent (that is, it is included

+    // by someone else).

+    //

+    Error (NULL, 0, 0, SourceFile->FileName, "file not found");

+    return STATUS_ERROR;

+  }

+  //

+  // Process the file found

+  //

+  ProcessFile (SourceFile);

+Finish:

+  //

+  // Close open files and return status

+  //

+  if (SourceFile->Fptr != NULL) {

+    fclose (SourceFile->Fptr);

+    SourceFile->Fptr = NULL;

+  }

+

+  return Status;

+}

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  //

+  // Get the file size, and then read the entire thing into memory.

+  // Allocate space for a terminator character.

+  //

+  fseek (SourceFile->Fptr, 0, SEEK_END);

+  SourceFile->FileSize = ftell (SourceFile->Fptr);

+  fseek (SourceFile->Fptr, 0, SEEK_SET);

+  SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));

+  if (SourceFile->FileBuffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);

+  SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;

+  //

+  // Pre-process the file to replace comments with spaces

+  //

+  PreprocessFile (SourceFile);

+  SourceFile->LineNum = 1;

+  return STATUS_SUCCESS;

+}

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  )

+/*++

+

+Routine Description:

+  Preprocess a file to replace all carriage returns with NULLs so

+  we can print lines from the file to the screen.

+  

+Arguments:

+  SourceFile - structure that we use to keep track of an input file.

+

+Returns:

+  Nothing.

+  

+--*/

+{

+  BOOLEAN InComment;

+

+  RewindFile (SourceFile);

+  InComment = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    //

+    // If a line-feed, then no longer in a comment

+    //

+    if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      InComment = 0;

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {

+      //

+      // Replace all carriage returns with a NULL so we can print stuff

+      //

+      SourceFile->FileBufferPtr[0] = 0;

+      SourceFile->FileBufferPtr++;

+    } else if (InComment) {

+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;

+      SourceFile->FileBufferPtr++;

+    } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {

+      SourceFile->FileBufferPtr += 2;

+      InComment = TRUE;

+    } else {

+      SourceFile->FileBufferPtr++;

+    }

+  }

+  //

+  // Could check for end-of-file and still in a comment, but

+  // should not be necessary. So just restore the file pointers.

+  //

+  RewindFile (SourceFile);

+}

+

+#if 0

+static

+T_CHAR *

+GetQuotedString (

+  SOURCE_FILE *SourceFile,

+  BOOLEAN     Optional

+  )

+{

+  T_CHAR  *String;

+  T_CHAR  *Start;

+  T_CHAR  *Ptr;

+  UINT32  Len;

+  BOOLEAN PreviousBackslash;

+

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    if (!Optional) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);

+    }

+

+    return NULL;

+  }

+

+  Len = 0;

+  SourceFile->FileBufferPtr++;

+  Start             = Ptr = SourceFile->FileBufferPtr;

+  PreviousBackslash = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (!PreviousBackslash)) {

+      break;

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {

+      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);

+      PreviousBackslash = FALSE;

+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {

+      PreviousBackslash = TRUE;

+    } else {

+      PreviousBackslash = FALSE;

+    }

+

+    SourceFile->FileBufferPtr++;

+    Len++;

+  }

+

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);

+  } else {

+    SourceFile->FileBufferPtr++;

+  }

+  //

+  // Now allocate memory for the string and save it off

+  //

+  String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));

+  if (String == NULL) {

+    Error (NULL, 0, 0, "memory allocation failed", NULL);

+    return NULL;

+  }

+  //

+  // Copy the string from the file buffer to the local copy.

+  // We do no reformatting of it whatsoever at this point.

+  //

+  Ptr = String;

+  while (Len > 0) {

+    *Ptr = *Start;

+    Start++;

+    Ptr++;

+    Len--;

+  }

+

+  *Ptr = 0;

+  return String;

+}

+#endif

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  //

+  // The file buffer pointer will typically get updated before the End-of-file flag in the

+  // source file structure, so check it first.

+  //

+  if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {

+    SourceFile->EndOfFile = TRUE;

+    return TRUE;

+  }

+

+  if (SourceFile->EndOfFile) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+#if 0

+static

+void

+ProcessTokenInclude (

+  SOURCE_FILE *SourceFile

+  )

+{

+  INT8        IncludeFileName[MAX_PATH];

+  INT8        *To;

+  UINT32      Len;

+  BOOLEAN     ReportedError;

+  SOURCE_FILE IncludedSourceFile;

+

+  ReportedError = FALSE;

+  if (SkipWhiteSpace (SourceFile) == 0) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);

+  }

+  //

+  // Should be quoted file name

+  //

+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);

+    goto FailDone;

+  }

+

+  SourceFile->FileBufferPtr++;

+  //

+  // Copy the filename as ascii to our local string

+  //

+  To  = IncludeFileName;

+  Len = 0;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);

+      goto FailDone;

+    }

+

+    if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {

+      SourceFile->FileBufferPtr++;

+      break;

+    }

+    //

+    // If too long, then report the error once and process until the closing quote

+    //

+    Len++;

+    if (!ReportedError && (Len >= sizeof (IncludeFileName))) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);

+      ReportedError = TRUE;

+    }

+

+    if (!ReportedError) {

+      //

+      // *To = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]);

+      //

+      *To = (T_CHAR) SourceFile->FileBufferPtr[0];

+      To++;

+    }

+

+    SourceFile->FileBufferPtr++;

+  }

+

+  if (!ReportedError) {

+    *To = 0;

+    memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));

+    strcpy (IncludedSourceFile.FileName, IncludeFileName);

+    //

+    // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;

+    //

+    ProcessIncludeFile (&IncludedSourceFile, SourceFile);

+    //

+    // printf ("including file '%s'\n", IncludeFileName);

+    //

+  }

+

+  return ;

+FailDone:

+  //

+  // Error recovery -- skip to next #

+  //

+  SourceFile->SkipToHash = TRUE;

+}

+#endif

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  switch (*SourceFile->FileBufferPtr) {

+  case T_CHAR_NULL:

+  case T_CHAR_CR:

+  case T_CHAR_SPACE:

+  case T_CHAR_TAB:

+  case T_CHAR_LF:

+    return TRUE;

+

+  default:

+    return FALSE;

+  }

+}

+

+UINT32

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  UINT32  Count;

+

+  Count = 0;

+  while (!EndOfFile (SourceFile)) {

+    Count++;

+    switch (*SourceFile->FileBufferPtr) {

+    case T_CHAR_NULL:

+    case T_CHAR_CR:

+    case T_CHAR_SPACE:

+    case T_CHAR_TAB:

+      SourceFile->FileBufferPtr++;

+      break;

+

+    case T_CHAR_LF:

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      if (mGlobals.Verbose) {

+        printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);

+      }

+      break;

+

+    default:

+      return Count - 1;

+    }

+  }

+  //

+  // Some tokens require trailing whitespace. If we're at the end of the

+  // file, then we count that as well.

+  //

+  if ((Count == 0) && (EndOfFile (SourceFile))) {

+    Count++;

+  }

+

+  return Count;

+}

+

+static

+UINT32

+t_strcmp (

+  T_CHAR *Buffer,

+  T_CHAR *Str

+  )

+{

+  UINT32  Len;

+

+  Len = 0;

+  while (*Str == *Buffer) {

+    Buffer++;

+    Str++;

+    Len++;

+  }

+

+  if (*Str) {

+    return 0;

+  }

+

+  return Len;

+}

+

+static

+UINT32

+t_strlen (

+  T_CHAR *Str

+  )

+{

+  UINT32  Len;

+  Len = 0;

+  while (*Str) {

+    Len++;

+    Str++;

+  }

+

+  return Len;

+}

+

+static

+UINT32

+t_strncmp (

+  T_CHAR *Str1,

+  T_CHAR *Str2,

+  UINT32 Len

+  )

+{

+  while (Len > 0) {

+    if (*Str1 != *Str2) {

+      return Len;

+    }

+

+    Len--;

+    Str1++;

+    Str2++;

+  }

+

+  return 0;

+}

+

+static

+T_CHAR *

+t_strcpy (

+  T_CHAR *Dest,

+  T_CHAR *Src

+  )

+{

+  T_CHAR  *SaveDest;

+  SaveDest = Dest;

+  while (*Src) {

+    *Dest = *Src;

+    Dest++;

+    Src++;

+  }

+

+  *Dest = 0;

+  return SaveDest;

+}

+

+#if 0

+static

+BOOLEAN

+IsValidIdentifierChar (

+  INT8      Char,

+  BOOLEAN   FirstChar

+  )

+{

+  //

+  // If it's the first character of an identifier, then

+  // it must be one of [A-Za-z_].

+  //

+  if (FirstChar) {

+    if (isalpha (Char) || (Char == '_')) {

+      return TRUE;

+    }

+  } else {

+    //

+    // If it's not the first character, then it can

+    // be one of [A-Za-z_0-9]

+    //

+    if (isalnum (Char) || (Char == '_')) {

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

+#endif

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  SourceFile->LineNum       = 1;

+  SourceFile->FileBufferPtr = SourceFile->FileBuffer;

+  SourceFile->EndOfFile     = 0;

+}

+

+#if 0

+static

+BOOLEAN

+SkipTo (

+  SOURCE_FILE  *SourceFile,

+  T_CHAR       TChar,

+  BOOLEAN      StopAfterNewline

+  )

+{

+  while (!EndOfFile (SourceFile)) {

+    //

+    // Check for the character of interest

+    //

+    if (SourceFile->FileBufferPtr[0] == TChar) {

+      return TRUE;

+    } else {

+      if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {

+        SourceFile->LineNum++;

+        if (StopAfterNewline) {

+          SourceFile->FileBufferPtr++;

+          if (SourceFile->FileBufferPtr[0] == 0) {

+            SourceFile->FileBufferPtr++;

+          }

+

+          return FALSE;

+        }

+      }

+

+      SourceFile->FileBufferPtr++;

+    }

+  }

+

+  return FALSE;

+}

+#endif

diff --git a/Source/GenFfsFile/build.xml b/Source/GenFfsFile/build.xml
new file mode 100644
index 0000000..71f8bc9
--- /dev/null
+++ b/Source/GenFfsFile/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenFfsFile Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenFfsFile"/>

+  <property name="FileSet" value="GenFfsFile.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools CustomizedCompress"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenFvImage/Ebc/PeCoffLoaderEx.c b/Source/GenFvImage/Ebc/PeCoffLoaderEx.c
new file mode 100644
index 0000000..e8cf8b6
--- /dev/null
+++ b/Source/GenFvImage/Ebc/PeCoffLoaderEx.c
@@ -0,0 +1,57 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    PeCoffLoaderEx.c

+

+Abstract:

+

+    EBC Specific relocation fixups

+

+Revision History

+

+--*/

+

+

+

+

+RETURN_STATUS

+PeCoffLoaderRelocateImageEx (

+  IN UINT16      *Reloc,

+  IN OUT CHAR8   *Fixup,

+  IN OUT CHAR8   **FixupData,

+  IN UINT64      Adjust

+  )

+/*++

+

+Routine Description:

+

+  Performs an IA-32 specific relocation fixup

+

+Arguments:

+

+  Reloc      - Pointer to the relocation record

+

+  Fixup      - Pointer to the address to fix up

+

+  FixupData  - Pointer to a buffer to log the fixups

+

+  Adjust     - The offset to adjust the fixup

+

+Returns:

+

+  EFI_UNSUPPORTED   - Unsupported now

+

+--*/

+{

+  return RETURN_UNSUPPORTED;

+}

diff --git a/Source/GenFvImage/GenFvImageExe.c b/Source/GenFvImage/GenFvImageExe.c
new file mode 100644
index 0000000..d0117b8
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageExe.c
@@ -0,0 +1,299 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenFvImageExe.c

+

+Abstract:

+

+  This contains all code necessary to build the GenFvImage.exe utility.       

+  This utility relies heavily on the GenFvImage Lib.  Definitions for both

+  can be found in the Tiano Firmware Volume Generation Utility 

+  Specification, review draft.

+

+--*/

+

+//

+// File included in build

+//

+#include "GenFvImageExe.h"

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s - Tiano Firmware Volume Generation Utility."" Version %i.%i\n\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION

+    );

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf ("Usage: %s -I FvInfFileName\n", UTILITY_NAME);

+  printf ("  Where:\n");

+  printf ("\tFvInfFileName is the name of the image description file.\n\n");

+}

+

+int

+main (

+  IN INTN   argc,

+  IN CHAR8  **argv

+  )

+/*++

+

+Routine Description:

+

+  This utility uses GenFvImage.Lib to build a firmware volume image.

+

+Arguments:

+

+  FvInfFileName      The name of an FV image description file.

+

+  Arguments come in pair in any order.

+    -I FvInfFileName 

+

+Returns:

+

+  EFI_SUCCESS            No error conditions detected.

+  EFI_INVALID_PARAMETER  One or more of the input parameters is invalid.

+  EFI_OUT_OF_RESOURCES   A resource required by the utility was unavailable.  

+                         Most commonly this will be memory allocation 

+                         or file creation.

+  EFI_LOAD_ERROR         GenFvImage.lib could not be loaded.

+  EFI_ABORTED            Error executing the GenFvImage lib.

+

+--*/

+{

+  EFI_STATUS  Status;

+  CHAR8       InfFileName[_MAX_PATH];

+  CHAR8       *InfFileImage;

+  UINTN       InfFileSize;

+  UINT8       *FvImage;

+  UINTN       FvImageSize;

+  UINT8       Index;

+  CHAR8       FvFileNameBuffer[_MAX_PATH];

+  CHAR8       *FvFileName;

+  FILE        *FvFile;

+  FILE        *SymFile;

+  CHAR8       SymFileNameBuffer[_MAX_PATH];

+  CHAR8       *SymFileName;

+  UINT8       *SymImage;

+  UINTN       SymImageSize;

+  CHAR8       *CurrentSymString;

+

+  FvFileName  = FvFileNameBuffer;

+  SymFileName = SymFileNameBuffer;

+

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Display utility information

+  //

+  PrintUtilityInfo ();

+

+  //

+  // Verify the correct number of arguments

+  //

+  if (argc != MAX_ARGS) {

+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);

+    PrintUsage ();

+    return GetUtilityStatus ();

+  }

+  //

+  // Initialize variables

+  //

+  strcpy (InfFileName, "");

+

+  //

+  // Parse the command line arguments

+  //

+  for (Index = 1; Index < MAX_ARGS; Index += 2) {

+    //

+    // Make sure argument pair begin with - or /

+    //

+    if (argv[Index][0] != '-' && argv[Index][0] != '/') {

+      Error (NULL, 0, 0, argv[Index], "argument pair must begin with \"-\" or \"/\"");

+      PrintUsage ();

+      return GetUtilityStatus ();

+    }

+    //

+    // Make sure argument specifier is only one letter

+    //

+    if (argv[Index][2] != 0) {

+      Error (NULL, 0, 0, argv[Index], "unrecognized argument");

+      PrintUsage ();

+      return GetUtilityStatus ();

+    }

+    //

+    // Determine argument to read

+    //

+    switch (argv[Index][1]) {

+

+    case 'I':

+    case 'i':

+      if (strlen (InfFileName) == 0) {

+        strcpy (InfFileName, argv[Index + 1]);

+      } else {

+        Error (NULL, 0, 0, argv[Index + 1], "FvInfFileName may only be specified once");

+        PrintUsage ();

+        return GetUtilityStatus ();

+      }

+      break;

+

+    default:

+      Error (NULL, 0, 0, argv[Index], "unrecognized argument");

+      PrintUsage ();

+      return GetUtilityStatus ();

+      break;

+    }

+  }

+  //

+  // Read the INF file image

+  //

+  Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);

+  if (EFI_ERROR (Status)) {

+    return STATUS_ERROR;

+  }

+  //

+  // Call the GenFvImage lib

+  //

+  Status = GenerateFvImage (

+            InfFileImage,

+            InfFileSize,

+            &FvImage,

+            &FvImageSize,

+            &FvFileName,

+            &SymImage,

+            &SymImageSize,

+            &SymFileName

+            );

+

+  if (EFI_ERROR (Status)) {

+    switch (Status) {

+

+    case EFI_INVALID_PARAMETER:

+      Error (NULL, 0, 0, "invalid parameter passed to GenFvImage Lib", NULL);

+      return GetUtilityStatus ();

+      break;

+

+    case EFI_ABORTED:

+      Error (NULL, 0, 0, "error detected while creating the file image", NULL);

+      return GetUtilityStatus ();

+      break;

+

+    case EFI_OUT_OF_RESOURCES:

+      Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL);

+      return GetUtilityStatus ();

+      break;

+

+    case EFI_VOLUME_CORRUPTED:

+      Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL);

+      return GetUtilityStatus ();

+      break;

+

+    case EFI_LOAD_ERROR:

+      Error (NULL, 0, 0, "could not load FV image generation library", NULL);

+      return GetUtilityStatus ();

+      break;

+

+    default:

+      Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status);

+      return GetUtilityStatus ();

+      break;

+    }

+  }

+  //

+  // Write file

+  //

+  FvFile = fopen (FvFileName, "wb");

+  if (FvFile == NULL) {

+    Error (NULL, 0, 0, FvFileName, "could not open output file");

+    free (FvImage);

+    free (SymImage);

+    return GetUtilityStatus ();

+  }

+

+  if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) {

+    Error (NULL, 0, 0, FvFileName, "failed to write to output file");

+    free (FvImage);

+    free (SymImage);

+    fclose (FvFile);

+    return GetUtilityStatus ();

+  }

+

+  fclose (FvFile);

+  free (FvImage);

+

+  //

+  // Write symbol file

+  //

+  if (strcmp (SymFileName, "")) {

+    SymFile = fopen (SymFileName, "wt");

+    if (SymFile == NULL) {

+      Error (NULL, 0, 0, SymFileName, "could not open output symbol file");

+      free (SymImage);

+      return GetUtilityStatus ();

+    }

+

+    fprintf (SymFile, "TEXTSYM format | V1.0\n");

+

+    CurrentSymString = SymImage;

+    while (((UINTN) CurrentSymString - (UINTN) SymImage) < SymImageSize) {

+      fprintf (SymFile, "%s", CurrentSymString);

+      CurrentSymString = (CHAR8 *) (((UINTN) CurrentSymString) + strlen (CurrentSymString) + 1);

+    }

+

+    fclose (SymFile);

+  }

+

+  free (SymImage);

+

+  return GetUtilityStatus ();

+}

diff --git a/Source/GenFvImage/GenFvImageExe.h b/Source/GenFvImage/GenFvImageExe.h
new file mode 100644
index 0000000..9b97935
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageExe.h
@@ -0,0 +1,98 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  GenFvImageExe.h

+

+Abstract:

+

+  Definitions for the PeimFixup exe utility.

+

+--*/

+

+//

+// Coded to Tiano Coding Standards

+//

+#ifndef _EFI_GEN_FV_IMAGE_EXE_H

+#define _EFI_GEN_FV_IMAGE_EXE_H

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include "GenFvImageLib.h"

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "GenFvImage"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION 0

+#define UTILITY_MINOR_VERSION 1

+#define UTILITY_DATE          __DATE__

+

+//

+// The maximum number of arguments accepted from the command line.

+//

+#define MAX_ARGS  3

+

+//

+// The function that displays general utility information

+//

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+//

+// The function that displays the utility usage message.

+//

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/Source/GenFvImage/GenFvImageLib.c b/Source/GenFvImage/GenFvImageLib.c
new file mode 100644
index 0000000..eb36663
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLib.c
@@ -0,0 +1,2719 @@
+/*++

+i

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenFvImageLib.c

+

+Abstract:

+

+  This file contains functions required to generate a Firmware Volume.

+

+--*/

+

+//

+// Include files

+//

+#ifdef __GNUC__

+#include <uuid/uuid.h>

+#include <sys/stat.h>

+#endif

+#include <string.h>

+#ifndef __GNUC__

+#include <io.h>

+#endif

+#include <assert.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/Variable.h>

+#include <Common/WorkingBlockHeader.h>

+#include <Guid/FirmwareFileSystem.h>

+

+#include "GenFvImageLib.h"

+#include "GenFvImageLibInternal.h"

+#include "CommonLib.h"

+#include "Crc32.h"

+#include "EfiUtilityMsgs.h"

+#include "FvLib.h"

+#include "EfiCompress.h"

+#include "WinNtInclude.h"

+

+

+//

+// Local function prototypes

+//

+EFI_STATUS

+GetPe32Info (

+  IN UINT8                  *Pe32,

+  OUT UINT32                *EntryPoint,

+  OUT UINT32                *BaseOfCode,

+  OUT UINT16                *MachineType

+  );

+

+//

+// Local function implementations.

+//

+EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;

+EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };

+

+//

+// This data array will be located at the base of the Firmware Volume Header (FVH)

+// in the boot block.  It must not exceed 14 bytes of code.  The last 2 bytes

+// will be used to keep the FVH checksum consistent.

+// This code will be run in response to a starutp IPI for HT-enabled systems.

+//

+#define SIZEOF_STARTUP_DATA_ARRAY 0x10

+

+UINT8                                   m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {

+  //

+  // EA D0 FF 00 F0               ; far jmp F000:FFD0

+  // 0, 0, 0, 0, 0, 0, 0, 0, 0,   ; Reserved bytes

+  // 0, 0                         ; Checksum Padding

+  //

+  0xEA,

+  0xD0,

+  0xFF,

+  0x0,

+  0xF0,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00

+};

+

+UINT8                                   m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {

+  //

+  // EB CE                               ; jmp short ($-0x30)

+  // ; (from offset 0x0 to offset 0xFFD0)

+  // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes

+  // 0, 0                                ; Checksum Padding

+  //

+  0xEB,

+  0xCE,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00,

+  0x00

+};

+

+EFI_STATUS

+ParseFvInf (

+  IN MEMORY_FILE  *InfFile,

+  IN FV_INFO      *FvInfo

+  )

+/*++

+

+Routine Description:

+

+  This function parses a FV.INF file and copies info into a FV_INFO structure.

+

+Arguments:

+

+  InfFile         Memory file image.

+  FvInfo          Information read from INF file.

+

+Returns:

+

+  EFI_SUCCESS       INF file information successfully retrieved.

+  EFI_ABORTED       INF file has an invalid format.

+  EFI_NOT_FOUND     A required string was not found in the INF file.

+--*/

+{

+  CHAR8       Value[_MAX_PATH];

+  UINT64      Value64;

+  UINTN       Index;

+  EFI_STATUS  Status;

+

+  //

+  // Initialize FV info

+  //

+  memset (FvInfo, 0, sizeof (FV_INFO));

+

+  //

+  // Read the FV base address

+  //

+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Get the base address

+    //

+    Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");

+      return EFI_ABORTED;

+    }

+

+    FvInfo->BaseAddress = Value64;

+  } else {

+    Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");

+    return EFI_ABORTED;

+  }

+  //

+  // Read the FV Guid

+  //

+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Get the guid value

+    //

+    Status = StringToGuid (Value, &FvInfo->FvGuid);

+    if (EFI_ERROR (Status)) {

+      memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));

+    }

+  } else {

+    memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));

+  }

+  //

+  // Read the FV file name

+  //

+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // copy the file name

+    //

+    strcpy (FvInfo->FvName, Value);

+  } else {

+    Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");

+    return EFI_ABORTED;

+  }

+  //

+  // Read the Sym file name

+  //

+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // copy the file name

+    //

+    strcpy (FvInfo->SymName, Value);

+  } else {

+    //

+    // Symbols not required, so init to NULL.

+    //

+    strcpy (FvInfo->SymName, "");

+  }

+  //

+  // Read the read disabled capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the read disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the read enabled capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the read disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the read status attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the read disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the write disabled capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the write disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the write enabled capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the write disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the write status attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the write disabled flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the lock capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the attribute flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the lock status attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the attribute flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the sticky write attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the attribute flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the memory mapped attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the attribute flag

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the erase polarity attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update the attribute flag

+    //

+    if (strcmp (Value, ONE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;

+    } else if (strcmp (Value, ZERO_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the alignment capabilities attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the word alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the dword alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the word alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the qword alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 32 byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 64 byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 128 byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 256 byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 512 byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 1K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 2K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 4K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 8K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 16K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 32K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");

+    return Status;

+  }

+  //

+  // Read the 64K byte alignment capability attribute

+  //

+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);

+

+  if (Status == EFI_SUCCESS) {

+    //

+    // Update attribute

+    //

+    if (strcmp (Value, TRUE_STRING) == 0) {

+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;

+    } else if (strcmp (Value, FALSE_STRING) != 0) {

+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);

+      return EFI_ABORTED;

+    }

+  } else {

+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");

+    return Status;

+  }

+

+  if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&

+      (

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||

+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)

+      )

+     ) {

+    Error (

+      NULL,

+      0,

+      0,

+      "illegal combination of alignment attributes",

+      "if %s is not %s, no individual alignments can be %s",

+      EFI_FVB_ALIGNMENT_CAP_STRING,

+      TRUE_STRING,

+      TRUE_STRING

+      );

+    return EFI_ABORTED;

+  }

+  //

+  // Read block maps

+  //

+  for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {

+    //

+    // Read the number of blocks

+    //

+    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Update the number of blocks

+      //

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;

+    } else {

+      //

+      // If there is no number of blocks, but there is a size, then we have a mismatched pair

+      // and should return an error.

+      //

+      Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);

+      if (!EFI_ERROR (Status)) {

+        Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);

+        return EFI_ABORTED;

+      } else {

+        //

+        // We are done

+        //

+        break;

+      }

+    }

+    //

+    // Read the size of blocks

+    //

+    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Update the number of blocks

+      //

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;

+    } else {

+      //

+      // There is a number of blocks, but there is no size, so we have a mismatched pair

+      // and should return an error.

+      //

+      Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);

+      return EFI_ABORTED;

+    }

+  }

+  //

+  // Read files

+  //

+  for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {

+    //

+    // Read the number of blocks

+    //

+    Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Add the file

+      //

+      strcpy (FvInfo->FvFiles[Index], Value);

+    } else {

+      break;

+    }

+  }

+

+  if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {

+    Index = 0;

+    //

+    // Read component FV_VARIABLE

+    //

+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Add the component

+      //

+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;

+    } else {

+      printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);

+    }

+

+    Index++;

+    //

+    // Read component FV_EVENT_LOG

+    //

+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Add the component

+      //

+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;

+    } else {

+      printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);

+    }

+

+    Index++;

+    //

+    // Read component FV_FTW_WORKING

+    //

+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Add the component

+      //

+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;

+    } else {

+      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);

+    }

+

+    Index++;

+    //

+    // Read component FV_FTW_SPARE

+    //

+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);

+

+    if (Status == EFI_SUCCESS) {

+      //

+      // Add the component

+      //

+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);

+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);

+      if (EFI_ERROR (Status)) {

+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);

+        return EFI_ABORTED;

+      }

+

+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;

+    } else {

+      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);

+    }

+  }

+  //

+  // Compute size for easy access later

+  //

+  FvInfo->Size = 0;

+  for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {

+    FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+UpdateFfsFileState (

+  IN EFI_FFS_FILE_HEADER          *FfsFile,

+  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader

+  )

+/*++

+

+Routine Description:

+

+  This function changes the FFS file attributes based on the erase polarity

+  of the FV.

+

+Arguments:

+

+  FfsFile   File header.

+  FvHeader  FV header.

+

+Returns:

+

+  None

+

+--*/

+{

+  if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {

+    FfsFile->State = (UINT8)~(FfsFile->State);

+  }

+}

+

+EFI_STATUS

+ReadFfsAlignment (

+  IN EFI_FFS_FILE_HEADER    *FfsFile,

+  IN OUT UINT32             *Alignment

+  )

+/*++

+

+Routine Description:

+

+  This function determines the alignment of the FFS input file from the file

+  attributes.

+

+Arguments:

+

+  FfsFile       FFS file to parse

+  Alignment     The minimum required alignment of the FFS file, in bytes

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              An error occurred.

+

+--*/

+{

+  //

+  // Verify input parameters.

+  //

+  if (FfsFile == NULL || Alignment == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  switch ((FfsFile->Attributes >> 3) & 0x07) {

+

+  case 0:

+    //

+    // 1 byte alignment

+    //

+    *Alignment = (1 << 0);

+    break;

+

+  case 1:

+    //

+    // 16 byte alignment

+    //

+    *Alignment = (1 << 4);

+    break;

+

+  case 2:

+    //

+    // 128 byte alignment

+    //

+    *Alignment = (1 << 7);

+    break;

+

+  case 3:

+    //

+    // 512 byte alignment

+    //

+    *Alignment = (1 << 9);

+    break;

+

+  case 4:

+    //

+    // 1K byte alignment

+    //

+    *Alignment = (1 << 10);

+    break;

+

+  case 5:

+    //

+    // 4K byte alignment

+    //

+    *Alignment = (1 << 12);

+    break;

+

+  case 6:

+    //

+    // 32K byte alignment

+    //

+    *Alignment = (1 << 15);

+    break;

+

+  case 7:

+    //

+    // 64K byte alignment

+    //

+    *Alignment = (1 << 16);

+    break;

+

+  default:

+    Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);

+    return EFI_ABORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddPadFile (

+  IN OUT MEMORY_FILE  *FvImage,

+  IN UINT32           DataAlignment

+  )

+/*++

+

+Routine Description:

+

+  This function adds a pad file to the FV image if it required to align the

+  data of the next file.

+

+Arguments:

+

+  FvImage         The memory image of the FV to add it to.  The current offset

+                  must be valid.

+  DataAlignment   The data alignment of the next FFS file.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_OUT_OF_RESOURCES     Insufficient resources exist in the FV to complete

+                           the pad file add.

+

+--*/

+{

+  EFI_FFS_FILE_HEADER *PadFile;

+  EFI_GUID            PadFileGuid;

+  UINTN               PadFileSize;

+

+  //

+  // Verify input parameters.

+  //

+  if (FvImage == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Basic assumption is we start from an 8 byte aligned address

+  // and our file header is a multiple of 8 bytes

+  //

+  assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);

+  assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);

+

+  //

+  // Check if a pad file is necessary

+  //

+  if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {

+    return EFI_SUCCESS;

+  }

+  //

+  // Write pad file header

+  //

+  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;

+

+  //

+  // Verify that we have enough space for the file header

+  //

+  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+#ifdef __GNUC__

+  {

+    uuid_t tmp_id;

+    uuid_generate (tmp_id);

+    memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID));

+  }

+#else

+  UuidCreate (&PadFileGuid);

+#endif

+  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));

+  memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));

+  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;

+  PadFile->Attributes = 0;

+

+  //

+  // Calculate the pad file size

+  //

+  //

+  // This is the earliest possible valid offset (current plus pad file header

+  // plus the next file header)

+  //

+  PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);

+

+  //

+  // Add whatever it takes to get to the next aligned address

+  //

+  while ((PadFileSize % DataAlignment) != 0) {

+    PadFileSize++;

+  }

+  //

+  // Subtract the next file header size

+  //

+  PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);

+

+  //

+  // Subtract the starting offset to get size

+  //

+  PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;

+

+  //

+  // Write pad file size (calculated size minus next file header size)

+  //

+  PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);

+  PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);

+  PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);

+

+  //

+  // Fill in checksums and state, they must be 0 for checksumming.

+  //

+  PadFile->IntegrityCheck.Checksum.Header = 0;

+  PadFile->IntegrityCheck.Checksum.File   = 0;

+  PadFile->State                          = 0;

+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));

+  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);

+  } else {

+    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+  }

+

+  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+  UpdateFfsFileState (

+    (EFI_FFS_FILE_HEADER *) PadFile,

+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage

+    );

+

+  //

+  // Verify that we have enough space (including the padding

+  //

+  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Update the current FV pointer

+  //

+  FvImage->CurrentFilePointer += PadFileSize;

+

+  return EFI_SUCCESS;

+}

+

+BOOLEAN

+IsVtfFile (

+  IN EFI_FFS_FILE_HEADER    *FileBuffer

+  )

+/*++

+

+Routine Description:

+

+  This function checks the header to validate if it is a VTF file

+

+Arguments:

+

+  FileBuffer     Buffer in which content of a file has been read.

+

+Returns:

+

+  TRUE    If this is a VTF file

+  FALSE   If this is not a VTF file

+

+--*/

+{

+  EFI_GUID  VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;

+  if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {

+    return TRUE;

+  } else {

+    return FALSE;

+  }

+}

+

+EFI_STATUS

+FfsRebaseImageRead (

+  IN     VOID    *FileHandle,

+  IN     UINTN   FileOffset,

+  IN OUT UINT32  *ReadSize,

+  OUT    VOID    *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file

+

+Arguments:

+

+  FileHandle - The handle to the PE/COFF file

+

+  FileOffset - The offset, in bytes, into the file to read

+

+  ReadSize   - The number of bytes to read from the file starting at FileOffset

+

+  Buffer     - A pointer to the buffer to read the data into.

+

+Returns:

+

+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset

+

+--*/

+{

+  CHAR8   *Destination8;

+  CHAR8   *Source8;

+  UINT32  Length;

+

+  Destination8  = Buffer;

+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);

+  Length        = *ReadSize;

+  while (Length--) {

+    *(Destination8++) = *(Source8++);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+EFI_STATUS

+AddSymFile (

+  IN UINT64               BaseAddress,

+  IN EFI_FFS_FILE_HEADER  *FfsFile,

+  IN OUT MEMORY_FILE      *SymImage,

+  IN CHAR8                *SourceFileName

+  )

+/*++

+

+Routine Description:

+

+  This function adds the SYM tokens in the source file to the destination file.

+  The SYM tokens are updated to reflect the base address.

+

+Arguments:

+

+  BaseAddress     The base address for the new SYM tokens.

+  FfsFile         Pointer to the beginning of the FFS file in question.

+  SymImage        The memory file to update with symbol information.

+  SourceFileName  The source file.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              An error occurred.

+

+--*/

+{

+  FILE                      *SourceFile;

+

+  CHAR8                     Buffer[_MAX_PATH];

+  CHAR8                     Type[_MAX_PATH];

+  CHAR8                     Address[_MAX_PATH];

+  CHAR8                     Section[_MAX_PATH];

+  CHAR8                     Token[_MAX_PATH];

+  CHAR8                     SymFileName[_MAX_PATH];

+  CHAR8                     CodeModuleName[_MAX_PATH];

+  CHAR8                     *Ptr;

+

+  UINT64                    TokenAddress;

+

+  EFI_STATUS                Status;

+  EFI_FILE_SECTION_POINTER  Pe32Section;

+  UINT32                    EntryPoint;

+  UINT32                    BaseOfCode;

+  UINT16                    MachineType;

+

+  //

+  // Verify input parameters.

+  //

+  if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {

+    Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Check if we want to add this file

+  //

+  //

+  // Get the file name

+  //

+  strcpy (Buffer, SourceFileName);

+

+  //

+  // Copy the file name for the path of the sym file and truncate the name portion.

+  //

+  strcpy (SymFileName, Buffer);

+  Ptr = strrchr (SymFileName, '\\');

+  assert (Ptr);

+  Ptr[0] = 0;

+

+  //

+  // Find the file extension and make it lower case

+  //

+  Ptr = strrchr (SymFileName, '.');

+  if (Ptr != NULL) {

+    strlwr (Ptr);

+  }

+  //

+  // Check if it is PEI file

+  //

+  if (strstr (Buffer, ".pei") != NULL) {

+    //

+    // Find the human readable portion

+    //

+    if (!strtok (Buffer, "-") ||

+        !strtok (NULL, "-") ||

+        !strtok (NULL, "-") ||

+        !strtok (NULL, "-") ||

+        !strtok (NULL, "-") ||

+        !strcpy (Buffer, strtok (NULL, "."))

+          ) {

+      Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);

+      return EFI_ABORTED;

+    }

+    //

+    // Save code module name

+    //

+    strcpy (CodeModuleName, Buffer);

+

+    //

+    // Add the symbol file name and extension to the file path.

+    //

+    strcat (Buffer, ".sym");

+    strcat (SymFileName, "\\");

+    strcat (SymFileName, Buffer);

+  } else {

+    //

+    // Only handle PEIM files.

+    //

+    return EFI_SUCCESS;

+  }

+  //

+  // Find PE32 section

+  //

+  Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);

+

+  //

+  // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address

+  //

+  if (Status == EFI_NOT_FOUND) {

+    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);

+  }

+

+  if (Status == EFI_SUCCESS) {

+    Status = GetPe32Info (

+              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),

+              &EntryPoint,

+              &BaseOfCode,

+              &MachineType

+              );

+  } else if (Status == EFI_NOT_FOUND) {

+    //

+    // For PIC, hardcode.

+    //

+    BaseOfCode = 0x60;

+    Status = EFI_SUCCESS;

+  } else {

+    Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);

+    return Status;

+  }

+

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);

+    return Status;

+  }

+

+  //

+  // Open the source file

+  //

+  SourceFile = fopen (SymFileName, "r");

+  if (SourceFile == NULL) {

+    //

+    // SYM files are not required.

+    //

+    return EFI_SUCCESS;

+  }

+  //

+  // Read the first line

+  //

+  if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {

+    Buffer[0] = 0;

+  }

+  //

+  // Make sure it matches the expected sym format

+  //

+  if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {

+    fclose (SourceFile);

+    Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);

+    return EFI_ABORTED;

+  }

+  //

+  // Read in the file

+  //

+  while (feof (SourceFile) == 0) {

+    //

+    // Read a line

+    //

+    if (fscanf (

+          SourceFile,

+          "%s | %s | %s | %s\n",

+          Type,

+          Address,

+          Section,

+          Token

+          ) == 4) {

+      //

+      // If the token starts with "??" ignore it

+      //

+      if (Token[0] == '?' && Token[1] == '?') {

+        continue;

+      }

+      //

+      // Get the token address

+      //

+      AsciiStringToUint64 (Address, TRUE, &TokenAddress);

+

+      //

+      // Add the base address

+      //

+      TokenAddress += BaseAddress;

+

+      //

+      // If PE32 or TE section then find the start of code.  For PIC it is hardcoded.

+      //

+      if (Pe32Section.Pe32Section) {

+        //

+        // Add the offset of the PE32 section

+        //

+        TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;

+

+        //

+        // Add the size of the PE32 section header

+        //

+        TokenAddress += sizeof (EFI_PE32_SECTION);

+      } else {

+        //

+        // For PIC hardcoded.

+        //

+        TokenAddress += 0x28;

+      }

+

+      //

+      // Add the beginning of the code

+      //

+      TokenAddress += BaseOfCode;

+

+      sprintf (

+        Buffer,

+        "%s | %016I64X | %s | _%s%s\n",

+        Type,

+        TokenAddress,

+        Section,

+        CodeModuleName,

+        Token

+        );

+      memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);

+      SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);

+    }

+  }

+

+  fclose (SourceFile);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddFile (

+  IN OUT MEMORY_FILE          *FvImage,

+  IN FV_INFO                  *FvInfo,

+  IN UINTN                    Index,

+  IN OUT EFI_FFS_FILE_HEADER  **VtfFileImage,

+  IN OUT MEMORY_FILE          *SymImage

+  )

+/*++

+

+Routine Description:

+

+  This function adds a file to the FV image.  The file will pad to the

+  appropriate alignment if required.

+

+Arguments:

+

+  FvImage       The memory image of the FV to add it to.  The current offset

+                must be valid.

+  FvInfo        Pointer to information about the FV.

+  Index         The file in the FvInfo file list to add.

+  VtfFileImage  A pointer to the VTF file within the FvImage.  If this is equal

+                to the end of the FvImage then no VTF previously found.

+  SymImage      The memory image of the Sym file to update if symbols are present.

+                The current offset must be valid.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              An error occurred.

+  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.

+

+--*/

+{

+  FILE                  *NewFile;

+  UINTN                 FileSize;

+  UINT8                 *FileBuffer;

+  UINTN                 NumBytesRead;

+  UINT32                CurrentFileAlignment;

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  CurrentFileBaseAddress;

+  UINT8                 VtfHeaderChecksum;

+  UINT8                 VtfFileChecksum;

+  UINT8                 FileState;

+  EFI_FFS_FILE_TAIL     TailValue;

+  UINT32                TailSize;

+  //

+  // Verify input parameters.

+  //

+  if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Read the file to add

+  //

+  NewFile = fopen (FvInfo->FvFiles[Index], "rb");

+

+  if (NewFile == NULL) {

+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");

+    return EFI_ABORTED;

+  }

+  //

+  // Get the file size

+  //

+  FileSize = _filelength (fileno (NewFile));

+

+  //

+  // Read the file into a buffer

+  //

+  FileBuffer = malloc (FileSize);

+  if (FileBuffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);

+

+  //

+  // Done with the file, from this point on we will just use the buffer read.

+  //

+  fclose (NewFile);

+

+  //

+  // Verify read successful

+  //

+  if (NumBytesRead != sizeof (UINT8) * FileSize) {

+    free (FileBuffer);

+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");

+    return EFI_ABORTED;

+  }

+  //

+  // Verify space exists to add the file

+  //

+  if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {

+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Update the file state based on polarity of the FV.

+  //

+  UpdateFfsFileState (

+    (EFI_FFS_FILE_HEADER *) FileBuffer,

+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage

+    );

+

+  //

+  // If we have a VTF file, add it at the top.

+  //

+  if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {

+    if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {

+      //

+      // No previous VTF, add this one.

+      //

+      *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);

+      //

+      // Sanity check. The file MUST align appropriately

+      //

+      if ((((UINTN) *VtfFileImage) & 0x07) != 0) {

+        Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);

+      }

+      //

+      // copy VTF File Header

+      //

+      memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));

+

+      //

+      // Copy VTF body

+      //

+      memcpy (

+        (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),

+        FileBuffer + sizeof (EFI_FFS_FILE_HEADER),

+        FileSize - sizeof (EFI_FFS_FILE_HEADER)

+        );

+

+      //

+      // re-calculate the VTF File Header

+      //

+      FileState = (*VtfFileImage)->State;

+      (*VtfFileImage)->State = 0;

+      *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;

+      (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;

+      (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;

+

+      VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));

+      (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;

+      //

+      // Determine if it has a tail

+      //

+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+        TailSize = sizeof (EFI_FFS_FILE_TAIL);

+      } else {

+        TailSize = 0;

+      }

+

+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {

+        VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);

+        (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;

+      } else {

+        (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+      }

+      //

+      // If it has a file tail, update it

+      //

+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+        TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));

+        *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;

+      }

+      (*VtfFileImage)->State = FileState;

+      free (FileBuffer);

+      return EFI_SUCCESS;

+    } else {

+      //

+      // Already found a VTF file.

+      //

+      Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);

+      free (FileBuffer);

+      return EFI_ABORTED;

+    }

+  }

+  //

+  // Check if alignment is required

+  //

+  Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);

+  if (EFI_ERROR (Status)) {

+    printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);

+    free (FileBuffer);

+    return EFI_ABORTED;

+  }

+  //

+  // Add pad file if necessary

+  //

+  Status = AddPadFile (FvImage, CurrentFileAlignment);

+  if (EFI_ERROR (Status)) {

+    printf ("ERROR: Could not align the file data properly.\n");

+    free (FileBuffer);

+    return EFI_ABORTED;

+  }

+  //

+  // Add file

+  //

+  if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {

+    //

+    // Copy the file

+    //

+    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);

+

+    //

+    // If the file is XIP, rebase

+    //

+    CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);

+    //

+    //    Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);

+    //    if (EFI_ERROR(Status)) {

+    //      printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);

+    //      return EFI_ABORTED;

+    //    }

+    //

+    // Update Symbol file

+    //

+    Status = AddSymFile (

+              CurrentFileBaseAddress,

+              (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,

+              SymImage,

+              FvInfo->FvFiles[Index]

+              );

+    assert (!EFI_ERROR (Status));

+

+    //

+    // Update the current pointer in the FV image

+    //

+    FvImage->CurrentFilePointer += FileSize;

+  } else {

+    printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);

+    return EFI_ABORTED;

+  }

+  //

+  // Make next file start at QWord Boundry

+  //

+  while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {

+    FvImage->CurrentFilePointer++;

+  }

+  //

+  // Free allocated memory.

+  //

+  free (FileBuffer);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddVariableBlock (

+  IN UINT8                    *FvImage,

+  IN UINTN                    Size,

+  IN FV_INFO                  *FvInfo

+  )

+{

+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;

+  VARIABLE_STORE_HEADER       *VarStoreHeader;

+  //

+  // Variable block should exclude FvHeader. Since the length of

+  // FvHeader depends on the block map, which is variable length,

+  // we could only decide the actual variable block length here.

+  //

+  FvHeader                  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;

+  FvImage                   = FvImage + FvHeader->HeaderLength;

+

+  VarStoreHeader            = (VARIABLE_STORE_HEADER *) FvImage;

+

+  VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;

+  VarStoreHeader->Size      = Size - FvHeader->HeaderLength;

+  VarStoreHeader->Format    = VARIABLE_STORE_FORMATTED;

+  VarStoreHeader->State     = VARIABLE_STORE_HEALTHY;

+  VarStoreHeader->Reserved  = 0;

+  VarStoreHeader->Reserved1 = 0;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddEventLogBlock (

+  IN UINT8                    *FvImage,

+  IN UINTN                    Size,

+  IN FV_INFO                  *FvInfo

+  )

+{

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddFTWWorkingBlock (

+  IN UINT8                    *FvImage,

+  IN UINTN                    Size,

+  IN FV_INFO                  *FvInfo

+  )

+{

+  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;

+  UINT32                                  Crc32;

+

+  Crc32     = 0;

+  FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;

+  memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));

+  FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);

+  CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);

+  FTWHeader->Crc = Crc32;

+  if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {

+    FTWHeader->WorkingBlockValid    = 0;

+    FTWHeader->WorkingBlockInvalid  = 1;

+  } else {

+    FTWHeader->WorkingBlockValid    = 1;

+    FTWHeader->WorkingBlockInvalid  = 0;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+AddFTWSpareBlock (

+  IN UINT8                    *FvImage,

+  IN UINTN                    Size,

+  IN FV_INFO                  *FvInfo

+  )

+{

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GenNonFFSFv (

+  IN UINT8                    *FvImage,

+  IN FV_INFO                  *FvInfo

+  )

+/*++

+

+Routine Description:

+

+  This function generate the non FFS FV image, such as the working block

+  and spare block. How each component of the FV is built is component

+  specific.

+

+Arguments:

+

+  FvImage       The memory image of the FV to add it to.  The current offset

+                must be valid.

+  FvInfo        Pointer to information about the FV.

+

+Returns:

+

+  EFI_SUCCESS              The function completed successfully.

+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.

+  EFI_ABORTED              An error occurred.

+  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.

+

+--*/

+{

+  UINTN                       Index;

+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;

+  UINT64                      TotalSize;

+

+  FvHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;

+  TotalSize = 0;

+

+  for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {

+    if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {

+      AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);

+    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {

+      AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);

+    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {

+      AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);

+    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {

+      AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);

+    } else {

+      printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);

+      return EFI_ABORTED;

+    }

+

+    FvImage   = FvImage + FvInfo->FvComponents[Index].Size;

+    TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;

+  }

+  //

+  // Index and TotalSize is zero mean there's no component, so this is an empty fv

+  //

+  if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {

+    printf ("Error. Component size does not sum up to FV size.\n");

+    return EFI_ABORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PadFvImage (

+  IN MEMORY_FILE          *FvImage,

+  IN EFI_FFS_FILE_HEADER  *VtfFileImage

+  )

+/*++

+

+Routine Description:

+

+  This function places a pad file between the last file in the FV and the VTF

+  file if the VTF file exists.

+

+Arguments:

+

+  FvImage       Memory file for the FV memory image

+  VtfFileImage  The address of the VTF file.  If this is the end of the FV

+                image, no VTF exists and no pad file is needed.

+

+Returns:

+

+  EFI_SUCCESS             Completed successfully.

+  EFI_INVALID_PARAMETER   One of the input parameters was NULL.

+

+--*/

+{

+  EFI_FFS_FILE_HEADER *PadFile;

+  UINTN               FileSize;

+

+  //

+  // If there is no VTF or the VTF naturally follows the previous file without a

+  // pad file, then there's nothing to do

+  //

+  if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {

+    return EFI_SUCCESS;

+  }

+  //

+  // Pad file starts at beginning of free space

+  //

+  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;

+

+  //

+  // write header

+  //

+  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));

+  memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));

+  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;

+  PadFile->Attributes = 0;

+

+  //

+  // FileSize includes the EFI_FFS_FILE_HEADER

+  //

+  FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;

+  PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);

+  PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);

+  PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);

+

+  //

+  // Fill in checksums and state, must be zero during checksum calculation.

+  //

+  PadFile->IntegrityCheck.Checksum.Header = 0;

+  PadFile->IntegrityCheck.Checksum.File   = 0;

+  PadFile->State                          = 0;

+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));

+  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);

+  } else {

+    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+  }

+

+  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+

+  UpdateFfsFileState (

+    (EFI_FFS_FILE_HEADER *) PadFile,

+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage

+    );

+  //

+  // Update the current FV pointer

+  //

+  FvImage->CurrentFilePointer = FvImage->Eof;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+UpdateResetVector (

+  IN MEMORY_FILE            *FvImage,

+  IN FV_INFO                *FvInfo,

+  IN EFI_FFS_FILE_HEADER    *VtfFile

+  )

+/*++

+

+Routine Description:

+

+  This parses the FV looking for the PEI core and then plugs the address into

+  the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to

+  complete an IA32 Bootstrap FV.

+

+Arguments:

+

+  FvImage       Memory file for the FV memory image

+  FvInfo        Information read from INF file.

+  VtfFile       Pointer to the VTF file in the FV image.

+

+Returns:

+

+  EFI_SUCCESS             Function Completed successfully.

+  EFI_ABORTED             Error encountered.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+  EFI_NOT_FOUND           PEI Core file not found.

+

+--*/

+{

+  EFI_FFS_FILE_HEADER       *PeiCoreFile;

+  EFI_FFS_FILE_HEADER       *SecCoreFile;

+  EFI_STATUS                Status;

+  EFI_FILE_SECTION_POINTER  Pe32Section;

+  UINT32                    EntryPoint;

+  UINT32                    BaseOfCode;

+  UINT16                    MachineType;

+  EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;

+  EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;

+  EFI_PHYSICAL_ADDRESS      *SecCoreEntryAddressPtr;

+  UINT32                    *Ia32ResetAddressPtr;

+  UINT8                     *BytePointer;

+  UINT8                     *BytePointer2;

+  UINT16                    *WordPointer;

+  UINT16                    CheckSum;

+  UINTN                     Index;

+  EFI_FFS_FILE_STATE        SavedState;

+  EFI_FFS_FILE_TAIL         TailValue;

+  UINT32                    TailSize;

+  UINT64                    FitAddress;

+  FIT_TABLE                 *FitTablePtr;

+

+  //

+  // Verify input parameters

+  //

+  if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Initialize FV library

+  //

+  InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);

+

+  //

+  // Verify VTF file

+  //

+  Status = VerifyFfsFile (VtfFile);

+  if (EFI_ERROR (Status)) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Find the PEI Core

+  //

+  Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);

+  if (EFI_ERROR (Status) || PeiCoreFile == NULL) {

+    Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);

+    return EFI_ABORTED;

+  }

+

+  //

+  // PEI Core found, now find PE32 or TE section

+  //

+  Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);

+  if (Status == EFI_NOT_FOUND) {

+    Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);

+  }

+

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);

+    return EFI_ABORTED;

+  }

+

+  Status = GetPe32Info (

+            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),

+            &EntryPoint,

+            &BaseOfCode,

+            &MachineType

+            );

+

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);

+    return EFI_ABORTED;

+  }

+  //

+  // Physical address is FV base + offset of PE32 + offset of the entry point

+  //

+  PeiCorePhysicalAddress = FvInfo->BaseAddress;

+  PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;

+  PeiCorePhysicalAddress += EntryPoint;

+

+  if (MachineType == EFI_IMAGE_MACHINE_IA64) {

+    //

+    // Update PEI_CORE address

+    //

+    //

+    // Set the uncached attribute bit in the physical address

+    //

+    PeiCorePhysicalAddress |= 0x8000000000000000ULL;

+

+    //

+    // Check if address is aligned on a 16 byte boundary

+    //

+    if (PeiCorePhysicalAddress & 0xF) {

+      printf (

+        "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",

+        PeiCorePhysicalAddress

+        );

+      return EFI_ABORTED;

+    }

+    //

+    // First Get the FIT table address

+    //

+    FitAddress  = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;

+

+    FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));

+

+    Status      = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);

+

+    if (!EFI_ERROR (Status)) {

+      UpdateFitCheckSum (FitTablePtr);

+    }

+    //

+    // Find the Sec Core

+    //

+    Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);

+    if (EFI_ERROR (Status) || SecCoreFile == NULL) {

+      Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);

+      return EFI_ABORTED;

+    }

+    //

+    // Sec Core found, now find PE32 section

+    //

+    Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);

+      return EFI_ABORTED;

+    }

+

+    Status = GetPe32Info (

+              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),

+              &EntryPoint,

+              &BaseOfCode,

+              &MachineType

+              );

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);

+      return EFI_ABORTED;

+    }

+    //

+    // Physical address is FV base + offset of PE32 + offset of the entry point

+    //

+    SecCorePhysicalAddress = FvInfo->BaseAddress;

+    SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;

+    SecCorePhysicalAddress += EntryPoint;

+

+    //

+    // Update SEC_CORE address

+    //

+    //

+    // Set the uncached attribute bit in the physical address

+    //

+    SecCorePhysicalAddress |= 0x8000000000000000ULL;

+

+    //

+    // Update the address

+    //

+    SecCoreEntryAddressPtr  = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);

+    *SecCoreEntryAddressPtr = SecCorePhysicalAddress;

+

+    //

+    // Check if address is aligned on a 16 byte boundary

+    //

+    if (SecCorePhysicalAddress & 0xF) {

+      printf (

+        "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",

+        SecCorePhysicalAddress

+        );

+      return EFI_ABORTED;

+    }

+  } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {

+    //

+    // Get the location to update

+    //

+    Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);

+

+    //

+    // Write lower 32 bits of physical address

+    //

+    *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;

+

+    //

+    // Update the BFV base address

+    //

+    Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 4);

+    *Ia32ResetAddressPtr  = (UINT32) (FvInfo->BaseAddress);

+

+    CheckSum              = 0x0000;

+

+    //

+    // Update the Startup AP in the FVH header block ZeroVector region.

+    //

+    BytePointer   = (UINT8 *) ((UINTN) FvImage->FileImage);

+    BytePointer2  = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;

+    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {

+      *BytePointer++ = *BytePointer2++;

+    }

+    //

+    // Calculate the checksum

+    //

+    WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);

+    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {

+      CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));

+      WordPointer++;

+    }

+    //

+    // Update the checksum field

+    //

+    BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);

+    BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);

+    WordPointer   = (UINT16 *) BytePointer;

+    *WordPointer  = (UINT16) (0x10000 - (UINT32) CheckSum);

+  } else {

+    Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);

+    return EFI_ABORTED;

+  }

+  //

+  // Determine if it has an FFS file tail.

+  //

+  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+    TailSize = sizeof (EFI_FFS_FILE_TAIL);

+  } else {

+    TailSize = 0;

+  }

+  //

+  // Now update file checksum

+  //

+  SavedState  = VtfFile->State;

+  VtfFile->IntegrityCheck.Checksum.File = 0;

+  VtfFile->State                        = 0;

+  if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+    VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (

+                                              (UINT8 *) VtfFile,

+                                              GetLength (VtfFile->Size) - TailSize

+                                              );

+  } else {

+    VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+  }

+

+  VtfFile->State = SavedState;

+

+  //

+  // Update tail if present

+  //

+  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+    TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));

+    *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetPe32Info (

+  IN UINT8                  *Pe32,

+  OUT UINT32                *EntryPoint,

+  OUT UINT32                *BaseOfCode,

+  OUT UINT16                *MachineType

+  )

+/*++

+

+Routine Description:

+

+  Retrieves the PE32 entry point offset and machine type from PE image or TeImage.  

+  See EfiImage.h for machine types.  The entry point offset is from the beginning 

+  of the PE32 buffer passed in.

+

+Arguments:

+

+  Pe32          Beginning of the PE32.

+  EntryPoint    Offset from the beginning of the PE32 to the image entry point.

+  BaseOfCode    Base address of code.

+  MachineType   Magic number for the machine type.

+

+Returns:

+

+  EFI_SUCCESS             Function completed successfully.

+  EFI_ABORTED             Error encountered.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+  EFI_UNSUPPORTED         The operation is unsupported.

+

+--*/

+{

+  EFI_IMAGE_DOS_HEADER  *DosHeader;

+  EFI_IMAGE_NT_HEADERS  *NtHeader;

+  EFI_TE_IMAGE_HEADER   *TeHeader;

+

+  //

+  // Verify input parameters

+  //

+  if (Pe32 == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // First check whether it is one TE Image.

+  //

+  TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;

+  if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {

+    //

+    // By TeImage Header to get output

+    //

+    *EntryPoint   = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;

+    *BaseOfCode   = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;

+    *MachineType  = TeHeader->Machine;

+  } else {

+  

+    //

+    // Then check whether 

+    // First is the DOS header

+    //

+    DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;

+  

+    //

+    // Verify DOS header is expected

+    //

+    if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+      printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);

+      return EFI_UNSUPPORTED;

+    }

+    //

+    // Immediately following is the NT header.

+    //

+    NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);

+  

+    //

+    // Verify NT header is expected

+    //

+    if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {

+      printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);

+      return EFI_UNSUPPORTED;

+    }

+    //

+    // Get output

+    //

+    *EntryPoint   = NtHeader->OptionalHeader.AddressOfEntryPoint;

+    *BaseOfCode   = NtHeader->OptionalHeader.BaseOfCode;

+    *MachineType  = NtHeader->FileHeader.Machine;

+  }

+

+  //

+  // Verify machine type is supported

+  //

+  if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {

+    printf ("ERROR: Unrecognized machine type in the PE32 file.\n");

+    return EFI_UNSUPPORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+//

+// Exposed function implementations (prototypes are defined in GenFvImageLib.h)

+//

+EFI_STATUS

+GenerateFvImage (

+  IN CHAR8    *InfFileImage,

+  IN UINTN    InfFileSize,

+  OUT UINT8   **FvImage,

+  OUT UINTN   *FvImageSize,

+  OUT CHAR8   **FvFileName,

+  OUT UINT8   **SymImage,

+  OUT UINTN   *SymImageSize,

+  OUT CHAR8   **SymFileName

+  )

+/*++

+

+Routine Description:

+

+  This is the main function which will be called from application.

+

+Arguments:

+

+  InfFileImage  Buffer containing the INF file contents.

+  InfFileSize   Size of the contents of the InfFileImage buffer.

+  FvImage       Pointer to the FV image created.

+  FvImageSize   Size of the FV image created and pointed to by FvImage.

+  FvFileName    Requested name for the FV file.

+  SymImage      Pointer to the Sym image created.

+  SymImageSize  Size of the Sym image created and pointed to by SymImage.

+  SymFileName   Requested name for the Sym file.

+

+Returns:

+

+  EFI_SUCCESS             Function completed successfully.

+  EFI_OUT_OF_RESOURCES    Could not allocate required resources.

+  EFI_ABORTED             Error encountered.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+

+--*/

+{

+  EFI_STATUS                  Status;

+  MEMORY_FILE                 InfMemoryFile;

+  MEMORY_FILE                 FvImageMemoryFile;

+  MEMORY_FILE                 SymImageMemoryFile;

+  FV_INFO                     FvInfo;

+  UINTN                       Index;

+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;

+  EFI_FFS_FILE_HEADER         *VtfFileImage;

+

+  //

+  // Check for invalid parameter

+  //

+  if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Initialize file structures

+  //

+  InfMemoryFile.FileImage           = InfFileImage;

+  InfMemoryFile.CurrentFilePointer  = InfFileImage;

+  InfMemoryFile.Eof                 = InfFileImage + InfFileSize;

+

+  //

+  // Parse the FV inf file for header information

+  //

+  Status = ParseFvInf (&InfMemoryFile, &FvInfo);

+  if (EFI_ERROR (Status)) {

+    printf ("ERROR: Could not parse the input INF file.\n");

+    return EFI_ABORTED;

+  }

+  //

+  // Update the file name return values

+  //

+  strcpy (*FvFileName, FvInfo.FvName);

+  strcpy (*SymFileName, FvInfo.SymName);

+

+  //

+  // Calculate the FV size

+  //

+  *FvImageSize = FvInfo.Size;

+

+  //

+  // Allocate the FV

+  //

+  *FvImage = malloc (*FvImageSize);

+  if (*FvImage == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Allocate space for symbol file storage

+  //

+  *SymImage = malloc (SYMBOL_FILE_SIZE);

+  if (*SymImage == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // Initialize the FV to the erase polarity

+  //

+  if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {

+    memset (*FvImage, -1, *FvImageSize);

+  } else {

+    memset (*FvImage, 0, *FvImageSize);

+  }

+  //

+  // Initialize FV header

+  //

+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;

+

+  //

+  // Initialize the zero vector to all zeros.

+  //

+  memset (FvHeader->ZeroVector, 0, 16);

+

+  //

+  // Copy the FFS GUID

+  //

+  memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));

+

+  FvHeader->FvLength    = *FvImageSize;

+  FvHeader->Signature   = EFI_FVH_SIGNATURE;

+  FvHeader->Attributes  = FvInfo.FvAttributes;

+  FvHeader->Revision    = EFI_FVH_REVISION;

+  FvHeader->Reserved[0] = 0;

+  FvHeader->Reserved[1] = 0;

+  FvHeader->Reserved[2] = 0;

+

+  //

+  // Copy firmware block map

+  //

+  for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {

+    FvHeader->FvBlockMap[Index].NumBlocks   = FvInfo.FvBlocks[Index].NumBlocks;

+    FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;

+  }

+  //

+  // Add block map terminator

+  //

+  FvHeader->FvBlockMap[Index].NumBlocks   = 0;

+  FvHeader->FvBlockMap[Index].BlockLength = 0;

+

+  //

+  // Complete the header

+  //

+  FvHeader->HeaderLength  = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);

+  FvHeader->Checksum      = 0;

+  FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));

+

+  //

+  // If there is no FFS file, find and generate each components of the FV

+  //

+  if (FvInfo.FvFiles[0][0] == 0) {

+    Status = GenNonFFSFv (*FvImage, &FvInfo);

+    if (EFI_ERROR (Status)) {

+      printf ("ERROR: Could not generate NonFFS FV.\n");

+      free (*FvImage);

+      return EFI_ABORTED;

+    }

+

+    return EFI_SUCCESS;

+  }

+  //

+  // Initialize our "file" view of the buffer

+  //

+  FvImageMemoryFile.FileImage           = *FvImage;

+  FvImageMemoryFile.CurrentFilePointer  = *FvImage + FvHeader->HeaderLength;

+  FvImageMemoryFile.Eof                 = *FvImage +*FvImageSize;

+

+  //

+  // Initialize our "file" view of the symbol file.

+  //

+  SymImageMemoryFile.FileImage          = *SymImage;

+  SymImageMemoryFile.CurrentFilePointer = *SymImage;

+  SymImageMemoryFile.Eof                = *FvImage + SYMBOL_FILE_SIZE;

+

+  //

+  // Initialize the FV library.

+  //

+  InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);

+

+  //

+  // Files start on 8 byte alignments, so move to the next 8 byte aligned

+  // address.  For now, just assert if it isn't.  Currently FV header is

+  // always a multiple of 8 bytes.

+  // BUGBUG: Handle this better

+  //

+  assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);

+

+  //

+  // Initialize the VTF file address.

+  //

+  VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;

+

+  //

+  // Add files to FV

+  //

+  for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {

+    //

+    // Add the file

+    //

+    Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);

+

+    //

+    // Exit if error detected while adding the file

+    //

+    if (EFI_ERROR (Status)) {

+      printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);

+      free (*FvImage);

+      return EFI_ABORTED;

+    }

+  }

+  //

+  // If there is a VTF file, some special actions need to occur.

+  //

+  if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {

+    //

+    // Pad from the end of the last file to the beginning of the VTF file.

+    //

+    Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);

+    if (EFI_ERROR (Status)) {

+      printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");

+      free (*FvImage);

+      return EFI_ABORTED;

+    }

+    //

+    // Update reset vector (SALE_ENTRY for IPF)

+    // Now for IA32 and IA64 platform, the fv which has bsf file must have the 

+    // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the   

+    // reset vector. If the PEI Core is found, the VTF file will probably get  

+    // corrupted by updating the entry point.                                  

+    //

+    if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {       

+      Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);

+      if (EFI_ERROR(Status)) {                                               

+        printf ("ERROR: Could not update the reset vector.\n");              

+        free (*FvImage);                                                     

+        return EFI_ABORTED;                                                  

+      }                                                                      

+    }

+  } 

+  //

+  // Determine final Sym file size

+  //

+  *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+UpdatePeiCoreEntryInFit (

+  IN FIT_TABLE     *FitTablePtr,

+  IN UINT64        PeiCorePhysicalAddress

+  )

+/*++

+

+Routine Description:

+

+  This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from

+  Sec to Pei Core

+

+Arguments:

+

+  FitTablePtr             - The pointer of FIT_TABLE.

+  PeiCorePhysicalAddress  - The address of Pei Core entry.

+

+Returns:

+

+  EFI_SUCCESS             - The PEI_CORE FIT entry was updated successfully.

+  EFI_NOT_FOUND           - Not found the PEI_CORE FIT entry.

+

+--*/

+{

+  FIT_TABLE *TmpFitPtr;

+  UINTN     Index;

+  UINTN     NumFitComponents;

+

+  TmpFitPtr         = FitTablePtr;

+  NumFitComponents  = TmpFitPtr->CompSize;

+

+  for (Index = 0; Index < NumFitComponents; Index++) {

+    if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {

+      TmpFitPtr->CompAddress = PeiCorePhysicalAddress;

+      return EFI_SUCCESS;

+    }

+

+    TmpFitPtr++;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+VOID

+UpdateFitCheckSum (

+  IN FIT_TABLE   *FitTablePtr

+  )

+/*++

+

+Routine Description:

+

+  This function is used to update the checksum for FIT.

+

+

+Arguments:

+

+  FitTablePtr             - The pointer of FIT_TABLE.

+

+Returns:

+

+  None.

+

+--*/

+{

+  if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {

+    FitTablePtr->CheckSum = 0;

+    FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);

+  }

+}

diff --git a/Source/GenFvImage/GenFvImageLib.h b/Source/GenFvImage/GenFvImageLib.h
new file mode 100644
index 0000000..47a5a3b
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLib.h
@@ -0,0 +1,142 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  GenFvImageLib.h

+

+Abstract:

+

+  This file contains describes the public interfaces to the GenFvImage Library.

+  The basic purpose of the library is to create Firmware Volume images.

+

+--*/

+

+#ifndef _EFI_GEN_FV_IMAGE_LIB_H

+#define _EFI_GEN_FV_IMAGE_LIB_H

+

+//

+// Include files

+//

+#include <Common/UefiBaseTypes.h>

+#include <Common/MultiPhase.h>

+

+#include "ParseInf.h"

+

+//

+// Following definition is used for FIT in IPF

+//

+#define COMP_TYPE_FIT_PEICORE 0x10

+#define COMP_TYPE_FIT_UNUSED  0x7F

+

+#define FIT_TYPE_MASK         0x7F

+#define CHECKSUM_BIT_MASK     0x80

+

+#pragma pack(1)

+

+typedef struct {

+  UINT64  CompAddress;

+  UINT32  CompSize;

+  UINT16  CompVersion;

+  UINT8   CvAndType;

+  UINT8   CheckSum;

+} FIT_TABLE;

+

+#pragma pack()

+//

+// Exported function prototypes

+//

+EFI_STATUS

+GenerateFvImage (

+  IN CHAR8    *InfFileImage,

+  IN UINTN    InfFileSize,

+  OUT UINT8   **FvImage,

+  OUT UINTN   *FvImageSize,

+  OUT CHAR8   **FvFileName,

+  OUT UINT8   **SymImage,

+  OUT UINTN   *SymImageSize,

+  OUT CHAR8   **SymFileName

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This is the main function which will be called from application.

+

+Arguments:

+

+  InfFileImage  Buffer containing the INF file contents.

+  InfFileSize   Size of the contents of the InfFileImage buffer.

+  FvImage       Pointer to the FV image created.

+  FvImageSize   Size of the FV image created and pointed to by FvImage.

+  FvFileName    Requested name for the FV file.

+  SymImage      Pointer to the Sym image created.

+  SymImageSize  Size of the Sym image created and pointed to by SymImage.

+  SymFileName   Requested name for the Sym file.

+    

+Returns:

+ 

+  EFI_SUCCESS             Function completed successfully.

+  EFI_OUT_OF_RESOURCES    Could not allocate required resources.

+  EFI_ABORTED             Error encountered.

+  EFI_INVALID_PARAMETER   A required parameter was NULL.

+

+--*/

+EFI_STATUS

+UpdatePeiCoreEntryInFit (

+  IN FIT_TABLE     *FitTablePtr,

+  IN UINT64        PeiCorePhysicalAddress

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from

+  Sec to Pei Core

+

+Arguments:

+

+  FitTablePtr             - The pointer of FIT_TABLE.

+  PeiCorePhysicalAddress  - The address of Pei Core entry.

+

+Returns:

+

+  EFI_SUCCESS             - The PEI_CORE FIT entry was updated successfully.

+  EFI_NOT_FOUND           - Not found the PEI_CORE FIT entry.

+

+--*/

+VOID

+UpdateFitCheckSum (

+  IN FIT_TABLE   *FitTablePtr

+  )

+;

+

+/*++

+

+Routine Description:

+

+  This function is used to update the checksum for FIT.

+

+

+Arguments:

+

+  FitTablePtr             - The pointer of FIT_TABLE.

+

+Returns:

+

+  None.

+

+--*/

+#endif

diff --git a/Source/GenFvImage/GenFvImageLibInternal.h b/Source/GenFvImage/GenFvImageLibInternal.h
new file mode 100644
index 0000000..cff3b1a
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLibInternal.h
@@ -0,0 +1,172 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+  GenFvImageLibInternal.h

+

+Abstract:

+

+  This file contains describes the private declarations for the GenFvImage Library.

+  The basic purpose of the library is to create Firmware Volume images.

+

+--*/

+

+#ifndef _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H

+#define _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H

+

+//

+// Include files

+//

+#include <stdlib.h>

+

+#include <Common/FirmwareVolumeHeader.h>

+

+#include "CommonLib.h"

+#include "GenFvImageLib.h"

+

+//

+// Private data declarations

+//

+//

+// The maximum number of block map entries supported by the library

+//

+#define MAX_NUMBER_OF_FV_BLOCKS 100

+

+//

+// The maximum number of files in the FV supported by the library

+//

+#define MAX_NUMBER_OF_FILES_IN_FV       1000

+#define MAX_NUMBER_OF_COMPONENTS_IN_FV  10

+

+//

+// INF file strings

+//

+#define OPTIONS_SECTION_STRING            "[options]"

+#define ATTRIBUTES_SECTION_STRING         "[attributes]"

+#define FILES_SECTION_STRING              "[files]"

+#define COMPONENT_SECTION_STRING          "[components]"

+

+#define EFI_FV_BASE_ADDRESS_STRING        "EFI_BASE_ADDRESS"

+#define EFI_FV_FILE_NAME_STRING           "EFI_FILE_NAME"

+#define EFI_SYM_FILE_NAME_STRING          "EFI_SYM_FILE_NAME"

+#define EFI_NUM_BLOCKS_STRING             "EFI_NUM_BLOCKS"

+#define EFI_BLOCK_SIZE_STRING             "EFI_BLOCK_SIZE"

+#define EFI_FV_GUID_STRING                "EFI_FV_GUID"

+

+#define EFI_FVB_READ_DISABLED_CAP_STRING  "EFI_READ_DISABLED_CAP"

+#define EFI_FVB_READ_ENABLED_CAP_STRING   "EFI_READ_ENABLED_CAP"

+#define EFI_FVB_READ_STATUS_STRING        "EFI_READ_STATUS"

+

+#define EFI_FVB_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP"

+#define EFI_FVB_WRITE_ENABLED_CAP_STRING  "EFI_WRITE_ENABLED_CAP"

+#define EFI_FVB_WRITE_STATUS_STRING       "EFI_WRITE_STATUS"

+

+#define EFI_FVB_LOCK_CAP_STRING           "EFI_LOCK_CAP"

+#define EFI_FVB_LOCK_STATUS_STRING        "EFI_LOCK_STATUS"

+

+#define EFI_FVB_STICKY_WRITE_STRING       "EFI_STICKY_WRITE"

+#define EFI_FVB_MEMORY_MAPPED_STRING      "EFI_MEMORY_MAPPED"

+#define EFI_FVB_ERASE_POLARITY_STRING     "EFI_ERASE_POLARITY"

+

+#define EFI_FVB_ALIGNMENT_CAP_STRING      "EFI_ALIGNMENT_CAP"

+#define EFI_FVB_ALIGNMENT_2_STRING        "EFI_ALIGNMENT_2"

+#define EFI_FVB_ALIGNMENT_4_STRING        "EFI_ALIGNMENT_4"

+#define EFI_FVB_ALIGNMENT_8_STRING        "EFI_ALIGNMENT_8"

+#define EFI_FVB_ALIGNMENT_16_STRING       "EFI_ALIGNMENT_16"

+#define EFI_FVB_ALIGNMENT_32_STRING       "EFI_ALIGNMENT_32"

+#define EFI_FVB_ALIGNMENT_64_STRING       "EFI_ALIGNMENT_64"

+#define EFI_FVB_ALIGNMENT_128_STRING      "EFI_ALIGNMENT_128"

+#define EFI_FVB_ALIGNMENT_256_STRING      "EFI_ALIGNMENT_256"

+#define EFI_FVB_ALIGNMENT_512_STRING      "EFI_ALIGNMENT_512"

+#define EFI_FVB_ALIGNMENT_1K_STRING       "EFI_ALIGNMENT_1K"

+#define EFI_FVB_ALIGNMENT_2K_STRING       "EFI_ALIGNMENT_2K"

+#define EFI_FVB_ALIGNMENT_4K_STRING       "EFI_ALIGNMENT_4K"

+#define EFI_FVB_ALIGNMENT_8K_STRING       "EFI_ALIGNMENT_8K"

+#define EFI_FVB_ALIGNMENT_16K_STRING      "EFI_ALIGNMENT_16K"

+#define EFI_FVB_ALIGNMENT_32K_STRING      "EFI_ALIGNMENT_32K"

+#define EFI_FVB_ALIGNMENT_64K_STRING      "EFI_ALIGNMENT_64K"

+

+//

+// Component sections

+//

+#define EFI_NV_VARIABLE_STRING    "EFI_NV_VARIABLE"

+#define EFI_NV_EVENT_LOG_STRING   "EFI_NV_EVENT_LOG"

+#define EFI_NV_FTW_WORKING_STRING "EFI_NV_FTW_WORKING"

+#define EFI_NV_FTW_SPARE_STRING   "EFI_NV_FTW_SPARE"

+

+#define EFI_FILE_NAME_STRING      "EFI_FILE_NAME"

+

+#define ONE_STRING                "1"

+#define ZERO_STRING               "0"

+#define TRUE_STRING               "TRUE"

+#define FALSE_STRING              "FALSE"

+#define NULL_STRING               "NULL"

+

+//

+// Defines to calculate the offset for PEI CORE entry points

+//

+#define IA32_PEI_CORE_ENTRY_OFFSET  0x20

+

+//

+// Defines to calculate the FIT table

+//

+#define IPF_FIT_ADDRESS_OFFSET  0x20

+

+//

+// Defines to calculate the offset for SALE_ENTRY

+//

+#define IPF_SALE_ENTRY_ADDRESS_OFFSET 0x18

+

+//

+// Symbol file definitions, current max size if 512K

+//

+#define SYMBOL_FILE_SIZE  0x80000

+

+#define FV_IMAGES_TOP_ADDRESS             0x100000000ULL

+

+//

+// Private data types

+//

+//

+// Component information

+//

+typedef struct {

+  UINTN Size;

+  CHAR8 ComponentName[_MAX_PATH];

+} COMPONENT_INFO;

+

+//

+// FV information holder

+//

+typedef struct {

+  EFI_PHYSICAL_ADDRESS    BaseAddress;

+  EFI_GUID                FvGuid;

+  UINTN                   Size;

+  CHAR8                   FvName[_MAX_PATH];

+  CHAR8                   SymName[_MAX_PATH];

+  EFI_FV_BLOCK_MAP_ENTRY  FvBlocks[MAX_NUMBER_OF_FV_BLOCKS];

+  EFI_FVB_ATTRIBUTES      FvAttributes;

+  CHAR8                   FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH];

+  COMPONENT_INFO          FvComponents[MAX_NUMBER_OF_COMPONENTS_IN_FV];

+} FV_INFO;

+

+//

+// Private function prototypes

+//

+EFI_STATUS

+ParseFvInf (

+  IN MEMORY_FILE  *InfFile,

+  IN FV_INFO      *FvInfo

+  )

+;

+

+#endif

diff --git a/Source/GenFvImage/build.xml b/Source/GenFvImage/build.xml
new file mode 100644
index 0000000..421b38f
--- /dev/null
+++ b/Source/GenFvImage/build.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenFvImage Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenFvImage"/>

+  <property name="FileSet" value="GenFvImageLib.c GenFvImageExe.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+    <if>

+      <istrue value="${OSX}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value=""/>

+      </then>

+    </if>

+

+    <if>

+      <istrue value="${cygwin}"/>

+      <then>

+        <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${msft}"/>

+      <then>

+        <property name="syslibdirs" value=""/>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    

+    <if>

+      <istrue value="${linux}"/>

+      <then>

+        <if>

+          <istrue value="${x86_64_linux}"/>

+          <then>

+            <property name="syslibdirs" value="/lib64"/>

+          </then>

+          <else>

+            <property name="syslibdirs" value="/usr/lib"/>

+          </else>

+        </if>

+        <property name="syslibs" value="uuid"/>

+      </then>

+    </if>

+    <echo message="syslibdirs set to: ${syslibdirs}"/>

+  </target>

+

+  <target name="Tool" depends="init, GenFvImage"/>

+

+  <target name="GenFvImage" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_IA32_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/${ToolName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+

+      <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>

+      <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>

+      <syslibset libs="RpcRT4" if="msft"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenSection/GenSection.c b/Source/GenSection/GenSection.c
new file mode 100644
index 0000000..353b1a3
--- /dev/null
+++ b/Source/GenSection/GenSection.c
@@ -0,0 +1,938 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenSection.c

+

+Abstract:

+

+  Creates output file that is a properly formed section per the FV spec.

+

+--*/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Protocol/GuidedSectionExtraction.h>

+

+#include "CommonLib.h"

+#include "EfiCompress.h"

+#include "EfiCustomizedCompress.h"

+#include "Crc32.h"

+#include "EfiUtilityMsgs.h"

+#include "GenSection.h"

+

+

+#define UTILITY_NAME            "GenSection"

+

+#define PARAMETER_NOT_SPECIFIED "Parameter not specified"

+#define MAXIMUM_INPUT_FILE_NUM  10

+

+char      *SectionTypeName[] = {

+  NULL,                                 // 0x00 - reserved

+  "EFI_SECTION_COMPRESSION",            // 0x01

+  "EFI_SECTION_GUID_DEFINED",           // 0x02

+  NULL,                                 // 0x03 - reserved

+  NULL,                                 // 0x04 - reserved

+  NULL,                                 // 0x05 - reserved

+  NULL,                                 // 0x06 - reserved

+  NULL,                                 // 0x07 - reserved

+  NULL,                                 // 0x08 - reserved

+  NULL,                                 // 0x09 - reserved

+  NULL,                                 // 0x0A - reserved

+  NULL,                                 // 0x0B - reserved

+  NULL,                                 // 0x0C - reserved

+  NULL,                                 // 0x0D - reserved

+  NULL,                                 // 0x0E - reserved

+  NULL,                                 // 0x0F - reserved

+  "EFI_SECTION_PE32",                   // 0x10

+  "EFI_SECTION_PIC",                    // 0x11

+  "EFI_SECTION_TE",                     // 0x12

+  "EFI_SECTION_DXE_DEPEX",              // 0x13

+  "EFI_SECTION_VERSION",                // 0x14

+  "EFI_SECTION_USER_INTERFACE",         // 0x15

+  "EFI_SECTION_COMPATIBILITY16",        // 0x16

+  "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",  // 0x17

+  "EFI_SECTION_FREEFORM_SUBTYPE_GUID",  // 0x18

+  "EFI_SECTION_RAW",                    // 0x19

+  NULL,                                 // 0x1A

+  "EFI_SECTION_PEI_DEPEX"               // 0x1B

+};

+

+char      *CompressionTypeName[]    = { "NONE", "STANDARD" };

+char      *GUIDedSectionTypeName[]  = { "CRC32" };

+EFI_GUID  gEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;

+

+static

+VOID

+PrintUsageMessage (

+  VOID

+  )

+{

+  UINTN SectionType;

+  UINTN DisplayCount;

+

+  printf ("Usage: "UTILITY_NAME "  -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n");

+  printf ("    Where SectionType is one of the following section types:\n\n");

+

+  DisplayCount = 0;

+  for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) {

+    if (SectionTypeName[SectionType] != NULL) {

+      printf ("       %s\n", SectionTypeName[SectionType]);

+    }

+  }

+

+  printf ("\n    and SectionType dependent parameters are as follows:\n\n");

+  printf (

+    "       %s:       -t < %s | %s >\n",

+    SectionTypeName[EFI_SECTION_COMPRESSION],

+    CompressionTypeName[EFI_NOT_COMPRESSED],

+    CompressionTypeName[EFI_STANDARD_COMPRESSION]

+    );

+  printf (

+    "       %s:      -t < %s >\n""                          // Currently only CRC32 is supported\n\n",

+    SectionTypeName[EFI_SECTION_GUID_DEFINED],

+    GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]

+    );

+  printf (

+    "       %s:           -v VersionNumber\n""                          [-a \"Version string\"]\n\n",

+    SectionTypeName[EFI_SECTION_VERSION]

+    );

+  printf (

+    "       %s:    -a \"Human readable name\"\n\n",

+    SectionTypeName[EFI_SECTION_USER_INTERFACE]

+    );

+}

+

+VOID

+Ascii2UnicodeWriteString (

+  char    *String,

+  FILE    *OutFile,

+  BOOLEAN WriteLangCode

+  )

+{

+  UINTN Index;

+  UINT8 AsciiNull;

+  //

+  // BUGBUG need to get correct language code...

+  //

+  char  *EnglishLangCode = "eng";

+  AsciiNull = 0;

+  //

+  // first write the language code (english only)

+  //

+  if (WriteLangCode) {

+    fwrite (EnglishLangCode, 1, 4, OutFile);

+  }

+  //

+  // Next, write out the string... Convert ASCII to Unicode in the process.

+  //

+  Index = 0;

+  do {

+    fwrite (&String[Index], 1, 1, OutFile);

+    fwrite (&AsciiNull, 1, 1, OutFile);

+  } while (String[Index++] != 0);

+}

+

+STATUS

+GenSectionCommonLeafSection (

+  char    **InputFileName,

+  int     InputFileNum,

+  UINTN   SectionType,

+  FILE    *OutFile

+  )

+/*++

+        

+Routine Description:

+           

+  Generate a leaf section of type other than EFI_SECTION_VERSION

+  and EFI_SECTION_USER_INTERFACE. Input file must be well formed.

+  The function won't validate the input file's contents. For

+  common leaf sections, the input file may be a binary file.

+  The utility will add section header to the file.

+            

+Arguments:

+               

+  InputFileName  - Name of the input file.

+                

+  InputFileNum   - Number of input files. Should be 1 for leaf section.

+

+  SectionType    - A valid section type string

+

+  OutFile        - Output file handle

+

+Returns:

+                       

+  STATUS_ERROR            - can't continue

+  STATUS_SUCCESS          - successful return

+

+--*/

+{

+  UINT64                    InputFileLength;

+  FILE                      *InFile;

+  UINT8                     *Buffer;

+  INTN                      TotalLength;

+  EFI_COMMON_SECTION_HEADER CommonSect;

+  STATUS                    Status;

+

+  if (InputFileNum > 1) {

+    Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");

+    return STATUS_ERROR;

+  } else if (InputFileNum < 1) {

+    Error (NULL, 0, 0, "no input file specified", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Open the input file

+  //

+  InFile = fopen (InputFileName[0], "rb");

+  if (InFile == NULL) {

+    Error (NULL, 0, 0, InputFileName[0], "failed to open input file");

+    return STATUS_ERROR;

+  }

+

+  Status  = STATUS_ERROR;

+  Buffer  = NULL;

+  //

+  // Seek to the end of the input file so we can determine its size

+  //

+  fseek (InFile, 0, SEEK_END);

+  fgetpos (InFile, &InputFileLength);

+  fseek (InFile, 0, SEEK_SET);

+  //

+  // Fill in the fields in the local section header structure

+  //

+  CommonSect.Type = (EFI_SECTION_TYPE) SectionType;

+  TotalLength     = sizeof (CommonSect) + (INTN) InputFileLength;

+  //

+  // Size must fit in 3 bytes

+  //

+  if (TotalLength >= 0x1000000) {

+    Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength);

+    goto Done;

+  }

+  //

+  // Now copy the size into the section header and write out the section header

+  //

+  memcpy (&CommonSect.Size, &TotalLength, 3);

+  fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);

+  //

+  // Allocate a buffer to read in the contents of the input file. Then

+  // read it in as one block and write it to the output file.

+  //

+  if (InputFileLength != 0) {

+    Buffer = (UINT8 *) malloc ((size_t) InputFileLength);

+    if (Buffer == NULL) {

+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+      goto Done;

+    }

+

+    if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {

+      Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");

+      goto Done;

+    }

+

+    if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {

+      Error (NULL, 0, 0, "failed to write to output file", NULL);

+      goto Done;

+    }

+  }

+

+  Status = STATUS_SUCCESS;

+Done:

+  fclose (InFile);

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+GetSectionContents (

+  char    **InputFileName,

+  int     InputFileNum,

+  UINT8   *FileBuffer,

+  UINTN   *BufferLength

+  )

+/*++

+        

+Routine Description:

+           

+  Get the contents of all section files specified in InputFileName

+  into FileBuffer.

+            

+Arguments:

+               

+  InputFileName  - Name of the input file.

+                

+  InputFileNum   - Number of input files. Should be at least 1.

+

+  FileBuffer     - Output buffer to contain data

+

+  BufferLength   - Actual length of the data 

+

+Returns:

+                       

+  EFI_SUCCESS on successful return

+  EFI_INVALID_PARAMETER if InputFileNum is less than 1

+  EFI_ABORTED if unable to open input file.

+

+--*/

+{

+  UINTN   Size;

+  UINTN   FileSize;

+  INTN    Index;

+  FILE    *InFile;

+

+  if (InputFileNum < 1) {

+    Error (NULL, 0, 0, "must specify at least one input file", NULL);

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Size = 0;

+  //

+  // Go through our array of file names and copy their contents

+  // to the output buffer.

+  //

+  for (Index = 0; Index < InputFileNum; Index++) {

+    InFile = fopen (InputFileName[Index], "rb");

+    if (InFile == NULL) {

+      Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");

+      return EFI_ABORTED;

+    }

+

+    fseek (InFile, 0, SEEK_END);

+    FileSize = ftell (InFile);

+    fseek (InFile, 0, SEEK_SET);

+    //

+    // Now read the contents of the file into the buffer

+    //

+    if (FileSize > 0) {

+      if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {

+        Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");

+        fclose (InFile);

+        return EFI_ABORTED;

+      }

+    }

+

+    fclose (InFile);

+    Size += (UINTN) FileSize;

+    //

+    // make sure section ends on a DWORD boundary

+    //

+    while ((Size & 0x03) != 0) {

+      FileBuffer[Size] = 0;

+      Size++;

+    }

+  }

+

+  *BufferLength = Size;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GenSectionCompressionSection (

+  char    **InputFileName,

+  int     InputFileNum,

+  UINTN   SectionType,

+  UINTN   SectionSubType,

+  FILE    *OutFile

+  )

+/*++

+        

+Routine Description:

+           

+  Generate an encapsulating section of type EFI_SECTION_COMPRESSION

+  Input file must be already sectioned. The function won't validate

+  the input files' contents. Caller should hand in files already 

+  with section header.

+            

+Arguments:

+               

+  InputFileName  - Name of the input file.

+                

+  InputFileNum   - Number of input files. Should be at least 1.

+

+  SectionType    - Section type to generate. Should be 

+                   EFI_SECTION_COMPRESSION

+

+  SectionSubType - Specify the compression algorithm requested. 

+  

+  OutFile        - Output file handle

+

+Returns:

+                       

+  EFI_SUCCESS           on successful return

+  EFI_INVALID_PARAMETER if InputFileNum is less than 1

+  EFI_ABORTED           if unable to open input file.

+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.

+--*/

+{

+  UINTN                   TotalLength;

+  UINTN                   InputLength;

+  UINTN                   CompressedLength;

+  UINT8                   *FileBuffer;

+  UINT8                   *OutputBuffer;

+  EFI_STATUS              Status;

+  EFI_COMPRESSION_SECTION CompressionSect;

+  COMPRESS_FUNCTION       CompressFunction;

+

+  if (SectionType != EFI_SECTION_COMPRESSION) {

+    Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InputLength       = 0;

+  FileBuffer        = NULL;

+  OutputBuffer      = NULL;

+  CompressedLength  = 0;

+  FileBuffer        = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));

+  if (FileBuffer == NULL) {

+    Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // read all input file contents into a buffer

+  //

+  Status = GetSectionContents (

+            InputFileName,

+            InputFileNum,

+            FileBuffer,

+            &InputLength

+            );

+  if (EFI_ERROR (Status)) {

+    free (FileBuffer);

+    return Status;

+  }

+

+  CompressFunction = NULL;

+

+  //

+  // Now data is in FileBuffer, compress the data

+  //

+  switch (SectionSubType) {

+  case EFI_NOT_COMPRESSED:

+    CompressedLength = InputLength;

+    break;

+

+  case EFI_STANDARD_COMPRESSION:

+    CompressFunction = (COMPRESS_FUNCTION) Compress;

+    break;

+

+  case EFI_CUSTOMIZED_COMPRESSION:

+    CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;

+    break;

+

+  default:

+    Error (NULL, 0, 0, "unknown compression type", NULL);

+    free (FileBuffer);

+    return EFI_ABORTED;

+  }

+

+  if (CompressFunction != NULL) {

+

+    Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);

+    if (Status == EFI_BUFFER_TOO_SMALL) {

+      OutputBuffer = malloc (CompressedLength);

+      if (!OutputBuffer) {

+        free (FileBuffer);

+        return EFI_OUT_OF_RESOURCES;

+      }

+

+      Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);

+    }

+

+    free (FileBuffer);

+    FileBuffer = OutputBuffer;

+

+    if (EFI_ERROR (Status)) {

+      if (FileBuffer != NULL) {

+        free (FileBuffer);

+      }

+

+      return Status;

+    }

+  }

+

+  TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);

+  //

+  // Add the section header for the compressed data

+  //

+  CompressionSect.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;

+  CompressionSect.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);

+  CompressionSect.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);

+  CompressionSect.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);

+  CompressionSect.CompressionType       = (UINT8) SectionSubType;

+  CompressionSect.UncompressedLength    = InputLength;

+

+  fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);

+  fwrite (FileBuffer, CompressedLength, 1, OutFile);

+  free (FileBuffer);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GenSectionGuidDefinedSection (

+  char    **InputFileName,

+  int     InputFileNum,

+  UINTN   SectionType,

+  UINTN   SectionSubType,

+  FILE    *OutFile

+  )

+/*++

+        

+Routine Description:

+           

+  Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED

+  Input file must be already sectioned. The function won't validate

+  the input files' contents. Caller should hand in files already 

+  with section header.

+            

+Arguments:

+               

+  InputFileName  - Name of the input file.

+                

+  InputFileNum   - Number of input files. Should be at least 1.

+

+  SectionType    - Section type to generate. Should be 

+                   EFI_SECTION_GUID_DEFINED

+

+  SectionSubType - Specify the authentication algorithm requested. 

+  

+  OutFile        - Output file handle

+

+Returns:

+                       

+  EFI_SUCCESS on successful return

+  EFI_INVALID_PARAMETER if InputFileNum is less than 1

+  EFI_ABORTED if unable to open input file.

+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.

+

+--*/

+{

+  INTN                  TotalLength;

+  INTN                  InputLength;

+  UINT8                 *FileBuffer;

+  UINT32                Crc32Checksum;

+  EFI_STATUS            Status;

+  CRC32_SECTION_HEADER  Crc32GuidSect;

+

+  if (SectionType != EFI_SECTION_GUID_DEFINED) {

+    Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InputLength = 0;

+  FileBuffer  = NULL;

+  FileBuffer  = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));

+  if (FileBuffer == NULL) {

+    Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");

+    return EFI_OUT_OF_RESOURCES;

+  }

+  //

+  // read all input file contents into a buffer

+  //

+  Status = GetSectionContents (

+            InputFileName,

+            InputFileNum,

+            FileBuffer,

+            &InputLength

+            );

+  if (EFI_ERROR (Status)) {

+    free (FileBuffer);

+    return Status;

+  }

+  //

+  // Now data is in FileBuffer, compress the data

+  //

+  switch (SectionSubType) {

+  case EFI_SECTION_CRC32_GUID_DEFINED:

+    Crc32Checksum = 0;

+    CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);

+    if (EFI_ERROR (Status)) {

+      free (FileBuffer);

+      return Status;

+    }

+

+    TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;

+    Crc32GuidSect.GuidSectionHeader.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;

+    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);

+    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);

+    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);

+    memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));

+    Crc32GuidSect.GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;

+    Crc32GuidSect.GuidSectionHeader.DataOffset  = CRC32_SECTION_HEADER_SIZE;

+    Crc32GuidSect.CRC32Checksum                 = Crc32Checksum;

+

+    break;

+

+  default:

+    Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");

+    free (FileBuffer);

+    return EFI_ABORTED;

+  }

+

+  fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);

+  fwrite (FileBuffer, InputLength, 1, OutFile);

+

+  free (FileBuffer);

+

+  return EFI_SUCCESS;

+}

+

+int

+main (

+  int  argc,

+  char *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Main

+

+Arguments:

+

+  command line parameters

+

+Returns:

+

+  EFI_SUCCESS    Section header successfully generated and section concatenated.

+  EFI_ABORTED    Could not generate the section

+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.

+

+--*/

+{

+  INTN                      Index;

+  INTN                      VersionNumber;

+  UINTN                     SectionType;

+  UINTN                     SectionSubType;

+  BOOLEAN                   InputFileRequired;

+  BOOLEAN                   SubTypeRequired;

+  FILE                      *InFile;

+  FILE                      *OutFile;

+  INTN                      InputFileNum;

+

+  char                      **InputFileName;

+  char                      *OutputFileName;

+  char                      AuxString[500] = { 0 };

+

+  char                      *ParamSectionType;

+  char                      *ParamSectionSubType;

+  char                      *ParamLength;

+  char                      *ParamVersion;

+  char                      *ParamDigitalSignature;

+

+  EFI_STATUS                Status;

+  EFI_COMMON_SECTION_HEADER CommonSect;

+

+  InputFileName         = NULL;

+  OutputFileName        = PARAMETER_NOT_SPECIFIED;

+  ParamSectionType      = PARAMETER_NOT_SPECIFIED;

+  ParamSectionSubType   = PARAMETER_NOT_SPECIFIED;

+  ParamLength           = PARAMETER_NOT_SPECIFIED;

+  ParamVersion          = PARAMETER_NOT_SPECIFIED;

+  ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;

+  Status                = EFI_SUCCESS;

+

+  VersionNumber         = 0;

+  SectionType           = 0;

+  SectionSubType        = 0;

+  InputFileRequired     = TRUE;

+  SubTypeRequired       = FALSE;

+  InFile                = NULL;

+  OutFile               = NULL;

+  InputFileNum          = 0;

+  Status                = EFI_SUCCESS;

+

+  SetUtilityName (UTILITY_NAME);

+  if (argc == 1) {

+    PrintUsageMessage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Parse command line

+  //

+  Index = 1;

+  while (Index < argc) {

+    if (strcmpi (argv[Index], "-i") == 0) {

+      //

+      // Input File found

+      //

+      Index++;

+      InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));

+      if (InputFileName == NULL) {

+        Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");

+        return EFI_OUT_OF_RESOURCES;

+      }

+

+      memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));

+      InputFileName[InputFileNum] = argv[Index];

+      InputFileNum++;

+      Index++;

+      //

+      // Parse subsequent parameters until another switch is encountered

+      //

+      while ((Index < argc) && (argv[Index][0] != '-')) {

+        if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {

+          //

+          // InputFileName buffer too small, need to realloc

+          //

+          InputFileName = (char **) realloc (

+                                      InputFileName,

+                                      (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)

+                                      );

+          if (InputFileName == NULL) {

+            Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");

+            return EFI_OUT_OF_RESOURCES;

+          }

+

+          memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));

+        }

+

+        InputFileName[InputFileNum] = argv[Index];

+        InputFileNum++;

+        Index++;

+      }

+

+    }

+

+    if (strcmpi (argv[Index], "-o") == 0) {

+      //

+      // Output file found

+      //

+      Index++;

+      OutputFileName = argv[Index];

+    } else if (strcmpi (argv[Index], "-s") == 0) {

+      //

+      // Section Type found

+      //

+      Index++;

+      ParamSectionType = argv[Index];

+    } else if (strcmpi (argv[Index], "-t") == 0) {

+      //

+      // Compression or Authentication type

+      //

+      Index++;

+      ParamSectionSubType = argv[Index];

+    } else if (strcmpi (argv[Index], "-l") == 0) {

+      //

+      // Length

+      //

+      Index++;

+      ParamLength = argv[Index];

+    } else if (strcmpi (argv[Index], "-v") == 0) {

+      //

+      // VersionNumber

+      //

+      Index++;

+      ParamVersion = argv[Index];

+    } else if (strcmpi (argv[Index], "-a") == 0) {

+      //

+      // Aux string

+      //

+      Index++;

+      //

+      // Note, the MSVC C-Start parses out and consolidates quoted strings from the command

+      // line.  Quote characters are stripped.  If this tool is ported to other environments

+      // this will need to be taken into account

+      //

+      strncpy (AuxString, argv[Index], 499);

+    } else if (strcmpi (argv[Index], "-d") == 0) {

+      //

+      // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)

+      //

+      Index++;

+      ParamDigitalSignature = argv[Index];

+    } else if (strcmpi (argv[Index], "-?") == 0) {

+      PrintUsageMessage ();

+      return STATUS_ERROR;

+    } else {

+      Error (NULL, 0, 0, argv[Index], "unknown option");

+      return GetUtilityStatus ();

+    }

+

+    Index++;

+  }

+  //

+  // At this point, all command line parameters are verified as not being totally

+  // bogus.  Next verify the command line parameters are complete and make

+  // sense...

+  //

+  if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {

+    SectionType     = EFI_SECTION_COMPRESSION;

+    SubTypeRequired = TRUE;

+    if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {

+      SectionSubType = EFI_NOT_COMPRESSED;

+    } else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {

+      SectionSubType = EFI_STANDARD_COMPRESSION;

+    } else {

+      Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");

+      PrintUsageMessage ();

+      return GetUtilityStatus ();

+    }

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {

+    SectionType     = EFI_SECTION_GUID_DEFINED;

+    SubTypeRequired = TRUE;

+    if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {

+      SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;

+    } else {

+      Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);

+      PrintUsageMessage ();

+      return GetUtilityStatus ();

+    }

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {

+    SectionType = EFI_SECTION_PE32;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {

+    SectionType = EFI_SECTION_PIC;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {

+    SectionType = EFI_SECTION_TE;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {

+    SectionType = EFI_SECTION_DXE_DEPEX;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {

+    SectionType       = EFI_SECTION_VERSION;

+    InputFileRequired = FALSE;

+    Index             = sscanf (ParamVersion, "%d", &VersionNumber);

+    if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {

+      Error (NULL, 0, 0, ParamVersion, "illegal version number");

+      PrintUsageMessage ();

+      return GetUtilityStatus ();

+    }

+

+    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {

+      AuxString[0] = 0;

+    }

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {

+    SectionType       = EFI_SECTION_USER_INTERFACE;

+    InputFileRequired = FALSE;

+    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {

+      Error (NULL, 0, 0, "user interface string not specified", NULL);

+      PrintUsageMessage ();

+      return GetUtilityStatus ();

+    }

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {

+    SectionType = EFI_SECTION_COMPATIBILITY16;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {

+    SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {

+    SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {

+    SectionType = EFI_SECTION_RAW;

+  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {

+    SectionType = EFI_SECTION_PEI_DEPEX;

+  } else {

+    Error (NULL, 0, 0, ParamSectionType, "unknown section type");

+    PrintUsageMessage ();

+    return GetUtilityStatus ();

+  }

+  //

+  // Open output file

+  //

+  OutFile = fopen (OutputFileName, "wb");

+  if (OutFile == NULL) {

+    Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");

+    if (InFile != NULL) {

+      fclose (InFile);

+    }

+

+    return GetUtilityStatus ();

+  }

+  //

+  // At this point, we've fully validated the command line, and opened appropriate

+  // files, so let's go and do what we've been asked to do...

+  //

+  //

+  // Within this switch, build and write out the section header including any

+  // section type specific pieces.  If there's an input file, it's tacked on later

+  //

+  switch (SectionType) {

+  case EFI_SECTION_COMPRESSION:

+    Status = GenSectionCompressionSection (

+              InputFileName,

+              InputFileNum,

+              SectionType,

+              SectionSubType,

+              OutFile

+              );

+    break;

+

+  case EFI_SECTION_GUID_DEFINED:

+    Status = GenSectionGuidDefinedSection (

+              InputFileName,

+              InputFileNum,

+              SectionType,

+              SectionSubType,

+              OutFile

+              );

+    break;

+

+  case EFI_SECTION_VERSION:

+    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;

+

+    Index           = sizeof (CommonSect);

+    //

+    // 2 characters for the build number

+    //

+    Index += 2;

+    //

+    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.

+    //

+    Index += (strlen (AuxString) * 2) + 2;

+    memcpy (&CommonSect.Size, &Index, 3);

+    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);

+    fwrite (&VersionNumber, 2, 1, OutFile);

+    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);

+    break;

+

+  case EFI_SECTION_USER_INTERFACE:

+    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;

+    Index           = sizeof (CommonSect);

+    //

+    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.

+    //

+    Index += (strlen (AuxString) * 2) + 2;

+    memcpy (&CommonSect.Size, &Index, 3);

+    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);

+    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);

+    break;

+

+  default:

+    //

+    // All other section types are caught by default (they're all the same)

+    //

+    Status = GenSectionCommonLeafSection (

+              InputFileName,

+              InputFileNum,

+              SectionType,

+              OutFile

+              );

+    break;

+  }

+

+  if (InputFileName != NULL) {

+    free (InputFileName);

+  }

+

+  fclose (OutFile);

+  //

+  // If we had errors, then delete the output file

+  //

+  if (GetUtilityStatus () == STATUS_ERROR) {

+    remove (OutputFileName);

+  }

+

+  return GetUtilityStatus ();

+}

diff --git a/Source/GenSection/GenSection.h b/Source/GenSection/GenSection.h
new file mode 100644
index 0000000..3606463
--- /dev/null
+++ b/Source/GenSection/GenSection.h
@@ -0,0 +1,42 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GenSection.h 

+

+Abstract:

+

+  Header file for GenSection.

+

+--*/

+

+//

+// Module Coded to Tiano Coding Conventions

+//

+#ifndef _EFI_GEN_SECTION_H

+#define _EFI_GEN_SECTION_H

+

+//

+// External Files Referenced

+//

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+

+typedef struct {

+  EFI_GUID_DEFINED_SECTION  GuidSectionHeader;

+  UINT32                    CRC32Checksum;

+} CRC32_SECTION_HEADER;

+

+#define EFI_SECTION_CRC32_GUID_DEFINED  0

+#define CRC32_SECTION_HEADER_SIZE       (sizeof (CRC32_SECTION_HEADER))

+

+#endif

diff --git a/Source/GenSection/build.xml b/Source/GenSection/build.xml
new file mode 100644
index 0000000..391028e
--- /dev/null
+++ b/Source/GenSection/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenSection Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenSection"/>

+  <property name="FileSet" value="GenSection.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools CustomizedCompress"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GenTEImage/GenTEImage.c b/Source/GenTEImage/GenTEImage.c
new file mode 100644
index 0000000..90f3b39
--- /dev/null
+++ b/Source/GenTEImage/GenTEImage.c
@@ -0,0 +1,916 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  GenTEImage.c

+  

+Abstract:

+

+  Utility program to shrink a PE32 image down by replacing

+  the DOS, PE, and optional headers with a minimal header.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h> // for PE32 structure definitions

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+

+//

+// Version of this utility

+//

+#define UTILITY_NAME    "GenTEImage"

+#define UTILITY_VERSION "v0.11"

+

+//

+// Define the max length of a filename

+//

+#define MAX_PATH                  256

+#define DEFAULT_OUTPUT_EXTENSION  ".te"

+

+//

+// Use this to track our command-line options and globals

+//

+struct {

+  INT8  OutFileName[MAX_PATH];

+  INT8  InFileName[MAX_PATH];

+  INT8  Verbose;

+  INT8  Dump;

+} mOptions;

+

+//

+// Use these to convert from machine type value to a named type

+//

+typedef struct {

+  UINT16  Value;

+  INT8    *Name;

+} STRING_LOOKUP;

+

+static STRING_LOOKUP  mMachineTypes[] = {

+  EFI_IMAGE_MACHINE_IA32,

+  "IA32",

+  EFI_IMAGE_MACHINE_IA64,

+  "IA64",

+  EFI_IMAGE_MACHINE_EBC,

+  "EBC",

+  0,

+  NULL

+};

+

+static STRING_LOOKUP  mSubsystemTypes[] = {

+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,

+  "EFI application",

+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,

+  "EFI boot service driver",

+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,

+  "EFI runtime driver",

+  0,

+  NULL

+};

+//

+//  Function prototypes

+//

+static

+void

+Usage (

+  VOID

+  );

+

+static

+STATUS

+ParseCommandLine (

+  int       Argc,

+  char      *Argv[]

+  );

+

+static

+STATUS

+CheckPE32File (

+  INT8      *FileName,

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  );

+

+static

+STATUS

+ProcessFile (

+  INT8      *InFileName,

+  INT8      *OutFileName

+  );

+

+static

+void

+DumpImage (

+  INT8      *FileName

+  );

+

+static

+INT8                  *

+GetMachineTypeStr (

+  UINT16    MachineType

+  );

+

+static

+INT8                  *

+GetSubsystemTypeStr (

+  UINT16  SubsystemType

+  );

+

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+

+Arguments:

+

+  Argc            - standard C main() argument count

+

+  Argv            - standard C main() argument list

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  INT8    *Ext;

+  UINT32  Status;

+

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Parse the command line arguments

+  //

+  if (ParseCommandLine (Argc, Argv)) {

+    return STATUS_ERROR;

+  }

+  //

+  // If dumping an image, then do that and quit

+  //

+  if (mOptions.Dump) {

+    DumpImage (mOptions.InFileName);

+    goto Finish;

+  }

+  //

+  // Determine the output filename. Either what they specified on

+  // the command line, or the first input filename with a different extension.

+  //

+  if (!mOptions.OutFileName[0]) {

+    strcpy (mOptions.OutFileName, mOptions.InFileName);

+    //

+    // Find the last . on the line and replace the filename extension with

+    // the default

+    //

+    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;

+         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');

+         Ext--

+        )

+      ;

+    //

+    // If dot here, then insert extension here, otherwise append

+    //

+    if (*Ext != '.') {

+      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);

+    }

+

+    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);

+  }

+  //

+  // Make sure we don't have the same filename for input and output files

+  //

+  if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {

+    Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");

+    goto Finish;

+  }

+  //

+  // Process the file

+  //

+  ProcessFile (mOptions.InFileName, mOptions.OutFileName);

+Finish:

+  Status = GetUtilityStatus ();

+  return Status;

+}

+

+static

+STATUS

+ProcessFile (

+  INT8      *InFileName,

+  INT8      *OutFileName

+  )

+/*++

+

+Routine Description:

+  

+  Process a PE32 EFI file.

+

+Arguments:

+  

+  InFileName      - the file name pointer to the input file

+  OutFileName     - the file name pointer to the output file

+

+Returns:

+

+  STATUS_SUCCESS  - the process has been finished successfully

+  STATUS_ERROR    - error occured during the processing

+

+--*/

+{

+  STATUS                      Status;

+  FILE                        *InFptr;

+  FILE                        *OutFptr;

+  UINT16                      MachineType;

+  UINT16                      SubSystem;

+  EFI_TE_IMAGE_HEADER         TEImageHeader;

+  UINT32                      PESigOffset;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;

+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;

+  UINT32                      BytesStripped;

+  UINT32                      FileSize;

+  UINT8                       *Buffer;

+  long                        SaveFilePosition;

+

+  InFptr  = NULL;

+  OutFptr = NULL;

+  Buffer  = NULL;

+  Status  = STATUS_ERROR;

+

+  //

+  // Try to open the input file

+  //

+  if ((InFptr = fopen (InFileName, "rb")) == NULL) {

+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Double-check the file to make sure it's what we expect it to be

+  //

+  if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {

+    goto Finish;

+  }

+  //

+  // Initialize our new header

+  //

+  memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));

+

+  //

+  // Seek to the end to get the file size

+  //

+  fseek (InFptr, 0, SEEK_END);

+  FileSize = ftell (InFptr);

+  fseek (InFptr, 0, SEEK_SET);

+

+  //

+  // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit

+  // offset (from the start of the file) to the PE signature, which always

+  // follows the MSDOS stub. The PE signature is immediately followed by the

+  // COFF file header.

+  //

+  //

+  if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {

+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);

+    goto Finish;

+  }

+

+  if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");

+    goto Finish;

+  }

+

+  if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {

+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");

+    goto Finish;

+  }

+  //

+  // We should now be at the COFF file header. Read it in and verify it's

+  // of an image type we support.

+  //

+  if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read file header from image");

+    goto Finish;

+  }

+

+  if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {

+    Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);

+    goto Finish;

+  }

+  //

+  // Calculate the total number of bytes we're going to strip off. The '4' is for the

+  // PE signature PE\0\0. Then sanity check the size.

+  //

+  BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;

+  if (BytesStripped >= FileSize) {

+    Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");

+    goto Finish;

+  }

+

+  if (BytesStripped &~0xFFFF) {

+    Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);

+    goto Finish;

+  }

+

+  TEImageHeader.StrippedSize = (UINT16) BytesStripped;

+

+  //

+  // Read in the optional header. Assume PE32, and if not, then re-read as PE32+

+  //

+  SaveFilePosition = ftell (InFptr);

+  if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");

+    goto Finish;

+  }

+

+  if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    //

+    // Fill in our new header with required data directory entries

+    //

+    TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;

+    //

+    // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);

+    //

+    // We're going to pack the subsystem into 1 byte. Make sure it fits

+    //

+    if (OptionalHeader32.Subsystem &~0xFF) {

+      Error (

+        NULL,

+        0,

+        0,

+        InFileName,

+        NULL,

+        "image subsystem 0x%X cannot be packed into 1 byte",

+        (UINT32) OptionalHeader32.Subsystem

+        );

+      goto Finish;

+    }

+

+    TEImageHeader.Subsystem   = (UINT8) OptionalHeader32.Subsystem;

+    TEImageHeader.BaseOfCode  = OptionalHeader32.BaseOfCode;

+    TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));

+    if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

+    }

+

+    if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;

+    }

+  } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {

+    //

+    // Rewind and re-read the optional header

+    //

+    fseek (InFptr, SaveFilePosition, SEEK_SET);

+    if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {

+      Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");

+      goto Finish;

+    }

+

+    TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;

+    //

+    // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);

+    //

+    // We're going to pack the subsystem into 1 byte. Make sure it fits

+    //

+    if (OptionalHeader64.Subsystem &~0xFF) {

+      Error (

+        NULL,

+        0,

+        0,

+        InFileName,

+        NULL,

+        "image subsystem 0x%X cannot be packed into 1 byte",

+        (UINT32) OptionalHeader64.Subsystem

+        );

+      goto Finish;

+    }

+

+    TEImageHeader.Subsystem   = (UINT8) OptionalHeader64.Subsystem;

+    TEImageHeader.BaseOfCode  = OptionalHeader32.BaseOfCode;

+    TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));

+    if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

+    }

+

+    if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;

+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;

+    }

+  } else {

+    Error (

+      NULL,

+      0,

+      0,

+      InFileName,

+      "unsupported magic number 0x%X found in optional header",

+      (UINT32) OptionalHeader32.Magic

+      );

+    goto Finish;

+  }

+  //

+  // Fill in the remainder of our new image header

+  //

+  TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;

+  TEImageHeader.Machine   = FileHeader.Machine;

+  //

+  // We're going to pack the number of sections into a single byte. Make sure it fits.

+  //

+  if (FileHeader.NumberOfSections &~0xFF) {

+    Error (

+      NULL,

+      0,

+      0,

+      InFileName,

+      NULL,

+      "image's number of sections 0x%X cannot be packed into 1 byte",

+      (UINT32) FileHeader.NumberOfSections

+      );

+    goto Finish;

+  }

+

+  TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;

+

+  //

+  // Now open our output file

+  //

+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");

+    goto Finish;

+  }

+  //

+  // Write the TE header

+  //

+  if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write image header to output file", NULL);

+    goto Finish;

+  }

+  //

+  // Position into the input file, read the part we're not stripping, and

+  // write it out.

+  //

+  fseek (InFptr, BytesStripped, SEEK_SET);

+  Buffer = (UINT8 *) malloc (FileSize - BytesStripped);

+  if (Buffer == NULL) {

+    Error (NULL, 0, 0, "application error", "failed to allocate memory");

+    goto Finish;

+  }

+

+  if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {

+    Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");

+    goto Finish;

+  }

+

+  if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {

+    Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");

+    goto Finish;

+  }

+

+  Status = STATUS_SUCCESS;

+

+Finish:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+  //

+  // Close the output file. If there was an error, delete the output file so

+  // that a subsequent build will rebuild it.

+  //

+  if (OutFptr != NULL) {

+    fclose (OutFptr);

+    if (GetUtilityStatus () == STATUS_ERROR) {

+      remove (OutFileName);

+    }

+  }

+

+  //

+  // Free up our buffer

+  //

+  if (Buffer != NULL) {

+    free (Buffer);

+  }

+

+  return Status;

+}

+

+static

+STATUS

+CheckPE32File (

+  INT8      *FileName,

+  FILE      *Fptr,

+  UINT16    *MachineType,

+  UINT16    *SubSystem

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileName    - GC_TODO: add argument description

+  Fptr        - GC_TODO: add argument description

+  MachineType - GC_TODO: add argument description

+  SubSystem   - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  /*++

+

+Routine Description:

+  

+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a

+  PE32 image file, and then return the machine type in the supplied pointer.

+

+Arguments:

+

+  Fptr          File pointer to the already-opened PE32 file

+  MachineType   Location to stuff the machine type of the PE32 file. This is needed

+                because the image may be Itanium-based, IA32, or EBC.

+

+Returns:

+

+  0             success

+  non-zero      otherwise

+

+--*/

+  EFI_IMAGE_DOS_HEADER      DosHeader;

+  EFI_IMAGE_FILE_HEADER     FileHdr;

+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;

+  UINT32                    PESig;

+  STATUS                    Status;

+

+  Status = STATUS_ERROR;

+  //

+  // Position to the start of the file

+  //

+  fseek (Fptr, 0, SEEK_SET);

+  //

+  // Read the DOS header

+  //

+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");

+    goto Finish;

+  }

+  //

+  // Check the magic number (0x5A4D)

+  //

+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");

+    goto Finish;

+  }

+  //

+  // Position into the file and check the PE signature

+  //

+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);

+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");

+    goto Finish;

+  }

+  //

+  // Check the PE signature in the header "PE\0\0"

+  //

+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");

+    goto Finish;

+  }

+  //

+  // Read the file header

+  //

+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");

+    goto Finish;

+  }

+  //

+  // Read the optional header so we can get the subsystem

+  //

+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");

+    goto Finish;

+  }

+

+  *SubSystem = OptionalHdr.Subsystem;

+  if (mOptions.Verbose) {

+    fprintf (stdout, "  Got subsystem = 0x%X from image\n", (int) *SubSystem);

+  }

+  //

+  // Good to go

+  //

+  Status = STATUS_SUCCESS;

+Finish:

+  fseek (Fptr, 0, SEEK_SET);

+  return Status;

+}

+

+static

+int

+ParseCommandLine (

+  int         Argc,

+  char        *Argv[]

+  )

+/*++

+

+Routine Description:

+  

+  Given the Argc/Argv program arguments, and a pointer to an options structure,

+  parse the command-line options and check their validity.

+

+

+Arguments:

+

+  Argc            - standard C main() argument count

+  Argv            - standard C main() argument list

+

+Returns:

+

+  STATUS_SUCCESS    success

+  non-zero          otherwise

+

+--*/

+// GC_TODO:    ] - add argument and description to function comment

+{

+  //

+  // Clear out the options

+  //

+  memset ((char *) &mOptions, 0, sizeof (mOptions));

+  //

+  // Skip over the program name

+  //

+  Argc--;

+  Argv++;

+  //

+  // If no arguments, assume they want usage info

+  //

+  if (Argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Process until no more arguments

+  //

+  while ((Argc > 0) && (Argv[0][0] == '-')) {

+    if (stricmp (Argv[0], "-o") == 0) {

+      //

+      // Output filename specified with -o

+      // Make sure there's another parameter

+      //

+      if (Argc > 1) {

+        strcpy (mOptions.OutFileName, Argv[1]);

+      } else {

+        Error (NULL, 0, 0, Argv[0], "missing output file name with option");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argv++;

+      Argc--;

+    } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {

+      //

+      // Help option

+      //

+      Usage ();

+      return STATUS_ERROR;

+    } else if (stricmp (Argv[0], "-v") == 0) {

+      //

+      // -v for verbose

+      //

+      mOptions.Verbose = 1;

+    } else if (stricmp (Argv[0], "-dump") == 0) {

+      //

+      // -dump for dumping an image

+      //

+      mOptions.Dump = 1;

+    } else {

+      Error (NULL, 0, 0, Argv[0], "unrecognized option");

+      Usage ();

+      return STATUS_ERROR;

+    }

+    //

+    // Next argument

+    //

+    Argv++;

+    Argc--;

+  }

+  //

+  // Better be one more arg for input file name

+  //

+  if (Argc == 0) {

+    Error (NULL, 0, 0, "input file name required", NULL);

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  if (Argc != 1) {

+    Error (NULL, 0, 0, Argv[1], "extra arguments on command line");

+    return STATUS_ERROR;

+  }

+

+  strcpy (mOptions.InFileName, Argv[0]);

+  return STATUS_SUCCESS;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+  

+  Print usage information for this utility.

+

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+

+--*/

+{

+  int               Index;

+  static const char *Msg[] = {

+    UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",

+    "  Generate a TE image from an EFI PE32 image",

+    "  Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",

+    "                [-e|-b] [FileName(s)]",

+    "    where:",

+    "      -v             - for verbose output",

+    "      -dump          - to dump the input file to a text file",

+    "      -h -?          - for this help information",

+    "      -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,

+    "      InFileName     - name of the input PE32 file",

+    "",

+    NULL

+  };

+  for (Index = 0; Msg[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Msg[Index]);

+  }

+}

+

+static

+VOID

+DumpImage (

+  INT8    *FileName

+  )

+/*++

+

+Routine Description:

+  

+  Dump a specified image information

+

+Arguments:

+  

+  FileName - File name pointer to the image to dump

+

+Returns:

+

+  Nothing.

+

+--*/

+{

+  FILE                *InFptr;

+  EFI_TE_IMAGE_HEADER TEImageHeader;

+  INT8                *NamePtr;

+

+  //

+  // Open the input file

+  //

+  InFptr  = NULL;

+

+  if ((InFptr = fopen (FileName, "rb")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open input file for reading");

+    return ;

+  }

+

+  if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {

+    Error (NULL, 0, 0, FileName, "failed to read image header from input file");

+    goto Finish;

+  }

+

+  if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {

+    Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");

+    goto Finish;

+  }

+  //

+  // Dump the header

+  //

+  fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));

+  fprintf (stdout, "  Signature:          0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);

+  NamePtr = GetMachineTypeStr (TEImageHeader.Machine);

+  fprintf (stdout, "  Machine:            0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);

+  NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);

+  fprintf (stdout, "  Subsystem:          0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);

+  fprintf (stdout, "  Number of sections  0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);

+  fprintf (stdout, "  Stripped size:      0x%04X\n", (UINT32) TEImageHeader.StrippedSize);

+  fprintf (stdout, "  Entry point:        0x%08X\n", TEImageHeader.AddressOfEntryPoint);

+  fprintf (stdout, "  Base of code:       0x%08X\n", TEImageHeader.BaseOfCode);

+  fprintf (stdout, "  Data directories:\n");

+  fprintf (

+    stdout,

+    "    %8X [%8X] RVA [size] of Base Relocation Directory\n",

+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,

+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size

+    );

+  fprintf (

+    stdout,

+    "    %8X [%8X] RVA [size] of Debug Directory\n",

+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,

+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size

+    );

+

+Finish:

+  if (InFptr != NULL) {

+    fclose (InFptr);

+  }

+}

+

+static

+INT8 *

+GetMachineTypeStr (

+  UINT16    MachineType

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  MachineType - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  int Index;

+

+  for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {

+    if (mMachineTypes[Index].Value == MachineType) {

+      return mMachineTypes[Index].Name;

+    }

+  }

+

+  return "unknown";

+}

+

+static

+INT8 *

+GetSubsystemTypeStr (

+  UINT16  SubsystemType

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  SubsystemType - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  int Index;

+

+  for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {

+    if (mSubsystemTypes[Index].Value == SubsystemType) {

+      return mSubsystemTypes[Index].Name;

+    }

+  }

+

+  return "unknown";

+}

diff --git a/Source/GenTEImage/build.xml b/Source/GenTEImage/build.xml
new file mode 100644
index 0000000..508035b
--- /dev/null
+++ b/Source/GenTEImage/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GenTEImage Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GenTEImage"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/GuidChk/CommonUtils.h b/Source/GuidChk/CommonUtils.h
new file mode 100644
index 0000000..f7a331e
--- /dev/null
+++ b/Source/GuidChk/CommonUtils.h
@@ -0,0 +1,57 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  CommonUtils.h

+  

+Abstract:

+

+  Common utility defines and structure definitions.

+  

+--*/

+

+#ifndef _COMMON_UTILS_H_

+#define _COMMON_UTILS_H_

+

+//

+// Basic types

+//

+typedef unsigned char UINT8;

+typedef char INT8;

+typedef unsigned short UINT16;

+typedef unsigned int UINT32;

+

+typedef UINT8 BOOLEAN;

+typedef UINT32 STATUS;

+

+#define TRUE            1

+#define FALSE           0

+

+#define STATUS_SUCCESS  0

+#define STATUS_WARNING  1

+#define STATUS_ERROR    2

+

+//

+// Linked list of strings

+//

+typedef struct _STRING_LIST {

+  struct _STRING_LIST *Next;

+  char                *Str;

+} STRING_LIST;

+

+int

+CreateGuidList (

+  INT8    *OutFileName

+  )

+;

+

+#endif // #ifndef _COMMON_UTILS_H_

diff --git a/Source/GuidChk/FileSearch.c b/Source/GuidChk/FileSearch.c
new file mode 100644
index 0000000..8b5b58f
--- /dev/null
+++ b/Source/GuidChk/FileSearch.c
@@ -0,0 +1,285 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  FileSearch.c

+  

+Abstract:

+

+  Module used to support file searches on the system.

+  

+--*/

+

+#include <stdio.h>

+

+#include "CommonUtils.h"

+#include "FileSearch.h"

+#include "UtilsMsgs.h"

+

+//

+// Internal file search flag for sanity checks

+//

+#define FILE_SEARCH_STARTED 0x8000

+#define FILE_SEARCH_INITED  0x4000

+

+static

+BOOLEAN

+FileSearchMeetsCriteria (

+  FILE_SEARCH_DATA    *FSData

+  );

+

+/*****************************************************************************/

+STATUS

+FileSearchInit (

+  FILE_SEARCH_DATA    *FSData

+  )

+{

+  memset ((char *) FSData, 0, sizeof (FILE_SEARCH_DATA));

+  FSData->Handle          = INVALID_HANDLE_VALUE;

+  FSData->FileSearchFlags = FILE_SEARCH_INITED;

+  FSData->FileName[0]     = 0;

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FileSearchStart (

+  FILE_SEARCH_DATA    *FSData,

+  char                *FileMask,

+  UINT32              SearchFlags

+  )

+{

+  BOOLEAN Done;

+

+  //

+  // Save their flags, and set a flag to indicate that they called this

+  // start function so we can perform extended checking in the other

+  // routines we have in this module.

+  //

+  FSData->FileSearchFlags |= (SearchFlags | FILE_SEARCH_STARTED);

+  FSData->FileName[0] = 0;

+

+  //

+  // Begin the search

+  //

+  FSData->Handle = FindFirstFile (FileMask, &(FSData->FindData));

+  if (FSData->Handle == INVALID_HANDLE_VALUE) {

+    return STATUS_ERROR;

+  }

+  //

+  // Keep looping through until we find a file meeting the caller's

+  // criteria per the search flags

+  //

+  Done = FALSE;

+  while (!Done) {

+    //

+    // If we're done (we found a match) copy the file name found and return

+    //

+    Done = FileSearchMeetsCriteria (FSData);

+    if (Done) {

+      return STATUS_SUCCESS;

+    }

+    //

+    // Go on to next file

+    //

+    if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {

+      return STATUS_NOT_FOUND;

+    }

+  }

+  //

+  // Not reached

+  //

+  return STATUS_NOT_FOUND;

+}

+

+//

+// Find the next file meeting their criteria and return it.

+//

+STATUS

+FileSearchFindNext (

+  FILE_SEARCH_DATA    *FSData

+  )

+{

+  BOOLEAN Done;

+

+  Done = FALSE;

+  while (!Done) {

+    if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {

+      return STATUS_NOT_FOUND;

+    }

+    //

+    // See if it matches their criteria

+    //

+    Done = FileSearchMeetsCriteria (FSData);

+    if (Done) {

+      return STATUS_SUCCESS;

+    }

+  }

+  //

+  // Not reached

+  //

+  return STATUS_NOT_FOUND;

+}

+//

+// Perform any cleanup necessary to close down a search

+//

+STATUS

+FileSearchDestroy (

+  FILE_SEARCH_DATA    *FSData

+  )

+{

+  if (FSData->Handle != INVALID_HANDLE_VALUE) {

+    FindClose (FSData->Handle);

+    FSData->Handle = INVALID_HANDLE_VALUE;

+  }

+

+  FSData->FileName[0]     = 0;

+  FSData->FileSearchFlags = 0;

+  return STATUS_SUCCESS;

+}

+

+static

+BOOLEAN

+FileSearchMeetsCriteria (

+  FILE_SEARCH_DATA    *FSData

+  )

+{

+  BOOLEAN     Status;

+  STRING_LIST *StrList;

+  UINT32      ExtLen;

+  UINT32      FileNameLen;

+

+  Status = FALSE;

+

+  //

+  // First clear the flag indicating this is neither a file or a

+  // directory.

+  //

+  FSData->FileFlags &= ~(FILE_SEARCH_DIR | FILE_SEARCH_FILE);

+

+  //

+  // We found a file. See if it matches the user's search criteria. First

+  // check for this being a directory, and they want directories, and

+  // it's not "." and it's not ".."

+  //

+  if ((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&

+      (FSData->FileSearchFlags & FILE_SEARCH_DIR) &&

+      (strcmp (FSData->FindData.cFileName, ".")) &&

+      (strcmp (FSData->FindData.cFileName, ".."))

+      ) {

+    //

+    // Assume we'll make it past this check

+    //

+    Status = TRUE;

+    //

+    // If they have a list of exclude directories, then check for those

+    //

+    StrList = FSData->ExcludeDirs;

+    while (StrList != NULL) {

+      if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {

+        Status = FALSE;

+        break;

+      }

+

+      StrList = StrList->Next;

+    }

+    //

+    // If we didn't fail due to excluded directories, then set the dir flag

+    //

+    if (Status) {

+      FSData->FileFlags |= FILE_SEARCH_DIR;

+    }

+    //

+    // Else check for a file, and they want files....

+    //

+  } else if (((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) &&

+           (FSData->FileSearchFlags & FILE_SEARCH_FILE)

+          ) {

+    //

+    // See if it's in our list of excluded files

+    //

+    Status  = TRUE;

+    StrList = FSData->ExcludeFiles;

+    while (StrList != NULL) {

+      if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {

+        Status = FALSE;

+        break;

+      }

+

+      StrList = StrList->Next;

+    }

+

+    if (Status) {

+      //

+      // See if it's in our list of excluded file extensions

+      //

+      FileNameLen = strlen (FSData->FindData.cFileName);

+      StrList     = FSData->ExcludeExtensions;

+      while (StrList != NULL) {

+        ExtLen = strlen (StrList->Str);

+        if (stricmp (

+              FSData->FindData.cFileName + FileNameLen - ExtLen,

+              StrList->Str

+              ) == 0) {

+          Status = FALSE;

+          break;

+        }

+

+        StrList = StrList->Next;

+      }

+    }

+

+    if (Status) {

+      FSData->FileFlags |= FILE_SEARCH_FILE;

+    }

+  }

+  //

+  // If it's a match, copy the filename into another field of the structure

+  // for portability.

+  //

+  if (Status) {

+    strcpy (FSData->FileName, FSData->FindData.cFileName);

+  }

+

+  return Status;

+}

+//

+// Exclude a list of subdirectories.

+//

+STATUS

+FileSearchExcludeDirs (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+{

+  FSData->ExcludeDirs = StrList;

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FileSearchExcludeFiles (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+{

+  FSData->ExcludeFiles = StrList;

+  return STATUS_SUCCESS;

+}

+

+STATUS

+FileSearchExcludeExtensions (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+{

+  FSData->ExcludeExtensions = StrList;

+  return STATUS_SUCCESS;

+}

diff --git a/Source/GuidChk/FileSearch.h b/Source/GuidChk/FileSearch.h
new file mode 100644
index 0000000..bc40265
--- /dev/null
+++ b/Source/GuidChk/FileSearch.h
@@ -0,0 +1,108 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  FileSearch.h

+  

+Abstract:

+

+  Header file to support file searching.

+  

+--*/

+

+#ifndef _FILE_SEARCH_H_

+#define _FILE_SEARCH_H_

+

+//

+// Since the file searching routines are OS dependent, put the

+// necessary include paths in this header file so that the non-OS-dependent

+// files don't need to include these windows-specific header files.

+//

+#include <stdio.h>

+#include <string.h>

+#include <ctype.h>

+#include <direct.h>

+#include <windows.h>

+

+//

+// Return codes of some of the file search routines

+//

+#define STATUS_NOT_FOUND  0x1000

+

+//

+// Flags for what to search for. Also used in the FileFlags return field.

+//

+#define FILE_SEARCH_DIR   0x0001

+#define FILE_SEARCH_FILE  0x0002

+

+//

+// Here's our class definition

+//

+typedef struct {

+  HANDLE          Handle;

+  WIN32_FIND_DATA FindData;

+  UINT32          FileSearchFlags;    // DIRS, FILES, etc

+  UINT32          FileFlags;

+  INT8            FileName[MAX_PATH]; // for portability

+  STRING_LIST     *ExcludeDirs;

+  STRING_LIST     *ExcludeFiles;

+  STRING_LIST     *ExcludeExtensions;

+} FILE_SEARCH_DATA;

+

+//

+// Here's our member functions

+//

+STATUS

+FileSearchInit (

+  FILE_SEARCH_DATA    *FSData

+  )

+;

+

+STATUS

+FileSearchDestroy (

+  FILE_SEARCH_DATA    *FSData

+  )

+;

+

+STATUS

+FileSearchStart (

+  FILE_SEARCH_DATA    *FSData,

+  char                *FileMask,

+  UINT32              SearchFlags

+  )

+;

+

+STATUS

+FileSearchFindNext (

+  FILE_SEARCH_DATA    *FSData

+  )

+;

+

+STATUS

+FileSearchExcludeDirs (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+;

+STATUS

+FileSearchExcludeExtensions (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+;

+STATUS

+FileSearchExcludeFiles (

+  FILE_SEARCH_DATA    *FSData,

+  STRING_LIST         *StrList

+  )

+;

+#endif

diff --git a/Source/GuidChk/GuidChk.c b/Source/GuidChk/GuidChk.c
new file mode 100644
index 0000000..de88405
--- /dev/null
+++ b/Source/GuidChk/GuidChk.c
@@ -0,0 +1,2348 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  GuidChk.c 

+  

+Abstract:

+

+  Parse files in a directory and subdirectories to find all guid definitions.

+  Then check them against each other to make sure there are no duplicates.

+  

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include "CommonUtils.h"

+#include "FileSearch.h"

+#include "UtilsMsgs.h"

+

+#define MAX_LINE_LEN  180 // we concatenate two lines sometimes

+// Define a structure that correlates filename extensions to an enumerated

+// type.

+//

+typedef struct {

+  INT8  *Extension;

+  INT8  ExtensionCode;

+} FILE_TYPE_TABLE_ENTRY;

+

+#define FILE_EXTENSION_UNKNOWN  0

+#define FILE_EXTENSION_C        1

+#define FILE_EXTENSION_H        2

+#define FILE_EXTENSION_IA32_ASM 3

+#define FILE_EXTENSION_IA32_INC 4

+#define FILE_EXTENSION_IA64_ASM 5

+#define FILE_EXTENSION_IA64_INC 6

+#define FILE_EXTENSION_PKG      7

+#define FILE_EXTENSION_INF      8

+

+FILE_TYPE_TABLE_ENTRY FileTypeTable[] = {

+  ".c",

+  FILE_EXTENSION_C,

+  ".h",

+  FILE_EXTENSION_H,

+  ".inc",

+  FILE_EXTENSION_IA32_INC,

+  ".asm",

+  FILE_EXTENSION_IA32_ASM,

+  ".s",

+  FILE_EXTENSION_IA64_ASM,

+  ".pkg",

+  FILE_EXTENSION_PKG,

+  ".inf",

+  FILE_EXTENSION_INF,

+  ".i",

+  FILE_EXTENSION_IA64_INC,

+  NULL,

+  0

+};

+

+typedef struct EFI_GUID {

+  UINT32  Data1;

+  UINT16  Data2;

+  UINT16  Data3;

+  UINT8   Data4[8];

+} EFI_GUID;

+

+typedef struct {

+  INT8  Data[4];

+  INT8  DataLen;

+} EFI_SIGNATURE;

+

+typedef struct _GUID_RECORD {

+  struct _GUID_RECORD *Next;

+  BOOLEAN             Reported;

+  INT8                *FileName;

+  INT8                *SymName;

+  EFI_GUID            Guid;

+} GUID_RECORD;

+

+typedef struct _SIGNATURE_RECORD {

+  struct _SIGNATURE_RECORD  *Next;

+  BOOLEAN                   Reported;

+  INT8                      *FileName;

+  EFI_SIGNATURE             Signature;

+} SIGNATURE_RECORD;

+

+//

+// Utility options

+//

+typedef struct {

+  INT8        DatabaseOutputFileName[MAX_PATH]; // with -b option

+  STRING_LIST *ExcludeDirs;                     // list of directory names not to process

+  STRING_LIST *ExcludeSubDirs;                  // list of directory names to not process subdirectories (build)

+  STRING_LIST *ExcludeFiles;                    // list of files to exclude (make.inf)

+  STRING_LIST *ExcludeExtensions;               // list of filename extensions to exclude (.inf, .pkg)

+  BOOLEAN     Verbose;

+  BOOLEAN     PrintFound;

+  BOOLEAN     CheckGuids;

+  BOOLEAN     CheckSignatures;

+  BOOLEAN     GuidXReference;

+} OPTIONS;

+

+static

+STATUS

+ProcessArgs (

+  int     Argc,

+  char    *Argv[]

+  );

+

+static

+VOID

+Usage (

+  VOID

+  );

+

+static

+STATUS

+ProcessDirectory (

+  INT8        *Path,

+  INT8        *DirectoryName

+  );

+

+static

+STATUS

+ProcessFile (

+  INT8                *DirectoryName,

+  INT8                *FileName

+  );

+

+static

+UINT32

+GetFileExtension (

+  INT8        *FileName

+  );

+

+static

+UINT32

+SkipWhiteSpace (

+  INT8    *Str

+  );

+

+static

+UINT32

+ValidSymbolName (

+  INT8    *Name

+  );

+

+static

+STATUS

+ProcessCFileGuids (

+  INT8    *FileName

+  );

+

+static

+STATUS

+AddSignature (

+  INT8      *FileName,

+  INT8      *StrDef,

+  UINT32    SigSize

+  );

+

+static

+STATUS

+ProcessCFileSigs (

+  INT8    *FileName

+  );

+

+static

+STATUS

+ProcessINFFileGuids (

+  INT8    *FileName

+  );

+

+static

+STATUS

+ProcessPkgFileGuids (

+  INT8    *FileName

+  );

+

+static

+STATUS

+ProcessIA32FileGuids (

+  INT8    *FileName

+  );

+

+static

+STATUS

+ProcessIA64FileGuids (

+  INT8    *FileName

+  );

+

+static

+BOOLEAN

+IsIA64GuidLine (

+  INT8      *Line,

+  UINT32    *GuidHigh,

+  UINT32    *GuidLow,

+  BOOLEAN   *Low,

+  INT8      *SymName

+  );

+

+static

+STATUS

+AddGuid11 (

+  INT8      *FileName,

+  UINT32    *Data,

+  INT8      *SymName

+  );

+

+static

+STATUS

+AddPkgGuid (

+  INT8      *FileName,

+  UINT32    *Data,

+  UINT64    *Data64

+  );

+

+static

+STATUS

+AddGuid16 (

+  INT8      *FileName,

+  UINT32    *Data

+  );

+

+static

+STATUS

+AddGuid64x2 (

+  INT8      *FileName,

+  UINT32    DataHH,                             // Upper 32-bits of upper 64 bits of guid

+  UINT32    DataHL,                             // Lower 32-bits of upper 64 bits

+  UINT32    DataLH,

+  UINT32    DataLL

+  );

+

+static

+VOID

+FreeGuids (

+  VOID

+  );

+

+static

+VOID

+FreeSigs (

+  VOID

+  );

+

+static

+STATUS

+CheckDuplicates (

+  VOID

+  );

+

+//

+// static

+// VOID

+// ReportGuid (

+//  INT8        *FileName,

+//  GUID_RECORD *FileRecord

+//  );

+//

+static

+VOID

+FreeOptions (

+  VOID

+  );

+

+static

+BOOLEAN

+CheckGuidData (

+  UINT32    *GuidData,

+  UINT32    DataCount

+  );

+

+/**************************** GLOBALS ****************************************/

+static GUID_RECORD      *gGuidList      = NULL;

+static SIGNATURE_RECORD *gSignatureList = NULL;

+static OPTIONS          gOptions;

+

+/*****************************************************************************/

+int

+main (

+  int     Argc,

+  char    *Argv[]

+  )

+{

+  INT8    *Cwd;

+  STATUS  Status;

+

+  SetUtilityName ("GuidChk");

+  //

+  // Get the current working directory and then process the command line

+  // arguments.

+  //

+  Cwd     = _getcwd (NULL, 0);

+  Status  = ProcessArgs (Argc, Argv);

+  if (Status != STATUS_SUCCESS) {

+    return Status;

+  }

+

+  if (gOptions.CheckGuids || gOptions.CheckSignatures) {

+    Status = ProcessDirectory (Cwd, NULL);

+    if (Status == STATUS_SUCCESS) {

+      //

+      // Check for duplicates

+      //

+      Status = CheckDuplicates ();

+    }

+  }

+

+  if (gOptions.DatabaseOutputFileName[0] != 0) {

+    CreateGuidList (gOptions.DatabaseOutputFileName);

+  }

+  //

+  // Free up the memory

+  //

+  free (Cwd);

+  FreeGuids ();

+  FreeSigs ();

+  FreeOptions ();

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+ProcessArgs (

+  int     Argc,

+  char    *Argv[]

+  )

+{

+  STRING_LIST *StrList;

+

+  memset ((char *) &gOptions, 0, sizeof (gOptions));

+  //

+  // skip over program name

+  //

+  Argc--;

+  Argv++;

+

+  if (Argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  while (Argc > 0) {

+    //

+    // Look for options

+    //

+    if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {

+      switch (Argv[0][1]) {

+      //

+      // Help option

+      //

+      case 'h':

+      case 'H':

+      case '?':

+        Usage ();

+        return STATUS_ERROR;

+        break;

+

+      //

+      // Check guids option

+      //

+      case 'g':

+      case 'G':

+        gOptions.CheckGuids = TRUE;

+        break;

+

+      //

+      // Check signatures option

+      //

+      case 's':

+      case 'S':

+        gOptions.CheckSignatures = TRUE;

+        break;

+

+      //

+      // Print guids found option

+      //

+      case 'p':

+      case 'P':

+        gOptions.PrintFound = TRUE;

+        break;

+

+      //

+      // Exclude files option

+      //

+      case 'f':

+      case 'F':

+        //

+        // Check for another arg

+        //

+        if (Argc < 2) {

+          Error (NULL, 0, 0, Argv[0], "missing argument with option");

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        StrList = malloc (sizeof (STRING_LIST));

+        if (StrList == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        memset ((char *) StrList, 0, sizeof (STRING_LIST));

+        StrList->Str          = Argv[1];

+        StrList->Next         = gOptions.ExcludeFiles;

+        gOptions.ExcludeFiles = StrList;

+        Argc--;

+        Argv++;

+        break;

+

+      //

+      // Exclude directories option

+      //

+      case 'd':

+      case 'D':

+        //

+        // Check for another arg

+        //

+        if (Argc < 2) {

+          Error (NULL, 0, 0, Argv[0], "missing argument with option");

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        StrList = malloc (sizeof (STRING_LIST));

+        if (StrList == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        memset ((char *) StrList, 0, sizeof (STRING_LIST));

+        StrList->Str          = Argv[1];

+        StrList->Next         = gOptions.ExcludeDirs;

+        gOptions.ExcludeDirs  = StrList;

+        Argc--;

+        Argv++;

+        break;

+

+      //

+      // -u  exclude all subdirectories of a given directory option

+      //

+      case 'u':

+      case 'U':

+        //

+        // Check for another arg

+        //

+        if (Argc < 2) {

+          Error (NULL, 0, 0, Argv[0], "missing argument with option");

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        StrList = malloc (sizeof (STRING_LIST));

+        if (StrList == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        memset ((char *) StrList, 0, sizeof (STRING_LIST));

+        StrList->Str            = Argv[1];

+        StrList->Next           = gOptions.ExcludeSubDirs;

+        gOptions.ExcludeSubDirs = StrList;

+        Argc--;

+        Argv++;

+        break;

+

+      //

+      // -e  exclude by filename extension option

+      //

+      case 'e':

+      case 'E':

+        //

+        // Check for another arg

+        //

+        if (Argc < 2) {

+          Error (NULL, 0, 0, Argv[0], "missing argument with option");

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        StrList = malloc (sizeof (STRING_LIST));

+        if (StrList == NULL) {

+          Error (NULL, 0, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        memset ((char *) StrList, 0, sizeof (STRING_LIST));

+        //

+        // Let them put a * in front of the filename extension

+        //

+        StrList->Str = Argv[1];

+        if (StrList->Str[0] == '*') {

+          StrList->Str++;

+        }

+

+        StrList->Next               = gOptions.ExcludeExtensions;

+        gOptions.ExcludeExtensions  = StrList;

+        Argc--;

+        Argv++;

+        break;

+

+      //

+      // Print guid with matching symbol name for guid definitions found

+      //

+      case 'x':

+      case 'X':

+        gOptions.GuidXReference = 1;

+        break;

+

+      //

+      // -b   Print the internal database list to a file

+      //

+      case 'b':

+      case 'B':

+        //

+        // Check for one more arg

+        //

+        if (Argc < 2) {

+          Error (NULL, 0, 0, Argv[0], "must specify file name with option");

+          Usage ();

+          return STATUS_ERROR;

+        }

+

+        strcpy (gOptions.DatabaseOutputFileName, Argv[1]);

+        Argc--;

+        Argv++;

+        break;

+

+      default:

+        Error (NULL, 0, 0, Argv[0], "invalid option");

+        Usage ();

+        return STATUS_ERROR;

+      }

+    } else {

+      break;

+    }

+    //

+    // Next arg

+    //

+    Argc--;

+    Argv++;

+  }

+

+  if (Argc > 0) {

+    Error (NULL, 0, 0, Argv[0], "invalid argument");

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Have to check signatures, GUIDs, or dump the GUID database.

+  //

+  if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) {

+    Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b");

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+//

+// Print usage instructions

+//

+static

+VOID

+Usage (

+  VOID

+  )

+{

+  int   Index;

+  char  *Str[] = {

+    "GuidChk - scan files for duplicate GUID or signature definitions",

+    "",

+    "Usage:  GuidChk {options}\n",

+    "  Options: ",

+    "    -d dirname     exclude searching of a directory",

+    "    -f filename    exclude searching of a file",

+    "    -e extension   exclude searching of files by extension",

+    "    -p             print all GUIDS found",

+    "    -g             check for duplicate guids",

+    "    -s             check for duplicate signatures",

+    "    -x             print guid+defined symbol name",

+    "    -b outfile     write internal GUID+basename list to outfile",

+    "    -u dirname     exclude searching all subdirectories of a directory",

+    "    -h -?          print this help text",

+    " ",

+    "   Example: GuidChk -g -u build -d fv -f make.inf -e .pkg",

+    "",

+    NULL

+  };

+  for (Index = 0; Str[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Str[Index]);

+  }

+}

+//

+// Process an entire directory by name

+//

+static

+STATUS

+ProcessDirectory (

+  INT8          *Path,

+  INT8          *DirectoryName

+  )

+{

+  FILE_SEARCH_DATA  FSData;

+  char              *FileMask;

+  BOOLEAN           Done;

+  UINT32            Len;

+  BOOLEAN           NoSubdirs;

+  STRING_LIST       *SLPtr;

+

+  //

+  // Root directory may be null

+  //

+  if (DirectoryName != NULL) {

+    //

+    // printf ("Processing directory: %s\n", DirectoryName);

+    //

+  }

+  //

+  // Initialize our file searching

+  //

+  FileSearchInit (&FSData);

+

+  //

+  // Exclude some directories, files, and extensions

+  //

+  FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs);

+  FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions);

+  FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles);

+  //

+  // See if this directory is in the list of directories that they

+  // don't want to process subdirectories of

+  //

+  NoSubdirs = FALSE;

+  if (DirectoryName != NULL) {

+    for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) {

+      if (stricmp (SLPtr->Str, DirectoryName) == 0) {

+        //

+        // printf ("not processing subdirectories of %s\n", DirectoryName);

+        //

+        NoSubdirs = TRUE;

+        break;

+      }

+    }

+  }

+  //

+  // Create a filemask of files to search for. We'll append "\*.*" on the

+  // end, so allocate some extra bytes.

+  //

+  Len = strlen (Path) + 10;

+  if (DirectoryName != NULL) {

+    Len += strlen (DirectoryName);

+  }

+

+  FileMask = malloc (Len);

+  if (FileMask == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Now put it all together

+  //

+  strcpy (FileMask, Path);

+  if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) {

+    strcat (FileMask, "\\");

+    strcat (FileMask, DirectoryName);

+  }

+

+  strcat (FileMask, "\\*.*");

+

+  //

+  // Start file searching for files and directories

+  //

+  FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR);

+

+  //

+  // Now hack the "\*.*" off the end of the filemask so we can use it to pass

+  // the full directory path on recursive calls to process directories.

+  //

+  FileMask[strlen (FileMask) - 4] = 0;

+

+  //

+  // Loop until no more files

+  //

+  Done = FALSE;

+  while (!Done) {

+    //

+    // printf ("Found %s...", FSData.FileName);

+    //

+    if (FSData.FileFlags & FILE_SEARCH_DIR) {

+      //

+      // printf ("directory\n");

+      //

+      if (!NoSubdirs) {

+        ProcessDirectory (FileMask, FSData.FileName);

+      }

+    } else if (FSData.FileFlags & FILE_SEARCH_FILE) {

+      //

+      // printf ("file\n");

+      //

+      ProcessFile (FileMask, FSData.FileName);

+    } else {

+      //

+      // printf ("unknown\n");

+      //

+    }

+

+    if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) {

+      Done = TRUE;

+    }

+  }

+  //

+  // Free up allocated memory

+  //

+  free (FileMask);

+

+  //

+  // Free up our file searching

+  //

+  FileSearchDestroy (&FSData);

+

+  return STATUS_SUCCESS;

+}

+//

+// Process a single file.

+//

+static

+STATUS

+ProcessFile (

+  INT8                *DirectoryName,

+  INT8                *FileName

+  )

+{

+  STATUS  Status;

+  UINT32  FileExtension;

+  INT8    FullFileName[MAX_PATH];

+

+  Status = STATUS_SUCCESS;

+

+  sprintf (FullFileName, "%s\\%s", DirectoryName, FileName);

+  //

+  // printf ("Found file: %s\n", FullFileName);

+  //

+  FileExtension = GetFileExtension (FileName);

+

+  //

+  // Process these for GUID checks

+  //

+  if (gOptions.CheckGuids) {

+    switch (FileExtension) {

+    case FILE_EXTENSION_C:

+    case FILE_EXTENSION_H:

+      Status = ProcessCFileGuids (FullFileName);

+      break;

+

+    case FILE_EXTENSION_PKG:

+      Status = ProcessPkgFileGuids (FullFileName);

+      break;

+

+    case FILE_EXTENSION_IA32_INC:

+    case FILE_EXTENSION_IA32_ASM:

+      Status = ProcessIA32FileGuids (FullFileName);

+      break;

+

+    case FILE_EXTENSION_INF:

+      Status = ProcessINFFileGuids (FullFileName);

+      break;

+

+    case FILE_EXTENSION_IA64_INC:

+    case FILE_EXTENSION_IA64_ASM:

+      Status = ProcessIA64FileGuids (FullFileName);

+      break;

+

+    default:

+      //

+      // No errors anyway

+      //

+      Status = STATUS_SUCCESS;

+      break;

+    }

+  }

+

+  if (gOptions.CheckSignatures) {

+    switch (FileExtension) {

+    case FILE_EXTENSION_C:

+    case FILE_EXTENSION_H:

+      Status = ProcessCFileSigs (FullFileName);

+      break;

+

+    default:

+      //

+      // No errors anyway

+      //

+      Status = STATUS_SUCCESS;

+      break;

+    }

+  }

+

+  return Status;

+}

+//

+// Return a code indicating the file name extension.

+//

+static

+UINT32

+GetFileExtension (

+  INT8        *FileName

+  )

+{

+  INT8  *Extension;

+  int   Index;

+

+  //

+  // Look back for a filename extension

+  //

+  for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) {

+    if (*Extension == '.') {

+      for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) {

+        if (stricmp (FileTypeTable[Index].Extension, Extension) == 0) {

+          return FileTypeTable[Index].ExtensionCode;

+        }

+      }

+    }

+  }

+

+  return FILE_TYPE_UNKNOWN;

+}

+//

+// Process a .pkg file.

+//

+// Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7

+//

+static

+STATUS

+ProcessPkgFileGuids (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN * 2];

+  INT8    *Cptr;

+  INT8    *Cptr2;

+  UINT32  GuidScan[11];

+  UINT64  Guid64;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read lines from the file until done

+  //

+  while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+    Cptr = Line;

+    Cptr += SkipWhiteSpace (Line);

+    if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) {

+      Cptr += 12;

+      Cptr += SkipWhiteSpace (Cptr);

+      if (*Cptr == '=') {

+        Cptr++;

+        Cptr += SkipWhiteSpace (Cptr + 1);

+        //

+        // Blank out dashes on the line.

+        //

+        for (Cptr2 = Cptr; *Cptr2; Cptr2++) {

+          if (*Cptr2 == '-') {

+            *Cptr2 = ' ';

+          }

+        }

+

+        if (sscanf (

+              Cptr,

+              "%X %X %X %X %I64X",

+              &GuidScan[0],

+              &GuidScan[1],

+              &GuidScan[2],

+              &GuidScan[3],

+              &Guid64

+              ) == 5) {

+          AddPkgGuid (FileName, GuidScan, &Guid64);

+        } else {

+          DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");

+        }

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// Process an IA32 assembly file.

+//

+// Look for:

+// FIND_FD_GUID_VAL equ  01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h

+// PEI_GUID_FileNameGuid_Gmch815  equ  081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h

+//

+static

+STATUS

+ProcessIA32FileGuids (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN];

+  INT8    *Cptr;

+  INT8    CSave;

+  INT8    *CSavePtr;

+  UINT32  Len;

+  UINT32  GuidData[16];

+  UINT32  Index;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read lines from the file until done

+  //

+  while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+    Cptr = Line;

+    Cptr += SkipWhiteSpace (Line);

+    //

+    // Look for xxxGUIDyyy equ 01h, 02h, 03h, ...

+    //

+    Len = ValidSymbolName (Cptr);

+    if (Len) {

+      //

+      // Terminate the line after the symbol name, then look for "guid" in

+      // the name.

+      //

+      CSavePtr  = Cptr + Len;

+      CSave     = *CSavePtr;

+      *CSavePtr = 0;

+      while (*Cptr) {

+        if (strnicmp (Cptr, "guid", 4) == 0) {

+          break;

+        }

+

+        Cptr++;

+      }

+      //

+      // If we found the string "guid", continue

+      //

+      if (*Cptr) {

+        //

+        // Restore the character on the line where we null-terminated the symbol

+        //

+        *CSavePtr = CSave;

+        Cptr      = CSavePtr;

+        Len       = SkipWhiteSpace (Cptr);

+        //

+        // Had to be some white space

+        //

+        if (Len) {

+          Cptr += Len;

+          //

+          // now look for "equ"

+          //

+          if (strnicmp (Cptr, "equ", 3) == 0) {

+            Cptr += 3;

+            Cptr += SkipWhiteSpace (Cptr);

+            //

+            // Now scan all the data

+            //

+            for (Index = 0; Index < 16; Index++) {

+              if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) {

+                break;

+              }

+              //

+              // Skip to next

+              //

+              while (isxdigit (*Cptr)) {

+                Cptr++;

+              }

+

+              if ((*Cptr != 'h') && (*Cptr != 'H')) {

+                break;

+              } else {

+                Cptr++;

+                while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) {

+                  Cptr++;

+                }

+              }

+            }

+            //

+            // Now see which form we had

+            //

+            if (Index == 16) {

+              AddGuid16 (FileName, GuidData);

+            } else if (Index == 11) {

+              AddGuid11 (FileName, GuidData, NULL);

+            }

+          }

+        }

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list

+// of guids.

+//

+static

+STATUS

+AddGuid16 (

+  INT8      *FileName,

+  UINT32    *Data

+  )

+{

+  GUID_RECORD *NewRec;

+  int         Index;

+

+  //

+  // Sanity check the data

+  //

+  if (!CheckGuidData (Data, 16)) {

+    return STATUS_ERROR;

+  }

+  //

+  // Allocate memory for a new guid structure

+  //

+  NewRec = malloc (sizeof (GUID_RECORD));

+  if (NewRec == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) NewRec, 0, sizeof (GUID_RECORD));

+  NewRec->FileName = malloc (strlen (FileName) + 1);

+  if (NewRec->FileName == NULL) {

+    free (NewRec);

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  strcpy (NewRec->FileName, FileName);

+  NewRec->Guid.Data1  = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24));

+  NewRec->Guid.Data2  = (UINT16) (Data[4] | (Data[5] << 8));

+  NewRec->Guid.Data3  = (UINT16) (Data[6] | (Data[7] << 8));

+  for (Index = 0; Index < 8; Index++) {

+    NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8];

+  }

+  //

+  // Add it to the list

+  //

+  NewRec->Next  = gGuidList;

+  gGuidList     = NewRec;

+

+  //

+  // Report it

+  // ReportGuid (FileName, NewRec);

+  //

+  return STATUS_SUCCESS;

+}

+//

+// Add a GUID defined as GuidLow: 0x1122334455667788

+//                       GuidHi:  0x99AABBCCDDEEFF00

+//

+// These are equivalent:

+// { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }

+//    and:

+// Low: 00FFEEDDCCBBAA99

+// Hi:  7788556611223344

+//

+static

+STATUS

+AddGuid64x2 (

+  INT8      *FileName,

+  UINT32    DataHH, // Upper 32-bits of upper 64 bits of guid

+  UINT32    DataHL, // Lower 32-bits of upper 64 bits

+  UINT32    DataLH,

+  UINT32    DataLL

+  )

+{

+  GUID_RECORD *NewRec;

+  int         Index;

+

+  //

+  // Allocate memory for a new guid structure

+  //

+  NewRec = malloc (sizeof (GUID_RECORD));

+  if (NewRec == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) NewRec, 0, sizeof (GUID_RECORD));

+  NewRec->FileName = malloc (strlen (FileName) + 1);

+  if (NewRec->FileName == NULL) {

+    free (NewRec);

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  strcpy (NewRec->FileName, FileName);

+  NewRec->Guid.Data1  = DataHL;

+  NewRec->Guid.Data2  = (UINT16) DataHH;

+  NewRec->Guid.Data3  = (UINT16) (DataHH >> 16);

+  for (Index = 0; Index < 4; Index++) {

+    NewRec->Guid.Data4[Index] = (UINT8) DataLL;

+    DataLL >>= 8;

+  }

+

+  for (Index = 0; Index < 4; Index++) {

+    NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH;

+    DataLH >>= 8;

+  }

+  //

+  // Add it to the list

+  //

+  NewRec->Next  = gGuidList;

+  gGuidList     = NewRec;

+

+  //

+  // Report it

+  // ReportGuid (FileName, NewRec);

+  //

+  return STATUS_SUCCESS;

+}

+//

+// Process INF files. Look for:

+// FILE_GUID            = 240612B6-A063-11d4-9A3A-0090273FC14D

+//

+static

+STATUS

+ProcessINFFileGuids (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN * 2];

+  INT8    *Cptr;

+  INT8    *Cptr2;

+  UINT32  GuidScan[11];

+  UINT64  Guid64;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read lines from the file until done

+  //

+  while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+    Cptr = Line;

+    Cptr += SkipWhiteSpace (Line);

+    if (strncmp (Cptr, "FILE_GUID", 9) == 0) {

+      Cptr += 9;

+      Cptr += SkipWhiteSpace (Cptr);

+      if (*Cptr == '=') {

+        Cptr++;

+        Cptr += SkipWhiteSpace (Cptr + 1);

+        //

+        // Blank out dashes on the line.

+        //

+        for (Cptr2 = Cptr; *Cptr2; Cptr2++) {

+          if (*Cptr2 == '-') {

+            *Cptr2 = ' ';

+          }

+        }

+

+        if (sscanf (

+              Cptr,

+              "%X %X %X %X %I64X",

+              &GuidScan[0],

+              &GuidScan[1],

+              &GuidScan[2],

+              &GuidScan[3],

+              &Guid64

+              ) == 5) {

+          AddPkgGuid (FileName, GuidScan, &Guid64);

+        } else {

+          DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");

+        }

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// Parse ('g','m','a','p','a','b','c','d')

+//

+static

+STATUS

+AddSignature (

+  INT8      *FileName,

+  INT8      *StrDef,

+  UINT32    SigSize

+  )

+{

+  SIGNATURE_RECORD  *NewRec;

+  INT8              *Cptr;

+  UINT32            Index;

+  BOOLEAN           Fail;

+

+  //

+  // Allocate memory for the new record

+  //

+  Fail    = FALSE;

+  NewRec  = malloc (sizeof (SIGNATURE_RECORD));

+  if (NewRec == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Allocate memory to save the file name

+  //

+  NewRec->FileName = malloc (strlen (FileName) + 1);

+  if (NewRec->FileName == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    free (NewRec);

+    return STATUS_ERROR;

+  }

+  //

+  // Fill in the fields

+  //

+  strcpy (NewRec->FileName, FileName);

+  NewRec->Signature.DataLen = (UINT8) SigSize;

+  //

+  // Skip to open parenthesis

+  //

+  Cptr = StrDef;

+  Cptr += SkipWhiteSpace (Cptr);

+  if (*Cptr != '(') {

+    Fail = TRUE;

+    goto Done;

+  }

+

+  Cptr++;

+  //

+  // Skip to first ' and start processing

+  //

+  while (*Cptr && (*Cptr != '\'')) {

+    Cptr++;

+  }

+

+  for (Index = 0; Index < SigSize; Index++) {

+    if (*Cptr == '\'') {

+      Cptr++;

+      NewRec->Signature.Data[Index] = (INT8) *Cptr;

+      //

+      // Skip to closing quote

+      //

+      Cptr++;

+      if (*Cptr != '\'') {

+        Fail = TRUE;

+        break;

+      }

+      //

+      // Skip over closing quote, go to next one

+      //

+      Cptr++;

+      while (*Cptr && (*Cptr != '\'')) {

+        Cptr++;

+      }

+    } else {

+      Fail = TRUE;

+      DebugMsg (NULL, 0, 0, StrDef, "failed to parse signature");

+      break;

+    }

+  }

+

+Done:

+  if (Fail) {

+    free (NewRec->FileName);

+    free (NewRec);

+    return STATUS_ERROR;

+  }

+

+  NewRec->Next    = gSignatureList;

+  gSignatureList  = NewRec;

+  return STATUS_SUCCESS;

+}

+//

+// Look for:

+// #define POOL_HEAD_SIGNATURE         EFI_SIGNATURE_16('p','h')

+// #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_32('g','m','a','p')

+// #define GCD_MEMORY_MAP_SIGNATURE    EFI_SIGNATURE_64('g','m','a','p','a','b','c','d')

+//

+static

+STATUS

+ProcessCFileSigs (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN * 2];

+  INT8    *Cptr;

+  UINT32  Len;

+  UINT32  LineLen;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read lines from the file until done

+  //

+  while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+    Cptr = Line;

+    Cptr += SkipWhiteSpace (Line);

+    //

+    // look for #define xxxGUIDxxx value

+    //

+    if (*Cptr == '#') {

+      Cptr++;

+      Cptr += SkipWhiteSpace (Cptr);

+      //

+      // Look for "define"

+      //

+      if (!strncmp (Cptr, "define", 6)) {

+        Cptr += 6;

+        //

+        // Better be whitespace

+        //

+        Len = SkipWhiteSpace (Cptr);

+        if (Len) {

+          Cptr += Len;

+          //

+          // See if it's a valid symbol name

+          //

+          Len = ValidSymbolName (Cptr);

+          if (Len) {

+            //

+            // It is a valid symbol name. See if there's a line continuation,

+            // and if so, read one more line.

+            // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"

+            //

+            LineLen = strlen (Line);

+            if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {

+              fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);

+            } else if (Line[LineLen - 1] == '\\') {

+              fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);

+            }

+

+            Cptr += Len;

+            Cptr += SkipWhiteSpace (Cptr);

+            if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) {

+              AddSignature (FileName, Cptr + 16, 2);

+            } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) {

+              AddSignature (FileName, Cptr + 16, 4);

+            } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) {

+              AddSignature (FileName, Cptr + 16, 8);

+            }

+          }

+        }

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// look for #define xxxGUIDyyy { 0x...}

+// xxx EFI_GUID  GuidName = { 0x... };

+//

+static

+STATUS

+ProcessCFileGuids (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN * 2];

+  INT8    *Cptr;

+  INT8    CSave;

+  INT8    *CSavePtr;

+  INT8    *TempCptr;

+  INT8    *SymName;

+  UINT32  Len;

+  UINT32  LineLen;

+  UINT32  GuidScan[11];

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read lines from the file until done

+  //

+  while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+    Cptr = Line;

+    Cptr += SkipWhiteSpace (Line);

+    //

+    // look for #define xxxGUIDxxx value

+    //

+    if (*Cptr == '#') {

+      Cptr++;

+      Cptr += SkipWhiteSpace (Cptr);

+      //

+      // Look for "define"

+      //

+      if (!strncmp (Cptr, "define", 6)) {

+        Cptr += 6;

+        //

+        // Better be whitespace

+        //

+        Len = SkipWhiteSpace (Cptr);

+        if (Len) {

+          Cptr += Len;

+          //

+          // See if it's a valid symbol name

+          //

+          Len = ValidSymbolName (Cptr);

+          if (Len) {

+            //

+            // It is a valid symbol name. See if there's a line continuation,

+            // and if so, read one more line.

+            // Then truncate after the symbol name, look for the string "GUID",

+            // and continue.

+            //

+            SymName = Cptr;

+            LineLen = strlen (Line);

+            if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {

+              fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);

+            } else if (Line[LineLen - 1] == '\\') {

+              fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);

+            }

+

+            CSavePtr  = Cptr + Len;

+            CSave     = *CSavePtr;

+            *CSavePtr = 0;

+            while (*Cptr) {

+              if (strncmp (Cptr, "GUID", 4) == 0) {

+                break;

+              }

+

+              Cptr++;

+            }

+            //

+            // If we didn't run out of string, then we found the GUID string.

+            // Now look for { 0x....... }

+            //

+            if (*Cptr) {

+              Cptr      = CSavePtr;

+              *CSavePtr = CSave;

+              Cptr += SkipWhiteSpace (Cptr);

+              if (*Cptr == '{') {

+                *Cptr = 0;

+                Cptr++;

+                //

+                // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }

+                // If you have one suffixed with "L", then it doesn't work. So hack off 'L' characters

+                // in the string.

+                //

+                for (TempCptr = Cptr; *TempCptr; TempCptr++) {

+                  if (*TempCptr == 'L') {

+                    if (*(TempCptr + 1) == ',') {

+                      *TempCptr       = ',';

+                      *(TempCptr + 1) = ' ';

+                    }

+                  }

+                }

+

+                if (sscanf (

+                      Cptr,

+                      "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",

+                      &GuidScan[0],

+                      &GuidScan[1],

+                      &GuidScan[2],

+                      &GuidScan[3],

+                      &GuidScan[4],

+                      &GuidScan[5],

+                      &GuidScan[6],

+                      &GuidScan[7],

+                      &GuidScan[8],

+                      &GuidScan[9],

+                      &GuidScan[10]

+                      ) == 11) {

+                  AddGuid11 (FileName, GuidScan, SymName);

+                }

+              }

+            }

+          }

+        }

+      }

+      //

+      // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };

+      //

+    } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {

+      //

+      // Read the next line if line continuation

+      //

+      LineLen = strlen (Line);

+      if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {

+        fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);

+      } else if (Line[LineLen - 1] == '\\') {

+        fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);

+      }

+

+      Cptr = CSavePtr + 8;

+      Cptr += SkipWhiteSpace (Cptr);

+      //

+      // Should be variable name next

+      //

+      Len     = ValidSymbolName (Cptr);

+      SymName = Cptr;

+      Cptr += Len;

+      Cptr += SkipWhiteSpace (Cptr);

+      if (*Cptr == '=') {

+        Cptr++;

+        Cptr += SkipWhiteSpace (Cptr);

+        //

+        // Should be open-brace next to define guid

+        //

+        if (*Cptr == '{') {

+          Cptr++;

+          //

+          // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }

+          //

+          if (sscanf (

+                Cptr,

+                "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",

+                &GuidScan[0],

+                &GuidScan[1],

+                &GuidScan[2],

+                &GuidScan[3],

+                &GuidScan[4],

+                &GuidScan[5],

+                &GuidScan[6],

+                &GuidScan[7],

+                &GuidScan[8],

+                &GuidScan[9],

+                &GuidScan[10]

+                ) == 11) {

+            AddGuid11 (FileName, GuidScan, Cptr);

+            //

+            // printf ("Found guid: %s", Cptr);

+            //

+          }

+        }

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// Process Intel Itanium(TM) GUID definitions. Look for:

+// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA

+// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0

+// in either order.

+// This function assumes no blank lines between definitions.

+//

+static

+STATUS

+ProcessIA64FileGuids (

+  INT8    *FileName

+  )

+{

+  FILE    *Fptr;

+  INT8    Line[MAX_LINE_LEN];

+  UINT32  Guid1H;

+  UINT32  Guid1L;

+  UINT32  Guid2H;

+  UINT32  Guid2L;

+  INT8    SymName1[MAX_LINE_LEN];

+  INT8    SymName2[MAX_LINE_LEN];

+  BOOLEAN Done;

+  BOOLEAN LowFirst;

+  BOOLEAN FoundLow;

+

+  if ((Fptr = fopen (FileName, "r")) == NULL) {

+    Error (NULL, 0, 0, FileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+

+  Done = FALSE;

+  if (fgets (Line, sizeof (Line), Fptr) == NULL) {

+    Done = 1;

+  }

+  //

+  // Read lines from the file until done. Since the guid definition takes

+  // two lines, we read lines in different places to recover gracefully

+  // from mismatches. For example, if you thought you found the first half,

+  // but the next line had a symbol mismatch, then you have to process the

+  // line again in case it's the start of a new definition.

+  //

+  while (!Done) {

+    //

+    // Check current line for GUID definition. Assume low define first.

+    //

+    if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) {

+      //

+      // Might have to swap guids later. Save off if we found the LOW first

+      //

+      if (FoundLow) {

+        LowFirst = TRUE;

+      } else {

+        LowFirst = FALSE;

+      }

+      //

+      // Read the next line and try for the rest of the guid definition

+      //

+      if (fgets (Line, sizeof (Line), Fptr) == NULL) {

+        Done = 1;

+      } else {

+        if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) {

+          //

+          // Found another. If the symbol names match, then save it off.

+          //

+          if (strcmp (SymName1, SymName2) == 0) {

+            //

+            // Yea, found one. Save it off.

+            //

+            if (LowFirst) {

+              AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L);

+            } else {

+              AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L);

+            }

+            //

+            // Read the next line for processing

+            //

+            if (fgets (Line, sizeof (Line), Fptr) == NULL) {

+              Done = 1;

+            }

+          } else {

+            //

+            // Don't get another line so that we reprocess this line in case it

+            // contains the start of a new definition.

+            // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n",

+            //    FileName, SymName1, SymName2);

+            //

+          }

+        } else {

+          //

+          // Second line was not a guid definition. Get the next line from the

+          // file.

+          //

+          if (fgets (Line, sizeof (Line), Fptr) == NULL) {

+            Done = 1;

+          }

+        }

+      }

+    } else {

+      //

+      // Not a guid define line. Next.

+      //

+      if (fgets (Line, sizeof (Line), Fptr) == NULL) {

+        Done = 1;

+      }

+    }

+  }

+

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+//

+// Given a line from an Itanium-based assembly file, check the line for a guid

+// defininition. One of either:

+// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA

+// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0

+// Return the defined value as two 32-bit values, and whether it's a high

+// or low guid.

+//

+static

+BOOLEAN

+IsIA64GuidLine (

+  INT8      *Line,

+  UINT32    *GuidHigh,

+  UINT32    *GuidLow,

+  BOOLEAN   *FoundLow,

+  INT8      *SymName

+  )

+{

+  INT8    *Cptr;

+  INT8    CSave;

+  INT8    *CSavePtr;

+  INT8    *SymStart;

+  UINT32  Len;

+

+  Cptr = Line;

+  Cptr += SkipWhiteSpace (Cptr);

+  //

+  // look for #define xxxGUID[L|H] 0xHexValue

+  //

+  if (*Cptr == '#') {

+    Cptr++;

+    Cptr += SkipWhiteSpace (Cptr);

+    //

+    // Look for "define"

+    //

+    if (!strncmp (Cptr, "define", 6)) {

+      Cptr += 6;

+      //

+      // Better be whitespace

+      //

+      Len = SkipWhiteSpace (Cptr);

+      if (Len) {

+        Cptr += Len;

+        //

+        // See if it's a valid symbol name

+        //

+        Len = ValidSymbolName (Cptr);

+        if (Len) {

+          //

+          // Save the start so we can copy it to their string if later checks are ok

+          //

+          SymStart = Cptr;

+          //

+          // It is a valid symbol name, look for the string GuidL or GuidH

+          //

+          CSavePtr  = Cptr + Len;

+          CSave     = *CSavePtr;

+          *CSavePtr = 0;

+          while (*Cptr) {

+            if (strncmp (Cptr, "GuidL", 5) == 0) {

+              *FoundLow = 1;

+              break;

+            } else if (strncmp (Cptr, "GuidH", 5) == 0) {

+              *FoundLow = 0;

+              break;

+            }

+

+            Cptr++;

+          }

+          //

+          // If we didn't run out of string, then we found the GUID string.

+          // Restore the null character we inserted above and continue.

+          // Now look for  0x.......

+          //

+          if (*Cptr) {

+            //

+            // Return symbol name less the "L" or "H"

+            //

+            strcpy (SymName, SymStart);

+            SymName[strlen (SymName) - 1] = 0;

+            Cptr                          = CSavePtr;

+            *CSavePtr                     = CSave;

+            Cptr += SkipWhiteSpace (Cptr);

+            if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) {

+              //

+              // skip over "0x"

+              //

+              Cptr += 2;

+              //

+              // 0x0123456789ABCDEF -- null terminate after 8 characters,

+              // scan, replace the character and scan at that point.

+              //

+              CSave       = *(Cptr + 8);

+              *(Cptr + 8) = 0;

+              if (sscanf (Cptr, "%X", GuidHigh) == 1) {

+                *(Cptr + 8) = CSave;

+                if (sscanf (Cptr + 8, "%X", GuidLow) == 1) {

+                  return TRUE;

+                }

+              }

+            }

+          }

+        }

+      }

+    }

+  }

+

+  return FALSE;

+}

+//

+// Look at the characters in the string and determine if it's a valid

+// symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]*

+//

+static

+UINT32

+ValidSymbolName (

+  INT8    *Name

+  )

+{

+  int Len;

+

+  Len = 0;

+

+  //

+  // Test first character

+  //

+  if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) {

+    Name++;

+    Len = 1;

+    while (*Name) {

+      if (((*Name >= 'a') && (*Name <= 'z')) ||

+          ((*Name >= 'A') && (*Name <= 'Z')) ||

+          ((*Name >= '0') && (*Name <= '9')) ||

+          (*Name == '_')

+          ) {

+        Name++;

+        Len++;

+      } else {

+        break;

+      }

+    }

+  }

+

+  return Len;

+}

+

+static

+UINT32

+SkipWhiteSpace (

+  INT8    *Str

+  )

+{

+  UINT32  Len;

+  Len = 0;

+  while (isspace (*Str) && *Str) {

+    Len++;

+    Str++;

+  }

+

+  return Len;

+}

+//

+// found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7

+//

+static

+STATUS

+AddPkgGuid (

+  INT8      *FileName,

+  UINT32    *Data,

+  UINT64    *Data64

+  )

+{

+  GUID_RECORD *NewRec;

+  int         Index;

+

+  //

+  // Sanity check the data

+  //

+  if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) {

+    Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // More checks for Data64?

+  // Allocate memory for a new one guid structure

+  //

+  NewRec = malloc (sizeof (GUID_RECORD));

+  if (NewRec == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) NewRec, 0, sizeof (GUID_RECORD));

+  NewRec->FileName = malloc (strlen (FileName) + 1);

+  if (NewRec->FileName == NULL) {

+    free (NewRec);

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  strcpy (NewRec->FileName, FileName);

+  NewRec->Guid.Data1    = Data[0];

+  NewRec->Guid.Data2    = (UINT16) Data[1];

+  NewRec->Guid.Data3    = (UINT16) Data[2];

+  NewRec->Guid.Data4[0] = (UINT8) Data[3];

+  NewRec->Guid.Data4[1] = (UINT8) (Data[3] >> 8);

+  for (Index = 2; Index < 8; Index++) {

+    NewRec->Guid.Data4[Index] = (UINT8) *Data64;

+    *Data64 >>= 8;

+  }

+  //

+  // Add it to the list

+  //

+  NewRec->Next  = gGuidList;

+  gGuidList     = NewRec;

+

+  //

+  // Report it

+  // ReportGuid (FileName, NewRec);

+  //

+  return STATUS_SUCCESS;

+}

+//

+// Add a guid consisting of 11 fields to our list of guids

+//

+static

+STATUS

+AddGuid11 (

+  INT8      *FileName,

+  UINT32    *Data,

+  INT8      *SymName

+  )

+{

+  GUID_RECORD *NewRec;

+  int         Index;

+

+  //

+  // Sanity check the data

+  //

+  if (!CheckGuidData (Data, 11)) {

+    return STATUS_ERROR;

+  }

+  //

+  // Allocate memory for a new one guid structure

+  //

+  NewRec = malloc (sizeof (GUID_RECORD));

+  if (NewRec == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) NewRec, 0, sizeof (GUID_RECORD));

+  NewRec->FileName = malloc (strlen (FileName) + 1);

+  if (NewRec->FileName == NULL) {

+    free (NewRec);

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  strcpy (NewRec->FileName, FileName);

+  if (SymName != NULL) {

+    NewRec->SymName = malloc (strlen (SymName) + 1);

+    if (NewRec->SymName == NULL) {

+      free (NewRec);

+      Error (NULL, 0, 0, "memory allocation failure", NULL);

+      return STATUS_ERROR;

+    }

+  }

+

+  strcpy (NewRec->SymName, SymName);

+

+  NewRec->Guid.Data1  = Data[0];

+  NewRec->Guid.Data2  = (UINT16) Data[1];

+  NewRec->Guid.Data3  = (UINT16) Data[2];

+  for (Index = 0; Index < 8; Index++) {

+    NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index];

+  }

+  //

+  // Add it to the list

+  //

+  NewRec->Next  = gGuidList;

+  gGuidList     = NewRec;

+

+  //

+  // Report it

+  // ReportGuid (FileName, NewRec);

+  //

+  return STATUS_SUCCESS;

+}

+//

+// For debug purposes, print each guid found

+//

+// static

+// VOID

+// ReportGuid (

+//  INT8        *FileName,

+// GUID_RECORD *NewGuid

+//  )

+// {

+//  //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1);

+// }

+//

+// Free up memory we allocated to keep track of guids defined.

+//

+static

+VOID

+FreeGuids (

+  VOID

+  )

+{

+  GUID_RECORD *NextRec;

+  while (gGuidList != NULL) {

+    NextRec = gGuidList->Next;

+    if (gGuidList->FileName != NULL) {

+      free (gGuidList->FileName);

+    }

+

+    if (gGuidList->SymName != NULL) {

+      free (gGuidList->SymName);

+    }

+

+    free (gGuidList);

+    gGuidList = NextRec;

+  }

+}

+

+static

+VOID

+FreeSigs (

+  VOID

+  )

+{

+  SIGNATURE_RECORD  *NextRec;

+  while (gSignatureList != NULL) {

+    NextRec = gSignatureList->Next;

+    if (gSignatureList->FileName != NULL) {

+      free (gSignatureList->FileName);

+    }

+

+    free (gSignatureList);

+    gSignatureList = NextRec;

+  }

+}

+//

+// Scan through all guids defined and compare each for duplicates.

+//

+static

+STATUS

+CheckDuplicates (

+  VOID

+  )

+{

+  GUID_RECORD       *CurrentFile;

+

+  GUID_RECORD       *TempFile;

+  SIGNATURE_RECORD  *CurrentSig;

+  SIGNATURE_RECORD  *TempSig;

+  STATUS            Status;

+  int               Index;

+  int               DupCount;

+  int               Len;

+  BOOLEAN           Same;

+  UINT32            GuidSum;

+  INT8              *SymName;

+

+  Status = STATUS_SUCCESS;

+

+  //

+  // If we're checking guids.....

+  //

+  if (gOptions.CheckGuids) {

+    //

+    // If -p option, print all guids found

+    //

+    if (gOptions.PrintFound) {

+      CurrentFile = gGuidList;

+      while (CurrentFile != NULL) {

+        fprintf (

+          stdout,

+          "GUID:  0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n",

+          (UINT32) CurrentFile->Guid.Data1,

+          (UINT32) CurrentFile->Guid.Data2,

+          (UINT32) CurrentFile->Guid.Data3,

+          (UINT32) CurrentFile->Guid.Data4[0],

+          (UINT32) CurrentFile->Guid.Data4[1],

+          (UINT32) CurrentFile->Guid.Data4[2],

+          (UINT32) CurrentFile->Guid.Data4[3],

+          (UINT32) CurrentFile->Guid.Data4[4],

+          (UINT32) CurrentFile->Guid.Data4[5],

+          (UINT32) CurrentFile->Guid.Data4[6],

+          (UINT32) CurrentFile->Guid.Data4[7],

+          CurrentFile->FileName

+          );

+        CurrentFile = CurrentFile->Next;

+      }

+    }

+

+    if (gOptions.GuidXReference) {

+      CurrentFile = gGuidList;

+      while (CurrentFile != NULL) {

+        //

+        // If no symbol name, print "unknown"

+        //

+        SymName = CurrentFile->SymName;

+        if (SymName == NULL) {

+          SymName = "unknown";

+        }

+

+        fprintf (

+          stdout,

+          "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n",

+          (UINT32) CurrentFile->Guid.Data1,

+          (UINT32) CurrentFile->Guid.Data2,

+          (UINT32) CurrentFile->Guid.Data3,

+          (UINT32) CurrentFile->Guid.Data4[0],

+          (UINT32) CurrentFile->Guid.Data4[1],

+          (UINT32) CurrentFile->Guid.Data4[2],

+          (UINT32) CurrentFile->Guid.Data4[3],

+          (UINT32) CurrentFile->Guid.Data4[4],

+          (UINT32) CurrentFile->Guid.Data4[5],

+          (UINT32) CurrentFile->Guid.Data4[6],

+          (UINT32) CurrentFile->Guid.Data4[7],

+          SymName

+          );

+        CurrentFile = CurrentFile->Next;

+      }

+    }

+    //

+    // Now go through all guids and report duplicates.

+    //

+    CurrentFile = gGuidList;

+    while (CurrentFile != NULL) {

+      DupCount  = 0;

+      TempFile  = CurrentFile->Next;

+      while (TempFile) {

+        //

+        // Compare the guids

+        //

+        if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) &&

+            (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) &&

+            (CurrentFile->Guid.Data3 == TempFile->Guid.Data3)

+            ) {

+          //

+          // OR in all the guid bytes so we can ignore NULL-guid definitions.

+          //

+          GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3;

+          Same    = TRUE;

+          for (Index = 0; Index < 8; Index++) {

+            GuidSum |= CurrentFile->Guid.Data4[Index];

+            if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) {

+              Same = FALSE;

+              break;

+            }

+          }

+          //

+          // If they're the same, and the guid was non-zero, print a message.

+          //

+          if (Same && GuidSum) {

+            if (DupCount == 0) {

+              Error (NULL, 0, 0, "duplicate GUIDS found", NULL);

+              fprintf (stdout, "   FILE1: %s\n", CurrentFile->FileName);

+            }

+

+            DupCount++;

+            fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempFile->FileName);

+            //

+            // Flag it as reported so we don't report it again if there's three or more

+            //

+            TempFile->Reported = TRUE;

+          }

+        }

+        //

+        // Next one

+        //

+        TempFile = TempFile->Next;

+      }

+      //

+      // Print the guid if we found duplicates

+      //

+      if (DupCount) {

+        fprintf (

+          stdout,

+          "   GUID:  0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",

+          (UINT32) CurrentFile->Guid.Data1,

+          (UINT32) CurrentFile->Guid.Data2,

+          (UINT32) CurrentFile->Guid.Data3,

+          (UINT32) CurrentFile->Guid.Data4[0],

+          (UINT32) CurrentFile->Guid.Data4[1],

+          (UINT32) CurrentFile->Guid.Data4[2],

+          (UINT32) CurrentFile->Guid.Data4[3],

+          (UINT32) CurrentFile->Guid.Data4[4],

+          (UINT32) CurrentFile->Guid.Data4[5],

+          (UINT32) CurrentFile->Guid.Data4[6],

+          (UINT32) CurrentFile->Guid.Data4[7]

+          );

+        //

+        // return STATUS_ERROR;

+        //

+      }

+      //

+      // Find the next one that hasn't been reported

+      //

+      do {

+        CurrentFile = CurrentFile->Next;

+      } while ((CurrentFile != NULL) && (CurrentFile->Reported));

+    }

+  }

+

+  if (gOptions.CheckSignatures) {

+    //

+    // Print ones found if specified

+    //

+    if (gOptions.PrintFound) {

+      CurrentSig = gSignatureList;

+      while (CurrentSig != NULL) {

+        Len = CurrentSig->Signature.DataLen;

+        for (Index = 0; Index < Len; Index++) {

+          fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);

+        }

+

+        fprintf (stdout, "  %s\n", CurrentSig->FileName);

+        CurrentSig = CurrentSig->Next;

+      }

+    }

+

+    CurrentSig = gSignatureList;

+    while (CurrentSig != NULL) {

+      DupCount  = 0;

+      TempSig   = CurrentSig->Next;

+      Len       = CurrentSig->Signature.DataLen;

+      while (TempSig) {

+        //

+        // Check for same length, then do string compare

+        //

+        if (Len == TempSig->Signature.DataLen) {

+          if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) {

+            //

+            // Print header message if first failure for this sig

+            //

+            if (DupCount == 0) {

+              Error (NULL, 0, 0, "duplicate signatures found", NULL);

+              fprintf (stdout, "   FILE1: %s\n", CurrentSig->FileName);

+            }

+

+            DupCount++;

+            fprintf (stdout, "   FILE%d: %s\n", DupCount + 1, TempSig->FileName);

+            TempSig->Reported = TRUE;

+          }

+        }

+

+        TempSig = TempSig->Next;

+      }

+

+      if (DupCount) {

+        fprintf (stdout, "   SIG:   ");

+        for (Index = 0; Index < Len; Index++) {

+          fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);

+        }

+

+        fprintf (stdout, "\n");

+      }

+      //

+      // On to the next one that hasn't been reported

+      //

+      do {

+        CurrentSig = CurrentSig->Next;

+      } while ((CurrentSig != NULL) && (CurrentSig->Reported));

+    }

+  }

+

+  return Status;

+}

+

+static

+VOID

+FreeOptions (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Free up any memory we allocated when processing command-line options.

+

+Arguments:

+  None.

+

+Returns:

+  NA

+

+Notes:

+  We don't free up the ->Str fields because we did not allocate them.

+  Instead, we just set the pointer to point to the actual parameter

+  from the command line.

+

+--*/

+{

+  STRING_LIST *Ptr;

+  while (gOptions.ExcludeDirs != NULL) {

+    Ptr = gOptions.ExcludeDirs->Next;

+    //

+    // free (gOptions.ExcludeDirs->Str);

+    //

+    free (gOptions.ExcludeDirs);

+    gOptions.ExcludeDirs = Ptr;

+  }

+

+  while (gOptions.ExcludeSubDirs != NULL) {

+    Ptr = gOptions.ExcludeSubDirs->Next;

+    //

+    // free (gOptions.ExcludeSubDirs->Str);

+    //

+    free (gOptions.ExcludeSubDirs);

+    gOptions.ExcludeSubDirs = Ptr;

+  }

+

+  while (gOptions.ExcludeExtensions != NULL) {

+    Ptr = gOptions.ExcludeExtensions->Next;

+    //

+    // free (gOptions.ExcludeExtensions->Str);

+    //

+    free (gOptions.ExcludeExtensions);

+    gOptions.ExcludeExtensions = Ptr;

+  }

+

+  while (gOptions.ExcludeFiles != NULL) {

+    Ptr = gOptions.ExcludeFiles->Next;

+    //

+    // free (gOptions.ExcludeFiles->Str);

+    //

+    free (gOptions.ExcludeFiles);

+    gOptions.ExcludeFiles = Ptr;

+  }

+}

+//

+// Given an array of 32-bit data, validate the data for the given number of

+// guid data. For example, it might have been scanned as 16 bytes of data, or

+// 11 fields of data.

+//

+static

+BOOLEAN

+CheckGuidData (

+  UINT32    *Data,

+  UINT32    DataCount

+  )

+{

+  UINT32  Index;

+

+  if (DataCount == 16) {

+    for (Index = 0; Index < 16; Index++) {

+      if (Data[Index] &~0xFF) {

+        return FALSE;

+      }

+    }

+

+    return TRUE;

+  } else if (DataCount == 11) {

+    //

+    // Data[0] never out of range (32-bit)

+    //

+    if ((Data[1] | Data[2]) &~0xFFFF) {

+      //

+      // Error ("Out of range value for GUID data word(s) [1] and/or [2]");

+      //

+      return FALSE;

+    }

+

+    for (Index = 0; Index < 8; Index++) {

+      if (Data[Index + 3] &~0xFF) {

+        //

+        // Error ("Out of range value for GUID data byte(s) [4] - [11]");

+        //

+        return FALSE;

+      }

+    }

+

+    return TRUE;

+  }

+

+  return FALSE;

+}

diff --git a/Source/GuidChk/GuidList.c b/Source/GuidChk/GuidList.c
new file mode 100644
index 0000000..bb6a44d
--- /dev/null
+++ b/Source/GuidChk/GuidList.c
@@ -0,0 +1,186 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  GuidList.c  

+

+Abstract:

+

+  Utility to create a GUID-to-name listing file that can

+  be used by other utilities. Basic operation is to take the

+  table of name+GUIDs that we have compiled into this utility,

+  and create a text file that can be parsed by other utilities

+  to do replacement of "name" with "GUID".

+

+Notes:

+  To add a new GUID to this database:

+    1. Add a "#include EFI_GUID_DEFINITION(name)" statement below

+    2. Modify the mGuidList[] array below to add the new GUID name

+

+  The only issue that may come up is that, if the source GUID file

+  is not in the standard GUID directory, then this utility won't

+  compile because the #include fails. In this case you'd need

+  to define a new macro (if it's in a standard place) or modify

+  this utility's makefile to add the path to your new .h file.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Guid/Apriori.h>

+#include <Guid/AcpiTableStorage.h>

+

+#include "EfiUtilityMsgs.h"

+

+

+#define GUID_XREF(varname, guid) { \

+    #varname, #guid, guid \

+  }

+

+#define NULL_GUID \

+  { \

+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 \

+  }

+

+typedef struct {

+  INT8      *VariableName;

+  INT8      *DefineName;

+  EFI_GUID  Guid;

+} GUID_LIST;

+

+//

+// This is our table of all GUIDs we want to print out to create

+// a GUID-to-name cross reference.

+// Use the #defined name from the GUID definition's source .h file.

+//

+static GUID_LIST  mGuidList[] = {

+  GUID_XREF(gAprioriGuid, EFI_APRIORI_GUID),

+  GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID),

+  // FIXME The next line was removed in the port to R9.

+  // GUID_XREF(gEfiDefaultBmpLogoGuid, EFI_DEFAULT_BMP_LOGO_GUID),

+  GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID),

+  //

+  // Terminator

+  //

+  {

+    NULL,

+    NULL,

+    NULL_GUID

+  }

+};

+

+void

+PrintGuidText (

+  FILE      *OutFptr,

+  INT8      *VariableName,

+  INT8      *DefineName,

+  EFI_GUID  *Guid

+  );

+

+int

+CreateGuidList (

+  INT8    *OutFileName

+  )

+/*++

+

+Routine Description:

+  Print our GUID/name list to the specified output file.

+  

+Arguments:

+  OutFileName  - name of the output file to write our results to.

+

+Returns:

+  0       if successful

+  nonzero otherwise

+  

+--*/

+{

+  FILE  *OutFptr;

+  int   Index;

+

+  //

+  // Open output file for writing. If the name is NULL, then write to stdout

+  //

+  if (OutFileName != NULL) {

+    OutFptr = fopen (OutFileName, "w");

+    if (OutFptr == NULL) {

+      Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");

+      return STATUS_ERROR;

+    }

+  } else {

+    OutFptr = stdout;

+  }

+

+  for (Index = 0; mGuidList[Index].VariableName != NULL; Index++) {

+    PrintGuidText (OutFptr, mGuidList[Index].VariableName, mGuidList[Index].DefineName, &mGuidList[Index].Guid);

+  }

+  //

+  // Close the output file if they specified one.

+  //

+  if (OutFileName != NULL) {

+    fclose (OutFptr);

+  }

+

+  return STATUS_SUCCESS;

+}

+

+void

+PrintGuidText (

+  FILE      *OutFptr,

+  INT8      *VariableName,

+  INT8      *DefineName,

+  EFI_GUID  *Guid

+  )

+/*++

+

+Routine Description:

+  Print a GUID/name combo in INF-style format

+

+  guid-guid-guid-guid DEFINE_NAME gName

+

+Arguments:

+  OutFptr       - file pointer to which to write the output

+  VariableName  - the GUID variable's name

+  DefineName    - the name used in the #define

+  Guid          - pointer to the GUID value

+

+Returns:

+  NA

+

+--*/

+{

+  if (OutFptr == NULL) {

+    OutFptr = stdout;

+  }

+

+  fprintf (

+    OutFptr,

+    "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s %s\n",

+    Guid->Data1,

+    Guid->Data2,

+    Guid->Data3,

+    Guid->Data4[0],

+    Guid->Data4[1],

+    Guid->Data4[2],

+    Guid->Data4[3],

+    Guid->Data4[4],

+    Guid->Data4[5],

+    Guid->Data4[6],

+    Guid->Data4[7],

+    DefineName,

+    VariableName

+    );

+}

diff --git a/Source/GuidChk/UtilsMsgs.c b/Source/GuidChk/UtilsMsgs.c
new file mode 100644
index 0000000..8aa343f
--- /dev/null
+++ b/Source/GuidChk/UtilsMsgs.c
@@ -0,0 +1,490 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  UtilsMsgs.c

+  

+Abstract:

+

+  EFI tools utility functions to display warning, error, and informational

+  messages.

+  

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <ctype.h>

+#include <stdarg.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "EfiUtilityMsgs.h"

+

+#define MAX_LINE_LEN  200

+

+//

+// Declare module globals for keeping track of the the utility's

+// name and other settings.

+//

+static STATUS mStatus             = STATUS_SUCCESS;

+static INT8   mUtilityName[50]    = { 0 };

+static INT8   *mSourceFileName    = NULL;

+static UINT32 mSourceFileLineNum  = 0;

+static UINT32 mErrorCount         = 0;

+static UINT32 mWarningCount       = 0;

+static UINT32 mDebugMsgMask       = 0;

+

+static

+void

+PrintMessage (

+  INT8    *Type,

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  va_list List

+  );

+

+void

+Error (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Prints an error message.

+  

+Arguments:

+  All arguments are optional, though the printed message may be useless if

+  at least something valid is not specified.

+  

+  FileName - name of the file or application. If not specified, then the

+             utilty name (as set by the utility calling SetUtilityName()

+             earlier) is used. Otherwise "Unknown utility" is used.

+  

+  LineNumber - the line number of error, typically used by parsers. If the

+               utility is not a parser, then 0 should be specified. Otherwise

+               the FileName and LineNumber info can be used to cause

+               MS Visual Studio to jump to the error.

+               

+  MessageCode - an application-specific error code that can be referenced in

+              other documentation. 

+

+  Text        - the text in question, typically used by parsers.

+  

+  MsgFmt - the format string for the error message. Can contain formatting

+           controls for use with the varargs.

+           

+Returns:

+  None.

+  

+Notes:

+  We print the following (similar to the Warn() and Debug() 

+  W

+  Typical error/warning message format:

+

+  bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters

+

+  BUGBUG -- these three utility functions are almost identical, and

+  should be modified to share code.

+

+  Visual Studio does not find error messages with:

+  

+     " error :"

+     " error 1:"

+     " error c1:"

+     " error 1000:"

+     " error c100:"

+

+  It does find:

+     " error c1000:"     

+--*/

+{

+  va_list List;

+  mErrorCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_ERROR) {

+    mStatus = STATUS_ERROR;

+  }

+}

+

+void

+ParserError (

+  UINT32  MessageCode,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a parser error, using the source file name and line number

+  set by a previous call to SetParserPosition().

+

+Arguments:

+  MessageCode   - application-specific error code

+  Text          - text to print in the error message

+  MsgFmt        - format string to print at the end of the error message

+  ...

+

+Returns:

+  NA

+

+--*/

+{

+  va_list List;

+  mErrorCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_ERROR) {

+    mStatus = STATUS_ERROR;

+  }

+}

+

+void

+ParserWarning (

+  UINT32  ErrorCode,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a parser warning, using the source file name and line number

+  set by a previous call to SetParserPosition().

+

+Arguments:

+  ErrorCode     - application-specific error code

+  OffendingText - text to print in the warning message

+  MsgFmt        - format string to print at the end of the warning message

+  ...

+

+Returns:

+  NA

+

+--*/

+{

+  va_list List;

+  mWarningCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_WARNING) {

+    mStatus = STATUS_WARNING;

+  }

+}

+

+void

+Warning (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a warning message.

+

+Arguments:

+  FileName    - name of the file where the warning was detected, or the name

+                of the application that detected the warning

+  

+  LineNumber  - the line number where the warning was detected (parsers).

+                0 should be specified if the utility is not a parser.

+               

+  MessageCode - an application-specific warning code that can be referenced in

+                other documentation. 

+

+  Text        - the text in question (parsers)

+  

+  MsgFmt      - the format string for the warning message. Can contain formatting

+                controls for use with varargs.

+                

+  ...

+           

+Returns:

+  None.

+

+--*/

+{

+  va_list List;

+  mWarningCount++;

+  va_start (List, MsgFmt);

+  PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);

+  va_end (List);

+  //

+  // Set status accordingly

+  //

+  if (mStatus < STATUS_WARNING) {

+    mStatus = STATUS_WARNING;

+  }

+}

+

+void

+DebugMsg (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MsgMask,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  ...

+  )

+/*++

+

+Routine Description:

+  Print a warning message.

+

+Arguments:

+  FileName    - typically the name of the utility printing the debug message, but

+                can be the name of a file being parsed.

+  

+  LineNumber  - the line number in FileName (parsers) 

+               

+  MsgMask     - an application-specific bitmask that, in combination with mDebugMsgMask,

+                determines if the debug message gets printed.

+

+  Text        - the text in question (parsers)

+  

+  MsgFmt      - the format string for the debug message. Can contain formatting

+                controls for use with varargs.

+          

+  ... 

+Returns:

+  None.

+

+--*/

+{

+  va_list List;

+  //

+  // If the debug mask is not applicable, then do nothing.

+  //

+  if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {

+    return ;

+  }

+

+  va_start (List, MsgFmt);

+  PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);

+  va_end (List);

+}

+

+static

+void

+PrintMessage (

+  INT8    *Type,

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MessageCode,

+  INT8    *Text,

+  INT8    *MsgFmt,

+  va_list List

+  )

+/*++

+

+Routine Description:

+  Worker routine for all the utility printing services. Prints the message in

+  a format that Visual Studio will find when scanning build outputs for

+  errors or warnings.

+

+Arguments:

+  Type        - "warning" or "error" string to insert into the message to be

+                printed. The first character of this string (converted to uppercase)

+                is used to preceed the MessageCode value in the output string.

+

+  FileName    - name of the file where the warning was detected, or the name

+                of the application that detected the warning

+  

+  LineNumber  - the line number where the warning was detected (parsers).

+                0 should be specified if the utility is not a parser.

+               

+  MessageCode - an application-specific warning code that can be referenced in

+                other documentation. 

+

+  Text        - part of the message to print

+  

+  MsgFmt      - the format string for the message. Can contain formatting

+                controls for use with varargs.

+

+  List        - Variable function parameter list.           

+Returns:

+  None.

+

+Notes:

+  If FileName == NULL then this utility will use the string passed into SetUtilityName(). 

+  

+  LineNumber is only used if the caller is a parser, in which case FileName refers to the

+  file being parsed.

+

+  Text and MsgFmt are both optional, though it would be of little use calling this function with

+  them both NULL.

+

+  Output will typically be of the form:

+    <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>

+

+    Parser (LineNumber != 0)

+      VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters

+    Generic utility (LineNumber == 0) 

+      UtilityName : error E1234 : Text string : MsgFmt string and args

+

+--*/

+{

+  INT8  Line[MAX_LINE_LEN];

+  INT8  Line2[MAX_LINE_LEN];

+  INT8  *Cptr;

+  //

+  // If given a filename, then add it (and the line number) to the string.

+  // If there's no filename, then use the program name if provided.

+  //

+  if (FileName != NULL) {

+    Cptr = FileName;

+  } else if (mUtilityName[0] != 0) {

+    Cptr = mUtilityName;

+  } else {

+    Cptr = "Unknown utility";

+  }

+

+  strcpy (Line, Cptr);

+  if (LineNumber != 0) {

+    sprintf (Line2, "(%d)", LineNumber);

+    strcat (Line, Line2);

+  }

+  //

+  // Have to print an error code or Visual Studio won't find the

+  // message for you. It has to be decimal digits too.

+  //

+  sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);

+  strcat (Line, Line2);

+  fprintf (stdout, "%s", Line);

+  //

+  // If offending text was provided, then print it

+  //

+  if (Text != NULL) {

+    fprintf (stdout, ": %s ", Text);

+  }

+  //

+  // Print formatted message if provided

+  //

+  if (MsgFmt != NULL) {

+    vsprintf (Line2, MsgFmt, List);

+    fprintf (stdout, ": %s", Line2);

+  }

+

+  fprintf (stdout, "\n");

+}

+

+void

+ParserSetPosition (

+  INT8    *SourceFileName,

+  UINT32  LineNum

+  )

+/*++

+

+Routine Description:

+  Set the position in a file being parsed. This can be used to 

+  print error messages deeper down in a parser.

+

+Arguments:

+  SourceFileName - name of the source file being parsed

+  LineNum        - line number of the source file being parsed

+

+Returns:

+  NA

+

+--*/

+{

+  mSourceFileName     = SourceFileName;

+  mSourceFileLineNum  = LineNum;

+}

+

+void

+SetUtilityName (

+  INT8    *UtilityName

+  )

+/*++

+

+Routine Description:

+  All printed error/warning/debug messages follow the same format, and

+  typically will print a filename or utility name followed by the error

+  text. However if a filename is not passed to the print routines, then

+  they'll print the utility name if you call this function early in your

+  app to set the utility name.

+  

+Arguments:

+  UtilityName  -  name of the utility, which will be printed with all

+                  error/warning/debug messags.

+

+Returns:

+  NA

+  

+--*/

+{

+  //

+  // Save the name of the utility in our local variable. Make sure its

+  // length does not exceed our buffer.

+  //

+  if (UtilityName != NULL) {

+    if (strlen (UtilityName) >= sizeof (mUtilityName)) {

+      Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");

+      strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);

+      mUtilityName[sizeof (mUtilityName) - 1] = 0;

+      return ;

+    } else {

+      strcpy (mUtilityName, UtilityName);

+    }

+  } else {

+    Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");

+  }

+}

+

+STATUS

+GetUtilityStatus (

+  VOID

+  )

+/*++

+

+Routine Description:

+  When you call Error() or Warning(), this module keeps track of it and

+  sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility

+  exits, it can call this function to get the status and use it as a return

+  value.

+  

+Arguments:

+  None.

+

+Returns:

+  Worst-case status reported, as defined by which print function was called.

+  

+--*/

+{

+  return mStatus;

+}

diff --git a/Source/GuidChk/UtilsMsgs.h b/Source/GuidChk/UtilsMsgs.h
new file mode 100644
index 0000000..5f6c701
--- /dev/null
+++ b/Source/GuidChk/UtilsMsgs.h
@@ -0,0 +1,106 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:  

+

+  UtilsMsgs.h

+  

+Abstract:

+

+  Prototypes for the EFI tools utility functions.

+  

+--*/

+

+#ifndef _UTILS_MESSAGES_H_

+#define _UTILS_MESSAGES_H_

+

+STATUS

+GetUtilityStatus (

+  VOID

+  )

+;

+

+//

+// If someone prints an error message and didn't specify a source file name,

+// then we print the utility name instead. However they must tell us the

+// utility name early on via this function.

+//

+VOID

+SetUtilityName (

+  INT8 *ProgramName

+  )

+;

+

+void

+Error (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  ErrorCode,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+;

+

+void

+Warning (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  ErrorCode,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+;

+

+void

+DebugMsg (

+  INT8    *FileName,

+  UINT32  LineNumber,

+  UINT32  MsgLevel,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+;

+

+void

+SetDebugMsgMask (

+  UINT32    MsgMask

+  )

+;

+

+void

+ParserSetPosition (

+  INT8    *SourceFileName,

+  UINT32  LineNum

+  )

+;

+

+void

+ParserError (

+  UINT32  ErrorCode,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+;

+

+void

+ParserWarning (

+  UINT32  ErrorCode,

+  INT8    *OffendingText,

+  INT8    *MsgFmt,

+  ...

+  )

+;

+

+#endif

diff --git a/Source/GuidChk/build.xml b/Source/GuidChk/build.xml
new file mode 100644
index 0000000..80f8ef0
--- /dev/null
+++ b/Source/GuidChk/build.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK GuidChk Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="GuidChk"/>

+  <property name="FileSet" value="*.c *.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <if>

+      <isfalse value="${gcc}"/>

+      <then>

+        <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+      </then>

+    </if>

+  </target>

+

+  <target name="init">

+    <if>

+      <istrue value="${gcc}"/>

+      <then>

+        <echo message="The EDK Tool: ${ToolName} is not built for GCC!"/>

+      </then>

+      <else>

+        <echo message="Building the EDK Tool: ${ToolName}"/>

+        <mkdir dir="${BUILD_DIR}"/>

+      </else>

+    </if>

+  </target>

+

+  <target name="Tool" depends="init" unless="gcc">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/Include/Common/BaseTypes.h b/Source/Include/Common/BaseTypes.h
new file mode 100644
index 0000000..b87e714
--- /dev/null
+++ b/Source/Include/Common/BaseTypes.h
@@ -0,0 +1,212 @@
+/** @file

+  Processor or Compiler specific defines for all supported processors.

+

+  This file is stand alone self consistent set of definitions. 

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  BaseTypes.h

+

+**/

+

+#ifndef __BASE_TYPES_H__

+#define __BASE_TYPES_H__

+

+//

+// Include processor specific binding

+//

+#include <ProcessorBind.h>

+#include <stdarg.h>

+

+#define MEMORY_FENCE()  MemoryFence ()

+#define BREAKPOINT()    CpuBreakpoint ()

+#define DEADLOOP()      CpuDeadLoop ()

+

+typedef struct {

+  UINT32  Data1;

+  UINT16  Data2;

+  UINT16  Data3;

+  UINT8   Data4[8];

+} GUID;

+

+

+//

+// Modifiers to absract standard types to aid in debug of problems

+//

+#define CONST     const

+#define STATIC    static

+#define VOID      void

+

+//

+// Modifiers for Data Types used to self document code.

+// This concept is borrowed for UEFI specification.

+//

+#ifndef IN

+//

+// Some other envirnments use this construct, so #ifndef to prevent

+// mulitple definition.

+//

+#define IN

+#define OUT

+#define OPTIONAL

+#endif

+

+//

+// Constants. They may exist in other build structures, so #ifndef them.

+//

+#ifndef TRUE

+//

+// BugBug: UEFI specification claims 1 and 0. We are concerned about the 

+//  complier portability so we did it this way.

+//

+#define TRUE  ((BOOLEAN)(1==1))

+#endif

+

+#ifndef FALSE

+#define FALSE ((BOOLEAN)(0==1))

+#endif

+

+#ifndef NULL

+#define NULL  ((VOID *) 0)

+#endif

+

+//

+//  Support for variable length argument lists using the ANSI standard.

+//  

+//  Since we are using the ANSI standard we used the standard nameing and

+//  did not folow the coding convention

+//

+//  VA_LIST  - typedef for argument list.

+//  VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.

+//  VA_END (VA_LIST Marker) - Clear Marker

+//  VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argumnet from

+//    the ... list. You must know the size and pass it in this macro.

+//

+//  example:

+//

+//  UINTN

+//  ExampleVarArg (

+//    IN UINTN  NumberOfArgs,

+//    ...

+//    )

+//  {

+//    VA_LIST Marker;

+//    UINTN   Index;

+//    UINTN   Result;

+//

+//    //

+//    // Initialize the Marker

+//    //

+//    VA_START (Marker, NumberOfArgs);

+//    for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {

+//      //

+//      // The ... list is a series of UINTN values, so average them up.

+//      //

+//      Result += VA_ARG (Marker, UINTN);

+//    }

+//

+//    VA_END (Marker);

+//    return Result

+//  }

+//

+

+#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))

+

+//

+// Also support coding convention rules for var arg macros

+//

+#ifndef VA_START

+

+// typedef CHAR8 *VA_LIST;

+// #define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v))

+// #define VA_ARG(ap, t)   (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t)))

+// #define VA_END(ap)      (ap = (VA_LIST) 0)

+// Use the native arguments for tools.

+#define VA_START va_start

+#define VA_ARG   va_arg

+#define VA_END   va_end

+#define VA_LIST  va_list

+

+#endif

+

+///

+///  CONTAINING_RECORD - returns a pointer to the structure

+///      from one of it's elements.

+///

+#define _CR(Record, TYPE, Field)  ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))

+

+///

+///  ALIGN_POINTER - aligns a pointer to the lowest boundry

+///

+#define ALIGN_POINTER(p, s) ((VOID *) ((p) + (((s) - ((UINTN) (p))) & ((s) - 1))))

+

+///

+///  ALIGN_VARIABLE - aligns a variable up to the next natural boundry for int size of a processor

+///

+#define ALIGN_VARIABLE(Value, Adjustment) \

+  Adjustment = 0U; \

+  if ((UINTN) (Value) % sizeof (UINTN)) { \

+    (Adjustment) = (UINTN)(sizeof (UINTN) - ((UINTN) (Value) % sizeof (UINTN))); \

+  } \

+  (Value) = (UINTN)((UINTN) (Value) + (UINTN) (Adjustment))

+

+//

+// EFI Error Codes common to all execution phases

+//

+

+typedef INTN RETURN_STATUS;

+

+///

+/// Set the upper bit to indicate EFI Error.

+///

+#define ENCODE_ERROR(a)              (MAX_BIT | (a))

+

+#define ENCODE_WARNING(a)            (a)

+#define RETURN_ERROR(a)              ((a) < 0)

+

+#define RETURN_SUCCESS               0

+#define RETURN_LOAD_ERROR            ENCODE_ERROR (1)

+#define RETURN_INVALID_PARAMETER     ENCODE_ERROR (2)

+#define RETURN_UNSUPPORTED           ENCODE_ERROR (3)

+#define RETURN_BAD_BUFFER_SIZE       ENCODE_ERROR (4)

+#define RETURN_BUFFER_TOO_SMALL      ENCODE_ERROR (5)

+#define RETURN_NOT_READY             ENCODE_ERROR (6)

+#define RETURN_DEVICE_ERROR          ENCODE_ERROR (7)

+#define RETURN_WRITE_PROTECTED       ENCODE_ERROR (8)

+#define RETURN_OUT_OF_RESOURCES      ENCODE_ERROR (9)

+#define RETURN_VOLUME_CORRUPTED      ENCODE_ERROR (10)

+#define RETURN_VOLUME_FULL           ENCODE_ERROR (11)

+#define RETURN_NO_MEDIA              ENCODE_ERROR (12)

+#define RETURN_MEDIA_CHANGED         ENCODE_ERROR (13)

+#define RETURN_NOT_FOUND             ENCODE_ERROR (14)

+#define RETURN_ACCESS_DENIED         ENCODE_ERROR (15)

+#define RETURN_NO_RESPONSE           ENCODE_ERROR (16)

+#define RETURN_NO_MAPPING            ENCODE_ERROR (17)

+#define RETURN_TIMEOUT               ENCODE_ERROR (18)

+#define RETURN_NOT_STARTED           ENCODE_ERROR (19)

+#define RETURN_ALREADY_STARTED       ENCODE_ERROR (20)

+#define RETURN_ABORTED               ENCODE_ERROR (21)

+#define RETURN_ICMP_ERROR            ENCODE_ERROR (22)

+#define RETURN_TFTP_ERROR            ENCODE_ERROR (23)

+#define RETURN_PROTOCOL_ERROR        ENCODE_ERROR (24)

+#define RETURN_INCOMPATIBLE_VERSION  ENCODE_ERROR (25)

+#define RETURN_SECURITY_VIOLATION    ENCODE_ERROR (26)

+#define RETURN_CRC_ERROR             ENCODE_ERROR (27)

+#define RETURN_END_OF_MEDIA          ENCODE_ERROR (28)

+#define RETURN_END_OF_FILE           ENCODE_ERROR (31)

+

+#define RETURN_WARN_UNKNOWN_GLYPH    ENCODE_WARNING (1)

+#define RETURN_WARN_DELETE_FAILURE   ENCODE_WARNING (2)

+#define RETURN_WARN_WRITE_FAILURE    ENCODE_WARNING (3)

+#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4)

+

+typedef UINT64 PHYSICAL_ADDRESS;

+

+#endif

diff --git a/Source/Include/Common/Capsule.h b/Source/Include/Common/Capsule.h
new file mode 100644
index 0000000..0434fdf
--- /dev/null
+++ b/Source/Include/Common/Capsule.h
@@ -0,0 +1,67 @@
+/** @file

+  Defines for the EFI Capsule functionality.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  Capsule.h

+

+  @par Revision Reference:

+  These definitions are from Capsule Spec Version 0.9.

+

+**/

+

+#ifndef _EFI_CAPSULE_H_

+#define _EFI_CAPSULE_H_

+

+//

+// Bits in the flags field of the capsule header

+//

+#define EFI_CAPSULE_HEADER_FLAG_SETUP 0x00000001  // supports setup changes

+

+

+#define CAPSULE_BLOCK_DESCRIPTOR_SIGNATURE  EFI_SIGNATURE_32 ('C', 'B', 'D', 'S')

+

+//

+// An array of these describe the blocks that make up a capsule for

+// a capsule update.

+//

+typedef struct {

+  UINT64                Length;     // length of the data block

+  EFI_PHYSICAL_ADDRESS  Data;       // physical address of the data block

+  UINT32                Signature;  // CBDS

+  UINT32                CheckSum;   // to sum this structure to 0

+} EFI_CAPSULE_BLOCK_DESCRIPTOR;

+

+typedef struct {

+  EFI_GUID  OemGuid;

+  UINT32    HeaderSize;

+  //

+  // UINT8                       OemHdrData[];

+  //

+} EFI_CAPSULE_OEM_HEADER;

+

+typedef struct {

+  EFI_GUID  CapsuleGuid;

+  UINT32    HeaderSize;

+  UINT32    Flags;

+  UINT32    CapsuleImageSize;

+  UINT32    SequenceNumber;

+  EFI_GUID  InstanceId;

+  UINT32    OffsetToSplitInformation;

+  UINT32    OffsetToCapsuleBody;

+  UINT32    OffsetToOemDefinedHeader;

+  UINT32    OffsetToAuthorInformation;

+  UINT32    OffsetToRevisionInformation;

+  UINT32    OffsetToShortDescription;

+  UINT32    OffsetToLongDescription;

+  UINT32    OffsetToApplicableDevices;

+} EFI_CAPSULE_HEADER;

+

+#endif // #ifndef _EFI_CAPSULE_H_

diff --git a/Source/Include/Common/Dependency.h b/Source/Include/Common/Dependency.h
new file mode 100644
index 0000000..744027d
--- /dev/null
+++ b/Source/Include/Common/Dependency.h
@@ -0,0 +1,50 @@
+/** @file

+  This module contains data specific to dependency expressions

+  and local function prototypes.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  Dependency.h

+

+**/

+

+#ifndef __DEPENDENCY_H__

+#define __DEPENDENCY_H__

+

+/// EFI_DEP_BEFORE       - If present, this must be the first and only opcode

+#define EFI_DEP_BEFORE        0x00

+

+/// EFI_DEP_AFTER        - If present, this must be the first and only opcode

+#define EFI_DEP_AFTER         0x01

+

+#define EFI_DEP_PUSH          0x02

+#define EFI_DEP_AND           0x03

+#define EFI_DEP_OR            0x04

+#define EFI_DEP_NOT           0x05

+#define EFI_DEP_TRUE          0x06

+#define EFI_DEP_FALSE         0x07

+#define EFI_DEP_END           0x08

+

+/// EFI_DEP_SOR          - If present, this must be the first opcode

+#define EFI_DEP_SOR           0x09

+

+///

+/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression

+///                        to save time.  A EFI_DEP_PUSH is evauated one an

+///                        replaced with EFI_DEP_REPLACE_TRUE

+///

+#define EFI_DEP_REPLACE_TRUE  0xff

+

+///

+/// Define the initial size of the dependency expression evaluation stack

+///

+#define DEPEX_STACK_SIZE_INCREMENT  0x1000

+

+#endif

diff --git a/Source/Include/Common/EfiImage.h b/Source/Include/Common/EfiImage.h
new file mode 100644
index 0000000..2f5c580
--- /dev/null
+++ b/Source/Include/Common/EfiImage.h
@@ -0,0 +1,716 @@
+/** @file

+  EFI image format for PE32+. Please note some data structures are different

+  for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64

+

+  @bug Fix text - doc as defined in MSFT EFI specification.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  EfiImage.h

+

+**/

+

+#ifndef __EFI_IMAGE_H__

+#define __EFI_IMAGE_H__

+

+//

+// PE32+ Subsystem type for EFI images

+//

+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION         10

+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11

+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12

+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13

+

+//

+// BugBug: Need to get a real answer for this problem. This is not in the

+//         PE specification.

+//

+//         A SAL runtime driver does not get fixed up when a transition to

+//         virtual mode is made. In all other cases it should be treated

+//         like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image

+//

+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER  13

+

+//

+// PE32+ Machine type for EFI images

+//

+#define IMAGE_FILE_MACHINE_I386     0x014c

+#define IMAGE_FILE_MACHINE_IA64     0x0200

+#define IMAGE_FILE_MACHINE_EBC      0x0EBC

+#define IMAGE_FILE_MACHINE_X64      0x8664

+//

+// Support old names for backward compatible

+//

+#define EFI_IMAGE_MACHINE_IA32      IMAGE_FILE_MACHINE_I386 

+#define EFI_IMAGE_MACHINE_IA64      IMAGE_FILE_MACHINE_IA64  

+#define EFI_IMAGE_MACHINE_IPF       IMAGE_FILE_MACHINE_IA64  

+#define EFI_IMAGE_MACHINE_EBC       IMAGE_FILE_MACHINE_EBC  

+#define EFI_IMAGE_MACHINE_X64       IMAGE_FILE_MACHINE_X64

+

+#define EFI_IMAGE_DOS_SIGNATURE     0x5A4D      // MZ

+#define EFI_IMAGE_OS2_SIGNATURE     0x454E      // NE

+#define EFI_IMAGE_OS2_SIGNATURE_LE  0x454C      // LE

+#define EFI_IMAGE_NT_SIGNATURE      0x00004550  // PE00

+#define EFI_IMAGE_EDOS_SIGNATURE    0x44454550  // PEED

+

+///

+/// PE images can start with an optional DOS header, so if an image is run

+///  under DOS it can print an error message.

+///

+typedef struct {

+  UINT16  e_magic;    // Magic number

+  UINT16  e_cblp;     // Bytes on last page of file

+  UINT16  e_cp;       // Pages in file

+  UINT16  e_crlc;     // Relocations

+  UINT16  e_cparhdr;  // Size of header in paragraphs

+  UINT16  e_minalloc; // Minimum extra paragraphs needed

+  UINT16  e_maxalloc; // Maximum extra paragraphs needed

+  UINT16  e_ss;       // Initial (relative) SS value

+  UINT16  e_sp;       // Initial SP value

+  UINT16  e_csum;     // Checksum

+  UINT16  e_ip;       // Initial IP value

+  UINT16  e_cs;       // Initial (relative) CS value

+  UINT16  e_lfarlc;   // File address of relocation table

+  UINT16  e_ovno;     // Overlay number

+  UINT16  e_res[4];   // Reserved words

+  UINT16  e_oemid;    // OEM identifier (for e_oeminfo)

+  UINT16  e_oeminfo;  // OEM information; e_oemid specific

+  UINT16  e_res2[10]; // Reserved words

+  UINT32  e_lfanew;   // File address of new exe header

+} EFI_IMAGE_DOS_HEADER;

+

+///

+/// File header format.

+///

+typedef struct {

+  UINT16  Machine;

+  UINT16  NumberOfSections;

+  UINT32  TimeDateStamp;

+  UINT32  PointerToSymbolTable;

+  UINT32  NumberOfSymbols;

+  UINT16  SizeOfOptionalHeader;

+  UINT16  Characteristics;

+} EFI_IMAGE_FILE_HEADER;

+

+#define EFI_IMAGE_SIZEOF_FILE_HEADER        20

+

+#define EFI_IMAGE_FILE_RELOCS_STRIPPED      0x0001  // Relocation info stripped from file.

+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE     0x0002  // File is executable  (i.e. no unresolved externel references).

+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004  // Line nunbers stripped from file.

+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008  // Local symbols stripped from file.

+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO    0x0080  // Bytes of machine word are reversed.

+#define EFI_IMAGE_FILE_32BIT_MACHINE        0x0100  // 32 bit word machine.

+#define EFI_IMAGE_FILE_DEBUG_STRIPPED       0x0200  // Debugging info stripped from file in .DBG file

+#define EFI_IMAGE_FILE_SYSTEM               0x1000  // System File.

+#define EFI_IMAGE_FILE_DLL                  0x2000  // File is a DLL.

+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI    0x8000  // Bytes of machine word are reversed.

+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN      0

+#define EFI_IMAGE_FILE_MACHINE_I386         0x14c   // Intel 386.

+#define EFI_IMAGE_FILE_MACHINE_R3000        0x162   // MIPS* little-endian, 0540 big-endian

+#define EFI_IMAGE_FILE_MACHINE_R4000        0x166   // MIPS* little-endian

+#define EFI_IMAGE_FILE_MACHINE_ALPHA        0x184   // Alpha_AXP*

+#define EFI_IMAGE_FILE_MACHINE_POWERPC      0x1F0   // IBM* PowerPC Little-Endian

+#define EFI_IMAGE_FILE_MACHINE_TAHOE        0x7cc   // Intel EM machine

+//

+// * Other names and brands may be claimed as the property of others.

+//

+

+///

+/// Directory format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  Size;

+} EFI_IMAGE_DATA_DIRECTORY;

+

+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16

+

+typedef struct {

+  UINT16  Magic;

+  UINT8   MajorLinkerVersion;

+  UINT8   MinorLinkerVersion;

+  UINT32  SizeOfCode;

+  UINT32  SizeOfInitializedData;

+  UINT32  SizeOfUninitializedData;

+  UINT32  AddressOfEntryPoint;

+  UINT32  BaseOfCode;

+  UINT32  BaseOfData;

+  UINT32  BaseOfBss;

+  UINT32  GprMask;

+  UINT32  CprMask[4];

+  UINT32  GpValue;

+} EFI_IMAGE_ROM_OPTIONAL_HEADER;

+

+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC      0x107

+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER  sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)

+

+typedef struct {

+  EFI_IMAGE_FILE_HEADER         FileHeader;

+  EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;

+} EFI_IMAGE_ROM_HEADERS;

+

+///

+/// @attention

+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64

+/// are for use ONLY by tools.  All proper EFI code MUST use

+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!

+///

+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b

+

+typedef struct {

+  //

+  // Standard fields.

+  //

+  UINT16                    Magic;

+  UINT8                     MajorLinkerVersion;

+  UINT8                     MinorLinkerVersion;

+  UINT32                    SizeOfCode;

+  UINT32                    SizeOfInitializedData;

+  UINT32                    SizeOfUninitializedData;

+  UINT32                    AddressOfEntryPoint;

+  UINT32                    BaseOfCode;

+  UINT32                    BaseOfData;

+  //

+  // NT additional fields.

+  //

+  UINT32                    ImageBase;

+  UINT32                    SectionAlignment;

+  UINT32                    FileAlignment;

+  UINT16                    MajorOperatingSystemVersion;

+  UINT16                    MinorOperatingSystemVersion;

+  UINT16                    MajorImageVersion;

+  UINT16                    MinorImageVersion;

+  UINT16                    MajorSubsystemVersion;

+  UINT16                    MinorSubsystemVersion;

+  UINT32                    Win32VersionValue;

+  UINT32                    SizeOfImage;

+  UINT32                    SizeOfHeaders;

+  UINT32                    CheckSum;

+  UINT16                    Subsystem;

+  UINT16                    DllCharacteristics;

+  UINT32                    SizeOfStackReserve;

+  UINT32                    SizeOfStackCommit;

+  UINT32                    SizeOfHeapReserve;

+  UINT32                    SizeOfHeapCommit;

+  UINT32                    LoaderFlags;

+  UINT32                    NumberOfRvaAndSizes;

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];

+} EFI_IMAGE_OPTIONAL_HEADER32;

+

+///

+/// @attention

+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64

+/// are for use ONLY by tools.  All proper EFI code MUST use

+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!

+///

+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b

+

+typedef struct {

+  //

+  // Standard fields.

+  //

+  UINT16                    Magic;

+  UINT8                     MajorLinkerVersion;

+  UINT8                     MinorLinkerVersion;

+  UINT32                    SizeOfCode;

+  UINT32                    SizeOfInitializedData;

+  UINT32                    SizeOfUninitializedData;

+  UINT32                    AddressOfEntryPoint;

+  UINT32                    BaseOfCode;

+  //

+  // NT additional fields.

+  //

+  UINT64                    ImageBase;

+  UINT32                    SectionAlignment;

+  UINT32                    FileAlignment;

+  UINT16                    MajorOperatingSystemVersion;

+  UINT16                    MinorOperatingSystemVersion;

+  UINT16                    MajorImageVersion;

+  UINT16                    MinorImageVersion;

+  UINT16                    MajorSubsystemVersion;

+  UINT16                    MinorSubsystemVersion;

+  UINT32                    Win32VersionValue;

+  UINT32                    SizeOfImage;

+  UINT32                    SizeOfHeaders;

+  UINT32                    CheckSum;

+  UINT16                    Subsystem;

+  UINT16                    DllCharacteristics;

+  UINT64                    SizeOfStackReserve;

+  UINT64                    SizeOfStackCommit;

+  UINT64                    SizeOfHeapReserve;

+  UINT64                    SizeOfHeapCommit;

+  UINT32                    LoaderFlags;

+  UINT32                    NumberOfRvaAndSizes;

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];

+} EFI_IMAGE_OPTIONAL_HEADER64;

+

+///

+/// @attention

+/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY

+/// by tools.  All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!

+///

+typedef struct {

+  UINT32                      Signature;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;

+} EFI_IMAGE_NT_HEADERS32;

+

+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)

+

+typedef struct {

+  UINT32                      Signature;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;

+} EFI_IMAGE_NT_HEADERS64;

+

+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)

+

+//

+// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the

+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build.  Same for

+// EFI_IMAGE_NT_HEADERS.  These definitions MUST be used by ALL EFI code.

+//

+#if   defined (MDE_CPU_IA32)

+

+typedef EFI_IMAGE_OPTIONAL_HEADER32     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS32          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_IPF)

+

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_X64)

+

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_EBC)

+

+//

+// This is just to make sure you can cross compile with the EBC compiiler.

+// It does not make sense to have a PE loader coded in EBC. You need to 

+// understand the basic 

+//

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)

+

+#else

+#error Unknown Processor Type

+#endif

+

+

+#define EFI_IMAGE_FIRST_SECTION(ntheader) \

+    ( \

+      (EFI_IMAGE_SECTION_HEADER *) \

+        ( \

+          (UINT32) ntheader + \

+          FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \

+          ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \

+        ) \

+    )

+

+//

+// Subsystem Values

+//

+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN     0

+#define EFI_IMAGE_SUBSYSTEM_NATIVE      1

+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2

+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.

+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI     5

+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI   7

+

+//

+// Directory Entries

+//

+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT      0

+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT      1

+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE    2

+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION   3

+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY    4

+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC   5

+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG       6

+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT   7

+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR   8

+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS         9

+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10

+

+//

+// Section header format.

+//

+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8

+

+typedef struct {

+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];

+  union {

+    UINT32  PhysicalAddress;

+    UINT32  VirtualSize;

+  } Misc;

+  UINT32  VirtualAddress;

+  UINT32  SizeOfRawData;

+  UINT32  PointerToRawData;

+  UINT32  PointerToRelocations;

+  UINT32  PointerToLinenumbers;

+  UINT16  NumberOfRelocations;

+  UINT16  NumberOfLinenumbers;

+  UINT32  Characteristics;

+} EFI_IMAGE_SECTION_HEADER;

+

+#define EFI_IMAGE_SIZEOF_SECTION_HEADER       40

+

+#define EFI_IMAGE_SCN_TYPE_NO_PAD             0x00000008  // Reserved.

+#define EFI_IMAGE_SCN_CNT_CODE                0x00000020

+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA    0x00000040

+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA  0x00000080

+

+#define EFI_IMAGE_SCN_LNK_OTHER               0x00000100  // Reserved.

+#define EFI_IMAGE_SCN_LNK_INFO                0x00000200  // Section contains comments or some other type of information.

+#define EFI_IMAGE_SCN_LNK_REMOVE              0x00000800  // Section contents will not become part of image.

+#define EFI_IMAGE_SCN_LNK_COMDAT              0x00001000

+

+#define EFI_IMAGE_SCN_ALIGN_1BYTES            0x00100000

+#define EFI_IMAGE_SCN_ALIGN_2BYTES            0x00200000

+#define EFI_IMAGE_SCN_ALIGN_4BYTES            0x00300000

+#define EFI_IMAGE_SCN_ALIGN_8BYTES            0x00400000

+#define EFI_IMAGE_SCN_ALIGN_16BYTES           0x00500000

+#define EFI_IMAGE_SCN_ALIGN_32BYTES           0x00600000

+#define EFI_IMAGE_SCN_ALIGN_64BYTES           0x00700000

+

+#define EFI_IMAGE_SCN_MEM_DISCARDABLE         0x02000000

+#define EFI_IMAGE_SCN_MEM_NOT_CACHED          0x04000000

+#define EFI_IMAGE_SCN_MEM_NOT_PAGED           0x08000000

+#define EFI_IMAGE_SCN_MEM_SHARED              0x10000000

+#define EFI_IMAGE_SCN_MEM_EXECUTE             0x20000000

+#define EFI_IMAGE_SCN_MEM_READ                0x40000000

+#define EFI_IMAGE_SCN_MEM_WRITE               0x80000000

+

+///

+/// Symbol format.

+///

+#define EFI_IMAGE_SIZEOF_SYMBOL 18

+

+//

+// Section values.

+//

+// Symbols have a section number of the section in which they are

+// defined. Otherwise, section numbers have the following meanings:

+//

+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0  // Symbol is undefined or is common.

+#define EFI_IMAGE_SYM_ABSOLUTE  (UINT16) -1 // Symbol is an absolute value.

+#define EFI_IMAGE_SYM_DEBUG     (UINT16) -2 // Symbol is a special debug item.

+//

+// Type (fundamental) values.

+//

+#define EFI_IMAGE_SYM_TYPE_NULL   0   // no type.

+#define EFI_IMAGE_SYM_TYPE_VOID   1   //

+#define EFI_IMAGE_SYM_TYPE_CHAR   2   // type character.

+#define EFI_IMAGE_SYM_TYPE_SHORT  3   // type short integer.

+#define EFI_IMAGE_SYM_TYPE_INT    4

+#define EFI_IMAGE_SYM_TYPE_LONG   5

+#define EFI_IMAGE_SYM_TYPE_FLOAT  6

+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7

+#define EFI_IMAGE_SYM_TYPE_STRUCT 8

+#define EFI_IMAGE_SYM_TYPE_UNION  9

+#define EFI_IMAGE_SYM_TYPE_ENUM   10  // enumeration.

+#define EFI_IMAGE_SYM_TYPE_MOE    11  // member of enumeration.

+#define EFI_IMAGE_SYM_TYPE_BYTE   12

+#define EFI_IMAGE_SYM_TYPE_WORD   13

+#define EFI_IMAGE_SYM_TYPE_UINT   14

+#define EFI_IMAGE_SYM_TYPE_DWORD  15

+

+//

+// Type (derived) values.

+//

+#define EFI_IMAGE_SYM_DTYPE_NULL      0 // no derived type.

+#define EFI_IMAGE_SYM_DTYPE_POINTER   1

+#define EFI_IMAGE_SYM_DTYPE_FUNCTION  2

+#define EFI_IMAGE_SYM_DTYPE_ARRAY     3

+

+//

+// Storage classes.

+//

+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION   (UINT8) -1

+#define EFI_IMAGE_SYM_CLASS_NULL              0

+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC         1

+#define EFI_IMAGE_SYM_CLASS_EXTERNAL          2

+#define EFI_IMAGE_SYM_CLASS_STATIC            3

+#define EFI_IMAGE_SYM_CLASS_REGISTER          4

+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF      5

+#define EFI_IMAGE_SYM_CLASS_LABEL             6

+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL   7

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT  8

+#define EFI_IMAGE_SYM_CLASS_ARGUMENT          9

+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG        10

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION   11

+#define EFI_IMAGE_SYM_CLASS_UNION_TAG         12

+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION   13

+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC  14

+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG          15

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM    16

+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM    17

+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD         18

+#define EFI_IMAGE_SYM_CLASS_BLOCK             100

+#define EFI_IMAGE_SYM_CLASS_FUNCTION          101

+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT     102

+#define EFI_IMAGE_SYM_CLASS_FILE              103

+#define EFI_IMAGE_SYM_CLASS_SECTION           104

+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL     105

+

+//

+// type packing constants

+//

+#define EFI_IMAGE_N_BTMASK  017

+#define EFI_IMAGE_N_TMASK   060

+#define EFI_IMAGE_N_TMASK1  0300

+#define EFI_IMAGE_N_TMASK2  0360

+#define EFI_IMAGE_N_BTSHFT  4

+#define EFI_IMAGE_N_TSHIFT  2

+

+//

+// Communal selection types.

+//

+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES    1

+#define EFI_IMAGE_COMDAT_SELECT_ANY             2

+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE       3

+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH     4

+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE     5

+

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3

+

+///

+/// Relocation format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  SymbolTableIndex;

+  UINT16  Type;

+} EFI_IMAGE_RELOCATION;

+

+#define EFI_IMAGE_SIZEOF_RELOCATION 10

+

+//

+// I386 relocation types.

+//

+#define EFI_IMAGE_REL_I386_ABSOLUTE 0   // Reference is absolute, no relocation is necessary

+#define EFI_IMAGE_REL_I386_DIR16    01  // Direct 16-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_REL16    02  // PC-relative 16-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_DIR32    06  // Direct 32-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_DIR32NB  07  // Direct 32-bit reference to the symbols virtual address, base not included

+#define EFI_IMAGE_REL_I386_SEG12    011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address

+#define EFI_IMAGE_REL_I386_SECTION  012

+#define EFI_IMAGE_REL_I386_SECREL   013

+#define EFI_IMAGE_REL_I386_REL32    024 // PC-relative 32-bit reference to the symbols virtual address

+

+///

+/// Based relocation format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  SizeOfBlock;

+} EFI_IMAGE_BASE_RELOCATION;

+

+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION  8

+

+//

+// Based relocation types.

+//

+#define EFI_IMAGE_REL_BASED_ABSOLUTE      0

+#define EFI_IMAGE_REL_BASED_HIGH          1

+#define EFI_IMAGE_REL_BASED_LOW           2

+#define EFI_IMAGE_REL_BASED_HIGHLOW       3

+#define EFI_IMAGE_REL_BASED_HIGHADJ       4

+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR  5

+#define EFI_IMAGE_REL_BASED_IA64_IMM64    9

+#define EFI_IMAGE_REL_BASED_DIR64         10

+

+///

+/// Line number format.

+///

+typedef struct {

+  union {

+    UINT32  SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.

+    UINT32  VirtualAddress;   // Virtual address of line number.

+  } Type;

+  UINT16  Linenumber;         // Line number.

+} EFI_IMAGE_LINENUMBER;

+

+#define EFI_IMAGE_SIZEOF_LINENUMBER 6

+

+//

+// Archive format.

+//

+#define EFI_IMAGE_ARCHIVE_START_SIZE        8

+#define EFI_IMAGE_ARCHIVE_START             "!<arch>\n"

+#define EFI_IMAGE_ARCHIVE_END               "`\n"

+#define EFI_IMAGE_ARCHIVE_PAD               "\n"

+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER     "/               "

+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER  "//              "

+

+typedef struct {

+  UINT8 Name[16];     // File member name - `/' terminated.

+  UINT8 Date[12];     // File member date - decimal.

+  UINT8 UserID[6];    // File member user id - decimal.

+  UINT8 GroupID[6];   // File member group id - decimal.

+  UINT8 Mode[8];      // File member mode - octal.

+  UINT8 Size[10];     // File member size - decimal.

+  UINT8 EndHeader[2]; // String to end header.

+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;

+

+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60

+

+//

+// DLL support.

+//

+

+///

+/// DLL Export Format

+///

+typedef struct {

+  UINT32  Characteristics;

+  UINT32  TimeDateStamp;

+  UINT16  MajorVersion;

+  UINT16  MinorVersion;

+  UINT32  Name;

+  UINT32  Base;

+  UINT32  NumberOfFunctions;

+  UINT32  NumberOfNames;

+  UINT32  AddressOfFunctions;

+  UINT32  AddressOfNames;

+  UINT32  AddressOfNameOrdinals;

+} EFI_IMAGE_EXPORT_DIRECTORY;

+

+///

+/// DLL support.

+/// Import Format

+///

+typedef struct {

+  UINT16  Hint;

+  UINT8   Name[1];

+} EFI_IMAGE_IMPORT_BY_NAME;

+

+typedef struct {

+  union {

+    UINT32                    Function;

+    UINT32                    Ordinal;

+    EFI_IMAGE_IMPORT_BY_NAME  *AddressOfData;

+  } u1;

+} EFI_IMAGE_THUNK_DATA;

+

+#define EFI_IMAGE_ORDINAL_FLAG              0x80000000

+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal)  ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)

+#define EFI_IMAGE_ORDINAL(Ordinal)          (Ordinal & 0xffff)

+

+typedef struct {

+  UINT32                Characteristics;

+  UINT32                TimeDateStamp;

+  UINT32                ForwarderChain;

+  UINT32                Name;

+  EFI_IMAGE_THUNK_DATA  *FirstThunk;

+} EFI_IMAGE_IMPORT_DESCRIPTOR;

+

+///

+/// Debug Format

+///

+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2

+

+typedef struct {

+  UINT32  Characteristics;

+  UINT32  TimeDateStamp;

+  UINT16  MajorVersion;

+  UINT16  MinorVersion;

+  UINT32  Type;

+  UINT32  SizeOfData;

+  UINT32  RVA;

+  UINT32  FileOffset;

+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;

+

+#define CODEVIEW_SIGNATURE_NB10 0x3031424E  // "NB10"

+typedef struct {

+  UINT32  Signature;                        // "NB10"

+  UINT32  Unknown;

+  UINT32  Unknown2;

+  UINT32  Unknown3;

+  //

+  // Filename of .PDB goes here

+  //

+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;

+

+#define CODEVIEW_SIGNATURE_RSDS 0x53445352  // "RSDS"

+typedef struct {

+  UINT32  Signature;                        // "RSDS"

+  UINT32  Unknown;

+  UINT32  Unknown2;

+  UINT32  Unknown3;

+  UINT32  Unknown4;

+  UINT32  Unknown5;

+  //

+  // Filename of .PDB goes here

+  //

+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;

+

+//

+// .pdata entries for X64

+//

+typedef struct {

+  UINT32  FunctionStartAddress;

+  UINT32  FunctionEndAddress;

+  UINT32  UnwindInfoAddress;

+} RUNTIME_FUNCTION;

+

+typedef struct {

+  UINT8  Version:3;

+  UINT8  Flags:5;

+  UINT8  SizeOfProlog;

+  UINT8  CountOfUnwindCodes;

+  UINT8  FrameRegister:4;

+  UINT8  FrameRegisterOffset:4;

+} UNWIND_INFO;

+

+///

+/// Header format for TE images

+///

+typedef struct {

+  UINT16                    Signature;            // signature for TE format = "VZ"

+  UINT16                    Machine;              // from the original file header

+  UINT8                     NumberOfSections;     // from the original file header

+  UINT8                     Subsystem;            // from original optional header

+  UINT16                    StrippedSize;         // how many bytes we removed from the header

+  UINT32                    AddressOfEntryPoint;  // offset to entry point -- from original optional header

+  UINT32                    BaseOfCode;           // from original image -- required for ITP debug

+  UINT64                    ImageBase;            // from original file header

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[2];     // only base relocation and debug directory

+} EFI_TE_IMAGE_HEADER;

+

+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56      // "VZ"

+

+//

+// Data directory indexes in our TE image header

+//

+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0

+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1

+

+#endif

diff --git a/Source/Include/Common/FirmwareFileSystem.h b/Source/Include/Common/FirmwareFileSystem.h
new file mode 100644
index 0000000..5678a95
--- /dev/null
+++ b/Source/Include/Common/FirmwareFileSystem.h
@@ -0,0 +1,98 @@
+/** @file

+  This file defines the data structures that comprise the FFS file system.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  FirmwareFileSystem.h

+

+  @par Revision Reference:

+  These definitions are from Firmware File System Spec 0.9.

+

+**/

+

+#ifndef __EFI_FFS_FILE_SYSTEM_H__

+#define __EFI_FFS_FILE_SYSTEM_H__

+

+///

+/// FFS specific file types

+///

+#define EFI_FV_FILETYPE_FFS_PAD 0xF0

+

+//

+// FFS File Attributes

+//

+#define FFS_ATTRIB_TAIL_PRESENT     0x01

+#define FFS_ATTRIB_RECOVERY         0x02

+#define FFS_ATTRIB_HEADER_EXTENSION 0x04

+#define FFS_ATTRIB_DATA_ALIGNMENT   0x38

+#define FFS_ATTRIB_CHECKSUM         0x40

+

+///

+/// FFS_FIXED_CHECKSUM is the default checksum value used when the

+/// FFS_ATTRIB_CHECKSUM attribute bit is clear

+/// note this is NOT an architecturally defined value, but is in this file for

+/// implementation convenience

+///

+#define FFS_FIXED_CHECKSUM  0x5A

+

+//

+// File state definitions

+//

+#define EFI_FILE_HEADER_CONSTRUCTION  0x01

+#define EFI_FILE_HEADER_VALID         0x02

+#define EFI_FILE_DATA_VALID           0x04

+#define EFI_FILE_MARKED_FOR_UPDATE    0x08

+#define EFI_FILE_DELETED              0x10

+#define EFI_FILE_HEADER_INVALID       0x20

+

+#define EFI_FILE_ALL_STATE_BITS       (EFI_FILE_HEADER_CONSTRUCTION | \

+                                 EFI_FILE_HEADER_VALID | \

+                                 EFI_FILE_DATA_VALID | \

+                                 EFI_FILE_MARKED_FOR_UPDATE | \

+                                 EFI_FILE_DELETED | \

+                                 EFI_FILE_HEADER_INVALID \

+          )

+

+#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \

+    ( \

+      (BOOLEAN) ( \

+          (FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \

+        ) \

+    )

+

+typedef UINT16  EFI_FFS_FILE_TAIL;

+

+///

+/// FFS file integrity check structure

+///

+typedef union {

+  struct {

+    UINT8 Header;

+    UINT8 File;

+  } Checksum;

+  UINT16  TailReference;

+} EFI_FFS_INTEGRITY_CHECK;

+

+//

+// FFS file header definition

+//

+typedef UINT8 EFI_FFS_FILE_ATTRIBUTES;

+typedef UINT8 EFI_FFS_FILE_STATE;

+

+typedef struct {

+  EFI_GUID                Name;

+  EFI_FFS_INTEGRITY_CHECK IntegrityCheck;

+  EFI_FV_FILETYPE         Type;

+  EFI_FFS_FILE_ATTRIBUTES Attributes;

+  UINT8                   Size[3];

+  EFI_FFS_FILE_STATE      State;

+} EFI_FFS_FILE_HEADER;

+

+#endif

diff --git a/Source/Include/Common/FirmwareVolumeHeader.h b/Source/Include/Common/FirmwareVolumeHeader.h
new file mode 100644
index 0000000..038dce6
--- /dev/null
+++ b/Source/Include/Common/FirmwareVolumeHeader.h
@@ -0,0 +1,109 @@
+/** @file

+  Defines data structure that is the volume header found at the beginning of

+  all firmware volumes that are either memory mapped, or have an

+  associated FirmwareVolumeBlock protocol.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  FirmwareVolumeHeader.h

+

+  @par Revision Reference:

+  These definitions are from Firmware Volume Block Spec 0.9.

+

+**/

+

+#ifndef __EFI_FIRMWARE_VOLUME_HEADER_H__

+#define __EFI_FIRMWARE_VOLUME_HEADER_H__

+

+//

+// Firmware Volume Block Attributes definition

+//

+typedef UINT32  EFI_FVB_ATTRIBUTES;

+

+//

+// Firmware Volume Block Attributes bit definitions

+//

+#define EFI_FVB_READ_DISABLED_CAP   0x00000001

+#define EFI_FVB_READ_ENABLED_CAP    0x00000002

+#define EFI_FVB_READ_STATUS         0x00000004

+

+#define EFI_FVB_WRITE_DISABLED_CAP  0x00000008

+#define EFI_FVB_WRITE_ENABLED_CAP   0x00000010

+#define EFI_FVB_WRITE_STATUS        0x00000020

+

+#define EFI_FVB_LOCK_CAP            0x00000040

+#define EFI_FVB_LOCK_STATUS         0x00000080

+

+#define EFI_FVB_STICKY_WRITE        0x00000200

+#define EFI_FVB_MEMORY_MAPPED       0x00000400

+#define EFI_FVB_ERASE_POLARITY      0x00000800

+

+#define EFI_FVB_ALIGNMENT_CAP       0x00008000

+#define EFI_FVB_ALIGNMENT_2         0x00010000

+#define EFI_FVB_ALIGNMENT_4         0x00020000

+#define EFI_FVB_ALIGNMENT_8         0x00040000

+#define EFI_FVB_ALIGNMENT_16        0x00080000

+#define EFI_FVB_ALIGNMENT_32        0x00100000

+#define EFI_FVB_ALIGNMENT_64        0x00200000

+#define EFI_FVB_ALIGNMENT_128       0x00400000

+#define EFI_FVB_ALIGNMENT_256       0x00800000

+#define EFI_FVB_ALIGNMENT_512       0x01000000

+#define EFI_FVB_ALIGNMENT_1K        0x02000000

+#define EFI_FVB_ALIGNMENT_2K        0x04000000

+#define EFI_FVB_ALIGNMENT_4K        0x08000000

+#define EFI_FVB_ALIGNMENT_8K        0x10000000

+#define EFI_FVB_ALIGNMENT_16K       0x20000000

+#define EFI_FVB_ALIGNMENT_32K       0x40000000

+#define EFI_FVB_ALIGNMENT_64K       0x80000000

+

+#define EFI_FVB_CAPABILITIES  (EFI_FVB_READ_DISABLED_CAP | \

+                              EFI_FVB_READ_ENABLED_CAP | \

+                              EFI_FVB_WRITE_DISABLED_CAP | \

+                              EFI_FVB_WRITE_ENABLED_CAP | \

+                              EFI_FVB_LOCK_CAP \

+                              )

+

+#define EFI_FVB_STATUS    (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EFI_FVB_LOCK_STATUS)

+

+///

+/// Firmware Volume Header Revision definition

+///

+#define EFI_FVH_REVISION  0x01

+

+///

+/// Firmware Volume Header Signature definition

+///

+#define EFI_FVH_SIGNATURE EFI_SIGNATURE_32 ('_', 'F', 'V', 'H')

+

+///

+/// Firmware Volume Header Block Map Entry definition

+///

+typedef struct {

+  UINT32  NumBlocks;

+  UINT32  BlockLength;

+} EFI_FV_BLOCK_MAP_ENTRY;

+

+///

+/// Firmware Volume Header definition

+///

+typedef struct {

+  UINT8                   ZeroVector[16];

+  EFI_GUID                FileSystemGuid;

+  UINT64                  FvLength;

+  UINT32                  Signature;

+  EFI_FVB_ATTRIBUTES      Attributes;

+  UINT16                  HeaderLength;

+  UINT16                  Checksum;

+  UINT8                   Reserved[3];

+  UINT8                   Revision;

+  EFI_FV_BLOCK_MAP_ENTRY  FvBlockMap[1];

+} EFI_FIRMWARE_VOLUME_HEADER;

+

+#endif

diff --git a/Source/Include/Common/FirmwareVolumeImageFormat.h b/Source/Include/Common/FirmwareVolumeImageFormat.h
new file mode 100644
index 0000000..14fa41b
--- /dev/null
+++ b/Source/Include/Common/FirmwareVolumeImageFormat.h
@@ -0,0 +1,277 @@
+/** @file

+  This file defines the data structures that are architecturally defined for file

+  images loaded via the FirmwareVolume protocol.  The Firmware Volume specification

+  is the basis for these definitions.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  FimrwareVolumeImageFormat.h

+

+  @par Revision Reference:

+  These definitions are from Firmware Volume Spec 0.9.

+

+**/

+

+#ifndef __FIRMWARE_VOLUME_IMAGE_FORMAT_H__

+#define __FIRMWARE_VOLUME_IMAGE_FORMAT_H__

+

+//

+// pack all data structures since this is actually a binary format and we cannot

+// allow internal padding in the data structures because of some compilerism..

+//

+#pragma pack(1)

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Architectural file types

+//

+typedef UINT8 EFI_FV_FILETYPE;

+

+#define EFI_FV_FILETYPE_ALL                   0x00

+#define EFI_FV_FILETYPE_RAW                   0x01

+#define EFI_FV_FILETYPE_FREEFORM              0x02

+#define EFI_FV_FILETYPE_SECURITY_CORE         0x03

+#define EFI_FV_FILETYPE_PEI_CORE              0x04

+#define EFI_FV_FILETYPE_DXE_CORE              0x05

+#define EFI_FV_FILETYPE_PEIM                  0x06

+#define EFI_FV_FILETYPE_DRIVER                0x07

+#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER  0x08

+#define EFI_FV_FILETYPE_APPLICATION           0x09

+//

+// File type 0x0A is reserved and should not be used

+//

+#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Section types

+//

+typedef UINT8 EFI_SECTION_TYPE;

+

+//

+// ************************************************************

+// The section type EFI_SECTION_ALL is a psuedo type.  It is

+// used as a wildcard when retrieving sections.  The section

+// type EFI_SECTION_ALL matches all section types.

+// ************************************************************

+//

+#define EFI_SECTION_ALL 0x00

+

+//

+// ************************************************************

+// Encapsulation section Type values

+// ************************************************************

+//

+#define EFI_SECTION_COMPRESSION   0x01

+#define EFI_SECTION_GUID_DEFINED  0x02

+

+//

+// ************************************************************

+// Leaf section Type values

+// ************************************************************

+//

+#define EFI_SECTION_FIRST_LEAF_SECTION_TYPE 0x10

+

+#define EFI_SECTION_PE32                    0x10

+#define EFI_SECTION_PIC                     0x11

+#define EFI_SECTION_TE                      0x12

+#define EFI_SECTION_DXE_DEPEX               0x13

+#define EFI_SECTION_VERSION                 0x14

+#define EFI_SECTION_USER_INTERFACE          0x15

+#define EFI_SECTION_COMPATIBILITY16         0x16

+#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE   0x17

+#define EFI_SECTION_FREEFORM_SUBTYPE_GUID   0x18

+#define EFI_SECTION_RAW                     0x19

+#define EFI_SECTION_PEI_DEPEX               0x1B

+

+#define EFI_SECTION_LAST_LEAF_SECTION_TYPE  0x1B

+#define EFI_SECTION_LAST_SECTION_TYPE       0x1B

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Common section header

+//

+typedef struct {

+  UINT8 Size[3];

+  UINT8 Type;

+} EFI_COMMON_SECTION_HEADER;

+

+#define SECTION_SIZE(SectionHeaderPtr) \

+    ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff))

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Compression section

+//

+//

+// CompressionType values

+//

+#define EFI_NOT_COMPRESSED          0x00

+#define EFI_STANDARD_COMPRESSION    0x01

+#define EFI_CUSTOMIZED_COMPRESSION  0x02

+

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+  UINT32                    UncompressedLength;

+  UINT8                     CompressionType;

+} EFI_COMPRESSION_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// GUID defined section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+  EFI_GUID                  SectionDefinitionGuid;

+  UINT16                    DataOffset;

+  UINT16                    Attributes;

+} EFI_GUID_DEFINED_SECTION;

+

+//

+// Bit values for Attributes

+//

+#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED  0x01

+#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID    0x02

+

+//

+// Bit values for AuthenticationStatus

+//

+#define EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE 0x000001

+#define EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED      0x000002

+#define EFI_AGGREGATE_AUTH_STATUS_NOT_TESTED        0x000004

+#define EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED       0x000008

+#define EFI_AGGREGATE_AUTH_STATUS_ALL               0x00000f

+

+#define EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE     0x010000

+#define EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED          0x020000

+#define EFI_LOCAL_AUTH_STATUS_NOT_TESTED            0x040000

+#define EFI_LOCAL_AUTH_STATUS_TEST_FAILED           0x080000

+#define EFI_LOCAL_AUTH_STATUS_ALL                   0x0f0000

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// PE32+ section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_PE32_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// PIC section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_PIC_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// PEIM header section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_PEIM_HEADER_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// DEPEX section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_DEPEX_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Version section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+  UINT16                    BuildNumber;

+  INT16                     VersionString[1];

+} EFI_VERSION_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// User interface section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+  INT16                     FileNameString[1];

+} EFI_USER_INTERFACE_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Code16 section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_CODE16_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Firmware Volume Image section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_FIRMWARE_VOLUME_IMAGE_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Freeform subtype GUID section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+  EFI_GUID                  SubTypeGuid;

+} EFI_FREEFORM_SUBTYPE_GUID_SECTION;

+

+//

+// ////////////////////////////////////////////////////////////////////////////

+//

+// Raw section

+//

+typedef struct {

+  EFI_COMMON_SECTION_HEADER CommonHeader;

+} EFI_RAW_SECTION;

+

+//

+// undo the pragma from the beginning...

+//

+#pragma pack()

+

+typedef union {

+  EFI_COMMON_SECTION_HEADER         *CommonHeader;

+  EFI_COMPRESSION_SECTION           *CompressionSection;

+  EFI_GUID_DEFINED_SECTION          *GuidDefinedSection;

+  EFI_PE32_SECTION                  *Pe32Section;

+  EFI_PIC_SECTION                   *PicSection;

+  EFI_PEIM_HEADER_SECTION           *PeimHeaderSection;

+  EFI_DEPEX_SECTION                 *DependencySection;

+  EFI_VERSION_SECTION               *VersionSection;

+  EFI_USER_INTERFACE_SECTION        *UISection;

+  EFI_CODE16_SECTION                *Code16Section;

+  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FVImageSection;

+  EFI_FREEFORM_SUBTYPE_GUID_SECTION *FreeformSubtypeSection;

+  EFI_RAW_SECTION                   *RawSection;

+} EFI_FILE_SECTION_POINTER;

+

+#endif

diff --git a/Source/Include/Common/InternalFormRepresentation.h b/Source/Include/Common/InternalFormRepresentation.h
new file mode 100644
index 0000000..bf3d824
--- /dev/null
+++ b/Source/Include/Common/InternalFormRepresentation.h
@@ -0,0 +1,422 @@
+/** @file

+  This file defines the encoding for the VFR (Visual Form Representation) language.

+  IFR is primarily consumed by the EFI presentation engine, and produced by EFI

+  internal application and drivers as well as all add-in card option-ROM drivers

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  InternalFormRepresentation.h

+

+  @par Revision Reference:

+  These definitions are from Human Interface Infrastructure Spec Version 0.92.

+

+**/

+

+#ifndef __EFI_INTERNAL_FORM_REPRESENTATION_H__

+#define __EFI_INTERNAL_FORM_REPRESENTATION_H__

+

+//

+// The following types are currently defined:

+//

+typedef UINT32  RELOFST;

+typedef CHAR16  *EFI_STRING;

+

+//

+// IFR Op codes

+//

+#define EFI_IFR_FORM_OP                 0x01

+#define EFI_IFR_SUBTITLE_OP             0x02

+#define EFI_IFR_TEXT_OP                 0x03

+#define EFI_IFR_GRAPHIC_OP              0x04

+#define EFI_IFR_ONE_OF_OP               0x05

+#define EFI_IFR_CHECKBOX_OP             0x06

+#define EFI_IFR_NUMERIC_OP              0x07

+#define EFI_IFR_PASSWORD_OP             0x08

+#define EFI_IFR_ONE_OF_OPTION_OP        0x09  // ONEOF OPTION field

+#define EFI_IFR_SUPPRESS_IF_OP          0x0A

+#define EFI_IFR_END_FORM_OP             0x0B

+#define EFI_IFR_HIDDEN_OP               0x0C

+#define EFI_IFR_END_FORM_SET_OP         0x0D

+#define EFI_IFR_FORM_SET_OP             0x0E

+#define EFI_IFR_REF_OP                  0x0F

+#define EFI_IFR_END_ONE_OF_OP           0x10

+#define EFI_IFR_END_OP                  EFI_IFR_END_ONE_OF_OP

+#define EFI_IFR_INCONSISTENT_IF_OP      0x11

+#define EFI_IFR_EQ_ID_VAL_OP            0x12

+#define EFI_IFR_EQ_ID_ID_OP             0x13

+#define EFI_IFR_EQ_ID_LIST_OP           0x14

+#define EFI_IFR_AND_OP                  0x15

+#define EFI_IFR_OR_OP                   0x16

+#define EFI_IFR_NOT_OP                  0x17

+#define EFI_IFR_END_IF_OP               0x18  // for endif of inconsistentif, suppressif, grayoutif

+#define EFI_IFR_GRAYOUT_IF_OP           0x19

+#define EFI_IFR_DATE_OP                 0x1A

+#define EFI_IFR_TIME_OP                 0x1B

+#define EFI_IFR_STRING_OP               0x1C

+#define EFI_IFR_LABEL_OP                0x1D

+#define EFI_IFR_SAVE_DEFAULTS_OP        0x1E

+#define EFI_IFR_RESTORE_DEFAULTS_OP     0x1F

+#define EFI_IFR_BANNER_OP               0x20

+#define EFI_IFR_INVENTORY_OP            0x21

+#define EFI_IFR_EQ_VAR_VAL_OP           0x22

+#define EFI_IFR_ORDERED_LIST_OP         0x23

+#define EFI_IFR_VARSTORE_OP             0x24

+#define EFI_IFR_VARSTORE_SELECT_OP      0x25

+#define EFI_IFR_VARSTORE_SELECT_PAIR_OP 0x26

+#define EFI_IFR_TRUE_OP                 0x27

+#define EFI_IFR_FALSE_OP                0x28

+#define EFI_IFR_GT_OP                   0x29

+#define EFI_IFR_GE_OP                   0x2A

+#define EFI_IFR_OEM_DEFINED_OP          0x2B

+#define EFI_IFR_LAST_OPCODE             EFI_IFR_OEM_DEFINED_OP

+#define EFI_IFR_OEM_OP                  0xFE

+#define EFI_IFR_NV_ACCESS_COMMAND       0xFF

+

+//

+// Define values for the flags fields in some VFR opcodes. These are

+// bitmasks.

+//

+#define EFI_IFR_FLAG_DEFAULT              0x01

+#define EFI_IFR_FLAG_MANUFACTURING        0x02

+#define EFI_IFR_FLAG_INTERACTIVE          0x04

+#define EFI_IFR_FLAG_NV_ACCESS            0x08

+#define EFI_IFR_FLAG_RESET_REQUIRED       0x10

+#define EFI_IFR_FLAG_LATE_CHECK           0x20

+

+#define EFI_NON_DEVICE_CLASS              0x00  // Useful when you do not want something in the Device Manager

+#define EFI_DISK_DEVICE_CLASS             0x01

+#define EFI_VIDEO_DEVICE_CLASS            0x02

+#define EFI_NETWORK_DEVICE_CLASS          0x04

+#define EFI_INPUT_DEVICE_CLASS            0x08

+#define EFI_ON_BOARD_DEVICE_CLASS         0x10

+#define EFI_OTHER_DEVICE_CLASS            0x20

+

+#define EFI_SETUP_APPLICATION_SUBCLASS    0x00

+#define EFI_GENERAL_APPLICATION_SUBCLASS  0x01

+#define EFI_FRONT_PAGE_SUBCLASS           0x02

+#define EFI_SINGLE_USE_SUBCLASS           0x03  // Used to display a single entity and then exit

+

+//

+// Used to flag dynamically created op-codes. This is meaningful to the IFR Library set

+// and the browser since we need to distinguish between compiled NV map data and created data.

+// We do not allow new entries to be created in the NV map dynamically however we still need

+// to display this information correctly.  To dynamically create op-codes and assume that their

+// data will be saved, ensure that the NV starting location they refer to is pre-defined in the

+// NV map.

+//

+#define EFI_IFR_FLAG_CREATED  128

+

+#pragma pack(1)

+//

+// IFR Structure definitions

+//

+typedef struct {

+  UINT8 OpCode;

+  UINT8 Length;

+} EFI_IFR_OP_HEADER;

+

+typedef struct {

+  EFI_IFR_OP_HEADER     Header;

+  EFI_GUID              Guid;

+  STRING_REF            FormSetTitle;

+  STRING_REF            Help;

+  EFI_PHYSICAL_ADDRESS  CallbackHandle;

+  UINT16                Class;

+  UINT16                SubClass;

+  UINT16                NvDataSize; // set once, size of the NV data as defined in the script

+} EFI_IFR_FORM_SET;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            FormId;

+  STRING_REF        FormTitle;

+} EFI_IFR_FORM;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            LabelId;

+} EFI_IFR_LABEL;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        SubTitle;

+} EFI_IFR_SUBTITLE;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        Help;

+  STRING_REF        Text;

+  STRING_REF        TextTwo;

+  UINT8             Flags;          // This is included solely for purposes of interactive/dynamic support.

+  UINT16            Key;            // Value to be passed to caller to identify this particular op-code

+} EFI_IFR_TEXT;

+

+//

+// goto

+//

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            FormId;

+  STRING_REF        Prompt;

+  STRING_REF        Help;   // The string Token for the context-help

+  UINT8             Flags;  // This is included solely for purposes of interactive/dynamic support.

+  UINT16            Key;    // Value to be passed to caller to identify this particular op-code

+} EFI_IFR_REF;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_END_FORM;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_END_FORM_SET;

+

+//

+// Also notice that the IFR_ONE_OF and IFR_CHECK_BOX are identical in structure......code assumes this to be true, if this ever

+// changes we need to revisit the InitializeTagStructures code

+//

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name

+  UINT8             Width;      // The Size of the Data being saved

+  STRING_REF        Prompt;     // The String Token for the Prompt

+  STRING_REF        Help;       // The string Token for the context-help

+} EFI_IFR_ONE_OF;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId; // The offset in NV for storage of the data

+  UINT8             MaxEntries; // The maximum number of options in the ordered list (=size of NVStore)

+  STRING_REF        Prompt;     // The string token for the prompt

+  STRING_REF        Help;       // The string token for the context-help

+} EFI_IFR_ORDERED_LIST;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name

+  UINT8             Width;      // The Size of the Data being saved

+  STRING_REF        Prompt;     // The String Token for the Prompt

+  STRING_REF        Help;       // The string Token for the context-help

+  UINT8             Flags;      // For now, if non-zero, means that it is the default option, - further definition likely

+  UINT16            Key;        // Value to be passed to caller to identify this particular op-code

+} EFI_IFR_CHECKBOX, EFI_IFR_CHECK_BOX;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        Option;     // The string token describing the option

+  UINT16            Value;      // The value associated with this option that is stored in the NVRAM if chosen

+  UINT8             Flags;      // For now, if non-zero, means that it is the default option, - further definition likely above

+  UINT16            Key;        // Value to be passed to caller to identify this particular op-code

+} EFI_IFR_ONE_OF_OPTION;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name

+  UINT8             Width;      // The Size of the Data being saved

+  STRING_REF        Prompt;     // The String Token for the Prompt

+  STRING_REF        Help;       // The string Token for the context-help

+  UINT8             Flags;      // This is included solely for purposes of interactive/dynamic support.

+  UINT16            Key;        // Value to be passed to caller to identify this particular op-code

+  UINT16            Minimum;

+  UINT16            Maximum;

+  UINT16            Step;       // If step is 0, then manual input is specified, otherwise, left/right arrow selection is called for

+  UINT16            Default;

+} EFI_IFR_NUMERIC;

+

+//

+// There is an interesting twist with regards to Time and Date.  This is one of the few items which can accept input from

+// a user, however may or may not need to use storage in the NVRAM space.  The decided method for determining if NVRAM space

+// will be used (only for a TimeOp or DateOp) is:  If .QuestionId == 0 && .Width == 0 (normally an impossibility) then use system

+// resources to store the data away and not NV resources.  In other words, the setup engine will call gRT->SetTime, and gRT->SetDate

+// for the saving of data, and the values displayed will be from the gRT->GetXXXX series of calls.

+//

+typedef struct {

+  EFI_IFR_NUMERIC Hour;

+  EFI_IFR_NUMERIC Minute;

+  EFI_IFR_NUMERIC Second;

+} EFI_IFR_TIME;

+

+typedef struct {

+  EFI_IFR_NUMERIC Year;

+  EFI_IFR_NUMERIC Month;

+  EFI_IFR_NUMERIC Day;

+} EFI_IFR_DATE;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId;   // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name

+  UINT8             Width;        // The Size of the Data being saved -- BUGBUG -- remove someday

+  STRING_REF        Prompt;       // The String Token for the Prompt

+  STRING_REF        Help;         // The string Token for the context-help

+  UINT8             Flags;        // This is included solely for purposes of interactive/dynamic support.

+  UINT16            Key;          // Value to be passed to caller to identify this particular op-code

+  UINT8             MinSize;      // Minimum allowable sized password

+  UINT8             MaxSize;      // Maximum allowable sized password

+  UINT16            Encoding;

+} EFI_IFR_PASSWORD;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId;   // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name

+  UINT8             Width;        // The Size of the Data being saved -- BUGBUG -- remove someday

+  STRING_REF        Prompt;       // The String Token for the Prompt

+  STRING_REF        Help;         // The string Token for the context-help

+  UINT8             Flags;        // This is included solely for purposes of interactive/dynamic support.

+  UINT16            Key;          // Value to be passed to caller to identify this particular op-code

+  UINT8             MinSize;      // Minimum allowable sized password

+  UINT8             MaxSize;      // Maximum allowable sized password

+} EFI_IFR_STRING;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_END_ONE_OF;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            Value;

+  UINT16            Key;

+} EFI_IFR_HIDDEN;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT8             Flags;

+} EFI_IFR_SUPPRESS;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT8             Flags;

+} EFI_IFR_GRAY_OUT;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        Popup;

+  UINT8             Flags;

+} EFI_IFR_INCONSISTENT;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId;   // offset into variable storage

+  UINT8             Width;        // size of variable storage

+  UINT16            Value;        // value to compare against

+} EFI_IFR_EQ_ID_VAL;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId;   // offset into variable storage

+  UINT8             Width;        // size of variable storage

+  UINT16            ListLength;

+  UINT16            ValueList[1];

+} EFI_IFR_EQ_ID_LIST;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            QuestionId1;  // offset into variable storage for first value to compare

+  UINT8             Width;        // size of variable storage (must be same for both)

+  UINT16            QuestionId2;  // offset into variable storage for second value to compare

+} EFI_IFR_EQ_ID_ID;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            VariableId;   // offset into variable storage

+  UINT16            Value;        // value to compare against

+} EFI_IFR_EQ_VAR_VAL;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_AND;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_OR;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_NOT;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_END_EXPR, EFI_IFR_END_IF;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            FormId;

+  STRING_REF        Prompt;

+  STRING_REF        Help;

+  UINT8             Flags;

+  UINT16            Key;

+} EFI_IFR_SAVE_DEFAULTS;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        Help;

+  STRING_REF        Text;

+  STRING_REF        TextTwo;      // optional text

+} EFI_IFR_INVENTORY;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  EFI_GUID          Guid;         // GUID for the variable

+  UINT16            VarId;        // variable store ID, as referenced elsewhere in the form

+  UINT16            Size;         // size of the variable storage

+} EFI_IFR_VARSTORE;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            VarId;        // variable store ID, as referenced elsewhere in the form

+} EFI_IFR_VARSTORE_SELECT;

+

+//

+// Used for the ideqid VFR statement where two variable stores may be referenced in the

+// same VFR statement.

+// A browser should treat this as an EFI_IFR_VARSTORE_SELECT statement and assume that all following

+// IFR opcodes use the VarId as defined here.

+//

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  UINT16            VarId;          // variable store ID, as referenced elsewhere in the form

+  UINT16            SecondaryVarId; // variable store ID, as referenced elsewhere in the form

+} EFI_IFR_VARSTORE_SELECT_PAIR;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_TRUE;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_FALSE;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_GT;

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+} EFI_IFR_GE;

+

+//

+// Save defaults and restore defaults have same structure

+//

+#define EFI_IFR_RESTORE_DEFAULTS  EFI_IFR_SAVE_DEFAULTS

+

+typedef struct {

+  EFI_IFR_OP_HEADER Header;

+  STRING_REF        Title;        // The string token for the banner title

+  UINT16            LineNumber;   // 1-based line number

+  UINT8             Alignment;    // left, center, or right-aligned

+} EFI_IFR_BANNER;

+

+#define EFI_IFR_BANNER_ALIGN_LEFT   0

+#define EFI_IFR_BANNER_ALIGN_CENTER 1

+#define EFI_IFR_BANNER_ALIGN_RIGHT  2

+#define EFI_IFR_BANNER_TIMEOUT      0xFF

+

+#pragma pack()

+

+#endif

diff --git a/Source/Include/Common/MultiPhase.h b/Source/Include/Common/MultiPhase.h
new file mode 100644
index 0000000..93867a5
--- /dev/null
+++ b/Source/Include/Common/MultiPhase.h
@@ -0,0 +1,84 @@
+/** @file

+  This includes some definitions that will be used in both PEI and DXE phases.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  MultiPhase.h

+

+**/

+

+#ifndef __MULTI_PHASE_H__

+#define __MULTI_PHASE_H__

+

+//

+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+//

+// Needed EFI defines for PEI

+//

+typedef UINT64  EFI_PHYSICAL_ADDRESS;

+

+typedef enum {

+  EfiReservedMemoryType,

+  EfiLoaderCode,

+  EfiLoaderData,

+  EfiBootServicesCode,

+  EfiBootServicesData,

+  EfiRuntimeServicesCode,

+  EfiRuntimeServicesData,

+  EfiConventionalMemory,

+  EfiUnusableMemory,

+  EfiACPIReclaimMemory,

+  EfiACPIMemoryNVS,

+  EfiMemoryMappedIO,

+  EfiMemoryMappedIOPortSpace,

+  EfiPalCode,

+  EfiMaxMemoryType

+} EFI_MEMORY_TYPE;

+

+typedef UINT32  EFI_STATUS_CODE_TYPE;

+typedef UINT32  EFI_STATUS_CODE_VALUE;

+

+typedef struct {

+  UINT16    HeaderSize;

+  UINT16    Size;

+  EFI_GUID  Type;

+} EFI_STATUS_CODE_DATA;

+

+typedef struct {

+  UINT64  Signature;

+  UINT32  Revision;

+  UINT32  HeaderSize;

+  UINT32  CRC32;

+  UINT32  Reserved;

+} EFI_TABLE_HEADER;

+

+#define EFI_PAGE_SIZE         4096

+

+

+typedef VOID    *EFI_HANDLE;

+typedef UINT16  EFI_HII_HANDLE;

+typedef UINT16  STRING_REF;

+typedef struct {

+  INT16     Value;

+  INT16     Exponent;

+} EFI_EXP_BASE10_DATA;

+

+//

+// Define macros to build data structure signatures from characters.

+//

+#define EFI_SIGNATURE_16(A, B)        ((A) | (B << 8))

+#define EFI_SIGNATURE_32(A, B, C, D)  (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16))

+#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \

+    (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32))

+

+

+#include <Protocol/DevicePath.h>

+

+#endif

diff --git a/Source/Include/Common/UefiBaseTypes.h b/Source/Include/Common/UefiBaseTypes.h
new file mode 100644
index 0000000..4954c10
--- /dev/null
+++ b/Source/Include/Common/UefiBaseTypes.h
@@ -0,0 +1,85 @@
+/** @file

+  This file makes the BaseTypes.h backward compatible with the ones used in the 

+  past for EFI and Tiano development. It's mostly just prepending an EFI_ on the 

+  definitions.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  UefiBaseTypes.h

+

+**/

+

+#ifndef __UEFI_BASE_TYPES_H__

+#define __UEFI_BASE_TYPES_H__

+

+#include <Common/BaseTypes.h>

+

+typedef UINT64    EFI_LBA;

+

+#define EFIERR(_a)                    ENCODE_ERROR(_a)

+

+#define EFI_MAX_BIT                   MAX_BIT

+#define EFI_MAX_ADDRESS               MAX_ADDRESS

+#define EFI_BREAKPOINT()              CpuBreakpoint ()

+#define EFI_DEADLOOP()                CpuDeadLoop ()

+#define EFI_ERROR(A)                  RETURN_ERROR(A)

+

+typedef GUID          EFI_GUID;

+typedef RETURN_STATUS EFI_STATUS;

+

+#define EFI_SUCCESS               RETURN_SUCCESS              

+#define EFI_LOAD_ERROR            RETURN_LOAD_ERROR           

+#define EFI_INVALID_PARAMETER     RETURN_INVALID_PARAMETER    

+#define EFI_UNSUPPORTED           RETURN_UNSUPPORTED          

+#define EFI_BAD_BUFFER_SIZE       RETURN_BAD_BUFFER_SIZE      

+#define EFI_BUFFER_TOO_SMALL      RETURN_BUFFER_TOO_SMALL     

+#define EFI_NOT_READY             RETURN_NOT_READY            

+#define EFI_DEVICE_ERROR          RETURN_DEVICE_ERROR         

+#define EFI_WRITE_PROTECTED       RETURN_WRITE_PROTECTED      

+#define EFI_OUT_OF_RESOURCES      RETURN_OUT_OF_RESOURCES     

+#define EFI_VOLUME_CORRUPTED      RETURN_VOLUME_CORRUPTED     

+#define EFI_VOLUME_FULL           RETURN_VOLUME_FULL          

+#define EFI_NO_MEDIA              RETURN_NO_MEDIA             

+#define EFI_MEDIA_CHANGED         RETURN_MEDIA_CHANGED        

+#define EFI_NOT_FOUND             RETURN_NOT_FOUND            

+#define EFI_ACCESS_DENIED         RETURN_ACCESS_DENIED        

+#define EFI_NO_RESPONSE           RETURN_NO_RESPONSE          

+#define EFI_NO_MAPPING            RETURN_NO_MAPPING           

+#define EFI_TIMEOUT               RETURN_TIMEOUT              

+#define EFI_NOT_STARTED           RETURN_NOT_STARTED          

+#define EFI_ALREADY_STARTED       RETURN_ALREADY_STARTED      

+#define EFI_ABORTED               RETURN_ABORTED              

+#define EFI_ICMP_ERROR            RETURN_ICMP_ERROR           

+#define EFI_TFTP_ERROR            RETURN_TFTP_ERROR           

+#define EFI_PROTOCOL_ERROR        RETURN_PROTOCOL_ERROR       

+#define EFI_INCOMPATIBLE_VERSION  RETURN_INCOMPATIBLE_VERSION 

+#define EFI_SECURITY_VIOLATION    RETURN_SECURITY_VIOLATION   

+#define EFI_CRC_ERROR             RETURN_CRC_ERROR   

+#define EFI_END_OF_MEDIA          RETURN_END_OF_MEDIA

+#define EFI_END_OF_FILE           RETURN_END_OF_FILE

+

+#define EFI_WARN_UNKNOWN_GLYPH    RETURN_WARN_UNKNOWN_GLYPH   

+#define EFI_WARN_DELETE_FAILURE   RETURN_WARN_DELETE_FAILURE  

+#define EFI_WARN_WRITE_FAILURE    RETURN_WARN_WRITE_FAILURE   

+#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL

+

+//

+// The EFI memory allocation functions work in units of EFI_PAGEs that are

+// 4K. This should in no way be confused with the page size of the processor.

+// An EFI_PAGE is just the quanta of memory in EFI.

+//

+#define EFI_PAGE_MASK         0xFFF

+#define EFI_PAGE_SHIFT        12

+

+#define EFI_SIZE_TO_PAGES(a)  (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0))

+

+#define EFI_PAGES_TO_SIZE(a)   ( (a) << EFI_PAGE_SHIFT)

+

+#endif

diff --git a/Source/Include/Common/Variable.h b/Source/Include/Common/Variable.h
new file mode 100644
index 0000000..bc0d640
--- /dev/null
+++ b/Source/Include/Common/Variable.h
@@ -0,0 +1,78 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiVariable.h

+  

+Abstract:

+  

+  Header file for EFI Variable Services

+

+--*/

+

+#ifndef _EFI_VARIABLE_H_

+#define _EFI_VARIABLE_H_

+

+#define VARIABLE_STORE_SIGNATURE  EFI_SIGNATURE_32 ('$', 'V', 'S', 'S')

+

+#define MAX_VARIABLE_SIZE         1024

+

+#define VARIABLE_DATA             0x55AA

+

+//

+// Variable Store Header flags

+//

+#define VARIABLE_STORE_FORMATTED  0x5a

+#define VARIABLE_STORE_HEALTHY    0xfe

+

+//

+// Variable Store Status

+//

+typedef enum {

+  EfiRaw,

+  EfiValid,

+  EfiInvalid,

+  EfiUnknown

+} VARIABLE_STORE_STATUS;

+

+//

+// Variable State flags

+//

+#define VAR_IN_DELETED_TRANSITION     0xfe  // Variable is in obsolete transistion

+#define VAR_DELETED                   0xfd  // Variable is obsolete

+#define VAR_ADDED                     0x7f  // Variable has been completely added

+#define IS_VARIABLE_STATE(_c, _Mask)  (BOOLEAN) (((~_c) & (~_Mask)) != 0)

+

+#pragma pack(1)

+

+typedef struct {

+  UINT32  Signature;

+  UINT32  Size;

+  UINT8   Format;

+  UINT8   State;

+  UINT16  Reserved;

+  UINT32  Reserved1;

+} VARIABLE_STORE_HEADER;

+

+typedef struct {

+  UINT16    StartId;

+  UINT8     State;

+  UINT8     Reserved;

+  UINT32    Attributes;

+  UINTN     NameSize;

+  UINTN     DataSize;

+  EFI_GUID  VendorGuid;

+} VARIABLE_HEADER;

+

+#pragma pack()

+

+#endif // _EFI_VARIABLE_H_

diff --git a/Source/Include/Common/WorkingBlockHeader.h b/Source/Include/Common/WorkingBlockHeader.h
new file mode 100644
index 0000000..235b740
--- /dev/null
+++ b/Source/Include/Common/WorkingBlockHeader.h
@@ -0,0 +1,47 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiWorkingBlockHeader.h

+

+Abstract:

+

+  Defines data structure that is the headers found at the runtime 

+  updatable firmware volumes, such as the FileSystemGuid of the 

+  working block, the header structure of the variable block, FTW

+  working block, or event log block.

+

+--*/

+

+#ifndef _EFI_WORKING_BLOCK_HEADER_H_

+#define _EFI_WORKING_BLOCK_HEADER_H_

+

+//

+// EFI Fault tolerant working block header

+// The header is immediately followed by the write queue.

+//

+typedef struct {

+  EFI_GUID  Signature;

+  UINT32    Crc;

+  UINT32    WorkingBlockValid : 1;

+  UINT32    WorkingBlockInvalid : 1;

+#define WORKING_BLOCK_VALID   0x1

+#define WORKING_BLOCK_INVALID 0x2

+  UINT32    Reserved : 6;

+  UINT8     Reserved3[3];

+  UINTN     WriteQueueSize;

+  //

+  // UINT8                WriteQueue[WriteQueueSize];

+  //

+} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER;

+

+#endif

diff --git a/Source/Include/Guid/AcpiTableStorage.h b/Source/Include/Guid/AcpiTableStorage.h
new file mode 100644
index 0000000..80b1154
--- /dev/null
+++ b/Source/Include/Guid/AcpiTableStorage.h
@@ -0,0 +1,30 @@
+/** @file

+  The ACPI table storage file is fully FFS compliant. 

+  The file is a number of sections of type EFI_SECTION_RAW.

+  This GUID is used to identify the file as an ACPI table storage file.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  AcpiTableStorage.h

+

+  @par Revision Reference:

+  GUID defined in ACPI Table Storage Spec Version 0.9.

+

+**/

+

+#ifndef _ACPI_TABLE_STORAGE_H_

+#define _ACPI_TABLE_STORAGE_H_

+

+#define EFI_ACPI_TABLE_STORAGE_GUID \

+  { 0x7e374e25, 0x8e01, 0x4fee, {0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd } }

+

+extern EFI_GUID gEfiAcpiTableStorageGuid;

+

+#endif

diff --git a/Source/Include/Guid/Apriori.h b/Source/Include/Guid/Apriori.h
new file mode 100644
index 0000000..ba92560
--- /dev/null
+++ b/Source/Include/Guid/Apriori.h
@@ -0,0 +1,32 @@
+/** @file

+  GUID used as an FV filename for A Priori file. The A Priori file contains a

+  list of FV filenames that the DXE dispatcher will schedule reguardless of

+  the dependency grammer.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  Apriori.h

+

+  @par Revision Reference:

+  GUID defined in DXE CIS spec version 0.91B

+

+**/

+

+#ifndef __APRIORI_GUID_H__

+#define __APRIORI_GUID_H__

+

+#define EFI_APRIORI_GUID \

+  { \

+    0xfc510ee7, 0xffdc, 0x11d4, {0xbd, 0x41, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \

+  }

+

+extern EFI_GUID gAprioriGuid;

+

+#endif

diff --git a/Source/Include/Guid/Capsule.h b/Source/Include/Guid/Capsule.h
new file mode 100644
index 0000000..7864b92
--- /dev/null
+++ b/Source/Include/Guid/Capsule.h
@@ -0,0 +1,43 @@
+/** @file

+  GUIDs used for EFI Capsule

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  Capsule.h

+

+  @par Revision Reference:

+  GUIDs defined in Capsule Spec Version 0.9

+

+**/

+

+#ifndef __CAPSULE_GUID_H__

+#define __CAPSULE_GUID_H__

+

+//

+// This is the GUID of the capsule header of the image on disk.

+//

+#define EFI_CAPSULE_GUID \

+  { \

+    0x3B6686BD, 0x0D76, 0x4030, {0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 } \

+  }

+

+//

+// This is the GUID of the configuration results file created by the capsule

+// application.

+//

+#define EFI_CONFIG_FILE_NAME_GUID \

+  { \

+    0x98B8D59B, 0xE8BA, 0x48EE, {0x98, 0xDD, 0xC2, 0x95, 0x39, 0x2F, 0x1E, 0xDB } \

+  }

+

+extern EFI_GUID gEfiCapsuleGuid;

+extern EFI_GUID gEfiConfigFileNameGuid;

+

+#endif

diff --git a/Source/Include/Guid/FirmwareFileSystem.h b/Source/Include/Guid/FirmwareFileSystem.h
new file mode 100644
index 0000000..06bfa7d
--- /dev/null
+++ b/Source/Include/Guid/FirmwareFileSystem.h
@@ -0,0 +1,40 @@
+/** @file

+  Guid used to define the Firmware File System.  See the Framework Firmware 

+  File System Specification for more details.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  FirmwareFileSystem.h

+

+  @par Revision Reference:

+  Guids defined in Firmware File System Spec 0.9

+

+**/

+

+#ifndef __FIRMWARE_FILE_SYSTEM_GUID_H__

+#define __FIRMWARE_FILE_SYSTEM_GUID_H__

+

+//

+// GUIDs defined by the FFS specification.

+//

+#define EFI_FIRMWARE_FILE_SYSTEM_GUID \

+  { \

+    0x7A9354D9, 0x0468, 0x444a, {0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF } \

+  }

+

+#define EFI_FFS_VOLUME_TOP_FILE_GUID \

+  { \

+    0x1BA0062E, 0xC779, 0x4582, {0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x9 } \

+  }

+

+extern EFI_GUID gEfiFirmwareFileSystemGuid;

+extern EFI_GUID gEfiFirmwareVolumeTopFileGuid;

+

+#endif

diff --git a/Source/Include/Ia32/ProcessorBind.h b/Source/Include/Ia32/ProcessorBind.h
new file mode 100644
index 0000000..587d8a6
--- /dev/null
+++ b/Source/Include/Ia32/ProcessorBind.h
@@ -0,0 +1,167 @@
+/** @file

+  Processor or Compiler specific defines and types for x64.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  ProcessorBind.h

+

+**/

+

+#ifndef __PROCESSOR_BIND_H__

+#define __PROCESSOR_BIND_H__

+

+//

+// Define the processor type so other code can make processor based choices

+//

+#define MDE_CPU_IA32

+

+//

+// Make sure we are useing the correct packing rules per EFI specification

+//

+#ifndef __GNUC__

+#pragma pack()

+#endif

+

+#if _MSC_EXTENSIONS

+

+//

+// Disable warning that make it impossible to compile at /W4

+// This only works for Microsoft* tools

+//

+

+//

+// Disabling bitfield type checking warnings.

+//

+#pragma warning ( disable : 4214 )

+

+//

+// Disabling the unreferenced formal parameter warnings.

+//

+#pragma warning ( disable : 4100 )

+

+//

+// Disable slightly different base types warning as CHAR8 * can not be set

+// to a constant string.

+//

+#pragma warning ( disable : 4057 )

+

+//

+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning

+//

+#pragma warning ( disable : 4127 )

+

+

+#endif

+

+

+#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L)

+  //

+  // No ANSI C 2000 stdint.h integer width declarations, so define equivalents

+  //

+ 

+  #if _MSC_EXTENSIONS 

+    

+    //

+    // use Microsoft* C complier dependent interger width types 

+    //

+    typedef unsigned __int64    UINT64;

+    typedef __int64             INT64;

+    typedef unsigned __int32    UINT32;

+    typedef __int32             INT32;

+    typedef unsigned short      UINT16;

+    typedef unsigned short      CHAR16;

+    typedef short               INT16;

+    typedef unsigned char       BOOLEAN;

+    typedef unsigned char       UINT8;

+    typedef char                CHAR8;

+    typedef char                INT8;

+  #else

+

+    //

+    // Assume standard IA-32 alignment. 

+    // BugBug: Need to check portability of long long

+    //

+    typedef unsigned long long  UINT64;

+    typedef long long           INT64;

+    typedef unsigned int        UINT32;

+    typedef int                 INT32;

+    typedef unsigned short      UINT16;

+    typedef unsigned short      CHAR16;

+    typedef short               INT16;

+    typedef unsigned char       BOOLEAN;

+    typedef unsigned char       UINT8;

+    typedef char                CHAR8;

+    typedef char                INT8;

+  #endif

+

+  #define UINT8_MAX 0xff

+

+#else

+  //

+  // Use ANSI C 2000 stdint.h integer width declarations

+  //

+  #include "stdint.h"

+  typedef uint8_t   BOOLEAN;

+  typedef int8_t    INT8;

+  typedef uint8_t   UINT8;

+  typedef int16_t   INT16;

+  typedef uint16_t  UINT16;

+  typedef int32_t   INT32;

+  typedef uint32_t  UINT32;

+  typedef int64_t   INT64;

+  typedef uint64_t  UINT64;

+  typedef char      CHAR8;

+  typedef uint16_t  CHAR16;

+

+#endif

+

+typedef UINT32  UINTN;

+typedef INT32   INTN;

+

+

+//

+// Processor specific defines

+//

+#define MAX_BIT     0x80000000

+#define MAX_2_BITS  0xC0000000

+

+//

+// Maximum legal IA-32 address

+//

+#define MAX_ADDRESS   0xFFFFFFFF

+

+//

+// Modifier to ensure that all protocol member functions and EFI intrinsics

+// use the correct C calling convention. All protocol member functions and

+// EFI intrinsics are required to modify thier member functions with EFIAPI.

+//

+#if _MSC_EXTENSIONS

+  //

+  // Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C.

+  // 

+  #define EFIAPI __cdecl  

+#endif

+

+#if __GNUC__

+  #define EFIAPI __attribute__((cdecl))    

+#endif

+

+//

+// The Microsoft* C compiler can removed references to unreferenced data items

+//  if the /OPT:REF linker option is used. We defined a macro as this is a 

+//  a non standard extension

+//

+#if _MSC_EXTENSIONS

+  #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany)

+#else

+  #define GLOBAL_REMOVE_IF_UNREFERENCED

+#endif

+

+#endif

diff --git a/Source/Include/IndustryStandard/pci22.h b/Source/Include/IndustryStandard/pci22.h
new file mode 100644
index 0000000..7fee279
--- /dev/null
+++ b/Source/Include/IndustryStandard/pci22.h
@@ -0,0 +1,481 @@
+/** @file

+  Support for PCI 2.2 standard.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  pci22.h

+

+**/

+

+#ifndef _PCI22_H

+#define _PCI22_H

+

+#define PCI_MAX_SEGMENT 0

+

+#define PCI_MAX_BUS     255

+

+#define PCI_MAX_DEVICE  31

+#define PCI_MAX_FUNC    7

+

+//

+// Command

+//

+#define PCI_VGA_PALETTE_SNOOP_DISABLED  0x20

+

+#pragma pack(push, 1)

+typedef struct {

+  UINT16  VendorId;

+  UINT16  DeviceId;

+  UINT16  Command;

+  UINT16  Status;

+  UINT8   RevisionID;

+  UINT8   ClassCode[3];

+  UINT8   CacheLineSize;

+  UINT8   LatencyTimer;

+  UINT8   HeaderType;

+  UINT8   BIST;

+} PCI_DEVICE_INDEPENDENT_REGION;

+

+typedef struct {

+  UINT32  Bar[6];

+  UINT32  CISPtr;

+  UINT16  SubsystemVendorID;

+  UINT16  SubsystemID;

+  UINT32  ExpansionRomBar;

+  UINT8   CapabilityPtr;

+  UINT8   Reserved1[3];

+  UINT32  Reserved2;

+  UINT8   InterruptLine;

+  UINT8   InterruptPin;

+  UINT8   MinGnt;

+  UINT8   MaxLat;

+} PCI_DEVICE_HEADER_TYPE_REGION;

+

+typedef struct {

+  PCI_DEVICE_INDEPENDENT_REGION Hdr;

+  PCI_DEVICE_HEADER_TYPE_REGION Device;

+} PCI_TYPE00;

+

+typedef struct {

+  UINT32  Bar[2];

+  UINT8   PrimaryBus;

+  UINT8   SecondaryBus;

+  UINT8   SubordinateBus;

+  UINT8   SecondaryLatencyTimer;

+  UINT8   IoBase;

+  UINT8   IoLimit;

+  UINT16  SecondaryStatus;

+  UINT16  MemoryBase;

+  UINT16  MemoryLimit;

+  UINT16  PrefetchableMemoryBase;

+  UINT16  PrefetchableMemoryLimit;

+  UINT32  PrefetchableBaseUpper32;

+  UINT32  PrefetchableLimitUpper32;

+  UINT16  IoBaseUpper16;

+  UINT16  IoLimitUpper16;

+  UINT8   CapabilityPtr;

+  UINT8   Reserved[3];

+  UINT32  ExpansionRomBAR;

+  UINT8   InterruptLine;

+  UINT8   InterruptPin;

+  UINT16  BridgeControl;

+} PCI_BRIDGE_CONTROL_REGISTER;

+

+typedef struct {

+  PCI_DEVICE_INDEPENDENT_REGION Hdr;

+  PCI_BRIDGE_CONTROL_REGISTER   Bridge;

+} PCI_TYPE01;

+

+typedef union {

+  PCI_TYPE00  Device;

+  PCI_TYPE01  Bridge;

+} PCI_TYPE_GENERIC;

+

+typedef struct {

+  UINT32  CardBusSocketReg; // Cardus Socket/ExCA Base

+  // Address Register

+  //

+  UINT16  Reserved;

+  UINT16  SecondaryStatus;      // Secondary Status

+  UINT8   PciBusNumber;         // PCI Bus Number

+  UINT8   CardBusBusNumber;     // CardBus Bus Number

+  UINT8   SubordinateBusNumber; // Subordinate Bus Number

+  UINT8   CardBusLatencyTimer;  // CardBus Latency Timer

+  UINT32  MemoryBase0;          // Memory Base Register 0

+  UINT32  MemoryLimit0;         // Memory Limit Register 0

+  UINT32  MemoryBase1;

+  UINT32  MemoryLimit1;

+  UINT32  IoBase0;

+  UINT32  IoLimit0;             // I/O Base Register 0

+  UINT32  IoBase1;              // I/O Limit Register 0

+  UINT32  IoLimit1;

+  UINT8   InterruptLine;        // Interrupt Line

+  UINT8   InterruptPin;         // Interrupt Pin

+  UINT16  BridgeControl;        // Bridge Control

+} PCI_CARDBUS_CONTROL_REGISTER;

+

+//

+// Definitions of PCI class bytes and manipulation macros.

+//

+#define PCI_CLASS_OLD                 0x00

+#define PCI_CLASS_OLD_OTHER           0x00

+#define PCI_CLASS_OLD_VGA             0x01

+

+#define PCI_CLASS_MASS_STORAGE        0x01

+#define PCI_CLASS_MASS_STORAGE_SCSI   0x00

+#define PCI_CLASS_MASS_STORAGE_IDE    0x01  // obsolete

+#define PCI_CLASS_IDE                 0x01

+#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02

+#define PCI_CLASS_MASS_STORAGE_IPI    0x03

+#define PCI_CLASS_MASS_STORAGE_RAID   0x04

+#define PCI_CLASS_MASS_STORAGE_OTHER  0x80

+

+#define PCI_CLASS_NETWORK             0x02

+#define PCI_CLASS_NETWORK_ETHERNET    0x00

+#define PCI_CLASS_ETHERNET            0x00  // obsolete

+#define PCI_CLASS_NETWORK_TOKENRING   0x01

+#define PCI_CLASS_NETWORK_FDDI        0x02

+#define PCI_CLASS_NETWORK_ATM         0x03

+#define PCI_CLASS_NETWORK_ISDN        0x04

+#define PCI_CLASS_NETWORK_OTHER       0x80

+

+#define PCI_CLASS_DISPLAY             0x03

+#define PCI_CLASS_DISPLAY_CTRL        0x03  // obsolete

+#define PCI_CLASS_DISPLAY_VGA         0x00

+#define PCI_CLASS_VGA                 0x00  // obsolete

+#define PCI_CLASS_DISPLAY_XGA         0x01

+#define PCI_CLASS_DISPLAY_3D          0x02

+#define PCI_CLASS_DISPLAY_OTHER       0x80

+#define PCI_CLASS_DISPLAY_GFX         0x80

+#define PCI_CLASS_GFX                 0x80  // obsolete

+#define PCI_CLASS_BRIDGE              0x06

+#define PCI_CLASS_BRIDGE_HOST         0x00

+#define PCI_CLASS_BRIDGE_ISA          0x01

+#define PCI_CLASS_ISA                 0x01  // obsolete

+#define PCI_CLASS_BRIDGE_EISA         0x02

+#define PCI_CLASS_BRIDGE_MCA          0x03

+#define PCI_CLASS_BRIDGE_P2P          0x04

+#define PCI_CLASS_BRIDGE_PCMCIA       0x05

+#define PCI_CLASS_BRIDGE_NUBUS        0x06

+#define PCI_CLASS_BRIDGE_CARDBUS      0x07

+#define PCI_CLASS_BRIDGE_RACEWAY      0x08

+#define PCI_CLASS_BRIDGE_ISA_PDECODE  0x80

+#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80  // obsolete

+#define PCI_CLASS_SERIAL              0x0C

+#define PCI_CLASS_SERIAL_FIREWIRE     0x00

+#define PCI_CLASS_SERIAL_ACCESS_BUS   0x01

+#define PCI_CLASS_SERIAL_SSA          0x02

+#define PCI_CLASS_SERIAL_USB          0x03

+#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04

+#define PCI_CLASS_SERIAL_SMB          0x05

+

+#define IS_CLASS1(_p, c)              ((_p)->Hdr.ClassCode[2] == (c))

+#define IS_CLASS2(_p, c, s)           (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s)))

+#define IS_CLASS3(_p, c, s, p)        (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p)))

+

+#define IS_PCI_DISPLAY(_p)            IS_CLASS1 (_p, PCI_CLASS_DISPLAY)

+#define IS_PCI_VGA(_p)                IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0)

+#define IS_PCI_8514(_p)               IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1)

+#define IS_PCI_GFX(_p)                IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0)

+#define IS_PCI_OLD(_p)                IS_CLASS1 (_p, PCI_CLASS_OLD)

+#define IS_PCI_OLD_VGA(_p)            IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA)

+#define IS_PCI_IDE(_p)                IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE)

+#define IS_PCI_SCSI(_p)               IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0)

+#define IS_PCI_RAID(_p)               IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0)

+#define IS_PCI_LPC(_p)                IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0)

+#define IS_PCI_P2P(_p)                IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0)

+#define IS_PCI_P2P_SUB(_p)            IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1)

+#define IS_PCI_USB(_p)                IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB)

+

+#define HEADER_TYPE_DEVICE            0x00

+#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01

+#define HEADER_TYPE_CARDBUS_BRIDGE    0x02

+

+#define HEADER_TYPE_MULTI_FUNCTION    0x80

+#define HEADER_LAYOUT_CODE            0x7f

+

+#define IS_PCI_BRIDGE(_p)             (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE))

+#define IS_CARDBUS_BRIDGE(_p)         (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE))

+#define IS_PCI_MULTI_FUNC(_p)         ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)

+

+#define PCI_DEVICE_ROMBAR             0x30

+#define PCI_BRIDGE_ROMBAR             0x38

+

+#define PCI_MAX_BAR                   6

+#define PCI_MAX_CONFIG_OFFSET         0x100

+//

+// bugbug: this is supported in PCI spec v2.3

+//

+#define PCI_EXP_MAX_CONFIG_OFFSET                   0x1000

+

+#define PCI_VENDOR_ID_OFFSET                        0x00

+#define PCI_DEVICE_ID_OFFSET                        0x02

+#define PCI_COMMAND_OFFSET                          0x04

+#define PCI_PRIMARY_STATUS_OFFSET                   0x06

+#define PCI_REVISION_ID_OFFSET                      0x08

+#define PCI_CLASSCODE_OFFSET                        0x09

+#define PCI_CACHELINE_SIZE_OFFSET                   0x0C

+#define PCI_LATENCY_TIMER_OFFSET                    0x0D

+#define PCI_HEADER_TYPE_OFFSET                      0x0E

+#define PCI_BIST_OFFSET                             0x0F

+

+#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET          0x3E

+#define PCI_BRIDGE_STATUS_REGISTER_OFFSET           0x1E

+

+#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET      0x18

+#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET    0x19

+#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET  0x1a

+

+typedef struct {

+  UINT8 Register;

+  UINT8 Function;

+  UINT8 Device;

+  UINT8 Bus;

+  UINT8 Reserved[4];

+} DEFIO_PCI_ADDR;

+

+typedef union {

+  struct {

+    UINT32  Reg : 8;

+    UINT32  Func : 3;

+    UINT32  Dev : 5;

+    UINT32  Bus : 8;

+    UINT32  Reserved : 7;

+    UINT32  Enable : 1;

+  } Bits;

+  UINT32  Uint32;

+} PCI_CONFIG_ACCESS_CF8;

+

+#pragma pack()

+

+#define EFI_ROOT_BRIDGE_LIST                            'eprb'

+#define PCI_EXPANSION_ROM_HEADER_SIGNATURE              0xaa55

+#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE       0x0EF1

+#define PCI_DATA_STRUCTURE_SIGNATURE                    EFI_SIGNATURE_32 ('P', 'C', 'I', 'R')

+#define PCI_CODE_TYPE_PCAT_IMAGE                        0x00

+#define PCI_CODE_TYPE_EFI_IMAGE                         0x03

+#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED         0x0001

+

+#define EFI_PCI_COMMAND_IO_SPACE                        0x0001

+#define EFI_PCI_COMMAND_MEMORY_SPACE                    0x0002

+#define EFI_PCI_COMMAND_BUS_MASTER                      0x0004

+#define EFI_PCI_COMMAND_SPECIAL_CYCLE                   0x0008

+#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE     0x0010

+#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP               0x0020

+#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND            0x0040

+#define EFI_PCI_COMMAND_STEPPING_CONTROL                0x0080

+#define EFI_PCI_COMMAND_SERR                            0x0100

+#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK               0x0200

+

+#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE    0x0001

+#define EFI_PCI_BRIDGE_CONTROL_SERR                     0x0002

+#define EFI_PCI_BRIDGE_CONTROL_ISA                      0x0004

+#define EFI_PCI_BRIDGE_CONTROL_VGA                      0x0008

+#define EFI_PCI_BRIDGE_CONTROL_VGA_16                   0x0010

+#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT             0x0020

+#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS      0x0040

+#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK        0x0080

+#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER    0x0100

+#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER  0x0200

+#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS             0x0400

+#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR       0x0800

+

+//

+// Following are the PCI-CARDBUS bridge control bit

+//

+#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE       0x0080

+#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE   0x0100

+#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE   0x0200

+#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400

+

+//

+// Following are the PCI status control bit

+//

+#define EFI_PCI_STATUS_CAPABILITY             0x0010

+#define EFI_PCI_STATUS_66MZ_CAPABLE           0x0020

+#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE     0x0080

+#define EFI_PCI_MASTER_DATA_PARITY_ERROR      0x0100

+

+#define EFI_PCI_CAPABILITY_PTR                0x34

+#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14

+

+#pragma pack(1)

+typedef struct {

+  UINT16  Signature;    // 0xaa55

+  UINT8   Reserved[0x16];

+  UINT16  PcirOffset;

+} PCI_EXPANSION_ROM_HEADER;

+

+typedef struct {

+  UINT16  Signature;    // 0xaa55

+  UINT16  InitializationSize;

+  UINT32  EfiSignature; // 0x0EF1

+  UINT16  EfiSubsystem;

+  UINT16  EfiMachineType;

+  UINT16  CompressionType;

+  UINT8   Reserved[8];

+  UINT16  EfiImageHeaderOffset;

+  UINT16  PcirOffset;

+} EFI_PCI_EXPANSION_ROM_HEADER;

+

+typedef struct {

+  UINT16  Signature;    // 0xaa55

+  UINT8   Size512;

+  UINT8   Reserved[15];

+  UINT16  PcirOffset;

+} EFI_LEGACY_EXPANSION_ROM_HEADER;

+

+typedef union {

+  UINT8                           *Raw;

+  PCI_EXPANSION_ROM_HEADER        *Generic;

+  EFI_PCI_EXPANSION_ROM_HEADER    *Efi;

+  EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt;

+} EFI_PCI_ROM_HEADER;

+

+typedef struct {

+  UINT32  Signature;    // "PCIR"

+  UINT16  VendorId;

+  UINT16  DeviceId;

+  UINT16  Reserved0;

+  UINT16  Length;

+  UINT8   Revision;

+  UINT8   ClassCode[3];

+  UINT16  ImageLength;

+  UINT16  CodeRevision;

+  UINT8   CodeType;

+  UINT8   Indicator;

+  UINT16  Reserved1;

+} PCI_DATA_STRUCTURE;

+

+//

+// PCI Capability List IDs and records

+//

+#define EFI_PCI_CAPABILITY_ID_PMI     0x01

+#define EFI_PCI_CAPABILITY_ID_AGP     0x02

+#define EFI_PCI_CAPABILITY_ID_VPD     0x03

+#define EFI_PCI_CAPABILITY_ID_SLOTID  0x04

+#define EFI_PCI_CAPABILITY_ID_MSI     0x05

+#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06

+#define EFI_PCI_CAPABILITY_ID_PCIX    0x07

+//

+// bugbug: this ID is defined in PCI spec v2.3

+//

+#define EFI_PCI_CAPABILITY_ID_PCIEXP  0x10

+

+typedef struct {

+  UINT8 CapabilityID;

+  UINT8 NextItemPtr;

+} EFI_PCI_CAPABILITY_HDR;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_PMI

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  PMC;

+  UINT16                  PMCSR;

+  UINT8                   BridgeExtention;

+  UINT8                   Data;

+} EFI_PCI_CAPABILITY_PMI;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_AGP

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT8                   Rev;

+  UINT8                   Reserved;

+  UINT32                  Status;

+  UINT32                  Command;

+} EFI_PCI_CAPABILITY_AGP;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_VPD

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  AddrReg;

+  UINT32                  DataReg;

+} EFI_PCI_CAPABILITY_VPD;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_SLOTID

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT8                   ExpnsSlotReg;

+  UINT8                   ChassisNo;

+} EFI_PCI_CAPABILITY_SLOTID;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_MSI

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  MsgCtrlReg;

+  UINT32                  MsgAddrReg;

+  UINT16                  MsgDataReg;

+} EFI_PCI_CAPABILITY_MSI32;

+

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  MsgCtrlReg;

+  UINT32                  MsgAddrRegLsdw;

+  UINT32                  MsgAddrRegMsdw;

+  UINT16                  MsgDataReg;

+} EFI_PCI_CAPABILITY_MSI64;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  //

+  // not finished - fields need to go here

+  //

+} EFI_PCI_CAPABILITY_HOTPLUG;

+

+//

+// Capability EFI_PCI_CAPABILITY_ID_PCIX

+//

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  CommandReg;

+  UINT32                  StatusReg;

+} EFI_PCI_CAPABILITY_PCIX;

+

+typedef struct {

+  EFI_PCI_CAPABILITY_HDR  Hdr;

+  UINT16                  SecStatusReg;

+  UINT32                  StatusReg;

+  UINT32                  SplitTransCtrlRegUp;

+  UINT32                  SplitTransCtrlRegDn;

+} EFI_PCI_CAPABILITY_PCIX_BRDG;

+

+#define DEVICE_ID_NOCARE    0xFFFF

+

+#define PCI_ACPI_UNUSED     0

+#define PCI_BAR_NOCHANGE    0

+#define PCI_BAR_OLD_ALIGN   0xFFFFFFFFFFFFFFFFULL

+#define PCI_BAR_EVEN_ALIGN  0xFFFFFFFFFFFFFFFEULL

+#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL

+#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL

+

+#define PCI_BAR_IDX0        0x00

+#define PCI_BAR_IDX1        0x01

+#define PCI_BAR_IDX2        0x02

+#define PCI_BAR_IDX3        0x03

+#define PCI_BAR_IDX4        0x04

+#define PCI_BAR_IDX5        0x05

+#define PCI_BAR_ALL         0xFF

+

+#pragma pack(pop)

+

+#endif

diff --git a/Source/Include/Library/PeCoffLib.h b/Source/Include/Library/PeCoffLib.h
new file mode 100644
index 0000000..08e8195
--- /dev/null
+++ b/Source/Include/Library/PeCoffLib.h
@@ -0,0 +1,131 @@
+/** @file

+	Memory Only PE COFF loader

+

+	Copyright (c) 2006, Intel Corporation                                                         

+	All rights reserved. This program and the accompanying materials                          

+	are licensed and made available under the terms and conditions of the BSD License         

+	which accompanies this distribution.  The full text of the license may be found at        

+	http://opensource.org/licenses/bsd-license.php                                            

+

+	THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+	WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+	Module Name:	PeCoffLib.h

+

+**/

+

+#ifndef __BASE_PE_COFF_LIB_H__

+#define __BASE_PE_COFF_LIB_H__

+

+//

+// Return status codes from the PE/COFF Loader services

+// BUGBUG: Find where used and see if can be replaced by RETURN_STATUS codes

+//

+#define IMAGE_ERROR_SUCCESS                      0

+#define IMAGE_ERROR_IMAGE_READ                   1  

+#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE  2

+#define IMAGE_ERROR_INVALID_MACHINE_TYPE         3

+#define IMAGE_ERROR_INVALID_SUBSYSTEM            4

+#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS        5

+#define IMAGE_ERROR_INVALID_IMAGE_SIZE           6

+#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT    7

+#define IMAGE_ERROR_SECTION_NOT_LOADED           8

+#define IMAGE_ERROR_FAILED_RELOCATION            9

+#define IMAGE_ERROR_FAILED_ICACHE_FLUSH          10

+

+

+//

+// PE/COFF Loader Read Function passed in by caller

+//

+typedef

+RETURN_STATUS

+(EFIAPI *PE_COFF_LOADER_READ_FILE) (

+  IN     VOID   *FileHandle,

+  IN     UINTN  FileOffset,

+  IN OUT UINTN  *ReadSize,

+  OUT    VOID   *Buffer

+  );

+

+//

+// Context structure used while PE/COFF image is being loaded and relocated

+//

+typedef struct {

+  PHYSICAL_ADDRESS                  ImageAddress;

+  UINT64                            ImageSize;

+  PHYSICAL_ADDRESS                  DestinationAddress;

+  PHYSICAL_ADDRESS                  EntryPoint;

+  PE_COFF_LOADER_READ_FILE          ImageRead;

+  VOID                              *Handle;

+  VOID                              *FixupData;

+  UINT32                            SectionAlignment;

+  UINT32                            PeCoffHeaderOffset;

+  UINT32                            DebugDirectoryEntryRva;

+  VOID                              *CodeView;

+  CHAR8                             *PdbPointer;

+  UINTN                             SizeOfHeaders;

+  UINT32                            ImageCodeMemoryType;

+  UINT32                            ImageDataMemoryType;

+  UINT32                            ImageError;

+  UINTN                             FixupDataSize;

+  UINT16                            Machine;

+  UINT16                            ImageType;

+  BOOLEAN                           RelocationsStripped;

+  BOOLEAN                           IsTeImage;

+} PE_COFF_LOADER_IMAGE_CONTEXT;

+

+

+/**

+	Retrieves information on a PE/COFF image

+

+	@param	ImageContext The context of the image being loaded

+

+	@retval	EFI_SUCCESS The information on the PE/COFF image was collected.

+	@retval	EFI_INVALID_PARAMETER ImageContext is NULL.

+	@retval	EFI_UNSUPPORTED The PE/COFF image is not supported.

+	@retval	Otherwise The error status from reading the PE/COFF image using the

+	ImageContext->ImageRead() function

+

+**/

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderGetImageInfo (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext

+  )

+;

+

+/**

+	Relocates a PE/COFF image in memory

+

+	@param	ImageContext Contains information on the loaded image to relocate

+

+	@retval EFI_SUCCESS      if the PE/COFF image was relocated

+	@retval EFI_LOAD_ERROR   if the image is not a valid PE/COFF image

+	@retval EFI_UNSUPPORTED  not support

+

+**/

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderRelocateImage (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext

+  )

+;

+

+/**

+	Loads a PE/COFF image into memory

+

+	@param	ImageContext Contains information on image to load into memory

+

+	@retval EFI_SUCCESS            if the PE/COFF image was loaded

+	@retval EFI_BUFFER_TOO_SMALL   if the caller did not provide a large enough buffer

+	@retval EFI_LOAD_ERROR         if the image is a runtime driver with no relocations

+	@retval EFI_INVALID_PARAMETER  if the image address is invalid

+

+**/

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderLoadImage (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext

+  )

+;

+

+#endif

diff --git a/Source/Include/Library/PrintLib.h b/Source/Include/Library/PrintLib.h
new file mode 100644
index 0000000..9c65459
--- /dev/null
+++ b/Source/Include/Library/PrintLib.h
@@ -0,0 +1,406 @@
+/** @file

+	Library that provides print services

+

+	Copyright (c) 2006, Intel Corporation                                                         

+	All rights reserved. This program and the accompanying materials                          

+	are licensed and made available under the terms and conditions of the BSD License         

+	which accompanies this distribution.  The full text of the license may be found at        

+	http://opensource.org/licenses/bsd-license.php                                            

+

+	THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+	WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+	Module Name:	PrintLib.h

+

+**/

+

+#ifndef __PRINT_LIB_H__

+#define __PRINT_LIB_H__

+

+//

+// Print primitives

+//

+#define LEFT_JUSTIFY      0x01

+#define COMMA_TYPE        0x08

+#define PREFIX_ZERO       0x20

+

+/**

+  Produces a Null-terminated Unicode string in an output buffer based on 

+  a Null-terminated Unicode format string and a VA_LIST argument list

+  

+  Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer

+  and BufferSize.  

+  The Unicode string is produced by parsing the format string specified by FormatString.  

+  Arguments are pulled from the variable argument list specified by Marker based on the 

+  contents of the format string.  

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          Unicode string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  @param  Marker          VA_LIST marker for the variable argument list.

+  

+  @return return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+UnicodeVSPrint (

+  OUT CHAR16        *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  IN  VA_LIST       Marker

+  );

+

+/**

+  Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated 

+  Unicode format string and variable argument list.

+  

+  Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The Unicode string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list based on the contents of the format string.

+  The length of the produced output buffer is returned.  

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          Unicode string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+UnicodeSPrint (

+  OUT CHAR16        *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  ...

+  );

+

+/**

+  Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated

+  ASCII format string and a VA_LIST argument list

+  

+  Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The Unicode string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list specified by Marker based on the 

+  contents of the format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          Unicode string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  @param  Marker          VA_LIST marker for the variable argument list.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+UnicodeVSPrintAsciiFormat (

+  OUT CHAR16       *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  IN  VA_LIST      Marker

+  );

+

+/**

+  Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated 

+  ASCII format string and  variable argument list.

+  

+  Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The Unicode string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list based on the contents of the 

+  format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          Unicode string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+UnicodeSPrintAsciiFormat (

+  OUT CHAR16       *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  );

+

+/**

+  Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated

+  ASCII format string and a VA_LIST argument list.

+  

+  Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The ASCII string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list specified by Marker based on 

+  the contents of the format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          ASCII string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  @param  Marker          VA_LIST marker for the variable argument list.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+AsciiVSPrint (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR8   *FormatString,

+  IN  VA_LIST       Marker

+  );

+

+/**

+  Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated

+  ASCII format string and  variable argument list.

+  

+  Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The ASCII string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list based on the contents of the 

+  format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          ASCII string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+AsciiSPrint (

+  OUT CHAR8        *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  );

+

+/**

+  Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated

+  ASCII format string and a VA_LIST argument list.

+  

+  Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The ASCII string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list specified by Marker based on 

+  the contents of the format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          ASCII string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  @param  Marker          VA_LIST marker for the variable argument list.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+AsciiVSPrintUnicodeFormat (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  IN  VA_LIST       Marker

+  );

+

+/**

+  Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated

+  ASCII format string and  variable argument list.

+  

+  Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer

+  and BufferSize.

+  The ASCII string is produced by parsing the format string specified by FormatString.

+  Arguments are pulled from the variable argument list based on the contents of the 

+  format string.

+  The length of the produced output buffer is returned.

+  If BufferSize is 0, then no output buffer is produced and 0 is returned.

+

+  If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().

+  If BufferSize is not 0 and FormatString is NULL, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than 

+  PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+  If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string

+  contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().

+

+  @param  StartOfBuffer   APointer to the output buffer for the produced Null-terminated 

+                          ASCII string.

+  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.

+  @param  FormatString    Null-terminated Unicode format string.

+  

+  @return Length of the produced output buffer.

+

+**/

+UINTN

+EFIAPI

+AsciiSPrintUnicodeFormat (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  ...

+  );

+

+/**

+  Converts a decimal value to a Null-terminated Unicode string.

+  

+  Converts the decimal number specified by Value to a Null-terminated Unicode 

+  string specified by Buffer containing at most Width characters.

+  If Width is 0 then a width of  MAXIMUM_VALUE_CHARACTERS is assumed.

+  The total number of characters placed in Buffer is returned.

+  If the conversion contains more than Width characters, then only the first

+  Width characters are returned, and the total number of characters 

+  required to perform the conversion is returned.

+  Additional conversion parameters are specified in Flags.  

+  The Flags bit LEFT_JUSTIFY is always ignored.

+  All conversions are left justified in Buffer.

+  If Width is 0, PREFIX_ZERO is ignored in Flags.

+  If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas

+  are inserted every 3rd digit starting from the right.

+  If Value is < 0, then the fist character in Buffer is a '-'.

+  If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, 

+  then Buffer is padded with '0' characters so the combination of the optional '-' 

+  sign character, '0' characters, digit characters for Value, and the Null-terminator

+  add up to Width characters.

+

+  If Buffer is NULL, then ASSERT().

+  If unsupported bits are set in Flags, then ASSERT().

+  If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()

+

+  @param  Buffer  Pointer to the output buffer for the produced Null-terminated

+                  Unicode string.

+  @param  Flags   The bitmask of flags that specify left justification, zero pad, and commas.

+  @param  Value   The 64-bit signed value to convert to a string.

+  @param  Width	  The maximum number of Unicode characters to place in Buffer.

+  

+  @return Total number of characters required to perform the conversion.

+

+**/

+UINTN

+EFIAPI

+UnicodeValueToString (

+  IN OUT CHAR16  *Buffer,

+  IN UINTN       Flags,

+  IN INT64       Value,

+  IN UINTN       Width

+  );

+

+/**

+  Converts a decimal value to a Null-terminated ASCII string.

+  

+  Converts the decimal number specified by Value to a Null-terminated ASCII string 

+  specified by Buffer containing at most Width characters.

+  If Width is 0 then a width of  MAXIMUM_VALUE_CHARACTERS is assumed.

+  The total number of characters placed in Buffer is returned.

+  If the conversion contains more than Width characters, then only the first Width

+  characters are returned, and the total number of characters required to perform

+  the conversion is returned.

+  Additional conversion parameters are specified in Flags.  

+  The Flags bit LEFT_JUSTIFY is always ignored.

+  All conversions are left justified in Buffer.

+  If Width is 0, PREFIX_ZERO is ignored in Flags.

+  If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas 

+  are inserted every 3rd digit starting from the right.

+  If Value is < 0, then the fist character in Buffer is a '-'.

+  If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, then Buffer

+  is padded with '0' characters so the combination of the optional '-'

+  sign character, '0' characters, digit characters for Value, and the 

+  Null-terminator add up to Width characters.

+

+  If Buffer is NULL, then ASSERT().

+  If unsupported bits are set in Flags, then ASSERT().

+  If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()

+

+  @param  Buffer  Pointer to the output buffer for the produced Null-terminated

+                  ASCII string.

+  @param  Flags   The bitmask of flags that specify left justification, zero pad, and commas.

+  @param  Value   The 64-bit signed value to convert to a string.

+  @param  Width	  The maximum number of ASCII characters to place in Buffer.

+  

+  @return Total number of characters required to perform the conversion.

+

+**/

+UINTN

+EFIAPI

+AsciiValueToString (

+  IN OUT CHAR8  *Buffer,

+  IN UINTN      Flags,

+  IN INT64      Value,

+  IN UINTN      Width

+  );

+

+#endif

diff --git a/Source/Include/Protocol/DevicePath.h b/Source/Include/Protocol/DevicePath.h
new file mode 100644
index 0000000..d019999
--- /dev/null
+++ b/Source/Include/Protocol/DevicePath.h
@@ -0,0 +1,94 @@
+/** @file

+  The device path protocol as defined in EFI 1.0.

+

+  The device path represents a programatic path to a device. It's the view

+  from a software point of view. It also must persist from boot to boot, so 

+  it can not contain things like PCI bus numbers that change from boot to boot.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  DevicePath.h

+

+**/

+

+#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__

+#define __EFI_DEVICE_PATH_PROTOCOL_H__

+

+//

+// Device Path protocol

+//

+#define EFI_DEVICE_PATH_PROTOCOL_GUID \

+  { \

+    0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \

+  }

+

+#pragma pack(1)

+

+typedef struct {

+  UINT8 Type;

+  UINT8 SubType;

+  UINT8 Length[2];

+} EFI_DEVICE_PATH_PROTOCOL;

+

+#pragma pack()

+                                             

+#define EFI_DP_TYPE_MASK                     0x7F

+#define EFI_DP_TYPE_UNPACKED                 0x80

+#define END_DEVICE_PATH_TYPE                 0x7f

+                                             

+#define EFI_END_ENTIRE_DEVICE_PATH           0xff

+#define EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE   0xff

+#define EFI_END_INSTANCE_DEVICE_PATH         0x01

+#define END_ENTIRE_DEVICE_PATH_SUBTYPE       EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE

+#define END_INSTANCE_DEVICE_PATH_SUBTYPE     EFI_END_INSTANCE_DEVICE_PATH

+                                             

+#define EFI_END_DEVICE_PATH_LENGTH           (sizeof (EFI_DEVICE_PATH_PROTOCOL))

+#define END_DEVICE_PATH_LENGTH               EFI_END_DEVICE_PATH_LENGTH

+                                             

+#define DP_IS_END_TYPE(a)                    

+#define DP_IS_END_SUBTYPE(a)                 (((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)

+#define DevicePathSubType(a)                 ((a)->SubType)

+#define IsDevicePathUnpacked(a)              ((a)->Type & EFI_DP_TYPE_UNPACKED)

+                                             

+#define EfiDevicePathNodeLength(a)           (((a)->Length[0]) | ((a)->Length[1] << 8))

+#define DevicePathNodeLength(a)              (EfiDevicePathNodeLength(a))

+#define EfiNextDevicePathNode(a)             ((EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) (a)) + EfiDevicePathNodeLength (a)))

+#define NextDevicePathNode(a)                (EfiNextDevicePathNode(a)) 

+                                             

+#define EfiDevicePathType(a)                 (((a)->Type) & EFI_DP_TYPE_MASK)

+#define DevicePathType(a)                    (EfiDevicePathType(a))

+#define EfiIsDevicePathEndType(a)            (EfiDevicePathType (a) == END_DEVICE_PATH_TYPE)

+#define IsDevicePathEndType(a)               (EfiIsDevicePathEndType(a)) 

+                                             

+                                             

+#define EfiIsDevicePathEndSubType(a)         ((a)->SubType == EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)

+#define IsDevicePathEndSubType(a)            (EfiIsDevicePathEndSubType(a))

+#define EfiIsDevicePathEndInstanceSubType(a) ((a)->SubType == EFI_END_INSTANCE_DEVICE_PATH)

+                                             

+#define EfiIsDevicePathEnd(a)                (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndSubType (a))

+#define IsDevicePathEnd(a)                   (EfiIsDevicePathEnd(a))

+#define EfiIsDevicePathEndInstance(a)        (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndInstanceSubType (a))

+

+

+#define SetDevicePathNodeLength(a,l) {                           \

+          (a)->Length[0] = (UINT8) (l);                          \

+          (a)->Length[1] = (UINT8) ((l) >> 8);                   \

+          }

+

+#define SetDevicePathEndNode(a)  {                               \

+          (a)->Type = END_DEVICE_PATH_TYPE;                      \

+          (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;         \

+          (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL);     \

+          (a)->Length[1] = 0;                                    \

+          }

+

+extern EFI_GUID gEfiDevicePathProtocolGuid;

+

+#endif

diff --git a/Source/Include/Protocol/GuidedSectionExtraction.h b/Source/Include/Protocol/GuidedSectionExtraction.h
new file mode 100644
index 0000000..d98c56a
--- /dev/null
+++ b/Source/Include/Protocol/GuidedSectionExtraction.h
@@ -0,0 +1,102 @@
+/** @file

+  This file declares GUIDed section extraction protocol.

+

+  This interface provides a means of decoding a GUID defined encapsulation 

+  section. There may be multiple different GUIDs associated with the GUIDed

+  section extraction protocol. That is, all instances of the GUIDed section

+  extraction protocol must have the same interface structure.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  GuidedSectionExtraction.h

+

+  @par Revision Reference:

+  This protocol is defined in Firmware Volume Specification.

+  Version 0.9

+

+**/

+

+#ifndef __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__

+#define __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__

+

+

+//

+// Protocol GUID definition. Each GUIDed section extraction protocol has the

+// same interface but with different GUID. All the GUIDs is defined here.

+// May add multiple GUIDs here.

+//

+#define EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID \

+  { \

+    0xFC1BCDB0, 0x7D31, 0x49aa, {0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 } \

+  }

+

+//

+// Forward reference for pure ANSI compatability

+//

+typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL  EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL;

+

+//

+// Protocol member functions

+//

+/**

+  Processes the input section and returns the data contained therein along 

+  with the authentication status.

+

+  @param  This                  Indicates the EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.  

+  @param  InputSection          Buffer containing the input GUIDed section to be processed.  

+  @param  OutputBuffer          *OutputBuffer is allocated from boot services pool memory 

+                                and contains the new section stream.  

+  @param  OutputSize            A pointer to a caller-allocated UINTN in which the size 

+                                of *OutputBuffer allocation is stored.   

+  @param  AuthenticationStatus  A pointer to a caller-allocated UINT32 that 

+                                indicates the authentication status of the output buffer.

+                                

+  @retval EFI_SUCCESS           The InputSection was successfully processed and the 

+                                section contents were returned.

+  @retval EFI_OUT_OF_RESOURCES  The system has insufficient resources to 

+                                process the request.

+  @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match 

+                                this instance of the GUIDed Section Extraction Protocol.

+

+**/

+

+typedef

+EFI_STATUS

+(EFIAPI *EFI_EXTRACT_GUIDED_SECTION) (

+  IN  EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL          *This,

+  IN  VOID                                            *InputSection,

+  OUT VOID                                            **OutputBuffer,

+  OUT UINTN                                           *OutputSize,

+  OUT UINT32                                          *AuthenticationStatus

+  );

+

+//

+// Protocol definition

+//

+/**

+  @par Protocol Description:

+  If a GUID-defined section is encountered when doing section extraction, 

+  the section extraction driver calls the appropriate instance of the GUIDed 

+  Section Extraction Protocol to extract the section stream contained therein.

+

+  @param ExtractSection

+  Takes the GUIDed section as input and produces the section stream data. 

+

+**/

+struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL {

+  EFI_EXTRACT_GUIDED_SECTION  ExtractSection;

+};

+

+//

+// may add other GUID here

+//

+extern EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid;

+

+#endif

diff --git a/Source/Include/Protocol/Hii.h b/Source/Include/Protocol/Hii.h
new file mode 100644
index 0000000..ceeba1c
--- /dev/null
+++ b/Source/Include/Protocol/Hii.h
@@ -0,0 +1,1024 @@
+/** @file

+  This file defines the Human Interface Infrastructure protocol which will 

+  be used by resources which want to publish IFR/Font/String data and have it 

+  collected by the Configuration engine.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  Hii.h

+

+  @par Revision Reference:

+  This protocol is defined in HII spec 0.92.

+

+**/

+

+#ifndef __HII_H__

+#define __HII_H__

+

+

+#define EFI_HII_PROTOCOL_GUID \

+  { \

+    0xea816d2c, 0xcee5, 0x4f02, {0x99, 0xb5, 0xd3, 0x90, 0x5c, 0xbb, 0xd0, 0x77 } \

+  }

+

+// BugBug:

+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+// If UGA goes away we need to put this some place. I'm not sure where?

+//

+//typedef struct {

+//  UINT8 Blue;

+//  UINT8 Green;

+//  UINT8 Red;

+//  UINT8 Reserved;

+//} EFI_UGA_PIXEL;

+

+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+//

+

+typedef struct _EFI_HII_PROTOCOL  EFI_HII_PROTOCOL;

+

+//

+// Global definition

+//

+#define NARROW_CHAR         0xFFF0

+#define WIDE_CHAR           0xFFF1

+#define NON_BREAKING_CHAR   0xFFF2

+#define GLYPH_WIDTH         8

+#define GLYPH_HEIGHT        19

+

+#define EFI_HII_FONT        1

+#define EFI_HII_STRING      2

+#define EFI_HII_IFR         3

+#define EFI_HII_KEYBOARD    4

+#define EFI_HII_HANDLES     5

+#define EFI_HII_VARIABLE    6

+#define EFI_HII_DEVICE_PATH 7

+

+

+// References to string tokens must use this macro to enable scanning for

+// token usages.

+//

+#define STRING_TOKEN(t) t

+

+//

+// The following types are currently defined:

+//

+typedef UINT16  EFI_FORM_ID;

+typedef UINT16  EFI_FORM_LABEL;

+

+#pragma pack(1)

+

+typedef struct {

+  UINT32  Length;

+  UINT16  Type;

+} EFI_HII_PACK_HEADER;

+

+//

+// A form list consists of a large variety of structure

+// possibilities so to represent the binary blob of data

+// associated with a package of forms, we will assume a

+// pointer to a self-describing data buffer.

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+} EFI_HII_IFR_PACK;

+

+typedef struct {

+  EFI_HII_PACK_HEADER Header;           // Must be filled in

+  EFI_HANDLE          ImageHandle;      // Must be filled in

+  EFI_HANDLE          DeviceHandle;     // Optional

+  EFI_HANDLE          ControllerHandle; // Optional

+  EFI_HANDLE          CallbackHandle;   // Optional

+  EFI_HANDLE          COBExportHandle;  // Optional

+} EFI_HII_HANDLE_PACK;

+

+//

+// ********************************************************

+// EFI_VARIABLE_CONTENTS

+// ********************************************************

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+  EFI_GUID            VariableGuid;

+  UINT32              VariableNameLength;

+  UINT16              VariableId;

+  //

+  //  CHAR16                VariableName[]; //Null-terminated

+  //

+} EFI_HII_VARIABLE_PACK;

+

+//

+// ********************************************************

+// EFI_DEVICE_PATH_PACK

+// ********************************************************

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+  //

+  //  EFI_DEVICE_PATH       DevicePath[];

+  //

+} EFI_HII_DEVICE_PATH_PACK;

+

+//

+// ********************************************************

+// EFI_HII_DATA_TABLE

+// ********************************************************

+//

+typedef struct {

+  EFI_HII_HANDLE  HiiHandle;

+  EFI_GUID        PackageGuid;

+  UINT32          DataTableSize;

+  UINT32          IfrDataOffset;

+  UINT32          StringDataOffset;

+  UINT32          VariableDataOffset;

+  UINT32          DevicePathOffset;

+  UINT32          NumberOfVariableData;

+  UINT32          NumberOfLanguages;

+  //

+  // EFI_HII_DEVICE_PATH_PACK DevicePath[];

+  // EFI_HII_VARIABLE_PACK VariableData[];

+  // EFI_HII_IFR_PACK IfrData;

+  // EFI_HII_STRING_PACK StringData[];

+  //

+} EFI_HII_DATA_TABLE;

+

+//

+// ********************************************************

+// EFI_HII_EXPORT_TABLE

+// ********************************************************

+//

+typedef struct {

+  UINT32    NumberOfHiiDataTables;

+  EFI_GUID  Revision;

+  //

+  // EFI_HII_DATA_TABLE HiiDataTable[];

+  //

+} EFI_HII_EXPORT_TABLE;

+

+typedef struct {

+  BOOLEAN               FormSetUpdate;      // If TRUE, next variable is significant

+  EFI_PHYSICAL_ADDRESS  FormCallbackHandle; // If not 0, will update Formset with this info

+  BOOLEAN               FormUpdate;         // If TRUE, next variable is significant

+  UINT16                FormValue;          // specify which form is to be updated if FormUpdate value is TRUE.

+  STRING_REF            FormTitle;          // If not 0, will update Form with this info

+  UINT16                DataCount;          // The number of Data entries in this structure

+  UINT8                 *Data;              // An array of 1+ op-codes, specified by DataCount

+} EFI_HII_UPDATE_DATA;

+

+//

+// String attributes

+//

+#define LANG_RIGHT_TO_LEFT  0x00000001

+

+//

+// A string package is used to localize strings to a particular

+// language.  The package is associated with a particular driver

+// or set of drivers.  Tools are used to associate tokens with

+// string references in forms and in programs.  These tokens are

+// language agnostic.  When paired with a language pack (directly

+// or indirectly), the string token resolves into an actual

+// UNICODE string.  The NumStringPointers determines how many

+// StringPointers (offset values) there are as well as the total

+// number of Strings that are defined.

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+  RELOFST             LanguageNameString;

+  RELOFST             PrintableLanguageName;

+  UINT32              NumStringPointers;

+  UINT32              Attributes;

+  //

+  //  RELOFST               StringPointers[];

+  //  EFI_STRING            Strings[];

+  //

+} EFI_HII_STRING_PACK;

+

+//

+// Glyph Attributes

+//

+#define EFI_GLYPH_NON_SPACING   1

+#define EFI_GLYPH_WIDE          2

+

+typedef struct {

+  CHAR16  UnicodeWeight;

+  UINT8   Attributes;

+  UINT8   GlyphCol1[GLYPH_HEIGHT];

+} EFI_NARROW_GLYPH;

+

+typedef struct {

+  CHAR16  UnicodeWeight;

+  UINT8   Attributes;

+  UINT8   GlyphCol1[GLYPH_HEIGHT];

+  UINT8   GlyphCol2[GLYPH_HEIGHT];

+  UINT8   Pad[3];

+} EFI_WIDE_GLYPH;

+

+//

+// A font list consists of a font header followed by a series

+// of glyph structures.  Note that fonts are not language specific.

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+  UINT16              NumberOfNarrowGlyphs;

+  UINT16              NumberOfWideGlyphs;

+} EFI_HII_FONT_PACK;

+

+//

+// The IfrData in the EFI_HII_IFR_PACK structure definition

+// is variable length, and not really part of the header. To

+// simplify from code the size of the header, define an

+// identical structure that does not include the IfrData field.

+// Then use sizeof() this new structure to determine the

+// actual size of the header.

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+} EFI_HII_IFR_PACK_HEADER;

+

+//

+// pedef EFI_HII_PACK_HEADER EFI_HII_IFR_PACK_HEADER;

+//

+typedef enum {

+  EfiKeyLCtrl,

+  EfiKeyA0,

+  EfiKeyLAlt,

+  EfiKeySpaceBar,

+  EfiKeyA2,

+  EfiKeyA3,

+  EfiKeyA4,

+  EfiKeyRCtrl,

+  EfiKeyLeftArrow,

+  EfiKeyDownArrow,

+  EfiKeyRightArrow,

+  EfiKeyZero,

+  EfiKeyPeriod,

+  EfiKeyEnter,

+  EfiKeyLShift,

+  EfiKeyB0,

+  EfiKeyB1,

+  EfiKeyB2,

+  EfiKeyB3,

+  EfiKeyB4,

+  EfiKeyB5,

+  EfiKeyB6,

+  EfiKeyB7,

+  EfiKeyB8,

+  EfiKeyB9,

+  EfiKeyB10,

+  EfiKeyRshift,

+  EfiKeyUpArrow,

+  EfiKeyOne,

+  EfiKeyTwo,

+  EfiKeyThree,

+  EfiKeyCapsLock,

+  EfiKeyC1,

+  EfiKeyC2,

+  EfiKeyC3,

+  EfiKeyC4,

+  EfiKeyC5,

+  EfiKeyC6,

+  EfiKeyC7,

+  EfiKeyC8,

+  EfiKeyC9,

+  EfiKeyC10,

+  EfiKeyC11,

+  EfiKeyC12,

+  EfiKeyFour,

+  EfiKeyFive,

+  EfiKeySix,

+  EfiKeyPlus,

+  EfiKeyTab,

+  EfiKeyD1,

+  EfiKeyD2,

+  EfiKeyD3,

+  EfiKeyD4,

+  EfiKeyD5,

+  EfiKeyD6,

+  EfiKeyD7,

+  EfiKeyD8,

+  EfiKeyD9,

+  EfiKeyD10,

+  EfiKeyD11,

+  EfiKeyD12,

+  EfiKeyD13,

+  EfiKeyDel,

+  EfiKeyEnd,

+  EfiKeyPgDn,

+  EfiKeySeven,

+  EfiKeyEight,

+  EfiKeyNine,

+  EfiKeyE0,

+  EfiKeyE1,

+  EfiKeyE2,

+  EfiKeyE3,

+  EfiKeyE4,

+  EfiKeyE5,

+  EfiKeyE6,

+  EfiKeyE7,

+  EfiKeyE8,

+  EfiKeyE9,

+  EfiKeyE10,

+  EfiKeyE11,

+  EfiKeyE12,

+  EfiKeyBackSpace,

+  EfiKeyIns,

+  EfiKeyHome,

+  EfiKeyPgUp,

+  EfiKeyNLck,

+  EfiKeySlash,

+  EfiKeyAsterisk,

+  EfiKeyMinus,

+  EfiKeyEsc,

+  EfiKeyF1,

+  EfiKeyF2,

+  EfiKeyF3,

+  EfiKeyF4,

+  EfiKeyF5,

+  EfiKeyF6,

+  EfiKeyF7,

+  EfiKeyF8,

+  EfiKeyF9,

+  EfiKeyF10,

+  EfiKeyF11,

+  EfiKeyF12,

+  EfiKeyPrint,

+  EfiKeySLck,

+  EfiKeyPause

+} EFI_KEY;

+

+typedef struct {

+  EFI_KEY Key;

+  CHAR16  Unicode;

+  CHAR16  ShiftedUnicode;

+  CHAR16  AltGrUnicode;

+  CHAR16  ShiftedAltGrUnicode;

+  UINT16  Modifier;

+} EFI_KEY_DESCRIPTOR;

+

+//

+// This structure allows a sparse set of keys to be redefined

+// or a complete redefinition of the keyboard layout.  Most

+// keyboards have a lot of commonality in their layouts, therefore

+// only defining those keys that need to change from the default

+// minimizes the passed in information.

+//

+// Additionally, when an update occurs, the active keyboard layout

+// will be switched to the newly updated keyboard layout.  This

+// allows for situations that when a keyboard layout driver is

+// loaded as part of system initialization, the system will default

+// the keyboard behavior to the new layout.

+//

+// Each call to update the keyboard mapping should contain the

+// complete set of key descriptors to be updated, since every

+// call to the HII which contains an EFI_HII_KEYBOARD_PACK will

+// wipe the previous set of overrides.  A call to

+//

+typedef struct {

+  EFI_HII_PACK_HEADER Header;

+  EFI_KEY_DESCRIPTOR  *Descriptor;

+  UINT8               DescriptorCount;

+} EFI_HII_KEYBOARD_PACK;

+

+//

+// The EFI_HII_PACKAGES can contain different types of packages just

+// after the structure as inline data.

+//

+typedef struct {

+  UINTN     NumberOfPackages;

+  EFI_GUID  *GuidId;

+  //

+  // EFI_HII_HANDLE_PACK    *HandlePack;        // Only one pack.

+  // EFI_HII_IFR_PACK       *IfrPack;           // Only one pack.

+  // EFI_HII_FONT_PACK      *FontPack[];        // Multiple packs ok

+  // EFI_HII_STRING_PACK    *StringPack[];      // Multiple packs ok

+  // EFI_HII_KEYBOARD_PACK  *KeyboardPack[];    // Multiple packs ok

+  //

+} EFI_HII_PACKAGES;

+

+typedef struct _EFI_HII_VARIABLE_PACK_LIST {

+  struct _EFI_HII_VARIABLE_PACK_LIST   *NextVariablePack;

+  EFI_HII_VARIABLE_PACK                *VariablePack;

+} EFI_HII_VARIABLE_PACK_LIST;

+

+#pragma pack()

+

+/**

+  Registers the various packs that are passed in via the Packages parameter. 

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Packages A pointer to an EFI_HII_PACKAGES package instance.

+  

+  @param  Handle A pointer to the EFI_HII_HANDLE instance.

+

+  @retval EFI_SUCCESS Data was extracted from Packages, the database 

+  was updated with the data, and Handle returned successfully.

+  

+  @retval EFI_INVALID_PARAMETER The content of Packages  was invalid. 

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_NEW_PACK) (

+  IN  EFI_HII_PROTOCOL    *This,

+  IN  EFI_HII_PACKAGES    *Packages,

+  OUT EFI_HII_HANDLE      *Handle

+  );

+

+/**

+  Removes a package from the HII database. 

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle that was registered to the data that is requested 

+  for removal. 

+

+  @retval EFI_SUCCESS The data associated with the Handle was removed 

+  from the HII database.

+  

+  @retval EFI_INVALID_PARAMETER The Handle was not valid. 

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_REMOVE_PACK) (

+  IN EFI_HII_PROTOCOL    *This,

+  IN EFI_HII_HANDLE      Handle

+  );

+

+/**

+  Determines the handles that are currently active in the database.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  HandleBufferLength On input, a pointer to the length of the handle 

+  buffer. On output, the length of the handle buffer that is required 

+  for the handles found.

+  

+  @param  Handle An array of EFI_HII_HANDLE instances returned.

+

+  @retval EFI_SUCCESS Handle was updated successfully.

+  

+  @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates 

+  that Handle is too small to support the number of handles.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_FIND_HANDLES) (

+  IN     EFI_HII_PROTOCOL *This,

+  IN OUT UINT16           *HandleBufferLength,

+  OUT    EFI_HII_HANDLE   *Handle

+  );

+

+/**

+  Exports the contents of the database into a buffer.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle An EFI_HII_HANDLE that corresponds to the desired 

+  handle to export. If the value is 0, the entire database will be exported.

+  In either case, the data will be exported in a format described by the 

+  structure definition of EFI_HII_EXPORT_TABLE.

+  

+  @param  BufferSize

+  On input, a pointer to the length of the buffer. On output, the length 

+  of the buffer that is required for the export data.

+  

+  @param  Buffer A pointer to a buffer that will contain the results of the export function.

+

+  @retval EFI_SUCCESS The buffer was successfully filled with BufferSize amount of data.

+  

+  @retval EFI_BUFFER_TOO_SMALL The value in BufferSize was too small to contain the export data.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_EXPORT) (

+  IN     EFI_HII_PROTOCOL *This,

+  IN     EFI_HII_HANDLE   Handle,

+  IN OUT UINTN            *BufferSize,

+  OUT    VOID             *Buffer

+  );

+

+/**

+  Remove any new strings that were added after the initial string export 

+  for this handle.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle on which the string resides.

+

+  @retval EFI_SUCCESS Remove strings from the handle successfully.

+  

+  @retval EFI_INVALID_PARAMETER The Handle was unknown.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_RESET_STRINGS) (

+  IN     EFI_HII_PROTOCOL   *This,

+  IN     EFI_HII_HANDLE     Handle

+  );

+

+/**

+  Tests if all of the characters in a string have corresponding font characters.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  StringToTest A pointer to a Unicode string.

+  

+  @param  FirstMissing A pointer to an index into the string. On input, 

+  the index of the first character in the StringToTest to examine. On exit, 

+  the index of the first character encountered for which a glyph is unavailable.

+  If all glyphs in the string are available, the index is the index of the 

+  terminator of the string.

+  

+  @param  GlyphBufferSize A pointer to a value. On output, if the function 

+  returns EFI_SUCCESS, it contains the amount of memory that is required to 

+  store the string¡¯s glyph equivalent.

+

+  @retval EFI_SUCCESS All glyphs are available. Note that an empty string 

+  always returns this value.

+  

+  @retval EFI_NOT_FOUND A glyph was not found for a character.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_TEST_STRING) (

+  IN     EFI_HII_PROTOCOL  *This,

+  IN     CHAR16            *StringToTest,

+  IN OUT UINT32            *FirstMissing,

+  OUT    UINT32            *GlyphBufferSize

+  );

+

+/**

+  Translates a Unicode character into the corresponding font glyph.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Source A pointer to a Unicode string.

+  

+  @param  Index On input, the offset into the string from which to fetch 

+  the character.On successful completion, the index is updated to the first 

+  character past the character(s) making up the just extracted glyph. 

+  

+  @param  GlyphBuffer Pointer to an array where the glyphs corresponding 

+  to the characters in the source may be stored. GlyphBuffer is assumed 

+  to be wide enough to accept a wide glyph character.

+  

+  @param  BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by 

+  this value is filled with the length of the glyph in pixels. It is unchanged 

+  if the call was unsuccessful.

+  

+  @param  InternalStatus The cell pointed to by this parameter must be 

+  initialized to zero prior to invoking the call the first time for any string.

+

+  @retval EFI_SUCCESS It worked.

+  

+  @retval EFI_NOT_FOUND A glyph for a character was not found.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_GLYPH) (

+  IN     EFI_HII_PROTOCOL  *This,

+  IN     CHAR16            *Source,

+  IN OUT UINT16            *Index,

+  OUT    UINT8             **GlyphBuffer,

+  OUT    UINT16            *BitWidth,

+  IN OUT UINT32            *InternalStatus

+  );

+

+/**

+  Translates a glyph into the format required for input to the Universal 

+  Graphics Adapter (UGA) Block Transfer (BLT) routines.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  GlyphBuffer A pointer to the buffer that contains glyph data.

+  

+  @param  Foreground The foreground setting requested to be used for the 

+  generated BltBuffer data. 

+  

+  @param  Background The background setting requested to be used for the 

+  generated BltBuffer data.

+  

+  @param  Count The entry in the BltBuffer upon which to act.

+  

+  @param  Width The width in bits of the glyph being converted.

+  

+  @param  Height The height in bits of the glyph being converted

+  

+  @param  BltBuffer A pointer to the buffer that contains the data that is 

+  ready to be used by the UGA BLT routines. 

+

+  @retval EFI_SUCCESS It worked.

+  

+  @retval EFI_NOT_FOUND A glyph for a character was not found.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GLYPH_TO_BLT) (

+  IN     EFI_HII_PROTOCOL   *This,

+  IN     UINT8              *GlyphBuffer,

+  IN     EFI_UGA_PIXEL      Foreground,

+  IN     EFI_UGA_PIXEL      Background,

+  IN     UINTN              Count,

+  IN     UINTN              Width,

+  IN     UINTN              Height,

+  IN OUT EFI_UGA_PIXEL      *BltBuffer

+  );

+

+/**

+  Allows a new string to be added to an already existing string package.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Pointer to a NULL-terminated string containing a single ISO 639-2 

+  language identifier, indicating the language in which the string is translated. 

+  

+  @param  Handle The handle of the language pack to which the string is to be added.

+  

+  @param  Reference The identifier of the string to be added. If the reference 

+  value is zero, then the string will be assigned a new identifier on that 

+  handle for the language specified. Otherwise, the string will be updated 

+  with the NewString Value. 

+  

+  @param  NewString The string to be added.

+

+  @retval EFI_SUCCESS The string was effectively registered.

+  

+  @retval EFI_INVALID_PARAMETER The Handle was unknown.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_NEW_STRING) (

+  IN     EFI_HII_PROTOCOL      *This,

+  IN     CHAR16                *Language,

+  IN     EFI_HII_HANDLE        Handle,

+  IN OUT STRING_REF            *Reference,

+  IN     CHAR16                *NewString

+  );

+

+/**

+  Allows a program to determine the primary languages that are supported 

+  on a given handle.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle on which the strings reside.

+  

+  @param  LanguageString A string allocated by GetPrimaryLanguages() that 

+  contains a list of all primary languages registered on the handle. 

+

+  @retval EFI_SUCCESS LanguageString was correctly returned.

+  

+  @retval EFI_INVALID_PARAMETER The Handle was unknown.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_PRI_LANGUAGES) (

+  IN  EFI_HII_PROTOCOL    *This,

+  IN  EFI_HII_HANDLE      Handle,

+  OUT EFI_STRING          *LanguageString

+  );

+

+/**

+  Allows a program to determine which secondary languages are supported 

+  on a given handle for a given primary language.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle on which the strings reside.

+  

+  @param  PrimaryLanguage Pointer to a NULL-terminated string containing a single 

+  ISO 639-2 language identifier, indicating the primary language.

+  

+  @param  LanguageString A string allocated by GetSecondaryLanguages() 

+  containing a list of all secondary languages registered on the handle.

+

+  @retval EFI_SUCCESS LanguageString was correctly returned.

+  

+  @retval EFI_INVALID_PARAMETER The Handle was unknown.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_SEC_LANGUAGES) (

+  IN  EFI_HII_PROTOCOL    *This,

+  IN  EFI_HII_HANDLE      Handle,

+  IN  CHAR16              *PrimaryLanguage,

+  OUT EFI_STRING          *LanguageString

+  );

+

+/**

+  Extracts a string from a package already registered with the EFI HII database.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle on which the string resides.

+  

+  @param  Token The string token assigned to the string.

+  

+  @param  Raw If TRUE, the string is returned unedited in the internal 

+  storage format described above. If false, the string returned is edited 

+  by replacing <cr> with <space> and by removing special characters such 

+  as the <wide> prefix.

+  

+  @param  LanguageString Pointer to a NULL-terminated string containing a 

+  single ISO 639-2 language identifier, indicating the language to print. 

+  If the LanguageString is empty (starts with a NULL), the default system 

+  language will be used to determine the language.

+  

+  @param  BufferLength Length of the StringBuffer.

+  

+  @param  StringBuffer The buffer designed to receive the characters in the string.

+

+  @retval EFI_SUCCESS StringBuffer is filled with a NULL-terminated string.

+  

+  @retval EFI_INVALID_PARAMETER The handle or string token is unknown.

+  

+  @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to 

+  allow the entire string to be stored. 

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_STRING) (

+  IN     EFI_HII_PROTOCOL  *This,

+  IN     EFI_HII_HANDLE    Handle,

+  IN     STRING_REF        Token,

+  IN     BOOLEAN           Raw,

+  IN     CHAR16            *LanguageString,

+  IN OUT UINTN             *BufferLength,

+  OUT    EFI_STRING        StringBuffer

+  );

+

+/**

+  Allows a program to extract a part of a string of not more than a given width. 

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The handle on which the string resides.

+  

+  @param  Token The string token assigned to the string. 

+  

+  @param  Index On input, the offset into the string where the line is to start.

+  On output, the index is updated to point to beyond the last character returned 

+  in the call.

+  

+  @param  LineWidth The maximum width of the line in units of narrow glyphs.

+  

+  @param  LanguageString Pointer to a NULL-terminated string containing a 

+  single ISO 639-2 language identifier, indicating the language to print.

+  

+  @param  BufferLength Pointer to the length of the StringBuffer. 

+  

+  @param  StringBuffer The buffer designed to receive the characters in the string. 

+

+  @retval EFI_SUCCESS StringBuffer filled with characters that will fit on the line.

+  

+  @retval EFI_NOT_FOUND The font glyph for at least one of the characters in 

+  the string is not in the font database.

+  

+  @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough 

+  to allow the entire string to be stored.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_LINE) (

+  IN     EFI_HII_PROTOCOL  *This,

+  IN     EFI_HII_HANDLE    Handle,

+  IN     STRING_REF        Token,

+  IN OUT UINT16            *Index,

+  IN     UINT16            LineWidth,

+  IN     CHAR16            *LanguageString,

+  IN OUT UINT16            *BufferLength,

+  OUT    EFI_STRING        StringBuffer

+  );

+

+/**

+  Allows a program to extract a form or form package that has previously 

+  been registered with the HII database.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle Handle on which the form resides.

+  

+  @param  FormId The ID of the form to return. If the ID is zero, 

+  the entire form package is returned. 

+  

+  @param  BufferLength On input, the length of the Buffer. On output, 

+  the length of the returned buffer, 

+  

+  @param  Buffer The buffer designed to receive the form(s).

+

+  @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength 

+  was updated.

+  

+  @retval EFI_INVALID_PARAMETER The handle is unknown.

+  

+  @retval EFI_NOT_FOUND A form on the requested handle cannot be found with 

+  the requested FormId.

+  

+  @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough 

+  to allow the form to be stored. 

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_FORMS) (

+  IN     EFI_HII_PROTOCOL  *This,

+  IN     EFI_HII_HANDLE    Handle,

+  IN     EFI_FORM_ID       FormId,

+  IN OUT UINTN             *BufferLength,

+  OUT    UINT8             *Buffer

+  );

+

+/**

+  Extracts the defaults that are associated with a given handle in the HII database.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle The HII handle from which will have default data retrieved.

+  

+  @param  DefaultMask The mask used to specify some type of default override when extracting 

+  the default image data.

+  

+  @param  VariablePackList A indirect pointer to the first entry of a link list with 

+  type EFI_HII_VARIABLE_PACK_LIST. 

+

+  @retval EFI_SUCCESS The VariablePackList was populated with the appropriate 

+  default setting data.

+  

+  @retval EFI_NOT_FOUND The IFR does not have any explicit or default map(s).

+  

+  @retval EFI_INVALID_PARAMETER The HII database entry associated with Handle 

+  contain invalid data.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_DEFAULT_IMAGE) (

+  IN     EFI_HII_PROTOCOL           *This,

+  IN     EFI_HII_HANDLE             Handle,

+  IN     UINTN                      DefaultMask,

+  OUT    EFI_HII_VARIABLE_PACK_LIST **VariablePackList

+  );

+

+/**

+  Allows the caller to update a form or form package that has previously been 

+  registered with the EFI HII database.

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  Handle Handle of the package where the form to be updated resides.

+  

+  @param  Label The label inside the form package where the update is to take place.

+  

+  @param  AddData If TRUE, adding data at a given Label; otherwise, 

+  if FALSE, removing data at a given Label.

+  

+  @param  Data The buffer containing the new tags to insert after the Label

+

+  @retval EFI_SUCCESS The form was updated with the new tags.

+  

+  @retval EFI_INVALID_PARAMETER The buffer for the buffer length does not 

+  contain an integral number of tags.

+  

+  @retval EFI_NOT_FOUND The Handle, Label, or FormId was not found. 

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_UPDATE_FORM) (

+  IN EFI_HII_PROTOCOL     *This,

+  IN EFI_HII_HANDLE       Handle,

+  IN EFI_FORM_LABEL       Label,

+  IN BOOLEAN              AddData,

+  IN EFI_HII_UPDATE_DATA  *Data

+  );

+

+/**

+  Retrieves the current keyboard layout. 

+

+  @param  This A pointer to the EFI_HII_PROTOCOL instance.

+  

+  @param  DescriptorCount A pointer to the number of Descriptor entries being 

+  described in the keyboard layout being retrieved.

+  

+  @param  Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR 

+  entries. Each entry will reflect the definition of a specific physical key.

+

+  @retval EFI_SUCCESS The keyboard layout was retrieved successfully.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT) (

+  IN     EFI_HII_PROTOCOL    *This,

+  OUT    UINT16              *DescriptorCount,

+  OUT    EFI_KEY_DESCRIPTOR  *Descriptor

+  );

+

+/**

+  @par Protocol Description:

+  The HII Protocol manages the HII database, which is a repository for data 

+  having to do with fonts, strings, forms, keyboards, and other future human 

+  interface items.

+

+  @param NewPack

+  Extracts the various packs from a package list.

+

+  @param RemovePack

+  Removes a package from the HII database.

+

+  @param FindHandles

+  Determines the handles that are currently active in the database.

+

+  @param ExportDatabase

+  Export the entire contents of the database to a buffer.

+

+  @param TestString

+  Tests if all of the characters in a string have corresponding font characters.

+

+  @param GetGlyph

+  Translates a Unicode character into the corresponding font glyph. 

+

+  @param GlyphToBlt

+  Converts a glyph value into a format that is ready for a UGA BLT command. 

+

+  @param NewString

+  Allows a new string to be added to an already existing string package.

+

+  @param GetPrimaryLanguages

+  Allows a program to determine the primary languages that are supported 

+  on a given handle. 

+

+  @param GetSecondaryLanguages

+  Allows a program to determine which secondary languages are supported 

+  on a given handle for a given primary language.

+

+  @param GetString

+  Extracts a string from a package that is already registered with the 

+  EFI HII database. 

+

+  @param ResetString

+  Remove any new strings that were added after the initial string export 

+  for this handle.

+

+  @param GetLine

+  Allows a program to extract a part of a string of not more than a given width.

+

+  @param GetForms

+  Allows a program to extract a form or form package that has been previously registered.

+

+  @param GetDefaultImage

+  Allows a program to extract the nonvolatile image that represents the default storage image. 

+

+  @param UpdateForm

+  Allows a program to update a previously registered form. 

+

+  @param GetKeyboardLayout

+  Allows a program to extract the current keyboard layout.

+

+**/

+struct _EFI_HII_PROTOCOL {

+  EFI_HII_NEW_PACK            NewPack;

+  EFI_HII_REMOVE_PACK         RemovePack;

+  EFI_HII_FIND_HANDLES        FindHandles;

+  EFI_HII_EXPORT              ExportDatabase;

+

+  EFI_HII_TEST_STRING         TestString;

+  EFI_HII_GET_GLYPH           GetGlyph;

+  EFI_HII_GLYPH_TO_BLT        GlyphToBlt;

+

+  EFI_HII_NEW_STRING          NewString;

+  EFI_HII_GET_PRI_LANGUAGES   GetPrimaryLanguages;

+  EFI_HII_GET_SEC_LANGUAGES   GetSecondaryLanguages;

+  EFI_HII_GET_STRING          GetString;

+  EFI_HII_RESET_STRINGS       ResetStrings;

+  EFI_HII_GET_LINE            GetLine;

+  EFI_HII_GET_FORMS           GetForms;

+  EFI_HII_GET_DEFAULT_IMAGE   GetDefaultImage;

+  EFI_HII_UPDATE_FORM         UpdateForm;

+

+  EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout;

+};

+

+extern EFI_GUID gEfiHiiProtocolGuid;

+

+#endif

diff --git a/Source/Include/Protocol/UgaDraw.h b/Source/Include/Protocol/UgaDraw.h
new file mode 100644
index 0000000..5586bdf
--- /dev/null
+++ b/Source/Include/Protocol/UgaDraw.h
@@ -0,0 +1,168 @@
+/** @file

+  UGA Draw protocol from the EFI 1.1 specification.

+

+  Abstraction of a very simple graphics device.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  UgaDraw.h

+

+**/

+

+#ifndef __UGA_DRAW_H__

+#define __UGA_DRAW_H__

+

+#define EFI_UGA_DRAW_PROTOCOL_GUID \

+  { \

+    0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \

+  }

+

+typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL;

+

+/**

+  Return the current video mode information.

+

+  @param  This                  Protocol instance pointer.

+  @param  HorizontalResolution  Current video horizontal resolution in pixels

+  @param  VerticalResolution    Current video vertical resolution in pixels

+  @param  ColorDepth            Current video color depth in bits per pixel

+  @param  RefreshRate           Current video refresh rate in Hz.

+

+  @retval EFI_SUCCESS           Mode information returned.

+  @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()

+  @retval EFI_INVALID_PARAMETER One of the input args was NULL.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) (

+  IN  EFI_UGA_DRAW_PROTOCOL *This,

+  OUT UINT32                *HorizontalResolution,

+  OUT UINT32                *VerticalResolution,

+  OUT UINT32                *ColorDepth,

+  OUT UINT32                *RefreshRate

+  )

+;

+

+/**

+  Return the current video mode information.

+

+  @param  This                 Protocol instance pointer.

+  @param  HorizontalResolution Current video horizontal resolution in pixels

+  @param  VerticalResolution   Current video vertical resolution in pixels

+  @param  ColorDepth           Current video color depth in bits per pixel

+  @param  RefreshRate          Current video refresh rate in Hz.

+

+  @retval EFI_SUCCESS          Mode information returned.

+  @retval EFI_NOT_STARTED      Video display is not initialized. Call SetMode ()

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE) (

+  IN  EFI_UGA_DRAW_PROTOCOL *This,

+  IN  UINT32                HorizontalResolution,

+  IN  UINT32                VerticalResolution,

+  IN  UINT32                ColorDepth,

+  IN  UINT32                RefreshRate

+  )

+;

+

+typedef struct {

+  UINT8 Blue;

+  UINT8 Green;

+  UINT8 Red;

+  UINT8 Reserved;

+} EFI_UGA_PIXEL;

+

+typedef union {

+  EFI_UGA_PIXEL Pixel;

+  UINT32        Raw;

+} EFI_UGA_PIXEL_UNION;

+

+typedef enum {

+  EfiUgaVideoFill,

+  EfiUgaVideoToBltBuffer,

+  EfiUgaBltBufferToVideo,

+  EfiUgaVideoToVideo,

+  EfiUgaBltMax

+} EFI_UGA_BLT_OPERATION;

+

+/**

+  Type specifying a pointer to a function to perform an UGA Blt operation.

+

+    The following table defines actions for BltOperations:

+

+    <B>EfiUgaVideoFill</B> - Write data from the  BltBuffer pixel (SourceX, SourceY) 

+      directly to every pixel of the video display rectangle 

+      (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). 

+      Only one pixel will be used from the BltBuffer. Delta is NOT used.

+

+    <B>EfiUgaVideoToBltBuffer</B> - Read data from the video display rectangle 

+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in 

+      the BltBuffer rectangle (DestinationX, DestinationY ) 

+      (DestinationX + Width, DestinationY + Height). If DestinationX or 

+      DestinationY is not zero then Delta must be set to the length in bytes 

+      of a row in the BltBuffer.

+

+    <B>EfiUgaBltBufferToVideo</B> - Write data from the  BltBuffer rectangle 

+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the 

+      video display rectangle (DestinationX, DestinationY) 

+      (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is 

+      not zero then Delta must be set to the length in bytes of a row in the 

+      BltBuffer.

+

+    <B>EfiUgaVideoToVideo</B> - Copy from the video display rectangle (SourceX, SourceY)

+     (SourceX + Width, SourceY + Height) .to the video display rectangle 

+     (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). 

+     The BltBuffer and Delta  are not used in this mode.

+

+

+    @param[in] This          - Protocol instance pointer.

+    @param[in] BltBuffer     - Buffer containing data to blit into video buffer. This 

+                               buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)

+    @param[in] BltOperation  - Operation to perform on BlitBuffer and video memory

+    @param[in] SourceX       - X coordinate of source for the BltBuffer.

+    @param[in] SourceY       - Y coordinate of source for the BltBuffer.

+    @param[in] DestinationX  - X coordinate of destination for the BltBuffer.

+    @param[in] DestinationY  - Y coordinate of destination for the BltBuffer.

+    @param[in] Width         - Width of rectangle in BltBuffer in pixels.

+    @param[in] Height        - Hight of rectangle in BltBuffer in pixels.

+    @param[in] Delta         - OPTIONAL

+  

+    @retval EFI_SUCCESS           - The Blt operation completed.

+    @retval EFI_INVALID_PARAMETER - BltOperation is not valid.

+    @retval EFI_DEVICE_ERROR      - A hardware error occured writting to the video buffer.

+

+--*/

+typedef

+EFI_STATUS

+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT) (

+  IN  EFI_UGA_DRAW_PROTOCOL                   * This,

+  IN  EFI_UGA_PIXEL                           * BltBuffer, OPTIONAL

+  IN  EFI_UGA_BLT_OPERATION                   BltOperation,

+  IN  UINTN                                   SourceX,

+  IN  UINTN                                   SourceY,

+  IN  UINTN                                   DestinationX,

+  IN  UINTN                                   DestinationY,

+  IN  UINTN                                   Width,

+  IN  UINTN                                   Height,

+  IN  UINTN                                   Delta         OPTIONAL

+  );

+

+struct _EFI_UGA_DRAW_PROTOCOL {

+  EFI_UGA_DRAW_PROTOCOL_GET_MODE  GetMode;

+  EFI_UGA_DRAW_PROTOCOL_SET_MODE  SetMode;

+  EFI_UGA_DRAW_PROTOCOL_BLT       Blt;

+};

+

+extern EFI_GUID gEfiUgaDrawProtocolGuid;

+

+#endif

diff --git a/Source/Include/X64/ProcessorBind.h b/Source/Include/X64/ProcessorBind.h
new file mode 100644
index 0000000..f865ce8
--- /dev/null
+++ b/Source/Include/X64/ProcessorBind.h
@@ -0,0 +1,193 @@
+/** @file

+  Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64).

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  ProcessorBind.h

+

+**/

+

+#ifndef __PROCESSOR_BIND_H__

+#define __PROCESSOR_BIND_H__

+

+//

+// Define the processor type so other code can make processor based choices

+//

+#define MDE_CPU_X64

+

+

+//

+// Make sure we are useing the correct packing rules per EFI specification

+//

+#pragma pack()

+

+

+#if _MSC_EXTENSIONS 

+    

+//

+// Disable warning that make it impossible to compile at /W4

+// This only works for Microsoft* tools

+//

+

+//

+// Disabling bitfield type checking warnings.

+//

+#pragma warning ( disable : 4214 )

+

+//

+// Disabling the unreferenced formal parameter warnings.

+//

+#pragma warning ( disable : 4100 )

+

+//

+// Disable slightly different base types warning as CHAR8 * can not be set

+// to a constant string.

+//

+#pragma warning ( disable : 4057 )

+

+//

+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning

+//

+#pragma warning ( disable : 4127 )

+

+

+#endif

+

+

+#if (__STDC_VERSION__ < 199901L)

+  //

+  // No ANSI C 2000 stdint.h integer width declarations, so define equivalents

+  //

+ 

+  #if _MSC_EXTENSIONS 

+    

+

+    //

+    // use Microsoft C complier dependent interger width types 

+    //

+    typedef unsigned __int64    UINT64;

+    typedef __int64             INT64;

+    typedef unsigned __int32    UINT32;

+    typedef __int32             INT32;

+    typedef unsigned short      UINT16;

+    typedef unsigned short      CHAR16;

+    typedef short               INT16;

+    typedef unsigned char       BOOLEAN;

+    typedef unsigned char       UINT8;

+    typedef char                CHAR8;

+    typedef char                INT8;

+  #else

+    #ifdef _EFI_P64 

+      //

+      // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints 

+      //  are 32-bits

+      //

+      typedef unsigned long long  UINT64;

+      typedef long long           INT64;

+      typedef unsigned int        UINT32;

+      typedef int                 INT32;

+      typedef unsigned short      CHAR16;

+      typedef unsigned short      UINT16;

+      typedef short               INT16;

+      typedef unsigned char       BOOLEAN;

+      typedef unsigned char       UINT8;

+      typedef char                CHAR8;

+      typedef char                INT8;

+    #else

+      //

+      // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit.

+      //

+      typedef unsigned long   UINT64;

+      typedef long            INT64;

+      typedef unsigned int    UINT32;

+      typedef int             INT32;

+      typedef unsigned short  UINT16;

+      typedef unsigned short  CHAR16;

+      typedef short           INT16;

+      typedef unsigned char   BOOLEAN;

+      typedef unsigned char   UINT8;

+      typedef char            CHAR8;

+      typedef char            INT8;

+    #endif

+  #endif

+

+  #define UINT8_MAX 0xff

+

+#else

+  //

+  // Use ANSI C 2000 stdint.h integer width declarations

+  //

+  #include <stdint.h>

+  typedef uint8_t   BOOLEAN;

+  typedef int8_t    INT8;

+  typedef uint8_t   UINT8;

+  typedef int16_t   INT16;

+  typedef uint16_t  UINT16;

+  typedef int32_t   INT32;

+  typedef uint32_t  UINT32;

+  typedef int64_t   INT64;

+  typedef uint64_t  UINT64;

+  typedef char      CHAR8;

+  typedef uint16_t  CHAR16;

+

+#endif

+

+typedef UINT64  UINTN;

+typedef INT64   INTN;

+

+

+//

+// Processor specific defines

+//

+#define MAX_BIT     0x8000000000000000

+#define MAX_2_BITS  0xC000000000000000

+

+//

+// Maximum legal Itanium-based address

+//

+#define MAX_ADDRESS   0xFFFFFFFFFFFFFFFF

+

+//

+// Modifier to ensure that all protocol member functions and EFI intrinsics

+// use the correct C calling convention. All protocol member functions and

+// EFI intrinsics are required to modify thier member functions with EFIAPI.

+//

+#if _MSC_EXTENSIONS 

+  ///

+  /// Define the standard calling convention reguardless of optimization level.

+  /// __cdecl is Microsoft* specific C extension.

+  /// 

+  #define EFIAPI __cdecl  

+#elif __GNUC__

+  ///

+  /// Define the standard calling convention reguardless of optimization level.

+  /// efidecl is an extension to GCC that supports the differnece between x64

+  /// GCC ABI and x64 Microsoft* ABI. EFI is closer to the Microsoft* ABI and

+  /// EFIAPI makes sure the right ABI is used for public interfaces. 

+  /// eficecl is a work in progress and we do not yet have the compiler

+  ///

+  #define EFIAPI 

+#else

+  #define EFIAPI       

+#endif

+

+//

+// The Microsoft* C compiler can removed references to unreferenced data items

+//  if the /OPT:REF linker option is used. We defined a macro as this is a 

+//  a non standard extension

+//

+#if _MSC_EXTENSIONS

+  #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany)

+#else

+  #define GLOBAL_REMOVE_IF_UNREFERENCED

+#endif

+

+#endif

+

diff --git a/Source/MakeDeps/MakeDeps.c b/Source/MakeDeps/MakeDeps.c
new file mode 100755
index 0000000..3943df0
--- /dev/null
+++ b/Source/MakeDeps/MakeDeps.c
@@ -0,0 +1,1284 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  MakeDeps.c  

+

+Abstract:

+

+  Recursively scan source files to find include files and emit them to 

+  create dependency lists.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "EfiUtilityMsgs.h"

+#include "CommonLib.h"

+

+//

+// Structure to maintain a linked list of strings

+//

+typedef struct _STRING_LIST {

+  struct _STRING_LIST *Next;

+  char                *Str;

+} STRING_LIST;

+

+#define UTILITY_NAME      "MakeDeps"

+

+#define MAX_LINE_LEN      2048

+#define MAX_PATH          2048

+#define START_NEST_DEPTH  1

+#define MAX_NEST_DEPTH    1000  // just in case we get in an endless loop.

+//

+// Define the relative paths used by the special #include macros

+//

+#define PROTOCOL_DIR_PATH       "Protocol/"

+#define GUID_DIR_PATH           "Guid/"

+#define ARCH_PROTOCOL_DIR_PATH  "ArchProtocol/"

+#define PPI_PROTOCOL_DIR_PATH   "Ppi/"

+

+//

+// Use this structure to keep track of all the special #include forms

+//

+typedef struct {

+  INT8  *IncludeMacroName;

+  INT8  *PathName;

+} INCLUDE_MACRO_CONVERSION;

+

+//

+// This data is used to convert #include macros like:

+//    #include EFI_PROTOCOL_DEFINITION(xxx)

+// into

+//    #include Protocol/xxx/xxx.h

+//

+static const INCLUDE_MACRO_CONVERSION mMacroConversion[] = {

+  "EFI_PROTOCOL_DEFINITION",

+  PROTOCOL_DIR_PATH,

+  "EFI_GUID_DEFINITION",

+  GUID_DIR_PATH,

+  "EFI_ARCH_PROTOCOL_DEFINITION",

+  ARCH_PROTOCOL_DIR_PATH,

+  "EFI_PROTOCOL_PRODUCER",

+  PROTOCOL_DIR_PATH,

+  "EFI_PROTOCOL_CONSUMER",

+  PROTOCOL_DIR_PATH,

+  "EFI_PROTOCOL_DEPENDENCY",

+  PROTOCOL_DIR_PATH,

+  "EFI_ARCH_PROTOCOL_PRODUCER",

+  ARCH_PROTOCOL_DIR_PATH,

+  "EFI_ARCH_PROTOCOL_CONSUMER",

+  ARCH_PROTOCOL_DIR_PATH,

+  "EFI_ARCH_PROTOCOL_DEPENDENCY",

+  ARCH_PROTOCOL_DIR_PATH,

+  "EFI_PPI_DEFINITION",

+  PPI_PROTOCOL_DIR_PATH,

+  "EFI_PPI_PRODUCER",

+  PPI_PROTOCOL_DIR_PATH,

+  "EFI_PPI_CONSUMER",

+  PPI_PROTOCOL_DIR_PATH,

+  "EFI_PPI_DEPENDENCY",

+  PPI_PROTOCOL_DIR_PATH,

+  NULL,

+  NULL

+};

+

+typedef struct _SYMBOL {

+  struct _SYMBOL  *Next;

+  INT8            *Name;

+  INT8            *Value;

+} SYMBOL;

+

+//

+// Here's all our globals. We need a linked list of include paths, a linked

+// list of source files, a linked list of subdirectories (appended to each

+// include path when searching), and flags to keep track of command-line options.

+//

+static struct {

+  STRING_LIST *IncludePaths;            // all include paths to search

+  STRING_LIST *SourceFiles;             // all source files to parse

+  STRING_LIST *SubDirs;                 // appended to each include path when searching

+  SYMBOL      *SymbolTable;             // for replacement strings

+  FILE        *OutFptr;                 // output dependencies to this file

+  BOOLEAN     Verbose;                  // for more detailed output

+  BOOLEAN     IgnoreNotFound;           // no warnings if files not found

+  BOOLEAN     QuietMode;                // -q - don't print missing file warnings

+  BOOLEAN     NoSystem;                 // don't process #include <system> files

+  BOOLEAN     NeverFail;                // always return success

+  BOOLEAN     NoDupes;                  // to not list duplicate dependency files (for timing purposes)

+  BOOLEAN     UseSumDeps;               // use summary dependency files if found

+  INT8        TargetFileName[MAX_PATH]; // target object filename

+  INT8        SumDepsPath[MAX_PATH];    // path to summary files

+  INT8        *OutFileName;             // -o option

+} mGlobals;

+

+static

+STATUS

+ProcessFile (

+  INT8            *TargetFileName,

+  INT8            *FileName,

+  UINT32          NestDepth,

+  STRING_LIST     *ProcessedFiles

+  );

+

+static

+FILE  *

+FindFile (

+  INT8    *FileName,

+  UINT32  FileNameLen

+  );

+

+static

+void

+PrintDependency (

+  INT8    *Target,

+  INT8    *DependentFile

+  );

+

+static

+void

+ReplaceSymbols (

+  INT8    *Str,

+  UINT32  StrSize

+  );

+

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  );

+

+static

+void

+Usage (

+  VOID

+  );

+

+static

+void

+FreeLists (

+  VOID

+  );

+

+int

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+

+  Call the routine to parse the command-line options, then process each file

+  to build dependencies.

+  

+Arguments:

+

+  Argc - Standard C main() argc.

+  Argv - Standard C main() argv.

+

+Returns:

+

+  0       if successful

+  nonzero otherwise

+  

+--*/

+{

+  STRING_LIST *File;

+  STRING_LIST ProcessedFiles;

+  STRING_LIST *TempList;

+  STATUS      Status;

+  INT8        *Cptr;

+  INT8        TargetFileName[MAX_PATH];

+

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Process the command-line arguments

+  //

+  Status = ProcessArgs (Argc, Argv);

+  if (Status != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+  //

+  // Go through the list of source files and process each.

+  //

+  memset (&ProcessedFiles, 0, sizeof (STRING_LIST));

+  File = mGlobals.SourceFiles;

+  while (File != NULL) {

+    //

+    // Clear out our list of processed files

+    //

+    TempList = ProcessedFiles.Next;

+    while (ProcessedFiles.Next != NULL) {

+      TempList = ProcessedFiles.Next->Next;

+      free (ProcessedFiles.Next->Str);

+      free (ProcessedFiles.Next);

+      ProcessedFiles.Next = TempList;

+    }

+    //

+    // Replace filename extension with ".obj" if they did not

+    // specifically specify the target file

+    //

+    if (mGlobals.TargetFileName[0] == 0) {

+      strcpy (TargetFileName, File->Str);

+      //

+      // Find the .extension

+      //

+      for (Cptr = TargetFileName + strlen (TargetFileName) - 1;

+           (*Cptr != '\\' && *Cptr != '/') && (Cptr > TargetFileName) && (*Cptr != '.');

+           Cptr--

+          )

+        ;

+      if (Cptr == TargetFileName) {

+        Error (NULL, 0, 0, File->Str, "could not locate extension in filename");

+        goto Finish;

+      }

+      //

+      // Tack on the ".obj"

+      //

+      strcpy (Cptr, ".obj");

+    } else {

+      //

+      // Copy the target filename they specified

+      //

+      strcpy (TargetFileName, mGlobals.TargetFileName);

+    }

+

+    Status = ProcessFile (TargetFileName, File->Str, START_NEST_DEPTH, &ProcessedFiles);

+    if (Status != STATUS_SUCCESS) {

+      goto Finish;

+    }

+

+    File = File->Next;

+  }

+

+Finish:

+  //

+  // Free up memory

+  //

+  FreeLists ();

+  //

+  // Free up our processed files list

+  //

+  TempList = ProcessedFiles.Next;

+  while (ProcessedFiles.Next != NULL) {

+    TempList = ProcessedFiles.Next->Next;

+    free (ProcessedFiles.Next->Str);

+    free (ProcessedFiles.Next);

+    ProcessedFiles.Next = TempList;

+  }

+  //

+  // Close our output file

+  //

+  if ((mGlobals.OutFptr != stdout) && (mGlobals.OutFptr != NULL)) {

+    fprintf(mGlobals.OutFptr, "\t\n");  // file ending flag

+    fclose (mGlobals.OutFptr);

+  }

+

+  if (mGlobals.NeverFail) {

+    return STATUS_SUCCESS;

+  }

+  //

+  // If any errors, then delete our output so that it will get created

+  // again on a rebuild.

+  //

+  if ((GetUtilityStatus () == STATUS_ERROR) && (mGlobals.OutFileName != NULL)) {

+    remove (mGlobals.OutFileName);

+  }

+

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+ProcessFile (

+  INT8            *TargetFileName,

+  INT8            *FileName,

+  UINT32          NestDepth,

+  STRING_LIST     *ProcessedFiles

+  )

+/*++

+

+Routine Description:

+

+  Given a source file name, open the file and parse all #include lines.

+  

+Arguments:

+

+  TargetFileName - name of the usually .obj target

+  FileName       - name of the file to process

+  NestDepth      - how deep we're nested in includes

+  ProcessedFiles - list of processed files.

+

+Returns:

+

+  standard status.

+  

+--*/

+{

+  FILE        *Fptr;

+  INT8        Line[MAX_LINE_LEN];

+  INT8        *Cptr;

+  INT8        *EndPtr;

+  INT8        *SaveCptr;

+  INT8        EndChar;

+  INT8        FileNameCopy[MAX_PATH];

+  INT8        MacroIncludeFileName[MAX_LINE_LEN];

+  INT8        SumDepsFile[MAX_PATH];

+  STATUS      Status;

+  UINT32      Index;

+  UINT32      LineNum;

+  STRING_LIST *ListPtr;

+

+  Status  = STATUS_SUCCESS;

+  Fptr    = NULL;

+  //

+  // Print the file being processed. Indent so you can tell the include nesting

+  // depth.

+  //

+  if (mGlobals.Verbose) {

+    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', FileName);

+  }

+  //

+  // If we're using summary dependency files, and a matching .dep file is

+  // found for this file, then just emit the summary dependency file as

+  // a dependency and return.

+  //

+  if (mGlobals.UseSumDeps) {

+    strcpy (SumDepsFile, mGlobals.SumDepsPath);

+    strcat (SumDepsFile, FileName);

+    for (Cptr = SumDepsFile + strlen (SumDepsFile) - 1;

+         (*Cptr != '\\' && *Cptr != '/') && (Cptr > SumDepsFile) && (*Cptr != '.');

+         Cptr--

+        )

+      ;

+    if (*Cptr == '.') {

+      strcpy (Cptr, ".dep");

+    } else {

+      strcat (SumDepsFile, ".dep");

+    }

+    //

+    // See if the summary dep file exists. Could use _stat() function, but

+    // it's less portable.

+    //

+    if ((Fptr = fopen (SumDepsFile, "r")) != NULL) {

+      PrintDependency (TargetFileName, SumDepsFile);

+      return STATUS_SUCCESS;

+    }

+  }

+  //

+  // If we're not doing duplicates, and we've already seen this filename,

+  // then return

+  //

+  if (mGlobals.NoDupes) {

+    for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) {

+      if (stricmp (FileName, ListPtr->Str) == 0) {

+        break;

+      }

+    }

+    //

+    // If we found a match, we're done. If we didn't, create a new element

+    // and add it to the list.

+    //

+    if (ListPtr != NULL) {

+      //

+      // Print a message if verbose mode

+      //

+      if (mGlobals.Verbose) {

+        DebugMsg (NULL, 0, 0, FileName, "duplicate include -- not processed again");

+      }

+

+      return STATUS_SUCCESS;

+    }

+

+    ListPtr       = malloc (sizeof (STRING_LIST));

+    ListPtr->Str  = malloc (strlen (FileName) + 1);

+    strcpy (ListPtr->Str, FileName);

+    ListPtr->Next         = ProcessedFiles->Next;

+    ProcessedFiles->Next  = ListPtr;

+  }

+

+  //

+  // Make sure we didn't exceed our maximum nesting depth

+  //

+  if (NestDepth > MAX_NEST_DEPTH) {

+    Error (NULL, 0, 0, FileName, "max nesting depth exceeded on file");

+    goto Finish;

+  }

+  //

+  // Make a local copy of the filename. Then we can manipulate it

+  // if we have to.

+  //

+  strcpy (FileNameCopy, FileName);

+  //

+  // Try to open the file locally

+  //

+  if ((Fptr = fopen (FileNameCopy, "r")) == NULL) {

+    //

+    // Try to find it among the paths.

+    //

+    Fptr = FindFile (FileNameCopy, sizeof (FileNameCopy));

+    if (Fptr == NULL) {

+      //

+      // If this is not the top-level file, and the command-line argument

+      // said to ignore missing files, then return ok

+      //

+      if (NestDepth != START_NEST_DEPTH) {

+        if (mGlobals.IgnoreNotFound) {

+          if (!mGlobals.QuietMode) {

+            DebugMsg (NULL, 0, 0, FileNameCopy, "could not find file");

+          }

+

+          return STATUS_SUCCESS;

+        } else {

+          Error (NULL, 0, 0, FileNameCopy, "could not find file");

+          return STATUS_ERROR;

+        }

+      } else {

+        //

+        // Top-level (first) file. Emit an error.

+        //

+        Error (NULL, 0, 0, FileNameCopy, "could not find file");

+        return STATUS_ERROR;

+      }

+    }

+  }

+  //

+  // Print the dependency, with string substitution

+  //

+  PrintDependency (TargetFileName, FileNameCopy);

+

+  //

+  // Now read in lines and find all #include lines. Allow them to indent, and

+  // to put spaces between the # and include.

+  //

+  LineNum = 0;

+  while ((fgets (Line, sizeof (Line), Fptr) != NULL) && (Status == STATUS_SUCCESS)) {

+    LineNum++;

+    Cptr = Line;

+    //

+    // Skip preceeding spaces on the line

+    //

+    while (*Cptr && (isspace (*Cptr))) {

+      Cptr++;

+    }

+    //

+    // Check for # character

+    //

+    if (*Cptr == '#') {

+      Cptr++;

+      //

+      // Check for "include"

+      //

+      while (*Cptr && (isspace (*Cptr))) {

+        Cptr++;

+      }

+

+      if (strncmp (Cptr, "include", 7) == 0) {

+        //

+        // Skip over "include" and move on to filename as "file" or <file>

+        //

+        Cptr += 7;

+        while (*Cptr && (isspace (*Cptr))) {

+          Cptr++;

+        }

+

+        if (*Cptr == '<') {

+          EndChar = '>';

+        } else if (*Cptr == '"') {

+          EndChar = '"';

+        } else {

+          //

+          // Handle special #include MACRO_NAME(file)

+          // Set EndChar to null so we fall through on processing below.

+          //

+          EndChar = 0;

+          //

+          // Look for all the special include macros and convert accordingly.

+          //

+          for (Index = 0; mMacroConversion[Index].IncludeMacroName != NULL; Index++) {

+            //

+            // Save the start of the string in case some macros are substrings

+            // of others.

+            //

+            SaveCptr = Cptr;

+            if (strncmp (

+                  Cptr,

+                  mMacroConversion[Index].IncludeMacroName,

+                  strlen (mMacroConversion[Index].IncludeMacroName)

+                  ) == 0) {

+              //

+              // Skip over the macro name

+              //

+              Cptr += strlen (mMacroConversion[Index].IncludeMacroName);

+              //

+              // Skip over open parenthesis, blank spaces, then find closing

+              // parenthesis or blank space

+              //

+              while (*Cptr && (isspace (*Cptr))) {

+                Cptr++;

+              }

+

+              if (*Cptr == '(') {

+                Cptr++;

+                while (*Cptr && (isspace (*Cptr))) {

+                  Cptr++;

+                }

+

+                EndPtr = Cptr;

+                while (*EndPtr && !isspace (*EndPtr) && (*EndPtr != ')')) {

+                  EndPtr++;

+                }

+

+                *EndPtr = 0;

+                //

+                // Create the path

+                //

+                strcpy (MacroIncludeFileName, mMacroConversion[Index].PathName);

+                strcat (MacroIncludeFileName, Cptr);

+                strcat (MacroIncludeFileName, "/");

+                strcat (MacroIncludeFileName, Cptr);

+                strcat (MacroIncludeFileName, ".h");

+                //

+                // Process immediately, then break out of the outside FOR loop.

+                //

+                Status = ProcessFile (TargetFileName, MacroIncludeFileName, NestDepth + 1, ProcessedFiles);

+                break;

+              }

+            }

+            //

+            // Restore the start

+            //

+            Cptr = SaveCptr;

+          }

+          //

+          // Don't recognize the include line? Ignore it. We assume that the

+          // file compiles anyway.

+          //

+          if (mMacroConversion[Index].IncludeMacroName == NULL) {

+            //

+            // Warning (FileNameCopy, LineNum, 0, "could not parse line", NULL);

+            // Status = STATUS_WARNING;

+            //

+          }

+        }

+        //

+        // Process "normal" includes. If the endchar is 0, then the

+        // file has already been processed. Otherwise look for the

+        // endchar > or ", and process the include file.

+        //

+        if (EndChar != 0) {

+          Cptr++;

+          EndPtr = Cptr;

+          while (*EndPtr && (*EndPtr != EndChar)) {

+            EndPtr++;

+          }

+

+          if (*EndPtr == EndChar) {

+            //

+            // If we're processing it, do it

+            //

+            if ((EndChar != '>') || (!mGlobals.NoSystem)) {

+              //

+              // Null terminate the filename and try to process it.

+              //

+              *EndPtr = 0;

+              Status  = ProcessFile (TargetFileName, Cptr, NestDepth + 1, ProcessedFiles);

+            }

+          } else {

+            Warning (FileNameCopy, LineNum, 0, "malformed include", "missing closing %c", EndChar);

+            Status = STATUS_WARNING;

+            goto Finish;

+          }

+        }

+      }

+    }

+  }

+

+Finish:

+  //

+  // Close open files and return status

+  //

+  if (Fptr != NULL) {

+    fclose (Fptr);

+  }

+

+  return Status;

+}

+

+static

+void

+PrintDependency (

+  INT8    *TargetFileName,

+  INT8    *DependentFile

+  )

+/*++

+

+Routine Description:

+

+  Given a target (.obj) file name, and a dependent file name, do any string

+  substitutions (per the command line options) on the file names, then

+  print the dependency line of form:

+  

+  TargetFileName : DependentFile

+  

+Arguments:

+

+  TargetFileName - build target file name

+  DependentFile  - file on which TargetFileName depends

+

+Returns:

+

+  None

+  

+--*/

+{

+  INT8  Str[MAX_PATH];

+

+  //

+  // Go through the symbols and do replacements

+  //

+  strcpy (Str, DependentFile);

+  ReplaceSymbols (Str, sizeof (Str));

+  fprintf (mGlobals.OutFptr, "%s\n", Str);

+}

+

+static

+void

+ReplaceSymbols (

+  INT8    *Str,

+  UINT32  StrSize

+  )

+{

+  SYMBOL  *Sym;

+  INT8    StrCopy[MAX_LINE_LEN];

+  INT8    *From;

+  INT8    *To;

+  BOOLEAN Replaced;

+

+  //

+  // Go through the entire string to look for replacement strings at

+  // every position.

+  //

+  From  = Str;

+  To    = StrCopy;

+  while (*From) {

+    //

+    // Copy the character

+    //

+    *To       = *From;

+    Replaced  = FALSE;

+    //

+    // Go through each symbol and try to find a string substitution

+    //

+    Sym = mGlobals.SymbolTable;

+    while (Sym != NULL) {

+      if (strnicmp (From, Sym->Value, strlen (Sym->Value)) == 0) {

+        //

+        // Replace the string, then advance the pointers past the

+        // replaced strings

+        //

+        strcpy (To, Sym->Name);

+        To += strlen (Sym->Name);

+        From += strlen (Sym->Value);

+        Replaced = TRUE;

+        //

+        // Break from the while()

+        //

+        break;

+      } else {

+        Sym = Sym->Next;

+      }

+    }

+

+    if (!Replaced) {

+      From++;

+      To++;

+    }

+  }

+  //

+  // Null terminate, and return it

+  //

+  *To = 0;

+  if (strlen (StrCopy) < StrSize) {

+    strcpy (Str, StrCopy);

+  }

+}

+//

+// Given a filename, try to find it along the include paths.

+//

+static

+FILE *

+FindFile (

+  INT8    *FileName,

+  UINT32  FileNameLen

+  )

+{

+  FILE        *Fptr;

+  STRING_LIST *List;

+  STRING_LIST *SubDir;

+  INT8        FullFileName[MAX_PATH * 2];

+

+  //

+  // Traverse the list of paths and try to find the file

+  //

+  List = mGlobals.IncludePaths;

+  while (List != NULL) {

+    //

+    // Put the path and filename together

+    //

+    if (strlen (List->Str) + strlen (FileName) + 1 > sizeof (FullFileName)) {

+      Error (

+        __FILE__,

+        __LINE__,

+        0,

+        "application error",

+        "cannot concatenate '%s' + '%s'",

+        List->Str,

+        FileName

+        );

+      return NULL;

+    }

+    //

+    // Append the filename to this include path and try to open the file.

+    //

+    strcpy (FullFileName, List->Str);

+    strcat (FullFileName, FileName);

+    if ((Fptr = fopen (FullFileName, "r")) != NULL) {

+      //

+      // Return the file name

+      //

+      if (FileNameLen <= strlen (FullFileName)) {

+        Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");

+        //

+        // fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName);

+        //

+        return NULL;

+      }

+

+      strcpy (FileName, FullFileName);

+      return Fptr;

+    }

+    //

+    // Didn't find it there. Now try this directory with every subdirectory

+    // the user specified on the command line

+    //

+    for (SubDir = mGlobals.SubDirs; SubDir != NULL; SubDir = SubDir->Next) {

+      strcpy (FullFileName, List->Str);

+      strcat (FullFileName, SubDir->Str);

+      strcat (FullFileName, FileName);

+      if ((Fptr = fopen (FullFileName, "r")) != NULL) {

+        //

+        // Return the file name

+        //

+        if (FileNameLen <= strlen (FullFileName)) {

+          Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");

+          return NULL;

+        }

+

+        strcpy (FileName, FullFileName);

+        return Fptr;

+      }

+    }

+

+    List = List->Next;

+  }

+  //

+  // Not found

+  //

+  return NULL;

+}

+//

+// Process the command-line arguments

+//

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  )

+{

+  STRING_LIST *NewList;

+  STRING_LIST *LastIncludePath;

+  STRING_LIST *LastSourceFile;

+  SYMBOL      *Symbol;

+  int         Index;

+  //

+  // Clear our globals

+  //

+  memset ((char *) &mGlobals, 0, sizeof (mGlobals));

+  mGlobals.NoDupes = TRUE;

+  //

+  // Skip program name

+  //

+  Argc--;

+  Argv++;

+  //

+  // Initialize locals

+  //

+  LastIncludePath = NULL;

+  LastSourceFile  = NULL;

+  //

+  // Process until no more args

+  //

+  while (Argc) {

+    //

+    // -i path    add include search path

+    //

+    if (stricmp (Argv[0], "-i") == 0) {

+      //

+      // check for one more arg

+      //

+      if (Argc > 1) {

+        //

+        // Allocate memory for a new list element, fill it in, and

+        // add it to our list of include paths. Always make sure it

+        // has a "\" on the end of it.

+        //

+        NewList = malloc (sizeof (STRING_LIST));

+        if (NewList == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        NewList->Next = NULL;

+        NewList->Str  = malloc (strlen (Argv[1]) + 2);

+        if (NewList->Str == NULL) {

+          free (NewList);

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        strcpy (NewList->Str, Argv[1]);

+        if (NewList->Str[strlen (NewList->Str) - 1] != '\\' && NewList->Str[strlen (NewList->Str) - 1] != '/') {

+          strcat (NewList->Str, "/");

+        }

+        //

+        // Add it to the end of the our list of include paths

+        //

+        if (mGlobals.IncludePaths == NULL) {

+          mGlobals.IncludePaths = NewList;

+        } else {

+          LastIncludePath->Next = NewList;

+        }

+

+        LastIncludePath = NewList;

+        //

+        // fprintf (stdout, "Added path: %s\n", NewList->Str);

+        //

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires an include path");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-f") == 0) {

+      //

+      // Check for one more arg

+      //

+      if (Argc > 1) {

+        //

+        // Allocate memory for a new list element, fill it in, and

+        // add it to our list of source files.

+        //

+        NewList = malloc (sizeof (STRING_LIST));

+        if (NewList == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        NewList->Next = NULL;

+        //

+        // Allocate space to replace ".c" with ".obj", plus null termination

+        //

+        NewList->Str = malloc (strlen (Argv[1]) + 5);

+        if (NewList->Str == NULL) {

+          free (NewList);

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        strcpy (NewList->Str, Argv[1]);

+        if (mGlobals.SourceFiles == NULL) {

+          mGlobals.SourceFiles = NewList;

+        } else {

+          LastSourceFile->Next = NewList;

+        }

+

+        LastSourceFile = NewList;

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires a file name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+      //

+      // The C compiler first looks for #include files in the directory where

+      // the source file came from. Add the file's source directory to the

+      // list of include paths.

+      //

+      NewList = malloc (sizeof (STRING_LIST));

+      if (NewList == NULL) {

+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+        return STATUS_ERROR;

+      }

+

+      NewList->Next = NULL;

+      NewList->Str  = malloc (strlen (Argv[1]) + 3);

+      if (NewList->Str == NULL) {

+        free (NewList);

+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+        return STATUS_ERROR;

+      }

+

+      strcpy (NewList->Str, Argv[1]);

+      //

+      // Back up in the source file name to the last backslash and terminate after it.

+      //

+      for (Index = strlen (NewList->Str) - 1; (Index > 0) && (NewList->Str[Index] != '\\' && NewList->Str[Index] != '/'); Index--)

+        ;

+      if (Index < 0) {

+        strcpy (NewList->Str, "./");

+      } else {

+        NewList->Str[Index + 1] = 0;

+      }

+      //

+      // Add it to the end of the our list of include paths

+      //

+      if (mGlobals.IncludePaths == NULL) {

+        mGlobals.IncludePaths = NewList;

+      } else {

+        LastIncludePath->Next = NewList;

+      }

+

+      if (mGlobals.Verbose) {

+        fprintf (stdout, "Adding include path: %s\n", NewList->Str);

+      }

+

+      LastIncludePath = NewList;

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-s") == 0) {

+      //

+      // -s subdir    add subdirectory subdir to list of subdirecties to scan.

+      // Check for one more arg first.

+      //

+      if (Argc > 1) {

+        //

+        // Allocate memory for a new list element, fill it in, and

+        // add it to our list of subdirectory include paths. Always

+        // make sure it has a "\" on the end of it.

+        //

+        NewList = malloc (sizeof (STRING_LIST));

+        if (NewList == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        NewList->Str = malloc (strlen (Argv[1]) + 2);

+        if (NewList->Str == NULL) {

+          free (NewList);

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        strcpy (NewList->Str, Argv[1]);

+        if (NewList->Str[strlen (NewList->Str) - 1] != '\\' && NewList->Str[strlen (NewList->Str) - 1] != '/') {

+          strcat (NewList->Str, "/");

+        }

+

+        NewList->Next     = mGlobals.SubDirs;

+        mGlobals.SubDirs  = NewList;

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires a subdirectory name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-sub") == 0) {

+      //

+      // -sub symname symvalue  to do string substitution in the output

+      //

+      if (Argc > 2) {

+        //

+        // Allocate memory for the symbol object

+        //

+        Symbol = malloc (sizeof (SYMBOL));

+        if (Symbol == NULL) {

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+        //

+        // Allocate memory for the symbol name and value, then save copies

+        //

+        Symbol->Name = malloc (strlen (Argv[1]) + 1);

+        if (Symbol->Name == NULL) {

+          free (Symbol);

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        strcpy (Symbol->Name, Argv[1]);

+        Symbol->Value = malloc (strlen (Argv[2]) + 1);

+        if (Symbol->Value == NULL) {

+          free (Symbol->Name);

+          free (Symbol);

+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);

+          return STATUS_ERROR;

+        }

+

+        strcpy (Symbol->Value, Argv[2]);

+        //

+        // Add it to the list

+        //

+        Symbol->Next          = mGlobals.SymbolTable;

+        mGlobals.SymbolTable  = Symbol;

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires a symbol name and value");

+        Usage ();

+        return STATUS_ERROR;

+      }

+      //

+      // Skip over args

+      //

+      Argc -= 2;

+      Argv += 2;

+    } else if (stricmp (Argv[0], "-nosystem") == 0) {

+      mGlobals.NoSystem = TRUE;

+    } else if (stricmp (Argv[0], "-nodupes") == 0) {

+      mGlobals.NoDupes = TRUE;

+    } else if (stricmp (Argv[0], "-nodups") == 0) {

+      mGlobals.NoDupes = TRUE;

+    } else if (stricmp (Argv[0], "-target") == 0) {

+      //

+      // -target TargetFileName  - Target object file (only one allowed right

+      // now) is TargetFileName rather than SourceFile.obj

+      //

+      if (Argc > 1) {

+        strcpy (mGlobals.TargetFileName, Argv[1]);

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires a target file name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-usesumdeps") == 0) {

+      //

+      // -usesumdeps Path - if we find an included file xxx.h, and file

+      // Path/xxx.dep exists, list Path/xxx.dep as a dependency rather than

+      // xxx.h and don't parse xxx.h. This allows you to create a dependency

+      // file for a commonly included file, and have its dependency file updated

+      // only if its included files are updated. Then anyone else including this

+      // common include file can simply have a dependency on that file's .dep file

+      // rather than on all the files included by it. Confusing enough?

+      //

+      mGlobals.UseSumDeps = 1;

+      if (Argc > 1) {

+        strcpy (mGlobals.SumDepsPath, Argv[1]);

+        //

+        // Add slash on end if not there

+        //

+        if (mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '\\' && mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '/') {

+          strcat (mGlobals.SumDepsPath, "/");

+        }

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires path to summary dependency files");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+

+    } else if (stricmp (Argv[0], "-o") == 0) {

+      //

+      // -o OutputFileName    - specify an output filename for dependency list

+      // check for one more arg

+      //

+      if (Argc > 1) {

+        //

+        // Try to open the file

+        //

+        if ((mGlobals.OutFptr = fopen (Argv[1], "w")) == NULL) {

+          Error (NULL, 0, 0, Argv[1], "could not open file for writing");

+          return STATUS_ERROR;

+        }

+

+        mGlobals.OutFileName = Argv[1];

+      } else {

+        Error (NULL, 0, 0, Argv[0], "option requires output file name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-v") == 0) {

+      mGlobals.Verbose = TRUE;

+    } else if (stricmp (Argv[0], "-neverfail") == 0) {

+      mGlobals.NeverFail = TRUE;

+    } else if (stricmp (Argv[0], "-q") == 0) {

+      mGlobals.QuietMode = TRUE;

+    } else if (stricmp (Argv[0], "-ignorenotfound") == 0) {

+      mGlobals.IgnoreNotFound = TRUE;

+    } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {

+      Usage ();

+      return STATUS_ERROR;

+    } else {

+      Error (NULL, 0, 0, Argv[0], "unrecognized option");

+      Usage ();

+      return STATUS_ERROR;

+    }

+

+    Argc--;

+    Argv++;

+  }

+  //

+  // Had to specify at least one source file

+  //

+  if (mGlobals.SourceFiles == NULL) {

+    Error (NULL, 0, 0, "must specify one source file name", NULL);

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Assume output to stdout if not specified

+  //

+  if (mGlobals.OutFptr == NULL) {

+    mGlobals.OutFptr = stdout;

+  }

+

+  return STATUS_SUCCESS;

+}

+//

+// Free the global string lists we allocated memory for

+//

+static

+void

+FreeLists (

+  VOID

+  )

+{

+  STRING_LIST *Temp;

+  SYMBOL      *NextSym;

+

+  //

+  // printf ("Free lists.....");

+  //

+  // Traverse the include paths, freeing each

+  // printf ("freeing include paths\n");

+  //

+  while (mGlobals.IncludePaths != NULL) {

+    Temp = mGlobals.IncludePaths->Next;

+    //

+    // printf ("Freeing include path string '%s' at 0x%X\n",

+    //  mGlobals.IncludePaths->Str, (int)(mGlobals.IncludePaths->Str));

+    //

+    free (mGlobals.IncludePaths->Str);

+    //

+    // printf ("Freeing include path object at 0x%X\n", (int)(mGlobals.IncludePaths));

+    //

+    free (mGlobals.IncludePaths);

+    mGlobals.IncludePaths = Temp;

+  }

+  //

+  // Traverse the source files, freeing each

+  //

+  while (mGlobals.SourceFiles != NULL) {

+    Temp = mGlobals.SourceFiles->Next;

+    free (mGlobals.SourceFiles->Str);

+    free (mGlobals.SourceFiles);

+    mGlobals.SourceFiles = Temp;

+  }

+  //

+  // Traverse the subdirectory list, freeing each

+  //

+  while (mGlobals.SubDirs != NULL) {

+    Temp = mGlobals.SubDirs->Next;

+    free (mGlobals.SubDirs->Str);

+    free (mGlobals.SubDirs);

+    mGlobals.SubDirs = Temp;

+  }

+  //

+  // Free the symbol table

+  //

+  while (mGlobals.SymbolTable != NULL) {

+    NextSym = mGlobals.SymbolTable->Next;

+    free (mGlobals.SymbolTable->Name);

+    free (mGlobals.SymbolTable->Value);

+    mGlobals.SymbolTable = NextSym;

+  }

+  //

+  // printf ("done\n");

+  //

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Print usage information for this utility.

+  

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+  

+--*/

+{

+  int               Index;

+  static const char *Str[] = {

+    UTILITY_NAME " -- make dependencies",

+    "  Usage: MakeDeps [options]",

+    "    Options include:",

+    "      -h or -?         for this help information",

+    "      -f SourceFile    add SourceFile to list of files to scan",

+    "      -i IncludePath   add IncludePath to list of search paths",

+    "      -o OutputFile    write output dependencies to OutputFile",

+    "      -s SubDir        for each IncludePath, also search IncludePath\\SubDir",

+    "      -v               for verbose output",

+    "      -ignorenotfound  don't warn for files not found",

+    "      -target Target   for single SourceFile, target is Target, not SourceFile.obj",

+    "      -q               quiet mode to not report files not found if ignored",

+    "      -sub sym str     replace all occurrances of 'str' with 'sym' in the output",

+    "      -nosystem        not process system <include> files",

+    "      -neverfail       always return a success return code",

+    //

+    //    "      -nodupes         keep track of include files, don't rescan duplicates",

+    //

+    "      -usesumdeps path use summary dependency files in 'path' directory.",

+    "",

+    NULL

+  };

+  for (Index = 0; Str[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Str[Index]);

+  }

+}

diff --git a/Source/MakeDeps/build.xml b/Source/MakeDeps/build.xml
new file mode 100755
index 0000000..6c532a1
--- /dev/null
+++ b/Source/MakeDeps/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK MakeDeps Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="MakeDeps"/>

+  <property name="FileSet" value="*.c *.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />   

+       

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/ModifyInf/ModifyInf.c b/Source/ModifyInf/ModifyInf.c
new file mode 100755
index 0000000..6008feb
--- /dev/null
+++ b/Source/ModifyInf/ModifyInf.c
@@ -0,0 +1,321 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  ModifyInf.c

+

+Abstract:

+

+  It is a simple tool to modify some fields in a FV inf file 

+  and output a new FV inf file.  

+

+--*/

+

+#include "stdio.h"

+#include "string.h"

+

+//

+// Read a line into buffer including '\r\n'

+//

+int

+ReadLine (

+  char *LineBuffer,

+  FILE *fp

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  LineBuffer  - GC_TODO: add argument description

+  fp          - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  int   CharC;

+  char  *Line;

+

+  Line = LineBuffer;

+

+  while ((CharC = fgetc (fp)) != EOF) {

+    *Line++ = (char) CharC;

+    if (CharC == 0x0a) {

+      break;

+    }

+  }

+

+  *Line = 0;

+

+  if (CharC == EOF) {

+    return 0;

+  } else {

+    return 1;

+  }

+

+}

+//

+// Write a line into output file

+//

+int

+WriteLine (

+  char *Line,

+  FILE *fp

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Line  - GC_TODO: add argument description

+  fp    - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  fwrite (Line, strlen (Line), 1, fp);

+  return 0;

+}

+//

+// Apply patterns to a line

+// Currently there are 2 patterns to support

+// '==' replace a field value with a new value

+// '+=' append a string at the end of original line

+// '-'  prevent the line from applying any patterns

+//      it has the highest priority

+//

+int

+ApplyPattern (

+  char *Line,

+  char *argv[],

+  int  argc

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  Line  - GC_TODO: add argument description

+  ]     - GC_TODO: add argument description

+  argc  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  static char Section[256];

+  char        PatternBuffer[256];

+  char        *Pattern;

+  char        *Pattern1;

+  char        *Pattern2;

+  int         PatternNum;

+  char        *Ptr;

+

+  Pattern     = PatternBuffer;

+

+  PatternNum  = argc;

+

+  //

+  // For section field

+  // record current scope section into static buffer

+  //

+  Ptr = Line;

+  if (*Ptr == '[') {

+    while (*Ptr != ']') {

+      if (!(*Ptr++)) {

+        return -1;

+      }

+    }

+

+    strcpy (Section, Line);

+    Section[Ptr - Line + 1] = 0;

+  }

+  //

+  // Apply each pattern on the line

+  //

+  while (PatternNum-- > 3) {

+

+    strcpy (Pattern, argv[PatternNum]);

+

+    //

+    // For pattern '-'

+    // keep it unmodified by other patterns

+    //

+    if (*Pattern == '-') {

+      if (strstr (Line, Pattern + 1)) {

+        return 0;

+      } else {

+        continue;

+      }

+    }

+    //

+    // For other patterns

+    // get its section at first if it has

+    //

+    if (*Pattern == '[') {

+      if (strncmp (Section, Pattern, strlen (Section))) {

+        //

+        // This pattern can't be appied for current section

+        //

+        continue;

+      }

+      //

+      // Strip the section field

+      //

+      while (*Pattern != ']') {

+        if (!(*Pattern++)) {

+          return -1;

+        }

+      }

+

+      Pattern++;

+    }

+    //

+    // Apply patterns

+    //

+    Pattern1  = strstr (Pattern, "==");

+    Pattern2  = strstr (Pattern, "+=");

+    if (Pattern1) {

+      //

+      // For pattern '=='

+      // replace the field value with a new string

+      //

+      if (!strncmp (Line, Pattern, Pattern1 - Pattern)) {

+        Pattern1 += 2;

+        Ptr = strstr (Line, "=");

+        if (!Ptr) {

+          return -1;

+        }

+

+        while (*(++Ptr) == ' ')

+          ;

+        *Ptr = 0;

+        strcat (Line, Pattern1);

+        strcat (Line, "\r\n");

+      }

+    } else if (Pattern2) {

+      //

+      // For pattern '+='

+      // append a string at end of the original string

+      //

+      if (!strncmp (Line, Pattern, Pattern2 - Pattern)) {

+        Pattern2 += 2;

+        Ptr = Line;

+        while (*Ptr != 0x0D && *Ptr != 0x0A) {

+          Ptr++;

+        }

+

+        *Ptr = 0;

+        strcat (Line, Pattern2);

+        strcat (Line, "\r\n");

+      }

+    }

+  }

+

+  return 0;

+}

+

+void

+Usage (

+  void

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  printf ("ModifyInf InputFVInfFileName OutputFVInfFileName [Pattern strings]\r\n");

+}

+

+int

+main (

+  int argc,

+  char*argv[]

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  argc  - GC_TODO: add argument description

+  ]     - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  char  LineBuffer[256];

+  FILE  *fpin;

+  FILE  *fpout;

+

+  if (argc < 3) {

+    Usage ();

+    return -1;

+  }

+

+  fpin = fopen (argv[1], "rb");

+  if (!fpin) {

+    printf ("Can't open input file!\r\n");

+    return -1;

+  }

+

+  fpout = fopen (argv[2], "wb");

+  if (!fpout) {

+    fclose (fpin);

+    printf ("Can't create output file!\r\n");

+    return -1;

+  }

+

+  while (ReadLine (LineBuffer, fpin)) {

+    ApplyPattern (LineBuffer, argv, argc);

+    WriteLine (LineBuffer, fpout);

+  }

+

+  fclose (fpin);

+  fclose (fpout);

+

+  return 0;

+}

diff --git a/Source/ModifyInf/build.xml b/Source/ModifyInf/build.xml
new file mode 100644
index 0000000..f536a98
--- /dev/null
+++ b/Source/ModifyInf/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK ModifyInf Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="ModifyInf"/>

+  <property name="FileSet" value="ModifyInf.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/Pccts/CHANGES_FROM_131.txt b/Source/Pccts/CHANGES_FROM_131.txt
new file mode 100644
index 0000000..500d84f
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_131.txt
@@ -0,0 +1,522 @@
+CHANGES FROM 1.31

+

+This file contains the migration of PCCTS from 1.31 in the order that

+changes were made.  1.32b7 is the last beta before full 1.32.

+Terence Parr, Parr Research Corporation 1995.

+

+

+======================================================================

+1.32b1

+Added Russell Quong to banner, changed banner for output slightly

+Fixed it so that you have before / after actions for C++ in class def

+Fixed bug in optimizer that made it sometimes forget to set internal

+        token pointers.  Only showed up when a {...} was in the "wrong spot".

+

+======================================================================

+1.32b2

+Added fixes by Dave Seidel for PC compilers in 32 bit mode (config.h

+and set.h).

+

+======================================================================

+1.32b3

+Fixed hideous bug in code generator for wildcard and for ~token op.

+

+from Dave Seidel

+

+   Added pcnames.bat

+   1. in antlr/main.c: change strcasecmp() to stricmp()

+

+   2. in dlg/output.c: use DLEXER_C instead on "DLexer.C"

+

+   3. in h/PBlackBox.h: use <iostream.h> instead of <stream.h>

+

+======================================================================

+1.32b4

+When the -ft option was used, any path prefix screwed up

+the gate on the .h files

+

+Fixed yet another bug due to the optimizer.

+

+The exception handling thing was a bit wacko:

+

+a : ( A B )? A B

+  | A C

+  ;

+  exception ...

+

+caused an exception if "A C" was the input.  In other words,

+it found that A C didn't match the (A B)? pred and caused

+an exception rather than trying the next alt.  All I did

+was to change the zzmatch_wsig() macros.

+

+Fixed some problems in gen.c relating to the name of token

+class bit sets in the output.

+

+Added the tremendously cool generalized predicate.  For the

+moment, I'll give this bried description.

+

+a : <<predicate>>? blah

+  | foo

+  ;

+

+This implies that (assuming blah and foo are syntactically

+ambiguous) "predicate" indicates the semantic validity of

+applying "blah".  If "predicate" is false, "foo" is attempted.

+

+Previously, you had to say:

+

+a : <<LA(1)==ID ? predicate : 1>>? ID

+  | ID

+  ;

+

+Now, you can simply use "predicate" without the ?: operator

+if you turn on ANTLR command line option: "-prc on".  This

+tells ANTLR to compute that all by itself.  It computes n

+tokens of lookahead where LT(n) or LATEXT(n) is the farthest

+ahead you look.

+

+If you give a predicate using "-prc on" that is followed

+by a construct that can recognize more than one n-sequence,

+you will get a warning from ANTLR.  For example,

+

+a : <<isTypeName(LT(1)->getText())>>? (ID|INT)

+  ;

+

+This is wrong because the predicate will be applied to INTs

+as well as ID's.  You should use this syntax to make

+the predicate more specific:

+

+a : (ID)? => <<isTypeName(LT(1)->getText())>>? (ID|INT)

+  ;

+

+which says "don't apply the predicate unless ID is the

+current lookahead context".

+

+You cannot currently have anything in the "(context)? =>"

+except sequences such as:

+

+( LPAREN ID | LPAREN SCOPE )? => <<pred>>?

+

+I haven't tested this THAT much, but it does work for the

+C++ grammar.

+

+======================================================================

+1.32b5

+

+Added getLine() to the ANTLRTokenBase and DLGBasedToken classes

+left line() for backward compatibility.

+----

+Removed SORCERER_TRANSFORM from the ast.h stuff.

+-------

+Fixed bug in code gen of ANTLR such that nested syn preds work more

+efficiently now.  The ANTLRTokenBuffer was getting very large

+with nested predicates.

+------

+Memory leak is now gone from ANTLRTokenBuf; all tokens are deleted.

+For backward compatibility reasons, you have to say parser->deleteTokens()

+or mytokenbuffer->deleteTokens() but later it will be the default mode.

+Say this after the parser is constructed. E.g.,

+

+    ParserBlackBox<DLGLexer, MyParser, ANTLRToken> p(stdin);

+    p.parser()->deleteTokens();

+    p.parser()->start_symbol();

+

+

+==============================

+1.32b6

+

+Changed so that deleteTokens() will do a delete ((ANTLRTokenBase *))

+on the ptr.  This gets the virtual destructor.

+

+Fixed some weird things in the C++ header files (a few return types).

+

+Made the AST routines correspond to the book and SORCERER stuff.

+

+New token stuff:  See testcpp/14/test.g

+

+ANTLR accepts a #pragma gc_tokens which says

+[1]     Generate label = copy(LT(1)) instead of label=LT(1) for

+        all labeled token references.

+[2]     User now has to define ANTLRTokenPtr (as a class or a typedef

+        to just a pointer) as well as the ANTLRToken class itself.

+		See the example.

+

+To delete tokens in token buffer, use deleteTokens() message on parser.

+

+        All tokens that fall off the ANTLRTokenBuffer get deleted

+        which is what currently happens when deleteTokens() message

+        has been sent to token buffer.

+

+We always generate ANTLRTokenPtr instead of 'ANTLRToken *' now.

+Then if no pragma set, ANTLR generates a

+

+        class ANTLRToken;

+        typedef ANTLRToken *ANTLRTokenPtr;

+

+in each file.

+

+Made a warning for x:rule_ref <<$x>>; still no warning for $i's, however.

+class BB {

+

+a : x:b y:A <<$x

+$y>>

+  ;

+

+b : B;

+

+}

+generates

+Antlr parser generator   Version 1.32b6   1989-1995

+test.g, line 3: error: There are no token ptrs for rule references: '$x'

+

+===================

+1.32b7:

+

+[With respect to token object garbage collection (GC), 1.32b7

+ backtracks from 1.32b6, but results in better and less intrusive GC.

+ This is the last beta version before full 1.32.]

+

+BIGGEST CHANGES:

+

+o	The "#pragma gc_tokens" is no longer used.

+

+o	.C files are now .cpp files (hence, makefiles will have to

+	be changed; or you can rerun genmk).  This is a good move,

+	but causes some backward incompatibility problems.  You can

+	avoid this by changing CPP_FILE_SUFFIX to ".C" in pccts/h/config.h.

+

+o	The token object class hierarchy has been flattened to include

+	only three classes: ANTLRAbstractToken, ANTLRCommonToken, and

+	ANTLRCommonNoRefCountToken.  The common token now does garbage

+	collection via ref counting.

+

+o	"Smart" pointers are now used for garbage collection.  That is,

+	ANTLRTokenPtr is used instead of "ANTLRToken *".

+

+o	The antlr.1 man page has been cleaned up slightly.

+

+o	The SUN C++ compiler now complains less about C++ support code.

+

+o	Grammars which subclass ANTLRCommonToken must wrap all token

+	pointer references in mytoken(token_ptr).  This is the only

+	serious backward incompatibility.  See below.

+

+

+MINOR CHANGES:

+

+--------------------------------------------------------

+1	deleteTokens()

+

+The deleteTokens() message to the parser or token buffer has been changed

+to one of:

+

+    void noGarbageCollectTokens()   { inputTokens->noGarbageCollectTokens(); }

+    void garbageCollectTokens()     { inputTokens->garbageCollectTokens(); }

+

+The token buffer deletes all non-referenced tokens by default now.

+

+--------------------------------------------------------

+2	makeToken()

+

+The makeToken() message returns a new type.  The function should look

+like:

+

+    virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,

+                                          ANTLRChar *txt,

+                                          int line)

+    {

+        ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt);

+        t->setLine(line);

+        return t;

+    }

+

+--------------------------------------------------------

+3	TokenType

+

+Changed TokenType-> ANTLRTokenType  (often forces changes in AST defs due

+to #[] constructor called to AST(tokentype, string)).

+

+--------------------------------------------------------

+4	AST()

+

+You must define AST(ANTLRTokenPtr t) now in your AST class definition.

+You might also have to include ATokPtr.h above the definition; e.g.,

+if AST is defined in a separate file, such as AST.h, it's a good idea

+to include ATOKPTR_H (ATokPtr.h).  For example,

+

+	#include ATOKPTR_H

+	class AST : public ASTBase {

+	protected:

+	    ANTLRTokenPtr token;

+	public:

+	    AST(ANTLRTokenPtr t) { token = t; }

+	    void preorder_action() {

+	        char *s = token->getText();

+	        printf(" %s", s);

+	    }

+	};

+

+Note the use of smart pointers rather than "ANTLRToken *".

+

+--------------------------------------------------------

+5	SUN C++

+

+From robertb oakhill.sps.mot.com Bob Bailey. Changed ANTLR C++ output

+to avoid an error in Sun C++ 3.0.1.  Made "public" return value

+structs created to hold multiple return values public.

+

+--------------------------------------------------------

+6	genmk

+

+Fixed genmk so that target List.* is not included anymore.  It's

+called SList.* anyway.

+

+--------------------------------------------------------

+7	\r vs \n

+

+Scott Vorthmann <vorth cmu.edu> fixed antlr.g in ANTLR so that \r

+is allowed as the return character as well as \n.

+

+--------------------------------------------------------

+8	Exceptions

+

+Bug in exceptions attached to labeled token/tokclass references.  Didn't gen

+code for exceptions.  This didn't work:

+

+a : "help" x:ID

+  ;

+        exception[x]

+        catch MismatchedToken : <<printf("eh?\n");>>

+

+Now ANTLR generates (which is kinda big, but necessary):

+

+        if ( !_match_wsig(ID) ) {

+                if ( guessing ) goto fail;

+                _signal=MismatchedToken;

+                switch ( _signal ) {

+                case MismatchedToken :

+                        printf("eh?\n");

+                        _signal = NoSignal;

+                        break;

+                default :

+                        goto _handler;

+                }

+        }

+

+which implies that you can recover and continue parsing after a missing/bad

+token reference.

+

+--------------------------------------------------------

+9	genmk

+

+genmk now correctly uses config file for CPP_FILE_SUFFIX stuff.

+

+--------------------------------------------------------

+10	general cleanup / PURIFY

+

+Anthony Green <green vizbiz.com> suggested a bunch of good general

+clean up things for the code; he also suggested a few things to

+help out the "PURIFY" memory allocation checker.

+

+--------------------------------------------------------

+11	$-variable references.

+

+Manuel ORNATO indicated that a $-variable outside of a rule caused

+ANTLR to crash.  I fixed this.

+

+12	Tom Moog suggestion

+

+Fail action of semantic predicate needs "{}" envelope.  FIXED.

+

+13	references to LT(1).

+

+I have enclosed all assignments such as:

+

+             _t22 = (ANTLRTokenPtr)LT(1);

+

+in "if ( !guessing )" so that during backtracking the reference count

+for token objects is not increased.

+

+

+TOKEN OBJECT GARBAGE COLLECTION

+

+1	INTRODUCTION

+

+The class ANTLRCommonToken is now garbaged collected through a "smart"

+pointer called ANTLRTokenPtr using reference counting.  Any token

+object not referenced by your grammar actions is destroyed by the

+ANTLRTokenBuffer when it must make room for more token objects.

+Referenced tokens are then destroyed in your parser when local

+ANTLRTokenPtr objects are deleted.  For example,

+

+a : label:ID ;

+

+would be converted to something like:

+

+void yourclass::a(void)

+{

+	zzRULE;

+	ANTLRTokenPtr label=NULL;	// used to be ANTLRToken *label;

+        zzmatch(ID);

+        label = (ANTLRTokenPtr)LT(1);

+	consume();

+	...

+}

+

+When the "label" object is destroyed (it's just a pointer to your

+input token object LT(1)), it decrements the reference count on the

+object created for the ID.  If the count goes to zero, the object

+pointed by label is deleted.

+

+To correctly manage the garbage collection, you should use

+ANTLRTokenPtr instead of "ANTLRToken *".  Most ANTLR support code

+(visible to the user) has been modified to use the smart pointers.

+

+***************************************************************

+Remember that any local objects that you create are not deleted when a

+lonjmp() is executed.  Unfortunately, the syntactic predicates (...)?

+use setjmp()/longjmp().  There are some situations when a few tokens

+will "leak".

+***************************************************************

+

+2	DETAILS

+

+o	The default is to perform token object garbage collection.

+	You may use parser->noGarbageCollectTokens() to turn off

+	garbage collection.

+

+

+o	The type ANTLRTokenPtr is always defined now (automatically).

+	If you do not wish to use smart pointers, you will have to

+	redefined ANTLRTokenPtr by subclassing, changing the header

+	file or changing ANTLR's code generation (easy enough to

+	do in gen.c).

+

+o	If you don't use ParserBlackBox, the new initialization sequence is:

+

+	    ANTLRTokenPtr aToken = new ANTLRToken;

+	    scan.setToken(mytoken(aToken));

+

+	where mytoken(aToken) gets an ANTLRToken * from the smart pointer.

+

+o	Define C++ preprocessor symbol DBG_REFCOUNTTOKEN to see a bunch of

+	debugging stuff for reference counting if you suspect something.

+

+

+3	WHY DO I HAVE TO TYPECAST ALL MY TOKEN POINTERS NOW??????

+

+If you subclass ANTLRCommonToken and then attempt to refer to one of

+your token members via a token pointer in your grammar actions, the

+C++ compiler will complain that your token object does not have that

+member.  For example, if you used to do this

+

+<<

+class ANTLRToken : public ANTLRCommonToken {

+        int muck;

+	...

+};

+>>

+

+class Foo {

+a : t:ID << t->muck = ...; >> ;

+}

+

+Now, you must do change the t->muck reference to:

+

+a : t:ID << mytoken(t)->muck = ...; >> ;

+

+in order to downcast 't' to be an "ANTLRToken *" not the

+"ANTLRAbstractToken *" resulting from ANTLRTokenPtr::operator->().

+The macro is defined as:

+

+/*

+ * Since you cannot redefine operator->() to return one of the user's

+ * token object types, we must down cast.  This is a drag.  Here's

+ * a macro that helps.  template: "mytoken(a-smart-ptr)->myfield".

+ */

+#define mytoken(tp) ((ANTLRToken *)(tp.operator->()))

+

+You have to use macro mytoken(grammar-label) now because smart

+pointers are not specific to a parser's token objects.  In other

+words, the ANTLRTokenPtr class has a pointer to a generic

+ANTLRAbstractToken not your ANTLRToken; the ANTLR support code must

+use smart pointers too, but be able to work with any kind of

+ANTLRToken.  Sorry about this, but it's C++'s fault not mine.  Some

+nebulous future version of the C++ compilers should obviate the need

+to downcast smart pointers with runtime type checking (and by allowing

+different return type of overridden functions).

+

+A way to have backward compatible code is to shut off the token object

+garbage collection; i.e., use parser->noGarbageCollectTokens() and

+change the definition of ANTLRTokenPtr (that's why you get source code

+<wink>).

+

+

+PARSER EXCEPTION HANDLING

+

+I've noticed some weird stuff with the exception handling.  I intend

+to give this top priority for the "book release" of ANTLR.

+

+==========

+1.32 Full Release

+

+o	Changed Token class hierarchy to be (Thanks to Tom Moog):

+

+        ANTLRAbstractToken

+          ANTLRRefCountToken

+             ANTLRCommonToken

+          ANTLRNoRefCountCommonToken

+

+o	Added virtual panic() to ANTLRAbstractToken.  Made ANTLRParser::panic()

+	virtual also.

+

+o	Cleaned up the dup() stuff in AST hierarchy to use shallowCopy() to

+	make node copies.  John Farr at Medtronic suggested this.  I.e.,

+	if you want to use dup() with either ANTLR or SORCERER or -transform

+	mode with SORCERER, you must defined shallowCopy() as:

+

+	virtual PCCTS_AST *shallowCopy()

+	{

+	    return new AST;

+	    p->setDown(NULL);

+	    p->setRight(NULL);

+	    return p;

+	}

+

+	or

+

+	virtual PCCTS_AST *shallowCopy()

+	{

+	    return new AST(*this);

+	}

+	

+	if you have defined a copy constructor such as

+

+	AST(const AST &t)	// shallow copy constructor

+	{

+		token = t.token;

+		iconst = t.iconst;

+		setDown(NULL);

+		setRight(NULL);

+	}

+

+o	Added a warning with -CC and -gk are used together.  This is broken,

+	hence a warning is appropriate.

+

+o	Added warning when #-stuff is used w/o -gt option.

+

+o	Updated MPW installation.

+

+o	"Miller, Philip W." <MILLERPW f1groups.fsd.jhuapl.edu> suggested

+	that genmk be use RENAME_OBJ_FLAG RENAME_EXE_FLAG instead of

+	hardcoding "-o" in genmk.c.

+

+o	made all exit() calls use EXIT_SUCCESS or EXIT_FAILURE.

+

+===========================================================================

+1.33

+

+EXIT_FAILURE and EXIT_SUCCESS were not always defined.  I had to modify

+a bunch of files to use PCCTS_EXIT_XXX, which forces a new version.  Sorry

+about that.

+

diff --git a/Source/Pccts/CHANGES_FROM_133.txt b/Source/Pccts/CHANGES_FROM_133.txt
new file mode 100644
index 0000000..2128c4f
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_133.txt
@@ -0,0 +1,2448 @@
+=======================================================================

+List of Implemented Fixes and Changes for Maintenance Releases of PCCTS

+=======================================================================

+

+                               DISCLAIMER

+

+ The software and these notes are provided "as is".  They may include

+ typographical or technical errors and their authors disclaims all

+ liability of any kind or nature for damages due to error, fault,

+ defect, or deficiency regardless of cause.  All warranties of any

+ kind, either express or implied, including, but not limited to, the

+ implied  warranties of merchantability and fitness for a particular

+ purpose are disclaimed.

+

+

+        -------------------------------------------------------

+        Note:  Items #153 to #1 are now in a separate file named

+                CHANGES_FROM_133_BEFORE_MR13.txt

+        -------------------------------------------------------

+        

+#312. (Changed in MR33) Bug caused by change #299.

+

+	In change #299 a warning message was suppressed when there was

+	no LT(1) in a semantic predicate and max(k,ck) was 1.  The 

+	changed caused the code which set a default predicate depth for

+	the semantic predicate to be left as 0 rather than set to 1.

+	

+	This manifested as an error at line #1559 of mrhost.c

+	

+	Reported by Peter Dulimov.

+	    

+#311. (Changed in MR33) Added sorcer/lib to Makefile.

+

+    Reported by Dale Martin.

+            

+#310. (Changed in MR32) In C mode zzastPush was spelled zzastpush in one case.

+

+    Reported by Jean-Claude Durand

+    

+#309. (Changed in MR32) Renamed baseName because of VMS name conflict

+

+    Renamed baseName to pcctsBaseName to avoid library name conflict with

+    VMS library routine.  Reported by Jean-François PIÉRONNE.

+    

+#308. (Changed in MR32) Used "template" as name of formal in C routine

+

+	In astlib.h routine ast_scan a formal was named "template".  This caused

+	problems when the C code was compiled with a C++ compiler.  Reported by

+	Sabyasachi Dey.

+            

+#307. (Changed in MR31) Compiler dependent bug in function prototype generation

+    

+    The code which generated function prototypes contained a bug which

+    was compiler/optimization dependent.  Under some circumstance an

+    extra character would be included in portions of a function prototype.

+    

+    Reported by David Cook.

+    

+#306. (Changed in MR30) Validating predicate following a token

+

+    A validating predicate which immediately followed a token match 

+    consumed the token after the predicate rather than before.  Prior

+    to this fix (in the following example) isValidTimeScaleValue() in

+    the predicate would test the text for TIMESCALE rather than for

+    NUMBER:

+     

+		time_scale :

+    		TIMESCALE

+    		<<isValidTimeScaleValue(LT(1)->getText())>>?

+    		ts:NUMBER

+    		( us:MICROSECOND << tVal = ...>>

+    		| ns:NANOSECOND << tVal = ...  >>

+    		)

+	

+	Reported by Adalbert Perbandt.

+	

+#305. (Changed in MR30) Alternatives with guess blocks inside (...)* blocks.

+

+	In MR14 change #175 fixed a bug in the prediction expressions for guess

+	blocks which were of the form (alpha)? beta.  Unfortunately, this

+	resulted in a new bug as exemplified by the example below, which computed

+	the first set for r as {B} rather than {B C}:

+	

+					r : ( (A)? B

+					    | C

+						)*

+  

+    This example doesn't make any sense as A is not a prefix of B, but it

+    illustrates the problem.  This bug did not appear for:

+    

+    				r : ( (A)?

+    				    | C

+    				    )*

+

+	because it does not use the (alpha)? beta form.

+

+	Item #175 fixed an asymmetry in ambiguity messages for the following

+	constructs which appear to have identical ambiguities (between repeating

+	the loop vs. exiting the loop).  MR30 retains this fix, but the implementation

+	is slightly different.

+	

+	          r_star : ( (A B)? )* A ;

+	          r_plus : ( (A B)? )+ A ;

+

+    Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).

+    

+#304. (Changed in MR30) Crash when mismatch between output value counts.

+

+	For a rule such as:

+	

+		r1 : r2>[i,j];

+		r2 >[int i, int j] : A;

+		

+	If there were extra actuals for the reference to rule r2 from rule r1

+	there antlr would crash.  This bug was introduced by change #276.

+

+	Reported by Sinan Karasu.

+	

+#303. (Changed in MR30) DLGLexerBase::replchar

+

+	DLGLexerBase::replchar and the C mode routine zzreplchar did not work 

+	properly when the new character was 0.

+      

+    Reported with fix by Philippe Laporte

+

+#302. (Changed in MR28) Fix significant problems in initial release of MR27.

+

+#301. (Changed in MR27) Default tab stops set to 2 spaces.

+

+    To have antlr generate true tabs rather than spaces, use "antlr -tab 0".

+    To generate 4 spaces per tab stop use "antlr -tab 4"

+    

+#300. (Changed in MR27)

+

+	Consider the following methods of constructing an AST from ID:

+	

+        rule1!

+                : id:ID << #0 = #[id]; >> ;

+        

+        rule2!

+                : id:ID << #0 = #id; >> ;

+        

+        rule3

+                : ID ;

+        

+        rule4

+                : id:ID << #0 = #id; >> ;

+        

+    For rule_2, the AST corresponding to id would always be NULL.  This

+    is because the user explicitly suppressed AST construction using the

+    "!" operator on the rule.  In MR27 the use of an AST expression

+    such as #id overrides the "!" operator and forces construction of

+    the AST.

+    

+    This fix does not apply to C mode ASTs when the ASTs are referenced

+    using numbers rather than symbols.

+

+	For C mode, this requires that the (optional) function/macro zzmk_ast

+	be defined.  This functions copies information from an attribute into

+	a previously allocated AST.

+

+    Reported by Jan Langer (jan langernetz.de)

+

+#299. (Changed in MR27) Don't warn if k=1 and semantic predicate missing LT(i)

+

+    If a semantic does not have a reference to LT(i) or (C mode LATEXT(i))

+    then pccts doesn't know how many lookahead tokens to use for context.

+    However, if max(k,ck) is 1 then there is really only one choice and

+    the warning is unnecessary.

+    

+#298. (Changed in MR27) Removed "register" for lastpos in dlgauto.c zzgettok

+

+#297. (Changed in MR27) Incorrect prototypes when used with classic C

+

+    There were a number of errors in function headers when antlr was

+    built with compilers that do not have __STDC__ or __cplusplus set.

+    

+    The functions which have variable length argument lists now use

+    PCCTS_USE_STDARG rather than __USE_PROTOTYPES__ to determine

+    whether to use stdargs or varargs.

+

+#296. (Changed in MR27) Complex return types in rules.

+

+    The following return type was not properly handled when 

+    unpacking a struct with containing multiple return values:

+    

+      rule > [int i, IIR_Bool (IIR_Decl::*constraint)()] : ...    

+

+    Instead of using "constraint", the program got lost and used

+    an empty string.

+    

+    Reported by P.A. Wilsey.

+

+#295. (Changed in MR27) Extra ";" following zzGUESS_DONE sometimes.

+

+    Certain constructs with guess blocks in MR23 led to extra ";"

+    preceding the "else" clause of an "if".

+

+    Reported by P.A. Wilsey.

+    

+#294. (Changed in MR27) Infinite loop in antlr for nested blocks

+

+    An oversight in detecting an empty alternative sometimes led

+    to an infinite loop in antlr when it encountered a rule with

+    nested blocks and guess blocks.

+    

+    Reported by P.A. Wilsey.

+    

+#293. (Changed in MR27) Sorcerer optimization of _t->type()

+

+    Sorcerer generated code may contain many calls to _t->type() in a

+    single statement.  This change introduces a temporary variable

+    to eliminate unnnecesary function calls.

+

+    Change implemented by Tom Molteno (tim videoscript.com).

+

+#292. (Changed in MR27)

+

+    WARNING:  Item #267 changes the signature of methods in the AST class.

+

+    **** Be sure to revise your AST functions of the same name  ***

+

+#291. (Changed in MR24)

+

+    Fix to serious code generation error in MR23 for (...)+ block.

+

+#290. (Changed in MR23) 

+

+    Item #247 describes a change in the way {...} blocks handled

+    an error.  Consider:

+

+            r1 : {A} b ;

+            b  : B;

+                

+                with input "C".

+

+    Prior to change #247, the error would resemble "expected B -

+    found C".  This is correct but incomplete, and therefore

+    misleading.  In #247 it was changed to "expected A, B - found

+    C".  This was fine, except for users of parser exception

+    handling because the exception was generated in the epilogue 

+    for {...} block rather than in rule b.  This made it difficult

+    for users of parser exception handling because B was not

+    expected in that context. Those not using parser exception

+    handling didn't notice the difference.

+

+    The current change restores the behavior prior to #247 when

+    parser exceptions are present, but retains the revised behavior

+    otherwise.  This change should be visible only when exceptions

+    are in use and only for {...} blocks and sub-blocks of the form

+    (something|something | something | epsilon) where epsilon represents

+    an empty production and it is the last alternative of a sub-block.

+    In contrast, (something | epsilon | something) should generate the

+    same code as before, even when exceptions are used.

+    

+    Reported by Philippe Laporte (philippe at transvirtual.com).

+

+#289. (Changed in MR23) Bug in matching complement of a #tokclass

+

+    Prior to MR23 when a #tokclass was matched in both its complemented form

+    and uncomplemented form, the bit set generated for its first use was used

+    for both cases.  However, the prediction expression was correctly computed

+    in both cases.  This meant that the second case would never be matched

+    because, for the second appearance, the prediction expression and the 

+    set to be matched would be complements of each other.

+        

+    Consider:

+        

+                #token A "a"

+                #token B "b"

+                #token C "c"

+                #tokclass AB {A B}

+                

+                r1 : AB    /* alt 1x */

+                   | ~AB   /* alt 1y */

+                   ;

+        

+    Prior to MR23, this resulted in alternative 1y being unreachable.  Had it

+    been written:

+        

+                r2 : ~AB  /* alt 2x */

+                   : AB   /* alt 2y */

+                   

+    then alternative 2y would have become unreachable.        

+        

+    This bug was only for the case of complemented #tokclass.  For complemented

+    #token the proper code was generated.           

+        

+#288. (Changed in MR23) #errclass not restricted to choice points

+

+    The #errclass directive is supposed to allow a programmer to define

+    print strings which should appear in syntax error messages as a replacement

+    for some combinations of tokens. For instance:

+    

+            #errclass Operator {PLUS MINUS TIMES DIVIDE}

+            

+    If a syntax message includes all four of these tokens, and there is no

+    "better" choice of error class, the word "Operator" will be used rather

+    than a list of the four token names.

+        

+    Prior to MR23 the #errclass definitions were used only at choice points

+    (which call the FAIL macro). In other cases where there was no choice

+    (e.g. where a single token or token class were matched) the #errclass

+    information was not used.

+

+    With MR23 the #errclass declarations are used for syntax error messages

+    when matching a #tokclass, a wildcard (i.e. "*"), or the complement of a

+    #token or #tokclass (e.g. ~Operator).

+

+    Please note that #errclass may now be defined using #tokclass names 

+    (see Item #284).

+

+    Reported by Philip A. Wilsey.

+

+#287. (Changed in MR23) Print name for #tokclass

+

+    Item #148 describes how to give a print name to a #token so that,for

+    example, #token ID could have the expression "identifier" in syntax

+    error messages.  This has been extended to #tokclass:

+    

+            #token ID("identifier")  "[a-zA-Z]+"

+            #tokclass Primitive("primitive type") 

+                                    {INT, FLOAT, CHAR, FLOAT, DOUBLE, BOOL} 

+

+    This is really a cosmetic change, since #tokclass names do not appear

+    in any error messages.

+        

+#286. (Changed in MR23) Makefile change to use of cd

+

+    In cases where a pccts subdirectory name matched a directory identified

+    in a $CDPATH environment variable the build would fail.  All makefile

+    cd commands have been changed from "cd xyz" to "cd ./xyz" in order

+    to avoid this problem.

+        

+#285. (Changed in MR23) Check for null pointers in some dlg structures

+

+    An invalid regular expression can cause dlg to build an invalid

+    structure to represent the regular expression even while it issues 

+    error messages.  Additional pointer checks were added.

+

+    Reported by Robert Sherry.

+

+#284. (Changed in MR23) Allow #tokclass in #errclass definitions

+

+    Previously, a #tokclass reference in the definition of an

+    #errclass was not handled properly. Instead of being expanded

+    into the set of tokens represented by the #tokclass it was

+    treated somewhat like an #errclass.  However, in a later phase

+    when all #errclass were expanded into the corresponding tokens

+    the #tokclass reference was not expanded (because it wasn't an

+    #errclass).  In effect the reference was ignored.

+

+    This has been fixed.

+

+    Problem reported by Mike Dimmick (mike dimmick.demon.co.uk).

+

+#283. (Changed in MR23) Option -tmake invoke's parser's tmake 

+

+    When the string #(...) appears in an action antlr replaces it with

+    a call to ASTBase::tmake(...) to construct an AST.  It is sometimes

+    useful to change the tmake routine so that it has access to information

+    in the parser - something which is not possible with a static method

+    in an application where they may be multiple parsers active.

+

+    The antlr option -tmake replaces the call to ASTBase::tmake with a call

+    to a user supplied tmake routine.

+   

+#282. (Changed in MR23) Initialization error for DBG_REFCOUNTTOKEN

+

+    When the pre-processor symbol DBG_REFCOUNTTOKEN is defined 

+    incorrect code is generated to initialize ANTLRRefCountToken::ctor and

+    dtor.

+

+    Fix reported by Sven Kuehn (sven sevenkuehn.de).

+   

+#281. (Changed in MR23) Addition of -noctor option for Sorcerer

+

+    Added a -noctor option to suppress generation of the blank ctor

+    for users who wish to define their own ctor.

+

+    Contributed by Jan Langer (jan langernetz.de).

+

+#280. (Changed in MR23) Syntax error message for EOF token

+

+    The EOF token now receives special treatment in syntax error messages

+    because there is no text matched by the eof token.  The token name

+    of the eof token is used unless it is "@" - in which case the string

+    "<eof>" is used.

+

+    Problem reported by Erwin Achermann (erwin.achermann switzerland.org).

+

+#279. (Changed in MR23) Exception groups

+

+    There was a bug in the way that exception groups were attached to

+    alternatives which caused problems when there was a block contained

+    in an alternative.  For instance, in the following rule;

+

+        statement : IF S { ELSE S } 

+                        exception ....

+        ;

+

+    the exception would be attached to the {...} block instead of the 

+    entire alternative because it was attached, in error, to the last

+    alternative instead of the last OPEN alternative.

+

+    Reported by Ty Mordane (tymordane hotmail.com).

+    

+#278. (Changed in MR23) makefile changes

+

+    Contributed by Tomasz Babczynski (faster lab05-7.ict.pwr.wroc.pl).

+

+    The -cfile option is not absolutely needed: when extension of

+    source file is one of the well-known C/C++ extensions it is 

+    treated as C/C++ source

+

+    The gnu make defines the CXX variable as the default C++ compiler

+    name, so I added a line to copy this (if defined) to the CCC var.

+

+    Added a -sor option: after it any -class command defines the class

+    name for sorcerer, not for ANTLR.  A file extended with .sor is 

+    treated as sorcerer input.  Because sorcerer can be called multiple

+    times, -sor option can be repeated.  Any files and classes (one class

+    per group) after each -sor makes one tree parser.

+

+    Not implemented:

+

+        1. Generate dependences for user c/c++ files.

+        2. Support for -sor in c mode not.

+

+    I have left the old genmk program in the directory as genmk_old.c.

+

+#277. (Changed in MR23) Change in macro for failed semantic predicates

+

+    In the past, a semantic predicate that failed generated a call to

+    the macro zzfailed_pred:

+

+        #ifndef zzfailed_pred

+        #define zzfailed_pred(_p) \

+          if (guessing) { \

+            zzGUESS_FAIL; \

+          } else { \

+            something(_p)

+          }

+        #endif

+

+    If a user wished to use the failed action option for semantic predicates:

+

+        rule : <<my_predicate>>? [my_fail_action] A

+             | ...

+

+           

+    the code for my_fail_action would have to contain logic for handling

+    the guess part of the zzfailed_pred macro.  The user should not have

+    to be aware of the guess logic in writing the fail action.

+

+    The zzfailed_pred has been rewritten to have three arguments:

+

+            arg 1: the stringized predicate of the semantic predicate

+            arg 2: 0 => there is no user-defined fail action

+                   1 => there is a user-defined fail action

+            arg 3: the user-defined fail action (if defined)

+                   otherwise a no-operation

+

+    The zzfailed_pred macro is now defined as:

+

+        #ifndef zzfailed_pred

+        #define zzfailed_pred(_p,_hasuseraction,_useraction) \

+          if (guessing) { \

+            zzGUESS_FAIL; \

+          } else { \

+            zzfailed_pred_action(_p,_hasuseraction,_useraction) \

+          }

+        #endif

+

+

+    With zzfailed_pred_action defined as:

+

+        #ifndef zzfailed_pred_action

+        #define zzfailed_pred_action(_p,_hasuseraction,_useraction) \

+            if (_hasUserAction) { _useraction } else { failedSemanticPredicate(_p); }

+        #endif

+

+    In C++ mode failedSemanticPredicate() is a virtual function.

+    In C mode the default action is a fprintf statement.

+

+    Suggested by Erwin Achermann (erwin.achermann switzerland.org).

+

+#276. (Changed in MR23) Addition of return value initialization syntax

+

+    In an attempt to reduce the problems caused by the PURIFY macro I have

+    added new syntax for initializing the return value of rules and the

+    antlr option "-nopurify".

+

+    A rule with a single return argument:

+

+        r1 > [Foo f = expr] :

+

+    now generates code that resembles:

+

+        Foo r1(void) {

+          Foo _retv = expr;

+          ...

+        }

+  

+    A rule with more than one return argument:

+

+        r2 > [Foo f = expr1, Bar b = expr2 ] :

+

+    generates code that resembles:

+

+        struct _rv1 {

+            Foo f;

+            Bar b;

+        }

+

+        _rv1 r2(void) {

+          struct _rv1 _retv;

+          _retv.f = expr1;

+          _retv.b = expr2;

+          ...

+        }

+

+    C++ style comments appearing in the initialization list may cause problems.

+

+#275. (Changed in MR23) Addition of -nopurify option to antlr

+

+    A long time ago the PURIFY macro was introduced to initialize

+    return value arguments and get rid of annying messages from program

+    that checked for unitialized variables.

+

+    This has caused significant annoyance for C++ users that had

+    classes with virtual functions or non-trivial contructors because

+    it would zero the object, including the pointer to the virtual

+    function table.  This could be defeated by redefining

+    the PURIFY macro to be empty, but it was a constant surprise to

+    new C++ users of pccts.

+

+    I would like to remove it, but I fear that some existing programs

+    depend on it and would break.  My temporary solution is to add

+    an antlr option -nopurify which disables generation of the PURIFY

+    macro call.

+

+    The PURIFY macro should be avoided in favor of the new syntax

+    for initializing return arguments described in item #275.

+

+    To avoid name clash, the PURIFY macro has been renamed PCCTS_PURIFY.

+

+#274. (Changed in MR23) DLexer.cpp renamed to DLexer.h

+      (Changed in MR23) ATokPtr.cpp renamed to ATokPtrImpl.h

+

+    These two files had .cpp extensions but acted like .h files because

+    there were included in other files. This caused problems for many IDE.

+    I have renamed them.  The ATokPtrImpl.h was necessary because there was

+    already an ATokPtr.h.

+

+#273. (Changed in MR23) Default win32 library changed to multi-threaded DLL

+

+    The model used for building the Win32 debug and release libraries has changed

+    to multi-threaded DLL.

+

+    To make this change in your MSVC 6 project:

+

+        Project -> Settings

+        Select the C++ tab in the right pane of the dialog box

+        Select "Category: Code Generation"

+        Under "Use run-time library" select one of the following:

+

+            Multi-threaded DLL

+            Debug Multi-threaded DLL

+           

+    Suggested by Bill Menees (bill.menees gogallagher.com) 

+    

+#272. (Changed in MR23) Failed semantic predicate reported via virtual function

+

+    In the past, a failed semantic predicated reported the problem via a

+    macro which used fprintf().  The macro now expands into a call on 

+    the virtual function ANTLRParser::failedSemanticPredicate().

+

+#271. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions

+

+    An bug (or at least an oddity) is that a reference to LT(1), LA(1),

+    or LATEXT(1) in an action which immediately follows a token match

+    in a rule refers to the token matched, not the token which is in

+    the lookahead buffer.  Consider:

+

+        r : abc <<action alpha>> D <<action beta>> E;

+

+    In this case LT(1) in action alpha will refer to the next token in

+    the lookahead buffer ("D"), but LT(1) in action beta will refer to

+    the token matched by D - the preceding token.

+

+    A warning has been added for users about this when an action

+    following a token match contains a reference to LT(1), LA(1), or LATEXT(1).

+

+    This behavior should be changed, but it appears in too many programs

+    now.  Another problem, perhaps more significant, is that the obvious

+    fix (moving the consume() call to before the action) could change the 

+    order in which input is requested and output appears in existing programs.

+

+    This problem was reported, along with a fix by Benjamin Mandel

+    (beny sd.co.il).  However, I felt that changing the behavior was too

+    dangerous for existing code.

+

+#270. (Changed in MR23) Removed static objects from PCCTSAST.cpp

+

+    There were some statically allocated objects in PCCTSAST.cpp

+    These were changed to non-static.

+

+#269. (Changed in MR23) dlg output for initializing static array

+

+    The output from dlg contains a construct similar to the

+    following:

+   

+        struct XXX {

+          static const int size;

+          static int array1[5];

+        };

+

+        const int XXX::size = 4;

+        int XXX::array1[size+1];

+

+    

+    The problem is that although the expression "size+1" used in

+    the definition of array1 is equal to 5 (the expression used to

+    declare array), it is not considered equivalent by some compilers.

+

+    Reported with fix by Volker H. Simonis (simonis informatik.uni-tuebingen.de)

+

+#268. (Changed in MR23) syn() routine output when k > 1

+

+    The syn() routine is supposed to print out the text of the

+    token causing the syntax error.  It appears that it always

+    used the text from the first lookahead token rather than the

+    appropriate one.  The appropriate one is computed by comparing

+    the token codes of lookahead token i (for i = 1 to k) with

+    the FIRST(i) set.

+    

+    This has been corrected in ANTLRParser::syn().

+

+    Reported by Bill Menees (bill.menees gogallagher.com) 

+

+#267. (Changed in MR23) AST traversal functions client data argument

+

+    The AST traversal functions now take an extra (optional) parameter

+    which can point to client data:

+

+        preorder_action(void* pData = NULL)

+        preorder_before_action(void* pData = NULL)

+        preorder_after_action(void* pData = NULL)

+

+    ****       Warning: this changes the AST signature.         ***

+    **** Be sure to revise your AST functions of the same name  ***

+

+    Bill Menees (bill.menees gogallagher.com) 

+    

+#266. (Changed in MR23) virtual function printMessage()

+

+    Bill Menees (bill.menees gogallagher.com) has completed the

+    tedious taks of replacing all calls to fprintf() with calls

+    to the virtual function printMessage().  For classes which

+    have a pointer to the parser it forwards the printMessage()

+    call to the parser's printMessage() routine.

+

+    This should make it significanly easier to redirect pccts

+    error and warning messages.

+

+#265. (Changed in MR23) Remove "labase++" in C++ mode

+

+    In C++ mode labase++ is called when a token is matched.

+    It appears that labase is not used in C++ mode at all, so

+    this code has been commented out.

+    

+#264. (Changed in MR23) Complete rewrite of ParserBlackBox.h

+

+    The parser black box (PBlackBox.h) was completely rewritten

+    by Chris Uzdavinis (chris atdesk.com) to improve its robustness.

+

+#263. (Changed in MR23) -preamble and -preamble_first rescinded

+

+    Changes for item #253 have been rescinded.

+

+#262. (Changed in MR23) Crash with -alpha option during traceback

+

+    Under some circumstances a -alpha traceback was started at the

+    "wrong" time.  As a result, internal data structures were not

+    initialized.

+

+    Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).

+

+#261. (Changed in MR23) Defer token fetch for C++ mode

+

+    Item #216 has been revised to indicate that use of the defer fetch

+    option (ZZDEFER_FETCH) requires dlg option -i.

+

+#260. (MR22) Raise default lex buffer size from 8,000 to 32,000 bytes.

+

+    ZZLEXBUFSIZE is the size (in bytes) of the buffer used by dlg 

+    generated lexers.  The default value has been raised to 32,000 and

+    the value used by antlr, dlg, and sorcerer has also been raised to

+    32,000.

+

+#259. (MR22) Default function arguments in C++ mode.

+

+    If a rule is declared:

+

+            rr [int i = 0] : ....

+

+    then the declaration generated by pccts resembles:

+

+            void rr(int i = 0);

+

+    however, the definition must omit the default argument:

+

+            void rr(int i) {...}

+

+    In the past the default value was not omitted.  In MR22

+    the generated code resembles:

+

+            void rr(int i /* = 0 */ ) {...}

+

+    Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de)

+

+

+    Note: In MR23 this was changed so that nested C style comments

+    ("/* ... */") would not cause problems.

+

+#258. (MR22)  Using a base class for your parser

+

+    In item #102 (MR10) the class statement was extended to allow one

+    to specify a base class other than ANTLRParser for the generated

+    parser.  It turned out that this was less than useful because

+    the constructor still specified ANTLRParser as the base class.

+

+    The class statement now uses the first identifier appearing after

+    the ":" as the name of the base class.  For example:

+

+        class MyParser : public FooParser {

+

+    Generates in MyParser.h:

+

+            class MyParser : public FooParser {

+

+    Generates in MyParser.cpp something that resembles:

+

+            MyParser::MyParser(ANTLRTokenBuffer *input) :

+                                         FooParser(input,1,0,0,4)

+            {

+                token_tbl = _token_tbl;

+                traceOptionValueDefault=1;    // MR10 turn trace ON

+            }

+

+    The base class constructor must have a signature similar to

+    that of ANTLRParser.

+

+#257. (MR21a) Removed dlg statement that -i has no effect in C++ mode.

+

+    This was incorrect.

+

+#256. (MR21a) Malformed syntax graph causes crash after error message.

+

+    In the past, certain kinds of errors in the very first grammar

+    element could cause the construction of a malformed graph 

+    representing the grammar.  This would eventually result in a

+    fatal internal error.  The code has been changed to be more

+    resistant to this particular error.

+

+#255. (MR21a) ParserBlackBox(FILE* f) 

+

+    This constructor set openByBlackBox to the wrong value.

+

+    Reported by Kees Bakker (kees_bakker tasking.nl).

+

+#254. (MR21a) Reporting syntax error at end-of-file

+

+    When there was a syntax error at the end-of-file the syntax

+    error routine would substitute "<eof>" for the programmer's

+    end-of-file symbol.  This substitution is now done only when

+    the programmer does not define his own end-of-file symbol

+    or the symbol begins with the character "@".

+

+    Reported by Kees Bakker (kees_bakker tasking.nl).

+

+#253. (MR21) Generation of block preamble (-preamble and -preamble_first)

+

+        *** This change was rescinded by item #263 ***

+

+    The antlr option -preamble causes antlr to insert the code

+    BLOCK_PREAMBLE at the start of each rule and block.  It does

+    not insert code before rules references, token references, or

+    actions.  By properly defining the macro BLOCK_PREAMBLE the

+    user can generate code which is specific to the start of blocks.

+

+    The antlr option -preamble_first is similar, but inserts the

+    code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol

+    PreambleFirst_123 is equivalent to the first set defined by

+    the #FirstSetSymbol described in Item #248.

+

+    I have not investigated how these options interact with guess

+    mode (syntactic predicates).

+

+#252. (MR21) Check for null pointer in trace routine

+

+    When some trace options are used when the parser is generated

+    without the trace enabled, the current rule name may be a

+    NULL pointer.  A guard was added to check for this in

+    restoreState.

+

+    Reported by Douglas E. Forester (dougf projtech.com).

+

+#251. (MR21) Changes to #define zzTRACE_RULES

+

+    The macro zzTRACE_RULES was being use to pass information to

+    AParser.h.  If this preprocessor symbol was not properly

+    set the first time AParser.h was #included, the declaration

+    of zzTRACEdata would be omitted (it is used by the -gd option).

+    Subsequent #includes of AParser.h would be skipped because of 

+    the #ifdef guard, so the declaration of zzTracePrevRuleName would

+    never be made.  The result was that proper compilation was very 

+    order dependent.

+

+    The declaration of zzTRACEdata was made unconditional and the

+    problem of removing unused declarations will be left to optimizers.

+    

+    Diagnosed by Douglas E. Forester (dougf projtech.com).

+

+#250. (MR21) Option for EXPERIMENTAL change to error sets for blocks

+

+    The antlr option -mrblkerr turns on an experimental feature

+    which is supposed to provide more accurate syntax error messages

+    for k=1, ck=1 grammars.  When used with k>1 or ck>1 grammars the

+    behavior should be no worse than the current behavior.

+

+    There is no problem with the matching of elements or the computation

+    of prediction expressions in pccts.  The task is only one of listing

+    the most appropriate tokens in the error message.  The error sets used

+    in pccts error messages are approximations of the exact error set when

+    optional elements in (...)* or (...)+ are involved.  While entirely

+    correct, the error messages are sometimes not 100% accurate.  

+

+    There is also a minor philosophical issue.  For example, suppose the

+    grammar expects the token to be an optional A followed by Z, and it 

+    is X.  X, of course, is neither A nor Z, so an error message is appropriate.

+    Is it appropriate to say "Expected Z" ?  It is correct, it is accurate,

+    but it is not complete.  

+

+    When k>1 or ck>1 the problem of providing the exactly correct

+    list of tokens for the syntax error messages ends up becoming

+    equivalent to evaluating the prediction expression for the

+    alternatives twice. However, for k=1 ck=1 grammars the prediction

+    expression can be computed easily and evaluated cheaply, so I

+    decided to try implementing it to satisfy a particular application.

+    This application uses the error set in an interactive command language

+    to provide prompts which list the alternatives available at that

+    point in the parser.  The user can then enter additional tokens to

+    complete the command line.  To do this required more accurate error 

+    sets then previously provided by pccts.

+

+    In some cases the default pccts behavior may lead to more robust error

+    recovery or clearer error messages then having the exact set of tokens.

+    This is because (a) features like -ge allow the use of symbolic names for

+    certain sets of tokens, so having extra tokens may simply obscure things

+    and (b) the error set is use to resynchronize the parser, so a good

+    choice is sometimes more important than having the exact set.

+

+    Consider the following example:

+

+            Note:  All examples code has been abbreviated

+            to the absolute minimum in order to make the

+            examples concise.

+

+        star1 : (A)* Z;

+

+    The generated code resembles:

+

+           old                new (with -mrblkerr)

+        --//-----------         --------------------

+        for (;;) {            for (;;) {

+            match(A);           match(A);

+        }                     }

+        match(Z);             if (! A and ! Z) then

+                                FAIL(...{A,Z}...);

+                              }

+                              match(Z);

+

+

+        With input X

+            old message: Found X, expected Z

+            new message: Found X, expected A, Z

+

+    For the example:

+

+        star2 : (A|B)* Z;

+

+           old                      new (with -mrblkerr)

+        -------------               --------------------

+        for (;;) {                  for (;;) {

+          if (!A and !B) break;       if (!A and !B) break;

+          if (...) {                  if (...) {

+            <same ...>                  <same ...>

+          }                           }

+          else {                      else {

+            FAIL(...{A,B,Z}...)         FAIL(...{A,B}...);

+          }                           }

+        }                           }

+        match(B);                   if (! A and ! B and !Z) then

+                                        FAIL(...{A,B,Z}...);

+                                    }

+                                    match(B);

+

+        With input X

+            old message: Found X, expected Z

+            new message: Found X, expected A, B, Z

+        With input A X

+            old message: Found X, expected Z

+            new message: Found X, expected A, B, Z

+

+            This includes the choice of looping back to the

+            star block.

+

+    The code for plus blocks:

+

+        plus1 : (A)+ Z;

+

+    The generated code resembles:

+

+           old                  new (with -mrblkerr)

+        -------------           --------------------

+        do {                    do {

+          match(A);               match(A);

+        } while (A)             } while (A)

+        match(Z);               if (! A and ! Z) then

+                                  FAIL(...{A,Z}...);

+                                }

+                                match(Z);

+

+        With input A X

+            old message: Found X, expected Z

+            new message: Found X, expected A, Z

+

+            This includes the choice of looping back to the

+            plus block.

+

+    For the example:

+

+        plus2 : (A|B)+ Z;

+

+           old                    new (with -mrblkerr)

+        -------------             --------------------

+        do {                        do {

+          if (A) {                    <same>

+            match(A);                 <same>

+          } else if (B) {             <same>

+            match(B);                 <same>

+          } else {                    <same>

+            if (cnt > 1) break;       <same>

+            FAIL(...{A,B,Z}...)         FAIL(...{A,B}...);

+          }                           }

+          cnt++;                      <same>

+        }                           }

+

+        match(Z);                   if (! A and ! B and !Z) then

+                                        FAIL(...{A,B,Z}...);

+                                    }

+                                    match(B);

+

+        With input X

+            old message: Found X, expected A, B, Z

+            new message: Found X, expected A, B

+        With input A X

+            old message: Found X, expected Z

+            new message: Found X, expected A, B, Z

+

+            This includes the choice of looping back to the

+            star block.

+    

+#249. (MR21) Changes for DEC/VMS systems

+

+    Jean-François Piéronne (jfp altavista.net) has updated some

+    VMS related command files and fixed some minor problems related

+    to building pccts under the DEC/VMS operating system.  For DEC/VMS

+    users the most important differences are:

+

+        a.  Revised makefile.vms

+        b.  Revised genMMS for genrating VMS style makefiles.

+

+#248. (MR21) Generate symbol for first set of an alternative

+

+    pccts can generate a symbol which represents the tokens which may

+    appear at the start of a block:

+

+        rr : #FirstSetSymbol(rr_FirstSet)  ( Foo | Bar ) ;

+

+    This will generate the symbol rr_FirstSet of type SetWordType with

+    elements Foo and Bar set. The bits can be tested using code similar 

+    to the following:

+

+        if (set_el(Foo, &rr_FirstSet)) { ...

+

+    This can be combined with the C array zztokens[] or the C++ routine

+    tokenName() to get the print name of the token in the first set.

+

+    The size of the set is given by the newly added enum SET_SIZE, a 

+    protected member of the generated parser's class.  The number of

+    elements in the generated set will not be exactly equal to the 

+    value of SET_SIZE because of synthetic tokens created by #tokclass,

+    #errclass, the -ge option, and meta-tokens such as epsilon, and

+    end-of-file.

+

+    The #FirstSetSymbol must appear immediately before a block

+    such as (...)+, (...)*, and {...}, and (...).  It may not appear

+    immediately before a token, a rule reference, or action.  However

+    a token or rule reference can be enclosed in a (...) in order to

+    make the use of #pragma FirstSetSymbol legal.

+

+            rr_bad : #FirstSetSymbol(rr_bad_FirstSet) Foo;   //  Illegal

+

+            rr_ok :  #FirstSetSymbol(rr_ok_FirstSet) (Foo);  //  Legal

+    

+    Do not confuse FirstSetSymbol sets with the sets used for testing

+    lookahead. The sets used for FirstSetSymbol have one element per bit,

+    so the number of bytes  is approximately the largest token number

+    divided by 8.  The sets used for testing lookahead store 8 lookahead 

+    sets per byte, so the length of the array is approximately the largest

+    token number.

+

+    If there is demand, a similar routine for follow sets can be added.

+

+#247. (MR21) Misleading error message on syntax error for optional elements.

+

+        ===================================================

+        The behavior has been revised when parser exception

+        handling is used.  See Item #290

+        ===================================================

+

+    Prior to MR21, tokens which were optional did not appear in syntax

+    error messages if the block which immediately followed detected a 

+    syntax error.

+

+    Consider the following grammar which accepts Number, Word, and Other:

+

+            rr : {Number} Word;

+

+    For this rule the code resembles:

+

+            if (LA(1) == Number) {

+                match(Number);

+                consume();

+            }

+            match(Word);

+

+    Prior to MR21, the error message for input "$ a" would be:

+

+            line 1: syntax error at "$" missing Word

+

+    With MR21 the message will be:

+

+            line 1: syntax error at "$" expecting Word, Number.

+

+    The generate code resembles:

+

+            if ( (LA(1)==Number) ) {

+                zzmatch(Number);

+                consume();

+            }

+            else {

+                if ( (LA(1)==Word) ) {

+                    /* nothing */

+                }

+                else {

+                    FAIL(... message for both Number and Word ...);

+                }

+            }

+            match(Word);

+        

+    The code generated for optional blocks in MR21 is slightly longer

+    than the previous versions, but it should give better error messages.

+

+    The code generated for:

+

+            { a | b | c }

+

+    should now be *identical* to:

+

+            ( a | b | c | )

+

+    which was not the case prior to MR21.

+

+    Reported by Sue Marvin (sue siara.com).

+

+#246. (Changed in MR21) Use of $(MAKE) for calls to make

+

+    Calls to make from the makefiles were replaced with $(MAKE)

+    because of problems when using gmake.

+

+    Reported with fix by Sunil K.Vallamkonda (sunil siara.com).

+

+#245. (Changed in MR21) Changes to genmk

+

+    The following command line options have been added to genmk:

+

+        -cfiles ... 

+            

+            To add a user's C or C++ files into makefile automatically.

+            The list of files must be enclosed in apostrophes.  This

+            option may be specified multiple times.

+

+        -compiler ...

+    

+            The name of the compiler to use for $(CCC) or $(CC).  The

+            default in C++ mode is "CC".  The default in C mode is "cc".

+

+        -pccts_path ...

+

+            The value for $(PCCTS), the pccts directory.  The default

+            is /usr/local/pccts.

+

+    Contributed by Tomasz Babczynski (t.babczynski ict.pwr.wroc.pl).

+

+#244. (Changed in MR21) Rename variable "not" in antlr.g

+

+    When antlr.g is compiled with a C++ compiler, a variable named

+    "not" causes problems.  Reported by Sinan Karasu

+    (sinan.karasu boeing.com).

+

+#243  (Changed in MR21) Replace recursion with iteration in zzfree_ast

+

+    Another refinement to zzfree_ast in ast.c to limit recursion.

+

+    NAKAJIMA Mutsuki (muc isr.co.jp).

+

+

+#242.  (Changed in MR21) LineInfoFormatStr

+

+    Added an #ifndef/#endif around LineInfoFormatStr in pcctscfg.h.

+

+#241. (Changed in MR21) Changed macro PURIFY to a no-op

+

+                ***********************

+                *** NOT IMPLEMENTED ***

+                ***********************

+

+        The PURIFY macro was changed to a no-op because it was causing 

+        problems when passing C++ objects.

+    

+        The old definition:

+    

+            #define PURIFY(r,s)     memset((char *) &(r),'\\0',(s));

+    

+        The new definition:

+    

+            #define PURIFY(r,s)     /* nothing */

+#endif

+

+#240. (Changed in MR21) sorcerer/h/sorcerer.h _MATCH and _MATCHRANGE

+

+    Added test for NULL token pointer.

+

+    Suggested by Peter Keller (keller ebi.ac.uk)

+

+#239. (Changed in MR21) C++ mode AParser::traceGuessFail

+

+    If tracing is turned on when the code has been generated

+    without trace code, a failed guess generates a trace report

+    even though there are no other trace reports.  This

+    make the behavior consistent with other parts of the

+    trace system.

+

+    Reported by David Wigg (wiggjd sbu.ac.uk).

+

+#238. (Changed in MR21) Namespace version #include files

+

+    Changed reference from CStdio to cstdio (and other

+    #include file names) in the namespace version of pccts.

+    Should have known better.

+

+#237. (Changed in MR21) ParserBlackBox(FILE*)

+    

+    In the past, ParserBlackBox would close the FILE in the dtor

+    even though it was not opened by ParserBlackBox.  The problem

+    is that there were two constructors, one which accepted a file   

+    name and did an fopen, the other which accepted a FILE and did

+    not do an fopen.  There is now an extra member variable which

+    remembers whether ParserBlackBox did the open or not.

+

+    Suggested by Mike Percy (mpercy scires.com).

+

+#236. (Changed in MR21) tmake now reports down pointer problem

+

+    When ASTBase::tmake attempts to update the down pointer of 

+    an AST it checks to see if the down pointer is NULL.  If it

+    is not NULL it does not do the update and returns NULL.

+    An attempt to update the down pointer is almost always a

+    result of a user error.  This can lead to difficult to find

+    problems during tree construction.

+

+    With this change, the routine calls a virtual function

+    reportOverwriteOfDownPointer() which calls panic to

+    report the problem.  Users who want the old behavior can

+    redefined the virtual function in their AST class.

+

+    Suggested by Sinan Karasu (sinan.karasu boeing.com)

+

+#235. (Changed in MR21) Made ANTLRParser::resynch() virtual

+

+    Suggested by Jerry Evans (jerry swsl.co.uk).

+

+#234. (Changed in MR21) Implicit int for function return value

+

+    ATokenBuffer:bufferSize() did not specify a type for the

+    return value.

+

+    Reported by Hai Vo-Ba (hai fc.hp.com).

+

+#233. (Changed in MR20) Converted to MSVC 6.0

+

+    Due to external circumstances I have had to convert to MSVC 6.0

+    The MSVC 5.0 project files (.dsw and .dsp) have been retained as

+    xxx50.dsp and xxx50.dsw.  The MSVC 6.0 files are named xxx60.dsp

+    and xxx60.dsw (where xxx is the related to the directory/project).

+

+#232. (Changed in MR20) Make setwd bit vectors protected in parser.h

+

+    The access for the setwd array in the parser header was not

+    specified.  As a result, it would depend on the code which 

+    preceded it.  In MR20 it will always have access "protected".

+

+    Reported by Piotr Eljasiak (eljasiak zt.gdansk.tpsa.pl).

+

+#231. (Changed in MR20) Error in token buffer debug code.

+

+    When token buffer debugging is selected via the pre-processor

+    symbol DEBUG_TOKENBUFFER there is an erroneous check in

+    AParser.cpp:

+

+        #ifdef DEBUG_TOKENBUFFER

+            if (i >= inputTokens->bufferSize() ||

+                inputTokens->minTokens() < LLk )     /* MR20 Was "<=" */

+        ...

+        #endif

+

+    Reported by David Wigg (wiggjd sbu.ac.uk).

+

+#230. (Changed in MR20) Fixed problem with #define for -gd option

+

+    There was an error in setting zzTRACE_RULES for the -gd (trace) option.

+

+    Reported by Gary Funck (gary intrepid.com).

+

+#229. (Changed in MR20) Additional "const" for literals

+

+    "const" was added to the token name literal table.

+    "const" was added to some panic() and similar routine

+

+#228. (Changed in MR20) dlg crashes on "()"

+

+    The following token defintion will cause DLG to crash.

+

+        #token "()"

+

+    When there is a syntax error in a regular expression

+    many of the dlg routines return a structure which has

+    null pointers.  When this is accessed by callers it

+    generates the crash.

+

+    I have attempted to fix the more common cases.

+

+    Reported by  Mengue Olivier (dolmen bigfoot.com).

+

+#227. (Changed in MR20) Array overwrite

+

+    Steveh Hand (sassth unx.sas.com) reported a problem which

+    was traced to a temporary array which was not properly

+    resized for deeply nested blocks.  This has been fixed.

+

+#226. (Changed in MR20) -pedantic conformance

+   

+    G. Hobbelt (i_a mbh.org) and THM made many, many minor 

+    changes to create prototypes for all the functions and

+    bring antlr, dlg, and sorcerer into conformance with

+    the gcc -pedantic option.

+

+    This may require uses to add pccts/h/pcctscfg.h to some

+    files or makefiles in order to have __USE_PROTOS defined.

+

+#225  (Changed in MR20) AST stack adjustment in C mode

+

+    The fix in #214 for AST stack adjustment in C mode missed 

+    some cases.

+

+    Reported with fix by Ger Hobbelt (i_a mbh.org).

+

+#224  (Changed in MR20) LL(1) and LL(2) with #pragma approx

+

+    This may take a record for the oldest, most trival, lexical

+    error in pccts.  The regular expressions for LL(1) and LL(2)

+    lacked an escape for the left and right parenthesis.

+

+    Reported by Ger Hobbelt (i_a mbh.org).

+

+#223  (Changed in MR20) Addition of IBM_VISUAL_AGE directory

+

+    Build files for antlr, dlg, and sorcerer under IBM Visual Age 

+    have been contributed by Anton Sergeev (ags mlc.ru).  They have

+    been placed in the pccts/IBM_VISUAL_AGE directory.

+

+#222  (Changed in MR20) Replace __STDC__ with __USE_PROTOS

+

+    Most occurrences of __STDC__ replaced with __USE_PROTOS due to

+    complaints from several users.

+

+#221  (Changed in MR20) Added #include for DLexerBase.h to PBlackBox.

+

+    Added #include for DLexerBase.h to PBlackBox.

+

+#220  (Changed in MR19) strcat arguments reversed in #pred parse

+

+    The arguments to strcat are reversed when creating a print

+    name for a hash table entry for use with #pred feature.

+

+    Problem diagnosed and fix reported by Scott Harrington 

+    (seh4 ix.netcom.com).

+

+#219. (Changed in MR19) C Mode routine zzfree_ast

+

+    Changes to reduce use of recursion for AST trees with only right

+    links or only left links in the C mode routine zzfree_ast.

+

+    Implemented by SAKAI Kiyotaka (ksakai isr.co.jp).

+

+#218. (Changed in MR19) Changes to support unsigned char in C mode

+

+    Changes to antlr.h and err.h to fix omissions in use of zzchar_t

+

+    Implemented by SAKAI Kiyotaka (ksakai isr.co.jp).

+

+#217. (Changed in MR19) Error message when dlg -i and -CC options selected

+    

+    *** This change was rescinded by item #257 ***

+

+    The parsers generated by pccts in C++ mode are not able to support the

+    interactive lexer option (except, perhaps, when using the deferred fetch

+    parser option.(Item #216).

+

+    DLG now warns when both -i and -CC are selected.

+

+    This warning was suggested by David Venditti (07751870267-0001 t-online.de).

+

+#216. (Changed in MR19) Defer token fetch for C++ mode

+

+    Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de)

+

+    Normally, pccts keeps the lookahead token buffer completely filled.

+    This requires max(k,ck) tokens of lookahead.  For some applications

+    this can cause deadlock problems.  For example, there may be cases

+    when the parser can't tell when the input has been completely consumed

+    until the parse is complete, but the parse can't be completed because 

+    the input routines are waiting for additional tokens to fill the

+    lookahead buffer.

+    

+    When the ANTLRParser class is built with the pre-processor option 

+    ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred

+    until LA(i) or LT(i) is called. 

+

+    To test whether this option has been built into the ANTLRParser class

+    use "isDeferFetchEnabled()".

+

+    Using the -gd trace option with the default tracein() and traceout()

+    routines will defeat the effort to defer the fetch because the

+    trace routines print out information about the lookahead token at

+    the start of the rule.

+    

+    Because the tracein and traceout routines are virtual it is 

+    easy to redefine them in your parser:

+

+        class MyParser {

+        <<

+            virtual void tracein(ANTLRChar * ruleName)

+                { fprintf(stderr,"Entering: %s\n", ruleName); }

+            virtual void traceout(ANTLRChar * ruleName)

+                { fprintf(stderr,"Leaving: %s\n", ruleName); }

+        >>

+ 

+    The originals for those routines are pccts/h/AParser.cpp

+ 

+    This requires use of the dlg option -i (interactive lexer).

+

+    This is implemented only for C++ mode.

+

+    This is experimental.  The interaction with guess mode (syntactic

+    predicates)is not known.

+

+#215. (Changed in MR19) Addition of reset() to DLGLexerBase

+

+    There was no obvious way to reset the lexer for reuse.  The

+    reset() method now does this.

+

+    Suggested by David Venditti (07751870267-0001 t-online.de).

+

+#214. (Changed in MR19)  C mode: Adjust AST stack pointer at exit

+

+    In C mode the AST stack pointer needs to be reset if there will

+    be multiple calls to the ANTLRx macros.

+

+    Reported with fix by Paul D. Smith (psmith baynetworks.com).

+

+#213. (Changed in MR18)  Fatal error with -mrhoistk (k>1 hoisting)

+

+    When rearranging code I forgot to un-comment a critical line of

+    code that handles hoisting of predicates with k>1 lookahead.  This

+    is now fixed.

+

+    Reported by Reinier van den Born (reinier vnet.ibm.com).

+

+#212. (Changed in MR17)  Mac related changes by Kenji Tanaka

+

+    Kenji Tanaka (kentar osa.att.ne.jp) has made a number of changes for

+    Macintosh users.

+

+    a.  The following Macintosh MPW files aid in installing pccts on Mac:

+

+            pccts/MPW_Read_Me

+

+            pccts/install68K.mpw

+            pccts/installPPC.mpw

+

+            pccts/antlr/antlr.r

+            pccts/antlr/antlr68K.make

+            pccts/antlr/antlrPPC.make

+

+            pccts/dlg/dlg.r

+            pccts/dlg/dlg68K.make

+            pccts/dlg/dlgPPC.make

+

+            pccts/sorcerer/sor.r

+            pccts/sorcerer/sor68K.make

+            pccts/sorcerer/sorPPC.make

+    

+       They completely replace the previous Mac installation files.

+            

+    b. The most significant is a change in the MAC_FILE_CREATOR symbol

+       in pcctscfg.h:

+

+        old: #define MAC_FILE_CREATOR 'MMCC'   /* Metrowerks C/C++ Text files */

+        new: #define MAC_FILE_CREATOR 'CWIE'   /* Metrowerks C/C++ Text files */

+

+    c.  Added calls to special_fopen_actions() where necessary.

+

+#211. (Changed in MR16a)  C++ style comment in dlg

+

+    This has been fixed.

+

+#210. (Changed in MR16a)  Sor accepts \r\n, \r, or \n for end-of-line

+

+    A user requested that Sorcerer be changed to accept other forms

+    of end-of-line.

+

+#209. (Changed in MR16) Name of files changed.

+

+        Old:  CHANGES_FROM_1.33

+        New:  CHANGES_FROM_133.txt

+

+        Old:  KNOWN_PROBLEMS

+        New:  KNOWN_PROBLEMS.txt

+

+#208. (Changed in MR16) Change in use of pccts #include files

+

+    There were problems with MS DevStudio when mixing Sorcerer and

+    PCCTS in the same source file.  The problem is caused by the

+    redefinition of setjmp in the MS header file setjmp.h.  In

+    setjmp.h the pre-processor symbol setjmp was redefined to be

+    _setjmp.  A later effort to execute #include <setjmp.h> resulted 

+    in an effort to #include <_setjmp.h>.  I'm not sure whether this

+    is a bug or a feature.  In any case, I decided to fix it by

+    avoiding the use of pre-processor symbols in #include statements

+    altogether.  This has the added benefit of making pre-compiled

+    headers work again.

+

+    I've replaced statements:

+

+        old: #include PCCTS_SETJMP_H

+        new: #include "pccts_setjmp.h"

+

+    Where pccts_setjmp.h contains:

+

+            #ifndef __PCCTS_SETJMP_H__

+            #define __PCCTS_SETJMP_H__

+    

+            #ifdef PCCTS_USE_NAMESPACE_STD

+            #include <Csetjmp>

+            #else

+            #include <setjmp.h>

+            #endif

+

+            #endif

+        

+    A similar change has been made for other standard header files

+    required by pccts and sorcerer: stdlib.h, stdarg.h, stdio.h, etc.

+

+    Reported by Jeff Vincent (JVincent novell.com) and Dale Davis

+    (DalDavis spectrace.com).

+

+#207. (Changed in MR16) dlg reports an invalid range for: [\0x00-\0xff]

+

+     -----------------------------------------------------------------

+     Note from MR23:  This fix does not work.  I am investigating why.

+     -----------------------------------------------------------------

+

+    dlg will report that this is an invalid range.

+

+    Diagnosed by Piotr Eljasiak (eljasiak no-spam.zt.gdansk.tpsa.pl):

+

+        I think this problem is not specific to unsigned chars

+        because dlg reports no error for the range [\0x00-\0xfe].

+

+        I've found that information on range is kept in field

+        letter (unsigned char) of Attrib struct. Unfortunately

+        the letter value internally is for some reasons increased

+        by 1, so \0xff is represented here as 0.

+

+        That's why dlg complains about the range [\0x00-\0xff] in

+        dlg_p.g:

+

+        if ($$.letter > $2.letter) {

+          error("invalid range  ", zzline);

+        } 

+

+    The fix is:

+

+        if ($$.letter > $2.letter && 255 != $$2.letter) {

+          error("invalid range  ", zzline);

+        } 

+

+#206. (Changed in MR16) Free zzFAILtext in ANTLRParser destructor

+

+    The ANTLRParser destructor now frees zzFAILtext.

+

+    Problem and fix reported by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#205. (Changed in MR16) DLGStringReset argument now const

+

+    Changed: void DLGStringReset(DLGChar *s) {...}

+    To:      void DLGStringReset(const DLGChar *s) {...}

+

+    Suggested by Dale Davis (daldavis spectrace.com)

+

+#204. (Changed in MR15a) Change __WATCOM__ to __WATCOMC__ in pcctscfg.h

+    

+    Reported by Oleg Dashevskii (olegdash my-dejanews.com).

+

+#203. (Changed in MR15) Addition of sorcerer to distribution kit

+

+    I have finally caved in to popular demand.  The pccts 1.33mr15

+    kit will include sorcerer.  The separate sorcerer kit will be

+    discontinued.

+

+#202. (Changed) in MR15) Organization of MS Dev Studio Projects in Kit

+

+    Previously there was one workspace that contained projects for

+    all three parts of pccts: antlr, dlg, and sorcerer.  Now each

+    part (and directory) has its own workspace/project and there

+    is an additional workspace/project to build a library from the

+    .cpp files in the pccts/h directory.

+

+    The library build will create pccts_debug.lib or pccts_release.lib

+    according to the configuration selected.  

+

+    If you don't want to build pccts 1.33MR15 you can download a

+    ready-to-run kit for win32 from http://www.polhode.com/win32.zip.

+    The ready-to-run for win32 includes executables, a pre-built static

+    library for the .cpp files in the pccts/h directory, and a  sample

+    application

+

+    You will need to define the environment variable PCCTS to point to

+    the root of the pccts directory hierarchy.

+

+#201. (Changed in MR15) Several fixes by K.J. Cummings (cummings peritus.com)

+

+      Generation of SETJMP rather than SETJMP_H in gen.c.

+

+      (Sor B19) Declaration of ref_vars_inits for ref_var_inits in

+      pccts/sorcerer/sorcerer.h.

+

+#200. (Changed in MR15) Remove operator=() in AToken.h

+

+      User reported that WatCom couldn't handle use of

+      explicit operator =().  Replace with equivalent

+      using cast operator.

+

+#199. (Changed in MR15) Don't allow use of empty #tokclass

+

+      Change antlr.g to disallow empty #tokclass sets.

+

+      Reported by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#198. Revised ANSI C grammar due to efforts by Manuel Kessler

+

+      Manuel Kessler (mlkessler cip.physik.uni-wuerzburg.de)

+

+          Allow trailing ... in function parameter lists.

+          Add bit fields.

+          Allow old-style function declarations.

+          Support cv-qualified pointers.

+          Better checking of combinations of type specifiers.

+          Release of memory for local symbols on scope exit.

+          Allow input file name on command line as well as by redirection.

+

+              and other miscellaneous tweaks.

+

+      This is not part of the pccts distribution kit. It must be

+      downloaded separately from:

+

+            http://www.polhode.com/ansi_mr15.zip

+

+#197. (Changed in MR14) Resetting the lookahead buffer of the parser

+

+      Explanation and fix by Sinan Karasu (sinan.karasu boeing.com)

+

+      Consider the code used to prime the lookahead buffer LA(i)

+      of the parser when init() is called:

+

+        void

+        ANTLRParser::

+        prime_lookahead()

+        {

+            int i;

+            for(i=1;i<=LLk; i++) consume();

+            dirty=0;

+            //lap = 0;      // MR14 - Sinan Karasu (sinan.karusu boeing.com)

+            //labase = 0;   // MR14

+            labase=lap;     // MR14

+        }

+

+      When the parser is instantiated, lap=0,labase=0 is set.

+

+      The "for" loop runs LLk times. In consume(), lap = lap +1 (mod LLk) is

+      computed.  Therefore, lap(before the loop) == lap (after the loop).

+

+      Now the only problem comes in when one does an init() of the parser

+      after an Eof has been seen. At that time, lap could be non zero.

+      Assume it was lap==1. Now we do a prime_lookahead(). If LLk is 2,

+      then

+

+        consume()

+        {

+            NLA = inputTokens->getToken()->getType();

+            dirty--;

+            lap = (lap+1)&(LLk-1);

+        }

+

+      or expanding NLA,

+

+        token_type[lap&(LLk-1)]) = inputTokens->getToken()->getType();

+        dirty--;

+        lap = (lap+1)&(LLk-1);

+

+      so now we prime locations 1 and 2.  In prime_lookahead it used to set

+      lap=0 and labase=0.  Now, the next token will be read from location 0,

+      NOT 1 as it should have been.

+

+      This was never caught before, because if a parser is just instantiated,

+      then lap and labase are 0, the offending assignment lines are

+      basically no-ops, since the for loop wraps around back to 0.

+

+#196. (Changed in MR14) Problems with "(alpha)? beta" guess

+

+    Consider the following syntactic predicate in a grammar

+    with 2 tokens of lookahead (k=2 or ck=2):

+

+        rule  : ( alpha )? beta ;

+        alpha : S t ;

+        t     : T U

+              | T

+              ;

+        beta  : S t Z ;

+

+    When antlr computes the prediction expression with one token

+    of lookahead for alts 1 and 2 of rule t it finds an ambiguity.

+

+    Because the grammar has a lookahead of 2 it tries to compute

+    two tokens of lookahead for alts 1 and 2 of t.  Alt 1 clearly

+    has a lookahead of (T U).  Alt 2 is one token long so antlr

+    tries to compute the follow set of alt 2, which means finding

+    the things which can follow rule t in the context of (alpha)?.

+    This cannot be computed, because alpha is only part of a rule,

+    and antlr can't tell what part of beta is matched by alpha and

+    what part remains to be matched.  Thus it impossible for antlr

+    to  properly determine the follow set of rule t.

+

+    Prior to 1.33MR14, the follow of (alpha)? was computed as

+    FIRST(beta) as a result of the internal representation of

+    guess blocks.

+

+    With MR14 the follow set will be the empty set for that context.

+

+    Normally, one expects a rule appearing in a guess block to also

+    appear elsewhere.  When the follow context for this other use

+    is "ored" with the empty set, the context from the other use

+    results, and a reasonable follow context results.  However if

+    there is *no* other use of the rule, or it is used in a different

+    manner then the follow context will be inaccurate - it was

+    inaccurate even before MR14, but it will be inaccurate in a

+    different way.

+

+    For the example given earlier, a reasonable way to rewrite the

+    grammar:

+

+        rule  : ( alpha )? beta

+        alpha : S t ;

+        t     : T U

+              | T

+              ;

+        beta  : alpha Z ;

+

+    If there are no other uses of the rule appearing in the guess

+    block it will generate a test for EOF - a workaround for

+    representing a null set in the lookahead tests.

+

+    If you encounter such a problem you can use the -alpha option

+    to get additional information:

+

+    line 2: error: not possible to compute follow set for alpha

+              in an "(alpha)? beta" block.

+

+    With the antlr -alpha command line option the following information

+    is inserted into the generated file:

+

+    #if 0

+

+      Trace of references leading to attempt to compute the follow set of

+      alpha in an "(alpha)? beta" block. It is not possible for antlr to

+      compute this follow set because it is not known what part of beta has

+      already been matched by alpha and what part remains to be matched.

+

+      Rules which make use of the incorrect follow set will also be incorrect

+

+         1 #token T              alpha/2   line 7     brief.g

+         2 end alpha             alpha/3   line 8     brief.g

+         2 end (...)? block at   start/1   line 2     brief.g

+

+    #endif

+

+    At the moment, with the -alpha option selected the program marks

+    any rules which appear in the trace back chain (above) as rules with

+    possible problems computing follow set.

+

+    Reported by Greg Knapen (gregory.knapen bell.ca).

+

+#195. (Changed in MR14) #line directive not at column 1

+

+      Under certain circunstances a predicate test could generate

+      a #line directive which was not at column 1.

+

+      Reported with fix by David Kågedal  (davidk lysator.liu.se)

+      (http://www.lysator.liu.se/~davidk/).

+

+#194. (Changed in MR14) (C Mode only) Demand lookahead with #tokclass

+

+      In C mode with the demand lookahead option there is a bug in the

+      code which handles matches for #tokclass (zzsetmatch and

+      zzsetmatch_wsig).

+

+      The bug causes the lookahead pointer to get out of synchronization

+      with the current token pointer.

+

+      The problem was reported with a fix by Ger Hobbelt (hobbelt axa.nl).

+

+#193. (Changed in MR14) Use of PCCTS_USE_NAMESPACE_STD

+

+      The pcctscfg.h now contains the following definitions:

+

+        #ifdef PCCTS_USE_NAMESPACE_STD

+        #define PCCTS_STDIO_H     <Cstdio>

+        #define PCCTS_STDLIB_H    <Cstdlib>

+        #define PCCTS_STDARG_H    <Cstdarg>

+        #define PCCTS_SETJMP_H    <Csetjmp>

+        #define PCCTS_STRING_H    <Cstring>

+        #define PCCTS_ASSERT_H    <Cassert>

+        #define PCCTS_ISTREAM_H   <istream>

+        #define PCCTS_IOSTREAM_H  <iostream>

+        #define PCCTS_NAMESPACE_STD     namespace std {}; using namespace std;

+        #else

+        #define PCCTS_STDIO_H     <stdio.h>

+        #define PCCTS_STDLIB_H    <stdlib.h>

+        #define PCCTS_STDARG_H    <stdarg.h>

+        #define PCCTS_SETJMP_H    <setjmp.h>

+        #define PCCTS_STRING_H    <string.h>

+        #define PCCTS_ASSERT_H    <assert.h>

+        #define PCCTS_ISTREAM_H   <istream.h>

+        #define PCCTS_IOSTREAM_H  <iostream.h>

+        #define PCCTS_NAMESPACE_STD

+        #endif

+

+      The runtime support in pccts/h uses these pre-processor symbols

+      consistently.

+

+      Also, antlr and dlg have been changed to generate code which uses

+      these pre-processor symbols rather than having the names of the

+      #include files hard-coded in the generated code.

+

+      This required the addition of "#include pcctscfg.h" to a number of

+      files in pccts/h.

+

+      It appears that this sometimes causes problems for MSVC 5 in

+      combination with the "automatic" option for pre-compiled headers.

+      In such cases disable the "automatic" pre-compiled headers option.

+

+      Suggested by Hubert Holin (Hubert.Holin Bigfoot.com).

+

+#192. (Changed in MR14) Change setText() to accept "const ANTLRChar *"

+

+      Changed ANTLRToken::setText(ANTLRChar *) to setText(const ANTLRChar *).

+      This allows literal strings to be used to initialize tokens.  Since

+      the usual token implementation (ANTLRCommonToken)  makes a copy of the

+      input string, this was an unnecessary limitation.

+

+      Suggested by Bob McWhirter (bob netwrench.com).

+

+#191. (Changed in MR14) HP/UX aCC compiler compatibility problem

+

+      Needed to explicitly declare zzINF_DEF_TOKEN_BUFFER_SIZE and

+      zzINF_BUFFER_TOKEN_CHUNK_SIZE as ints in pccts/h/AParser.cpp.

+

+      Reported by David Cook (dcook bmc.com).

+

+#190. (Changed in MR14) IBM OS/2 CSet compiler compatibility problem

+

+      Name conflict with "_cs" in pccts/h/ATokenBuffer.cpp

+

+      Reported by David Cook (dcook bmc.com).

+

+#189. (Changed in MR14) -gxt switch in C mode

+

+      The -gxt switch in C mode didn't work because of incorrect

+      initialization.

+

+      Reported by Sinan Karasu (sinan boeing.com).

+

+#188. (Changed in MR14) Added pccts/h/DLG_stream_input.h

+

+      This is a DLG stream class based on C++ istreams.

+

+      Contributed by Hubert Holin (Hubert.Holin Bigfoot.com).

+

+#187. (Changed in MR14) Rename config.h to pcctscfg.h

+

+      The PCCTS configuration file has been renamed from config.h to

+      pcctscfg.h.  The problem with the original name is that it led

+      to name collisions when pccts parsers were combined with other

+      software.

+

+      All of the runtime support routines in pccts/h/* have been

+      changed to use the new name.  Existing software can continue

+      to use pccts/h/config.h. The contents of pccts/h/config.h is

+      now just "#include "pcctscfg.h".

+

+      I don't have a record of the user who suggested this.

+

+#186. (Changed in MR14) Pre-processor symbol DllExportPCCTS class modifier

+

+      Classes in the C++ runtime support routines are now declared:

+

+        class DllExportPCCTS className ....

+

+      By default, the pre-processor symbol is defined as the empty

+      string.  This if for use by MSVC++ users to create DLL classes.

+

+      Suggested by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#185. (Changed in MR14) Option to not use PCCTS_AST base class for ASTBase

+

+      Normally, the ASTBase class is derived from PCCTS_AST which contains

+      functions useful to Sorcerer.  If these are not necessary then the

+      user can define the pre-processor symbol "PCCTS_NOT_USING_SOR" which

+      will cause the ASTBase class to replace references to PCCTS_AST with

+      references to ASTBase where necessary.

+

+      The class ASTDoublyLinkedBase will contain a pure virtual function

+      shallowCopy() that was formerly defined in class PCCTS_AST.

+

+      Suggested by Bob McWhirter (bob netwrench.com).

+

+#184. (Changed in MR14) Grammars with no tokens generate invalid tokens.h

+

+      Reported by Hubert Holin (Hubert.Holin bigfoot.com).

+

+#183. (Changed in MR14) -f to specify file with names of grammar files

+

+      In DEC/VMS it is difficult to specify very long command lines.

+      The -f option allows one to place the names of the grammar files

+      in a data file in order to bypass limitations of the DEC/VMS

+      command language interpreter.

+

+      Addition supplied by Bernard Giroud (b_giroud decus.ch).

+

+#182. (Changed in MR14) Output directory option for DEC/VMS

+

+      Fix some problems with the -o option under DEC/VMS.

+

+      Fix supplied by Bernard Giroud (b_giroud decus.ch).

+

+#181. (Changed in MR14) Allow chars > 127 in DLGStringInput::nextChar()

+

+      Changed DLGStringInput to cast the character using (unsigned char)

+      so that languages with character codes greater than 127 work

+      without changes.

+

+      Suggested by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#180. (Added in MR14) ANTLRParser::getEofToken()

+

+      Added "ANTLRToken ANTLRParser::getEofToken() const" to match the

+      setEofToken routine.

+

+      Requested by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#179. (Fixed in MR14) Memory leak for BufFileInput subclass of DLGInputStream

+

+      The BufFileInput class described in Item #142 neglected to release

+      the allocated buffer when an instance was destroyed.

+

+      Reported by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#178. (Fixed in MR14) Bug in "(alpha)? beta" guess blocks first sets

+

+      In 1.33 vanilla, and all maintenance releases prior to MR14

+      there is a bug in the handling of guess blocks which use the

+      "long" form:

+

+                  (alpha)? beta

+

+      inside a (...)*, (...)+, or {...} block.

+

+      This problem does *not* apply to the case where beta is omitted

+      or when the syntactic predicate is on the leading edge of an

+      alternative.

+

+      The problem is that both alpha and beta are stored in the

+      syntax diagram, and that some analysis routines would fail

+      to skip the alpha portion when it was not on the leading edge.

+      Consider the following grammar with -ck 2:

+

+                r : ( (A)? B )* C D

+

+                  | A B      /* forces -ck 2 computation for old antlr    */

+                             /*              reports ambig for alts 1 & 2 */

+

+                  | B C      /* forces -ck 2 computation for new antlr    */

+                             /*              reports ambig for alts 1 & 3 */

+                  ;

+

+      The prediction expression for the first alternative should be

+      LA(1)={B C} LA(2)={B C D}, but previous versions of antlr

+      would compute the prediction expression as LA(1)={A C} LA(2)={B D}

+

+      Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided

+      a very clear example of the problem and identified the probable cause.

+

+#177. (Changed in MR14) #tokdefs and #token with regular expression

+

+      In MR13 the change described by Item #162 caused an existing

+      feature of antlr to fail.  Prior to the change it was possible

+      to give regular expression definitions and actions to tokens

+      which were defined via the #tokdefs directive.

+

+      This now works again.

+

+      Reported by Manfred Kogler (km cast.uni-linz.ac.at).

+

+#176. (Changed in MR14) Support for #line in antlr source code

+

+      Note: this was implemented by Arpad Beszedes (beszedes inf.u-szeged.hu).

+

+      In 1.33MR14 it is possible for a pre-processor to generate #line

+      directives in the antlr source and have those line numbers and file

+      names used in antlr error messages and in the #line directives

+      generated by antlr.

+

+      The #line directive may appear in the following forms:

+

+            #line ll "sss" xx xx ...

+

+      where ll represents a line number, "sss" represents the name of a file

+      enclosed in quotation marks, and xxx are arbitrary integers.

+

+      The following form (without "line") is not supported at the moment:

+

+            # ll "sss" xx xx ...

+

+      The result:

+

+        zzline

+

+            is replaced with ll from the # or #line directive

+

+        FileStr[CurFile]

+

+            is updated with the contents of the string (if any)

+            following the line number

+

+      Note

+      ----

+      The file-name string following the line number can be a complete

+      name with a directory-path. Antlr generates the output files from

+      the input file name (by replacing the extension from the file-name

+      with .c or .cpp).

+

+      If the input file (or the file-name from the line-info) contains

+      a path:

+

+        "../grammar.g"

+

+      the generated source code will be placed in "../grammar.cpp" (i.e.

+      in the parent directory).  This is inconvenient in some cases

+      (even the -o switch can not be used) so the path information is

+      removed from the #line directive.  Thus, if the line-info was

+

+        #line 2 "../grammar.g"

+

+      then the current file-name will become "grammar.g"

+

+      In this way, the generated source code according to the grammar file

+      will always be in the current directory, except when the -o switch

+      is used.

+

+#175. (Changed in MR14) Bug when guess block appears at start of (...)*

+

+      In 1.33 vanilla and all maintenance releases prior to 1.33MR14

+      there is a bug when a guess block appears at the start of a (...)+.

+      Consider the following k=1 (ck=1) grammar:

+

+            rule :

+                  ( (STAR)? ZIP )* ID ;

+

+      Prior to 1.33MR14, the generated code resembled:

+

+        ...

+        zzGUESS_BLOCK

+        while ( 1 ) {

+            if ( ! LA(1)==STAR) break;

+            zzGUESS

+            if ( !zzrv ) {

+                zzmatch(STAR);

+                zzCONSUME;

+                zzGUESS_DONE

+                zzmatch(ZIP);

+                zzCONSUME;

+            ...

+

+      Note that the routine uses STAR for the prediction expression

+      rather than ZIP.  With 1.33MR14 the generated code resembles:

+

+        ...

+        while ( 1 ) {

+            if ( ! LA(1)==ZIP) break;

+        ...

+

+      This problem existed only with (...)* blocks and was caused

+      by the slightly more complicated graph which represents (...)*

+      blocks.  This caused the analysis routine to compute the first

+      set for the alpha part of the "(alpha)? beta" rather than the

+      beta part.

+

+      Both (...)+ and {...} blocks handled the guess block correctly.

+

+      Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided

+      a very clear example of the problem and identified the probable cause.

+

+#174. (Changed in MR14) Bug when action precedes syntactic predicate

+

+      In 1.33 vanilla, and all maintenance releases prior to MR14,

+      there was a bug when a syntactic predicate was immediately

+      preceded by an action.  Consider the following -ck 2 grammar:

+

+            rule :

+                   <<int i;>>

+                   (alpha)? beta C

+                 | A B

+                 ;

+

+            alpha : A ;

+            beta  : A B;

+

+      Prior to MR14, the code generated for the first alternative

+      resembled:

+

+        ...

+        zzGUESS

+        if ( !zzrv && LA(1)==A && LA(2)==A) {

+            alpha();

+            zzGUESS_DONE

+            beta();

+            zzmatch(C);

+            zzCONSUME;

+        } else {

+        ...

+

+      The prediction expression (i.e. LA(1)==A && LA(2)==A) is clearly

+      wrong because LA(2) should be matched to B (first[2] of beta is {B}).

+

+      With 1.33MR14 the prediction expression is:

+

+        ...

+        if ( !zzrv && LA(1)==A && LA(2)==B) {

+            alpha();

+            zzGUESS_DONE

+            beta();

+            zzmatch(C);

+            zzCONSUME;

+        } else {

+        ...

+

+      This will only affect users in which alpha is shorter than

+      than max(k,ck) and there is an action immediately preceding

+      the syntactic predicate.

+

+      This problem was reported by reported by Arpad Beszedes

+      (beszedes inf.u-szeged.hu) who provided a very clear example

+      of the problem and identified the presence of the init-action

+      as the likely culprit.

+

+#173. (Changed in MR13a) -glms for Microsoft style filenames with -gl

+

+      With the -gl option antlr generates #line directives using the

+      exact name of the input files specified on the command line.

+      An oddity of the Microsoft C and C++ compilers is that they

+      don't accept file names in #line directives containing "\"

+      even though these are names from the native file system.

+

+      With -glms option, the "\" in file names appearing in #line

+      directives is replaced with a "/" in order to conform to

+      Microsoft compiler requirements.

+

+      Reported by Erwin Achermann (erwin.achermann switzerland.org).

+

+#172. (Changed in MR13) \r\n in antlr source counted as one line

+

+      Some MS software uses \r\n to indicate a new line.  Antlr

+      now recognizes this in counting lines.

+

+      Reported by Edward L. Hepler (elh ece.vill.edu).

+

+#171. (Changed in MR13) #tokclass L..U now allowed

+

+      The following is now allowed:

+

+            #tokclass ABC { A..B C }

+

+      Reported by Dave Watola (dwatola amtsun.jpl.nasa.gov)

+

+#170. (Changed in MR13) Suppression for predicates with lookahead depth >1

+

+      In MR12 the capability for suppression of predicates with lookahead

+      depth=1 was introduced.  With MR13 this had been extended to

+      predicates with lookahead depth > 1 and released for use by users

+      on an experimental basis.

+

+      Consider the following grammar with -ck 2 and the predicate in rule

+      "a" with depth 2:

+

+            r1  : (ab)* "@"

+                ;

+

+            ab  : a

+                | b

+                ;

+

+            a   : (A B)? => <<p(LATEXT(2))>>? A B C

+                ;

+

+            b   : A B C

+                ;

+

+      Normally, the predicate would be hoisted into rule r1 in order to

+      determine whether to call rule "ab".  However it should *not* be

+      hoisted because, even if p is false, there is a valid alternative

+      in rule b.  With "-mrhoistk on" the predicate will be suppressed.

+

+      If "-info p" command line option is present the following information

+      will appear in the generated code:

+

+                while ( (LA(1)==A)

+        #if 0

+

+        Part (or all) of predicate with depth > 1 suppressed by alternative

+            without predicate

+

+        pred  <<  p(LATEXT(2))>>?

+                  depth=k=2  ("=>" guard)  rule a  line 8  t1.g

+          tree context:

+            (root = A

+               B

+            )

+

+        The token sequence which is suppressed: ( A B )

+        The sequence of references which generate that sequence of tokens:

+

+           1 to ab          r1/1       line 1     t1.g

+           2 ab             ab/1       line 4     t1.g

+           3 to b           ab/2       line 5     t1.g

+           4 b              b/1        line 11    t1.g

+           5 #token A       b/1        line 11    t1.g

+           6 #token B       b/1        line 11    t1.g

+

+        #endif

+

+      A slightly more complicated example:

+

+            r1  : (ab)* "@"

+                ;

+

+            ab  : a

+                | b

+                ;

+

+            a   : (A B)? => <<p(LATEXT(2))>>? (A  B | D E)

+                ;

+

+            b   : <<q(LATEXT(2))>>? D E

+                ;

+

+

+      In this case, the sequence (D E) in rule "a" which lies behind

+      the guard is used to suppress the predicate with context (D E)

+      in rule b.

+

+                while ( (LA(1)==A || LA(1)==D)

+            #if 0

+

+            Part (or all) of predicate with depth > 1 suppressed by alternative

+                without predicate

+

+            pred  <<  q(LATEXT(2))>>?

+                              depth=k=2  rule b  line 11  t2.g

+              tree context:

+                (root = D

+                   E

+                )

+

+            The token sequence which is suppressed: ( D E )

+            The sequence of references which generate that sequence of tokens:

+

+               1 to ab          r1/1       line 1     t2.g

+               2 ab             ab/1       line 4     t2.g

+               3 to a           ab/1       line 4     t2.g

+               4 a              a/1        line 8     t2.g

+               5 #token D       a/1        line 8     t2.g

+               6 #token E       a/1        line 8     t2.g

+

+            #endif

+            &&

+            #if 0

+

+            pred  <<  p(LATEXT(2))>>?

+                              depth=k=2  ("=>" guard)  rule a  line 8  t2.g

+              tree context:

+                (root = A

+                   B

+                )

+

+            #endif

+

+            (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) )  {

+                ab();

+                ...

+

+#169. (Changed in MR13) Predicate test optimization for depth=1 predicates

+

+      When the MR12 generated a test of a predicate which had depth 1

+      it would use the depth >1 routines, resulting in correct but

+      inefficient behavior.  In MR13, a bit test is used.

+

+#168. (Changed in MR13) Token expressions in context guards

+

+      The token expressions appearing in context guards such as:

+

+            (A B)? => <<test(LT(1))>>?  someRule

+

+      are computed during an early phase of antlr processing.  As

+      a result, prior to MR13, complex expressions such as:

+

+            ~B

+            L..U

+            ~L..U

+            TokClassName

+            ~TokClassName

+

+      were not computed properly.  This resulted in incorrect

+      context being computed for such expressions.

+

+      In MR13 these context guards are verified for proper semantics

+      in the initial phase and then re-evaluated after complex token

+      expressions have been computed in order to produce the correct

+      behavior.

+

+      Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).

+

+#167. (Changed in MR13) ~L..U

+

+      Prior to MR13, the complement of a token range was

+      not properly computed.

+

+#166. (Changed in MR13) token expression L..U

+

+      The token U was represented as an unsigned char, restricting

+      the use of L..U to cases where U was assigned a token number

+      less than 256.  This is corrected in MR13.

+

+#165. (Changed in MR13) option -newAST

+

+      To create ASTs from an ANTLRTokenPtr antlr usually calls

+      "new AST(ANTLRTokenPtr)".  This option generates a call

+      to "newAST(ANTLRTokenPtr)" instead.  This allows a user

+      to define a parser member function to create an AST object.

+

+      Similar changes for ASTBase::tmake and ASTBase::link were not

+      thought necessary since they do not create AST objects, only

+      use existing ones.

+

+#164. (Changed in MR13) Unused variable _astp

+

+      For many compilations, we have lived with warnings about

+      the unused variable _astp.  It turns out that this varible

+      can *never* be used because the code which references it was

+      commented out.

+

+      This investigation was sparked by a note from Erwin Achermann

+      (erwin.achermann switzerland.org).

+

+#163. (Changed in MR13) Incorrect makefiles for testcpp examples

+

+      All the examples in pccts/testcpp/* had incorrect definitions

+      in the makefiles for the symbol "CCC".  Instead of CCC=CC they

+      had CC=$(CCC).

+

+      There was an additional problem in testcpp/1/test.g due to the

+      change in ANTLRToken::getText() to a const member function

+      (Item #137).

+

+      Reported by Maurice Mass (maas cuci.nl).

+

+#162. (Changed in MR13) Combining #token with #tokdefs

+

+      When it became possible to change the print-name of a

+      #token (Item #148) it became useful to give a #token

+      statement whose only purpose was to giving a print name

+      to the #token.  Prior to this change this could not be

+      combined with the #tokdefs feature.

+

+#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h

+

+#160. (Changed in MR13) Omissions in list of names for remap.h

+

+      When a user selects the -gp option antlr creates a list

+      of macros in remap.h to rename some of the standard

+      antlr routines from zzXXX to userprefixXXX.

+

+      There were number of omissions from the remap.h name

+      list related to the new trace facility.  This was reported,

+      along with a fix, by Bernie Solomon (bernard ug.eds.com).

+

+#159. (Changed in MR13) Violations of classic C rules

+

+      There were a number of violations of classic C style in

+      the distribution kit.  This was reported, along with fixes,

+      by Bernie Solomon (bernard ug.eds.com).

+

+#158. (Changed in MR13) #header causes problem for pre-processors

+

+      A user who runs the C pre-processor on antlr source suggested

+      that another syntax be allowed.  With MR13 such directives

+      such as #header, #pragma, etc. may be written as "\#header",

+      "\#pragma", etc.  For escaping pre-processor directives inside

+      a #header use something like the following:

+

+            \#header

+            <<

+                \#include <stdio.h>

+            >>

+

+#157. (Fixed in MR13) empty error sets for rules with infinite recursion

+

+      When the first set for a rule cannot be computed due to infinite

+      left recursion and it is the only alternative for a block then

+      the error set for the block would be empty.  This would result

+      in a fatal error.

+

+      Reported by Darin Creason (creason genedax.com)

+

+#156. (Changed in MR13) DLGLexerBase::getToken() now public

+

+#155. (Changed in MR13) Context behind predicates can suppress

+

+      With -mrhoist enabled the context behind a guarded predicate can

+      be used to suppress other predicates.  Consider the following grammar:

+

+        r0 : (r1)+;

+

+        r1  : rp

+            | rq

+            ;

+        rp  : <<p LATEXT(1)>>? B ;

+        rq : (A)? => <<q LATEXT(1)>>? (A|B);

+

+      In earlier versions both predicates "p" and "q" would be hoisted into

+      rule r0. With MR12c predicate p is suppressed because the context which

+      follows predicate q includes "B" which can "cover" predicate "p".  In

+      other words, in trying to decide in r0 whether to call r1, it doesn't

+      really matter whether p is false or true because, either way, there is

+      a valid choice within r1.

+

+#154. (Changed in MR13) Making hoist suppression explicit using <<nohoist>>

+

+      A common error, even among experienced pccts users, is to code

+      an init-action to inhibit hoisting rather than a leading action.

+      An init-action does not inhibit hoisting.

+

+      This was coded:

+

+        rule1 : <<;>> rule2

+

+      This is what was meant:

+

+        rule1 : <<;>> <<;>> rule2

+

+      With MR13, the user can code:

+

+        rule1 : <<;>> <<nohoist>> rule2

+

+      The following will give an error message:

+

+        rule1 : <<nohoist>> rule2

+

+      If the <<nohoist>> appears as an init-action rather than a leading

+      action an error message is issued.  The meaning of an init-action

+      containing "nohoist" is unclear: does it apply to just one

+      alternative or to all alternatives ?

+

+

+

+

+

+

+

+

+        -------------------------------------------------------

+        Note:  Items #153 to #1 are now in a separate file named

+                CHANGES_FROM_133_BEFORE_MR13.txt

+        -------------------------------------------------------

diff --git a/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt b/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt
new file mode 100644
index 0000000..bba5ecd
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt
@@ -0,0 +1,3666 @@
+

+    ------------------------------------------------------------

+           This is the second part of a two part file.

+      This is a list of changes to pccts 1.33 prior to MR13

+       For more recent information see CHANGES_FROM_133.txt

+    ------------------------------------------------------------

+

+                               DISCLAIMER

+

+ The software and these notes are provided "as is".  They may include

+ typographical or technical errors and their authors disclaims all

+ liability of any kind or nature for damages due to error, fault,

+ defect, or deficiency regardless of cause.  All warranties of any

+ kind, either express or implied, including, but not limited to, the

+ implied  warranties of merchantability and fitness for a particular

+ purpose are disclaimed.

+

+

+#153. (Changed in MR12b) Bug in computation of -mrhoist suppression set

+

+      Consider the following grammar with k=1 and "-mrhoist on":

+

+            r1  : (A)? => ((p>>? x      /* l1 */

+                | r2                    /* l2 */

+                ;

+            r2  :  A                    /* l4 */

+                | (B)? => <<q>>? y      /* l5 */

+                ;

+

+      In earlier versions the mrhoist routine would see that both l1 and

+      l2 contained predicates and would assume that this prevented either

+      from acting to suppress the other predicate.  In the example above

+      it didn't realize the A at line l4 is capable of suppressing the

+      predicate at l1 even though alt l2 contains (indirectly) a predicate.

+

+      This is fixed  in MR12b.

+

+      Reported by Reinier van den Born (reinier@vnet.ibm.com)

+

+#153. (Changed in MR12a) Bug in computation of -mrhoist suppression set

+

+      An oversight similar to that described in Item #152 appeared in

+      the computation of the set that "covered" a predicate.  If a

+      predicate expression included a term such as p=AND(q,r) the context

+      of p was taken to be context(q) & context(r), when it should have

+      been context(q) | context(r).  This is fixed in MR12a.

+

+#152. (Changed in MR12) Bug in generation of predicate expressions

+

+      The primary purpose for MR12 is to make quite clear that MR11 is

+      obsolete and to fix the bug related to predicate expressions.

+

+      In MR10 code was added to optimize the code generated for

+      predicate expression tests.  Unfortunately, there was a

+      significant oversight in the code which resulted in a bug in

+      the generation of code for predicate expression tests which

+      contained predicates combined using AND:

+

+            r0 : (r1)* "@" ;

+            r1 : (AAA)? => <<p LATEXT(1)>>? r2 ;

+            r2 : (BBB)? => <<q LATEXT(1)>>? Q

+               | (BBB)? => <<r LATEXT(1)>>? Q

+               ;

+

+      In MR11 (and MR10 when using "-mrhoist on") the code generated

+      for r0 to predict r1 would be equivalent to:

+

+        if ( LA(1)==Q &&

+                (LA(1)==AAA && LA(1)==BBB) &&

+                    ( p && ( q || r )) ) {

+

+      This is incorrect because it expresses the idea that LA(1)

+      *must* be AAA in order to attempt r1, and *must* be BBB to

+      attempt r2.  The result was that r1 became unreachable since

+      both condition can not be simultaneously true.

+

+      The general philosophy of code generation for predicates

+      can be summarized as follows:

+

+            a. If the context is true don't enter an alt

+               for which the corresponding predicate is false.

+

+               If the context is false then it is okay to enter

+               the alt without evaluating the predicate at all.

+

+            b. A predicate created by ORing of predicates has

+               context which is the OR of their individual contexts.

+

+            c. A predicate created by ANDing of predicates has

+               (surprise) context which is the OR of their individual

+               contexts.

+

+            d. Apply these rules recursively.

+

+            e. Remember rule (a)

+

+      The correct code should express the idea that *if* LA(1) is

+      AAA then p must be true to attempt r1, but if LA(1) is *not*

+      AAA then it is okay to attempt r1, provided that *if* LA(1) is

+      BBB then one of q or r must be true.

+

+        if ( LA(1)==Q &&

+                ( !(LA(1)==AAA || LA(1)==BBB) ||

+                    ( ! LA(1) == AAA || p) &&

+                    ( ! LA(1) == BBB || q || r ) ) ) {

+

+      I believe this is fixed in MR12.

+

+      Reported by Reinier van den Born (reinier@vnet.ibm.com)

+

+#151a. (Changed in MR12) ANTLRParser::getLexer()

+

+      As a result of several requests, I have added public methods to

+      get a pointer to the lexer belonging to a parser.

+

+            ANTLRTokenStream *ANTLRParser::getLexer() const

+

+                Returns a pointer to the lexer being used by the

+                parser.  ANTLRTokenStream is the base class of

+                DLGLexer

+

+            ANTLRTokenStream *ANTLRTokenBuffer::getLexer() const

+

+                Returns a pointer to the lexer being used by the

+                ANTLRTokenBuffer.  ANTLRTokenStream is the base

+                class of DLGLexer

+

+      You must manually cast the ANTLRTokenStream to your program's

+      lexer class. Because the name of the lexer's class is not fixed.

+      Thus it is impossible to incorporate it into the DLGLexerBase

+      class.

+

+#151b.(Changed in MR12) ParserBlackBox member getLexer()

+

+      The template class ParserBlackBox now has a member getLexer()

+      which returns a pointer to the lexer.

+

+#150. (Changed in MR12) syntaxErrCount and lexErrCount now public

+

+      See Item #127 for more information.

+

+#149. (Changed in MR12) antlr option -info o (letter o for orphan)

+

+      If there is more than one rule which is not referenced by any

+      other rule then all such rules are listed.  This is useful for

+      alerting one to rules which are not used, but which can still

+      contribute to ambiguity.  For example:

+

+            start : a Z ;

+            unused: a A ;

+            a     : (A)+ ;

+

+      will cause an ambiguity report for rule "a" which will be

+      difficult to understand if the user forgets about rule "unused"

+      simply because it is not used in the grammar.

+

+#148. (Changed in MR11) #token names appearing in zztokens,token_tbl

+

+      In a #token statement like the following:

+

+            #token Plus "\+"

+

+      the string "Plus" appears in the zztokens array (C mode) and

+      token_tbl (C++ mode).  This string is used in most error

+      messages.  In MR11 one has the option of using some other string,

+      (e.g.  "+") in those tables.

+

+      In MR11 one can write:

+

+            #token Plus ("+")             "\+"

+            #token RP   ("(")             "\("

+            #token COM  ("comment begin") "/\*"

+

+      A #token statement is allowed to appear in more than one #lexclass

+      with different regular expressions.  However, the token name appears

+      only once in the zztokens/token_tbl array.  This means that only

+      one substitute can be specified for a given #token name.  The second

+      attempt to define a substitute name (different from the first) will

+      result in an error message.

+

+#147. (Changed in MR11) Bug in follow set computation

+

+      There is a bug in 1.33 vanilla and all maintenance releases

+      prior to MR11 in the computation of the follow set.  The bug is

+      different than that described in Item #82 and probably more

+      common.  It was discovered in the ansi.g grammar while testing

+      the "ambiguity aid" (Item #119). The search for a bug started

+      when the ambiguity aid was unable to discover the actual source

+      of an ambiguity reported by antlr.

+

+      The problem appears when an optimization of the follow set

+      computation is used inappropriately.  The result is that the

+      follow set used is the "worst case".  In other words, the error

+      can lead to false reports of ambiguity.  The good news is that

+      if you have a grammar in which you have addressed all reported

+      ambiguities you are ok.  The bad news is that you may have spent

+      time fixing ambiguities that were not real, or used k=2 when

+      ck=2 might have been sufficient, and so on.

+

+      The following grammar demonstrates the problem:

+

+        ------------------------------------------------------------

+            expr          :   ID ;

+

+            start         :   stmt SEMI ;

+

+            stmt          :   CASE expr COLON

+                          |   expr SEMI

+                          |   plain_stmt

+                          ;

+

+            plain_stmt    :   ID COLON ;

+        ------------------------------------------------------------

+

+      When compiled with k=1 and ck=2 it will report:

+

+         warning: alts 2 and 3 of the rule itself ambiguous upon

+                                             { IDENTIFIER }, { COLON }

+

+      When antlr analyzes "stmt" it computes the first[1] set of all

+      alternatives.  It finds an ambiguity between alts 2 and 3 for ID.

+      It then computes the first[2] set for alternatives 2 and 3 to resolve

+      the ambiguity.  In computing the first[2] set of "expr" (which is

+      only one token long) it needs to determine what could follow "expr".

+      Under a certain combination of circumstances antlr forgets that it

+      is trying to analyze "stmt" which can only be followed by SEMI and

+      adds to the first[2] set of "expr" the "global" follow set (including

+      "COLON") which could follow "expr" (under other conditions) in the

+      phrase "CASE expr COLON".

+

+#146. (Changed in MR11) Option -treport for locating "difficult" alts

+

+      It can be difficult to determine which alternatives are causing

+      pccts to work hard to resolve an ambiguity.  In some cases the

+      ambiguity is successfully resolved after much CPU time so there

+      is no message at all.

+

+      A rough measure of the amount of work being peformed which is

+      independent of the CPU speed and system load is the number of

+      tnodes created.  Using "-info t" gives information about the

+      total number of tnodes created and the peak number of tnodes.

+

+        Tree Nodes:  peak 1300k  created 1416k  lost 0

+

+      It also puts in the generated C or C++ file the number of tnodes

+      created for a rule (at the end of the rule).  However this

+      information is not sufficient to locate the alternatives within

+      a rule which are causing the creation of tnodes.

+

+      Using:

+

+             antlr -treport 100000 ....

+

+      causes antlr to list on stdout any alternatives which require the

+      creation of more than 100,000 tnodes, along with the lookahead sets

+      for those alternatives.

+

+      The following is a trivial case from the ansi.g grammar which shows

+      the format of the report.  This report might be of more interest

+      in cases where 1,000,000 tuples were created to resolve the ambiguity.

+

+      -------------------------------------------------------------------------

+        There were 0 tuples whose ambiguity could not be resolved

+             by full lookahead

+        There were 157 tnodes created to resolve ambiguity between:

+

+          Choice 1: statement/2  line 475  file ansi.g

+          Choice 2: statement/3  line 476  file ansi.g

+

+            Intersection of lookahead[1] sets:

+

+               IDENTIFIER

+

+            Intersection of lookahead[2] sets:

+

+               LPARENTHESIS     COLON            AMPERSAND        MINUS

+               STAR             PLUSPLUS         MINUSMINUS       ONESCOMPLEMENT

+               NOT              SIZEOF           OCTALINT         DECIMALINT

+               HEXADECIMALINT   FLOATONE         FLOATTWO         IDENTIFIER

+               STRING           CHARACTER

+      -------------------------------------------------------------------------

+

+#145. (Documentation)  Generation of Expression Trees

+

+      Item #99 was misleading because it implied that the optimization

+      for tree expressions was available only for trees created by

+      predicate expressions and neglected to mention that it required

+      the use of "-mrhoist on".  The optimization applies to tree

+      expressions created for grammars with k>1 and for predicates with

+      lookahead depth >1.

+

+      In MR11 the optimized version is always used so the -mrhoist on

+      option need not be specified.

+

+#144. (Changed in MR11) Incorrect test for exception group

+

+      In testing for a rule's exception group the label a pointer

+      is compared against '\0'.  The intention is "*pointer".

+

+      Reported by Jeffrey C. Fried (Jeff@Fried.net).

+

+#143. (Changed in MR11) Optional ";" at end of #token statement

+

+      Fixes problem of:

+

+            #token X "x"

+

+            <<

+                parser action

+            >>

+

+      Being confused with:

+

+            #token X "x" <<lexical action>>

+

+#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream

+

+      Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class

+      BufFileInput derived from DLGInputStream which provides a

+      function lookahead(char *string) to test characters in the

+      input stream more than one character ahead.

+

+      The default amount of lookahead is specified by the constructor

+      and defaults to 8 characters.  This does *not* include the one

+      character of lookahead maintained internally by DLG in member "ch"

+      and which is not available for testing via BufFileInput::lookahead().

+

+      This is a useful class for overcoming the one-character-lookahead

+      limitation of DLG without resorting to a lexer capable of

+      backtracking (like flex) which is not integrated with antlr as is

+      DLG.

+

+      There are no restrictions on copying or using BufFileInput.* except

+      that the authorship and related information must be retained in the

+      source code.

+

+      The class is located in pccts/h/BufFileInput.* of the kit.

+

+#141. (Changed in MR11) ZZDEBUG_CONSUME for ANTLRParser::consume()

+

+      A debug aid has been added to file ANTLRParser::consume() in

+      file AParser.cpp:

+

+            #ifdef ZZDEBUG_CONSUME_ACTION

+                zzdebug_consume_action();

+            #endif

+

+      Suggested by Sramji Ramanathan (ps@kumaran.com).

+

+#140. (Changed in MR11) #pred to define predicates

+

+      +---------------------------------------------------+

+      | Note: Assume "-prc on" for this entire discussion |

+      +---------------------------------------------------+

+

+      A problem with predicates is that each one is regarded as

+      unique and capable of disambiguating cases where two

+      alternatives have identical lookahead.  For example:

+

+        rule : <<pred(LATEXT(1))>>? A

+             | <<pred(LATEXT(1))>>? A

+             ;

+

+      will not cause any error messages or warnings to be issued

+      by earlier versions of pccts.  To compare the text of the

+      predicates is an incomplete solution.

+

+      In 1.33MR11 I am introducing the #pred statement in order to

+      solve some problems with predicates.  The #pred statement allows

+      one to give a symbolic name to a "predicate literal" or a

+      "predicate expression" in order to refer to it in other predicate

+      expressions or in the rules of the grammar.

+

+      The predicate literal associated with a predicate symbol is C

+      or C++ code which can be used to test the condition.  A

+      predicate expression defines a predicate symbol in terms of other

+      predicate symbols using "!", "&&", and "||".  A predicate symbol

+      can be defined in terms of a predicate literal, a predicate

+      expression, or *both*.

+

+      When a predicate symbol is defined with both a predicate literal

+      and a predicate expression, the predicate literal is used to generate

+      code, but the predicate expression is used to check for two

+      alternatives with identical predicates in both alternatives.

+

+      Here are some examples of #pred statements:

+

+        #pred  IsLabel       <<isLabel(LATEXT(1))>>?

+        #pred  IsLocalVar    <<isLocalVar(LATEXT(1))>>?

+        #pred  IsGlobalVar   <<isGlobalVar(LATEXT(1)>>?

+        #pred  IsVar         <<isVar(LATEXT(1))>>?       IsLocalVar || IsGlobalVar

+        #pred  IsScoped      <<isScoped(LATEXT(1))>>?    IsLabel || IsLocalVar

+

+      I hope that the use of EBNF notation to describe the syntax of the

+      #pred statement will not cause problems for my readers (joke).

+

+        predStatement : "#pred"

+                            CapitalizedName

+                              (

+                                  "<<predicate_literal>>?"

+                                | "<<predicate_literal>>?"  predOrExpr

+                                | predOrExpr

+                              )

+                      ;

+

+        predOrExpr    : predAndExpr ( "||" predAndExpr ) * ;

+

+        predAndExpr   : predPrimary ( "&&" predPrimary ) * ;

+

+        predPrimary   : CapitalizedName

+                      | "!" predPrimary

+                      | "(" predOrExpr ")"

+                      ;

+

+      What is the purpose of this nonsense ?

+

+      To understand how predicate symbols help, you need to realize that

+      predicate symbols are used in two different ways with two different

+      goals.

+

+        a. Allow simplification of predicates which have been combined

+           during predicate hoisting.

+

+        b. Allow recognition of identical predicates which can't disambiguate

+           alternatives with common lookahead.

+

+      First we will discuss goal (a).  Consider the following rule:

+

+            rule0: rule1

+                 | ID

+                 | ...

+                 ;

+

+            rule1: rule2

+                 | rule3

+                 ;

+

+            rule2: <<isX(LATEXT(1))>>? ID ;

+            rule3: <<!isX(LATEXT(1)>>? ID ;

+

+      When the predicates in rule2 and rule3 are combined by hoisting

+      to create a prediction expression for rule1 the result is:

+

+            if ( LA(1)==ID

+                && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ...

+

+      This is inefficient, but more importantly, can lead to false

+      assumptions that the predicate expression distinguishes the rule1

+      alternative with some other alternative with lookahead ID.  In

+      MR11 one can write:

+

+            #pred IsX     <<isX(LATEXT(1))>>?

+

+            ...

+

+            rule2: <<IsX>>? ID  ;

+            rule3: <<!IsX>>? ID ;

+

+      During hoisting MR11 recognizes this as a special case and

+      eliminates the predicates.  The result is a prediction

+      expression like the following:

+

+            if ( LA(1)==ID ) { rule1(); ...

+

+      Please note that the following cases which appear to be equivalent

+      *cannot* be simplified by MR11 during hoisting because the hoisting

+      logic only checks for a "!" in the predicate action, not in the

+      predicate expression for a predicate symbol.

+

+        *Not* equivalent and is not simplified during hoisting:

+

+            #pred IsX      <<isX(LATEXT(1))>>?

+            #pred NotX     <<!isX(LATEXT(1))>>?

+            ...

+            rule2: <<IsX>>? ID  ;

+            rule3: <<NotX>>? ID ;

+

+        *Not* equivalent and is not simplified during hoisting:

+

+            #pred IsX      <<isX(LATEXT(1))>>?

+            #pred NotX     !IsX

+            ...

+            rule2: <<IsX>>? ID  ;

+            rule3: <<NotX>>? ID ;

+

+      Now we will discuss goal (b).

+

+      When antlr discovers that there is a lookahead ambiguity between

+      two alternatives it attempts to resolve the ambiguity by searching

+      for predicates in both alternatives.  In the past any predicate

+      would do, even if the same one appeared in both alternatives:

+

+            rule: <<p(LATEXT(1))>>? X

+                | <<p(LATEXT(1))>>? X

+                ;

+

+      The #pred statement is a start towards solving this problem.

+      During ambiguity resolution (*not* predicate hoisting) the

+      predicates for the two alternatives are expanded and compared.

+      Consider the following example:

+

+            #pred Upper     <<isUpper(LATEXT(1))>>?

+            #pred Lower     <<isLower(LATEXT(1))>>?

+            #pred Alpha     <<isAlpha(LATEXT(1))>>?  Upper || Lower

+

+            rule0: rule1

+                 | <<Alpha>>? ID

+                 ;

+

+            rule1:

+                 | rule2

+                 | rule3

+                 ...

+                 ;

+

+            rule2: <<Upper>>? ID;

+            rule3: <<Lower>>? ID;

+

+      The definition of #pred Alpha expresses:

+

+            a. to test the predicate use the C code "isAlpha(LATEXT(1))"

+

+            b. to analyze the predicate use the information that

+               Alpha is equivalent to the union of Upper and Lower,

+

+      During ambiguity resolution the definition of Alpha is expanded

+      into "Upper || Lower" and compared with the predicate in the other

+      alternative, which is also "Upper || Lower".  Because they are

+      identical MR11 will report a problem.

+

+    -------------------------------------------------------------------------

+      t10.g, line 5: warning: the predicates used to disambiguate rule rule0

+             (file t10.g alt 1 line 5 and alt 2 line 6)

+             are identical when compared without context and may have no

+             resolving power for some lookahead sequences.

+    -------------------------------------------------------------------------

+

+      If you use the "-info p" option the output file will contain:

+

+    +----------------------------------------------------------------------+

+    |#if 0                                                                 |

+    |                                                                      |

+    |The following predicates are identical when compared without          |

+    |  lookahead context information.  For some ambiguous lookahead        |

+    |  sequences they may not have any power to resolve the ambiguity.     |

+    |                                                                      |

+    |Choice 1: rule0/1  alt 1  line 5  file t10.g                          |

+    |                                                                      |

+    |  The original predicate for choice 1 with available context          |

+    |    information:                                                      |

+    |                                                                      |

+    |    OR expr                                                           |

+    |                                                                      |

+    |      pred  <<  Upper>>?                                              |

+    |                        depth=k=1  rule rule2  line 14  t10.g         |

+    |        set context:                                                  |

+    |           ID                                                         |

+    |                                                                      |

+    |      pred  <<  Lower>>?                                              |

+    |                        depth=k=1  rule rule3  line 15  t10.g         |

+    |        set context:                                                  |

+    |           ID                                                         |

+    |                                                                      |

+    |  The predicate for choice 1 after expansion (but without context     |

+    |    information):                                                     |

+    |                                                                      |

+    |    OR expr                                                           |

+    |                                                                      |

+    |      pred  <<  isUpper(LATEXT(1))>>?                                 |

+    |                        depth=k=1  rule   line 1  t10.g               |

+    |                                                                      |

+    |      pred  <<  isLower(LATEXT(1))>>?                                 |

+    |                        depth=k=1  rule   line 2  t10.g               |

+    |                                                                      |

+    |                                                                      |

+    |Choice 2: rule0/2  alt 2  line 6  file t10.g                          |

+    |                                                                      |

+    |  The original predicate for choice 2 with available context          |

+    |    information:                                                      |

+    |                                                                      |

+    |  pred  <<  Alpha>>?                                                  |

+    |                    depth=k=1  rule rule0  line 6  t10.g              |

+    |    set context:                                                      |

+    |       ID                                                             |

+    |                                                                      |

+    |  The predicate for choice 2 after expansion (but without context     |

+    |    information):                                                     |

+    |                                                                      |

+    |  OR expr                                                             |

+    |                                                                      |

+    |    pred  <<  isUpper(LATEXT(1))>>?                                   |

+    |                      depth=k=1  rule   line 1  t10.g                 |

+    |                                                                      |

+    |    pred  <<  isLower(LATEXT(1))>>?                                   |

+    |                      depth=k=1  rule   line 2  t10.g                 |

+    |                                                                      |

+    |                                                                      |

+    |#endif                                                                |

+    +----------------------------------------------------------------------+

+

+      The comparison of the predicates for the two alternatives takes

+      place without context information, which means that in some cases

+      the predicates will be considered identical even though they operate

+      on disjoint lookahead sets.  Consider:

+

+            #pred Alpha

+

+            rule1: <<Alpha>>? ID

+                 | <<Alpha>>? Label

+                 ;

+

+      Because the comparison of predicates takes place without context

+      these will be considered identical.  The reason for comparing

+      without context is that otherwise it would be necessary to re-evaluate

+      the entire predicate expression for each possible lookahead sequence.

+      This would require more code to be written and more CPU time during

+      grammar analysis, and it is not yet clear whether anyone will even make

+      use of the new #pred facility.

+

+      A temporary workaround might be to use different #pred statements

+      for predicates you know have different context.  This would avoid

+      extraneous warnings.

+

+      The above example might be termed a "false positive".  Comparison

+      without context will also lead to "false negatives".  Consider the

+      following example:

+

+            #pred Alpha

+            #pred Beta

+

+            rule1: <<Alpha>>? A

+                 | rule2

+                 ;

+

+            rule2: <<Alpha>>? A

+                 | <<Beta>>?  B

+                 ;

+

+      The predicate used for alt 2 of rule1 is (Alpha || Beta).  This

+      appears to be different than the predicate Alpha used for alt1.

+      However, the context of Beta is B.  Thus when the lookahead is A

+      Beta will have no resolving power and Alpha will be used for both

+      alternatives.  Using the same predicate for both alternatives isn't

+      very helpful, but this will not be detected with 1.33MR11.

+

+      To properly handle this the predicate expression would have to be

+      evaluated for each distinct lookahead context.

+

+      To determine whether two predicate expressions are identical is

+      difficult.  The routine may fail to identify identical predicates.

+

+      The #pred feature also compares predicates to see if a choice between

+      alternatives which is resolved by a predicate which makes the second

+      choice unreachable.  Consider the following example:

+

+            #pred A         <<A(LATEXT(1)>>?

+            #pred B         <<B(LATEXT(1)>>?

+            #pred A_or_B    A || B

+

+            r   : s

+                | t

+                ;

+            s   : <<A_or_B>>? ID

+                ;

+            t   : <<A>>? ID

+                ;

+

+        ----------------------------------------------------------------------------

+        t11.g, line 5: warning: the predicate used to disambiguate the

+               first choice of  rule r

+             (file t11.g alt 1 line 5 and alt 2 line 6)

+             appears to "cover" the second predicate when compared without context.

+             The second predicate may have no resolving power for some lookahead

+               sequences.

+        ----------------------------------------------------------------------------

+

+#139. (Changed in MR11) Problem with -gp in C++ mode

+

+      The -gp option to add a prefix to rule names did not work in

+      C++ mode.  This has been fixed.

+

+      Reported by Alexey Demakov (demakov@kazbek.ispras.ru).

+

+#138. (Changed in MR11) Additional makefiles for non-MSVC++ MS systems

+

+      Sramji Ramanathan (ps@kumaran.com) has supplied makefiles for

+      building antlr and dlg with Win95/NT development tools that

+      are not based on MSVC5.  They are pccts/antlr/AntlrMS.mak and

+      pccts/dlg/DlgMS.mak.

+

+      The first line of the makefiles require a definition of PCCTS_HOME.

+

+      These are in additiion to the AntlrMSVC50.* and DlgMSVC50.*

+      supplied by Jeff Vincent (JVincent@novell.com).

+

+#137. (Changed in MR11) Token getType(), getText(), getLine() const members

+

+      --------------------------------------------------------------------

+      If you use ANTLRCommonToken this change probably does not affect you.

+      --------------------------------------------------------------------

+

+      For a long time it has bothered me that these accessor functions

+      in ANTLRAbstractToken were not const member functions.  I have

+      refrained from changing them because it require users to modify

+      existing token class definitions which are derived directly

+      from ANTLRAbstractToken.  I think it is now time.

+

+      For those who are not used to C++, a "const member function" is a

+      member function which does not modify its own object - the thing

+      to which "this" points. This is quite different from a function

+      which does not modify its arguments

+

+      Most token definitions based on ANTLRAbstractToken have something like

+      the following in order to create concrete definitions of the pure

+      virtual methods in ANTLRAbstractToken:

+

+        class MyToken : public ANTLRAbstractToken {

+            ...

+            ANTLRTokenType getType() {return _type; }

+            int getLine()            {return _line; }

+            ANTLRChar * getText()    {return _text; }

+            ...

+        }

+

+      The required change is simply to put "const" following the function

+      prototype in the header (.h file) and the definition file (.cpp if

+      it is not inline):

+

+        class MyToken : public ANTLRAbstractToken {

+            ...

+            ANTLRTokenType getType() const {return _type; }

+            int getLine() const            {return _line; }

+            ANTLRChar * getText() const    {return _text; }

+            ...

+        }

+

+      This was originally proposed a long time ago by Bruce

+      Guenter (bruceg@qcc.sk.ca).

+

+#136. (Changed in MR11) Added getLength() to ANTLRCommonToken

+

+      Classes ANTLRCommonToken and ANTLRCommonTokenNoRefCountToken

+      now have a member function:

+

+            int getLength() const { return strlen(getText()) }

+

+      Suggested by Sramji Ramanathan (ps@kumaran.com).

+

+#135. (Changed in MR11) Raised antlr's own default ZZLEXBUFSIZE to 8k

+

+#134a. (ansi_mr10.zip)  T.J. Parr's ANSI C grammar made 1.33MR11 compatible

+

+       There is a typographical error in the definition of BITWISEOREQ:

+

+        #token BITWISEOREQ "!=" should be "\|="

+

+       When this change is combined with the bugfix to the follow set cache

+       problem (Item #147) and a minor rearrangement of the grammar

+       (Item #134b) it becomes a k=1 ck=2 grammar.

+

+#134b. (ansi_mr10.zip)  T.J. Parr's ANSI C grammar made 1.33MR11 compatible

+

+      The following changes were made in the ansi.g grammar (along with

+      using -mrhoist on):

+

+        ansi.g

+        ======

+        void tracein(char *)     ====>    void tracein(const char *)

+        void traceout(char *)    ====>    void traceout(const char *)

+

+        <LT(1)->getType()==IDENTIFIER ? isTypeName(LT(1)->getText()) : 1>>?

+        ====> <<isTypeName(LT(1)->getText())>>?

+

+        <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \

+                        isTypeName(LT(2)->getText()) : 1>>?

+        ====> (LPARENTHESIS IDENTIFIER)? => <<isTypeName(LT(2)->getText())>>?

+

+        <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \

+                        isTypeName(LT(2)->getText()) : 1>>?

+        ====> (LPARENTHESIS IDENTIFIER)? => <<isTypeName(LT(2)->getText())>>?

+

+        added to init(): traceOptionValueDefault=0;

+        added to init(): traceOption(-1);

+

+        change rule "statement":

+

+            statement

+                :   plain_label_statement

+                |   case_label_statement

+                |   <<;>> expression SEMICOLON

+                |   compound_statement

+                |   selection_statement

+                |   iteration_statement

+                |   jump_statement

+                |   SEMICOLON

+                ;

+

+            plain_label_statement

+                :   IDENTIFIER COLON statement

+                ;

+

+            case_label_statement

+                :   CASE constant_expression COLON statement

+                |   DEFAULT COLON statement

+            ;

+

+        support.cpp

+        ===========

+        void tracein(char *)     ====>    void tracein(const char *)

+        void traceout(char *)    ====>    void traceout(const char *)

+

+        added to tracein():  ANTLRParser::tracein(r);  // call superclass method

+        added to traceout(): ANTLRParser::traceout(r); // call superclass method

+

+        Makefile

+        ========

+        added to AFLAGS: -mrhoist on -prc on

+

+#133. (Changed in 1.33MR11) Make trace options public in ANTLRParser

+

+      In checking T.J. Parr's ANSI C grammar for compatibility with

+      1.33MR11 discovered that it was inconvenient to have the

+      trace facilities with protected access.

+

+#132. (Changed in 1.33MR11) Recognition of identical predicates in alts

+

+      Prior to 1.33MR11, there would be no ambiguity warning when the

+      very same predicate was used to disambiguate both alternatives:

+

+        test: ref B

+            | ref C

+            ;

+

+        ref : <<pred(LATEXT(1)>>? A

+

+      In 1.33MR11 this will cause the warning:

+

+        warning: the predicates used to disambiguate rule test

+            (file v98.g alt 1 line 1 and alt 2 line 2)

+             are identical and have no resolving power

+

+        -----------------  Note  -----------------

+

+          This is different than the following case

+

+                test: <<pred(LATEXT(1))>>? A B

+                    | <<pred(LATEXT(1)>>?  A C

+                    ;

+

+          In this case there are two distinct predicates

+          which have exactly the same text.  In the first

+          example there are two references to the same

+          predicate.  The problem represented by this

+          grammar will be addressed later.

+

+#131. (Changed in 1.33MR11) Case insensitive command line options

+

+      Command line switches like "-CC" and keywords like "on", "off",

+      and "stdin" are no longer case sensitive in antlr, dlg, and sorcerer.

+

+#130. (Changed in 1.33MR11) Changed ANTLR_VERSION to int from string

+

+      The ANTLR_VERSION was not an integer, making it difficult to

+      perform conditional compilation based on the antlr version.

+

+      Henceforth, ANTLR_VERSION will be:

+

+            (base_version * 10000) + release number

+

+            thus 1.33MR11 will be: 133*100+11 = 13311

+

+      Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE).

+

+#129. (Changed in 1.33MR11) Addition of ANTLR_VERSION to <parserName>.h

+

+      The following code is now inserted into <parserName>.h amd

+      stdpccts.h:

+

+            #ifndef ANTLR_VERSION

+            #define ANTLR_VERSION 13311

+            #endif

+

+      Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE)

+

+#128. (Changed in 1.33MR11) Redundant predicate code in (<<pred>>? ...)+

+

+      Prior to 1.33MR11, the following grammar would generate

+      redundant tests for the "while" condition.

+

+        rule2 : (<<pred>>? X)+ X

+              | B

+              ;

+

+      The code would resemble:

+

+            if (LA(1)==X) {

+                if (pred) {

+                    do {

+                        if (!pred) {zzfailed_pred("  pred");}

+                        zzmatch(X); zzCONSUME;

+                    } while (LA(1)==X && pred && pred);

+            } else {...

+

+      With 1.33MR11 the redundant predicate test is omitted.

+

+#127. (Changed in 1.33MR11)

+

+                    Count Syntax Errors     Count DLG Errors

+                    -------------------     ----------------

+

+       C++ mode     ANTLRParser::           DLGLexerBase::

+                      syntaxErrCount          lexErrCount

+       C mode       zzSyntaxErrCount        zzLexErrCount

+

+       The C mode variables are global and initialized to 0.

+       They are *not* reset to 0 automatically when antlr is

+       restarted.

+

+       The C++ mode variables are public.  They are initialized

+       to 0 by the constructors.  They are *not* reset to 0 by the

+       ANTLRParser::init() method.

+

+       Suggested by Reinier van den Born (reinier@vnet.ibm.com).

+

+#126. (Changed in 1.33MR11) Addition of #first <<...>>

+

+       The #first <<...>> inserts the specified text in the output

+       files before any other #include statements required by pccts.

+       The only things before the #first text are comments and

+       a #define ANTLR_VERSION.

+

+       Requested by  and Esa Pulkkinen (esap@cs.tut.fi) and Alexin

+       Zoltan (alexin@inf.u-szeged.hu).

+

+#125. (Changed in 1.33MR11) Lookahead for (guard)? && <<p>>? predicates

+

+       When implementing the new style of guard predicate (Item #113)

+       in 1.33MR10 I decided to temporarily ignore the problem of

+       computing the "narrowest" lookahead context.

+

+       Consider the following k=1 grammar:

+

+            start : a

+                  | b

+                  ;

+

+            a     : (A)? && <<pred1(LATEXT(1))>>? ab ;

+            b     : (B)? && <<pred2(LATEXT(1))>>? ab ;

+

+            ab    : A | B ;

+

+       In MR10 the context for both "a" and "b" was {A B} because this is

+       the first set of rule "ab".  Normally, this is not a problem because

+       the predicate which follows the guard inhibits any ambiguity report

+       by antlr.

+

+       In MR11 the first set for rule "a" is {A} and for rule "b" it is {B}.

+

+#124. A Note on the New "&&" Style Guarded Predicates

+

+        I've been asked several times, "What is the difference between

+        the old "=>" style guard predicates and the new style "&&" guard

+        predicates, and how do you choose one over the other" ?

+

+        The main difference is that the "=>" does not apply the

+        predicate if the context guard doesn't match, whereas

+        the && form always does.  What is the significance ?

+

+        If you have a predicate which is not on the "leading edge"

+        it cannot be hoisted.  Suppose you need a predicate that

+        looks at LA(2).  You must introduce it manually.  The

+        classic example is:

+

+            castExpr :

+                     LP typeName RP

+                     | ....

+                     ;

+

+            typeName : <<isTypeName(LATEXT(1))>>?  ID

+                     | STRUCT ID

+                     ;

+

+        The problem  is that typeName isn't on the leading edge

+        of castExpr, so the predicate isTypeName won't be hoisted into

+        castExpr to help make a decision on which production to choose.

+

+        The *first* attempt to fix it is this:

+

+            castExpr :

+                     <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+        Unfortunately, this won't work because it ignores

+        the problem of STRUCT.  The solution is to apply

+        isTypeName() in castExpr if LA(2) is an ID and

+        don't apply it when LA(2) is STRUCT:

+

+            castExpr :

+                     (LP ID)? => <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+        In conclusion, the "=>" style guarded predicate is

+        useful when:

+

+            a. the tokens required for the predicate

+               are not on the leading edge

+            b. there are alternatives in the expression

+               selected by the predicate for which the

+               predicate is inappropriate

+

+        If (b) were false, then one could use a simple

+        predicate (assuming "-prc on"):

+

+            castExpr :

+                     <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+            typeName : <<isTypeName(LATEXT(1))>>?  ID

+                     ;

+

+        So, when do you use the "&&" style guarded predicate ?

+

+        The new-style "&&" predicate should always be used with

+        predicate context.  The context guard is in ADDITION to

+        the automatically computed context.  Thus it useful for

+        predicates which depend on the token type for reasons

+        other than context.

+

+        The following example is contributed by Reinier van den Born

+        (reinier@vnet.ibm.com).

+

+ +-------------------------------------------------------------------------+

+ | This grammar has two ways to call functions:                            |

+ |                                                                         |

+ |  - a "standard" call syntax with parens and comma separated args        |

+ |  - a shell command like syntax (no parens and spacing separated args)   |

+ |                                                                         |

+ | The former also allows a variable to hold the name of the function,     |

+ | the latter can also be used to call external commands.                  |

+ |                                                                         |

+ | The grammar (simplified) looks like this:                               |

+ |                                                                         |

+ |   fun_call   :     ID "(" { expr ("," expr)* } ")"                      |

+ |                                  /* ID is function name */              |

+ |              | "@" ID "(" { expr ("," expr)* } ")"                      |

+ |                                  /* ID is var containing fun name */    |

+ |              ;                                                          |

+ |                                                                         |

+ |   command    : ID expr*          /* ID is function name */              |

+ |              | path expr*        /* path is external command name */    |

+ |              ;                                                          |

+ |                                                                         |

+ |   path       : ID                /* left out slashes and such */        |

+ |              | "@" ID            /* ID is environment var */            |

+ |              ;                                                          |

+ |                                                                         |

+ |   expr       : ....                                                     |

+ |              | "(" expr ")";                                            |

+ |                                                                         |

+ |   call       : fun_call                                                 |

+ |              | command                                                  |

+ |              ;                                                          |

+ |                                                                         |

+ | Obviously the call is wildly ambiguous. This is more or less how this   |

+ | is to be resolved:                                                      |

+ |                                                                         |

+ |    A call begins with an ID or an @ followed by an ID.                  |

+ |                                                                         |

+ |    If it is an ID and if it is an ext. command name  -> command         |

+ |                       if followed by a paren         -> fun_call        |

+ |                       otherwise                      -> command         |

+ |                                                                         |

+ |    If it is an @  and if the ID is a var name        -> fun_call        |

+ |                       otherwise                      -> command         |

+ |                                                                         |

+ | One can implement these rules quite neatly using && predicates:         |

+ |                                                                         |

+ |   call       : ("@" ID)? && <<isVarName(LT(2))>>? fun_call              |

+ |              | (ID)?     && <<isExtCmdName>>?     command               |

+ |              | (ID "(")?                          fun_call              |

+ |              |                                    command               |

+ |              ;                                                          |

+ |                                                                         |

+ | This can be done better, so it is not an ideal example, but it          |

+ | conveys the principle.                                                  |

+ +-------------------------------------------------------------------------+

+

+#123. (Changed in 1.33MR11) Correct definition of operators in ATokPtr.h

+

+        The return value of operators in ANTLRTokenPtr:

+

+        changed: unsigned ... operator !=(...)

+             to: int ... operator != (...)

+        changed: unsigned ... operator ==(...)

+             to: int ... operator == (...)

+

+        Suggested by R.A. Nelson (cowboy@VNET.IBM.COM)

+

+#122. (Changed in 1.33MR11)  Member functions to reset DLG in C++ mode

+

+         void DLGFileReset(FILE *f) { input = f; found_eof = 0; }

+         void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; }

+

+        Supplied by R.A. Nelson (cowboy@VNET.IBM.COM)

+

+#121. (Changed in 1.33MR11)  Another attempt to fix -o (output dir) option

+

+      Another attempt is made to improve the -o option of antlr, dlg,

+      and sorcerer.  This one by JVincent (JVincent@novell.com).

+

+      The current rule:

+

+        a. If -o  is not specified than any explicit directory

+           names are retained.

+

+        b. If -o is specified than the -o directory name overrides any

+           explicit directory names.

+

+        c. The directory name of the grammar file is *not* stripped

+           to create the main output file.  However it is stil subject

+           to override by the -o directory name.

+

+#120. (Changed in 1.33MR11) "-info f" output to stdout rather than stderr

+

+      Added option 0 (e.g. "-info 0") which is a noop.

+

+#119. (Changed in 1.33MR11) Ambiguity aid for grammars

+

+      The user can ask for additional information on ambiguities reported

+      by antlr to stdout.  At the moment, only one ambiguity report can

+      be created in an antlr run.

+

+      This feature is enabled using the "-aa" (Ambiguity Aid)  option.

+

+      The following options control the reporting of ambiguities:

+

+          -aa ruleName       Selects reporting by name of rule

+          -aa lineNumber     Selects reporting by line number

+                               (file name not compared)

+

+          -aam               Selects "multiple" reporting for a token

+                             in the intersection set of the

+                             alternatives.

+

+                             For instance, the token ID may appear dozens

+                             of times in various paths as the program

+                             explores the rules which are reachable from

+                             the point of an ambiguity. With option -aam

+                             every possible path the search program

+                             encounters is reported.

+

+                             Without -aam only the first encounter is

+                             reported.  This may result in incomplete

+                             information, but the information may be

+                             sufficient and much shorter.

+

+          -aad depth         Selects the depth of the search.

+                             The default value is 1.

+

+                             The number of paths to be searched, and the

+                             size of the report can grow geometrically

+                             with the -ck value if a full search for all

+                             contributions to the source of the ambiguity

+                             is explored.

+

+                             The depth represents the number of tokens

+                             in the lookahead set which are matched against

+                             the set of ambiguous tokens.  A depth of 1

+                             means that the search stops when a lookahead

+                             sequence of just one token is matched.

+

+                             A k=1 ck=6 grammar might generate 5,000 items

+                             in a report if a full depth 6 search is made

+                             with the Ambiguity Aid.  The source of the

+                             problem may be in the first token and obscured

+                             by the volume of data - I hesitate to call

+                             it information.

+

+                             When the user selects a depth > 1, the search

+                             is first performed at depth=1 for both

+                             alternatives, then depth=2 for both alternatives,

+                             etc.

+

+      Sample output for rule grammar in antlr.g itself:

+

+  +---------------------------------------------------------------------+

+  | Ambiguity Aid                                                       |

+  |                                                                     |

+  |   Choice 1: grammar/70                 line 632  file a.g           |

+  |   Choice 2: grammar/82                 line 644  file a.g           |

+  |                                                                     |

+  |   Intersection of lookahead[1] sets:                                |

+  |                                                                     |

+  |      "\}"             "class"          "#errclass"      "#tokclass" |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:1  ("#errclass")                        |

+  |  1 in (...)* block                grammar/70       line 632   a.g   |

+  |  2 to error                       grammar/73       line 635   a.g   |

+  |  3 error                          error/1          line 894   a.g   |

+  |  4 #token "#errclass"             error/2          line 895   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:2  ("#tokclass")                        |

+  |  2 to tclass                      grammar/74       line 636   a.g   |

+  |  3 tclass                         tclass/1         line 937   a.g   |

+  |  4 #token "#tokclass"             tclass/2         line 938   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:3  ("class")                            |

+  |  2 to class_def                   grammar/75       line 637   a.g   |

+  |  3 class_def                      class_def/1      line 669   a.g   |

+  |  4 #token "class"                 class_def/3      line 671   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:4  ("\}")                               |

+  |  2 #token "\}"                    grammar/76       line 638   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:5  ("#errclass")                        |

+  |  1 in (...)* block                grammar/83       line 645   a.g   |

+  |  2 to error                       grammar/93       line 655   a.g   |

+  |  3 error                          error/1          line 894   a.g   |

+  |  4 #token "#errclass"             error/2          line 895   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:6  ("#tokclass")                        |

+  |  2 to tclass                      grammar/94       line 656   a.g   |

+  |  3 tclass                         tclass/1         line 937   a.g   |

+  |  4 #token "#tokclass"             tclass/2         line 938   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:7  ("class")                            |

+  |  2 to class_def                   grammar/95       line 657   a.g   |

+  |  3 class_def                      class_def/1      line 669   a.g   |

+  |  4 #token "class"                 class_def/3      line 671   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:8  ("\}")                               |

+  |  2 #token "\}"                    grammar/96       line 658   a.g   |

+  +---------------------------------------------------------------------+

+

+      For a linear lookahead set ambiguity (where k=1 or for k>1 but

+      when all lookahead sets [i] with i<k all have degree one) the

+      reports appear in the following order:

+

+        for (depth=1 ; depth <= "-aad depth" ; depth++) {

+          for (alternative=1; alternative <=2 ; alternative++) {

+            while (matches-are-found) {

+              group++;

+              print-report

+            };

+          };

+       };

+

+      For reporting a k-tuple ambiguity, the reports appear in the

+      following order:

+

+        for (depth=1 ; depth <= "-aad depth" ; depth++) {

+          while (matches-are-found) {

+            for (alternative=1; alternative <=2 ; alternative++) {

+              group++;

+              print-report

+            };

+          };

+       };

+

+      This is because matches are generated in different ways for

+      linear lookahead and k-tuples.

+

+#118. (Changed in 1.33MR11) DEC VMS makefile and VMS related changes

+

+      Revised makefiles for DEC/VMS operating system for antlr, dlg,

+      and sorcerer.

+

+      Reduced names of routines with external linkage to less than 32

+      characters to conform to DEC/VMS linker limitations.

+

+      Jean-Francois Pieronne discovered problems with dlg and antlr

+      due to the VMS linker not being case sensitive for names with

+      external linkage.  In dlg the problem was with "className" and

+      "ClassName".  In antlr the problem was with "GenExprSets" and

+      "genExprSets".

+

+      Added genmms, a version of genmk for the DEC/VMS version of make.

+      The source is in directory pccts/support/DECmms.

+

+      All VMS contributions by Jean-Francois Pieronne (jfp@iname.com).

+

+#117. (Changed in 1.33MR10) new EXPERIMENTAL predicate hoisting code

+

+      The hoisting of predicates into rules to create prediction

+      expressions is a problem in antlr.  Consider the following

+      example (k=1 with -prc on):

+

+        start   : (a)* "@" ;

+        a       : b | c ;

+        b       : <<isUpper(LATEXT(1))>>? A ;

+        c       : A ;

+

+      Prior to 1.33MR10 the code generated for "start" would resemble:

+

+        while {

+            if (LA(1)==A &&

+                    (!LA(1)==A || isUpper())) {

+              a();

+            }

+        };

+

+      This code is wrong because it makes rule "c" unreachable from

+      "start".  The essence of the problem is that antlr fails to

+      recognize that there can be a valid alternative within "a" even

+      when the predicate <<isUpper(LATEXT(1))>>? is false.

+

+      In 1.33MR10 with -mrhoist the hoisting of the predicate into

+      "start" is suppressed because it recognizes that "c" can

+      cover all the cases where the predicate is false:

+

+        while {

+            if (LA(1)==A) {

+              a();

+            }

+        };

+

+      With the antlr "-info p" switch the user will receive information

+      about the predicate suppression in the generated file:

+

+      --------------------------------------------------------------

+        #if 0

+

+        Hoisting of predicate suppressed by alternative without predicate.

+        The alt without the predicate includes all cases where

+            the predicate is false.

+

+           WITH predicate: line 7  v1.g

+           WITHOUT predicate: line 7  v1.g

+

+        The context set for the predicate:

+

+             A

+

+        The lookahead set for the alt WITHOUT the semantic predicate:

+

+             A

+

+        The predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 9  v1.g

+            set context:

+               A

+            tree context: null

+

+        Chain of referenced rules:

+

+            #0  in rule start (line 5 v1.g) to rule a

+            #1  in rule a (line 7 v1.g)

+

+        #endif

+      --------------------------------------------------------------

+

+      A predicate can be suppressed by a combination of alternatives

+      which, taken together, cover a predicate:

+

+        start   : (a)* "@" ;

+

+        a       : b | ca | cb | cc ;

+

+        b       : <<isUpper(LATEXT(1))>>? ( A | B | C ) ;

+

+        ca      : A ;

+        cb      : B ;

+        cc      : C ;

+

+      Consider a more complex example in which "c" covers only part of

+      a predicate:

+

+        start   : (a)* "@" ;

+

+        a       : b

+                | c

+                ;

+

+        b       : <<isUpper(LATEXT(1))>>?

+                    ( A

+                    | X

+                    );

+

+        c       : A

+                ;

+

+      Prior to 1.33MR10 the code generated for "start" would resemble:

+

+        while {

+            if ( (LA(1)==A || LA(1)==X) &&

+                    (! (LA(1)==A || LA(1)==X) || isUpper()) {

+              a();

+            }

+        };

+

+      With 1.33MR10 and -mrhoist the predicate context is restricted to

+      the non-covered lookahead.  The code resembles:

+

+        while {

+            if ( (LA(1)==A || LA(1)==X) &&

+                  (! (LA(1)==X) || isUpper()) {

+              a();

+            }

+        };

+

+      With the antlr "-info p" switch the user will receive information

+      about the predicate restriction in the generated file:

+

+      --------------------------------------------------------------

+        #if 0

+

+        Restricting the context of a predicate because of overlap

+          in the lookahead set between the alternative with the

+          semantic predicate and one without

+        Without this restriction the alternative without the predicate

+          could not be reached when input matched the context of the

+          predicate and the predicate was false.

+

+           WITH predicate: line 11  v4.g

+           WITHOUT predicate: line 12  v4.g

+

+        The original context set for the predicate:

+

+             A                X

+

+        The lookahead set for the alt WITHOUT the semantic predicate:

+

+             A

+

+        The intersection of the two sets

+

+             A

+

+        The original predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 15  v4.g

+            set context:

+               A                X

+            tree context: null

+

+        The new (modified) form of the predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 15  v4.g

+            set context:

+               X

+            tree context: null

+

+        #endif

+      --------------------------------------------------------------

+

+      The bad news about -mrhoist:

+

+        (a) -mrhoist does not analyze predicates with lookahead

+            depth > 1.

+

+        (b) -mrhoist does not look past a guarded predicate to

+            find context which might cover other predicates.

+

+      For these cases you might want to use syntactic predicates.

+      When a semantic predicate fails during guess mode the guess

+      fails and the next alternative is tried.

+

+      Limitation (a) is illustrated by the following example:

+

+        start    : (stmt)* EOF ;

+

+        stmt     : cast

+                 | expr

+                 ;

+        cast     : <<isTypename(LATEXT(2))>>? LP ID RP ;

+

+        expr     : LP ID RP ;

+

+      This is not much different from the first example, except that

+      it requires two tokens of lookahead context to determine what

+      to do.  This predicate is NOT suppressed because the current version

+      is unable to handle predicates with depth > 1.

+

+      A predicate can be combined with other predicates during hoisting.

+      In those cases the depth=1 predicates are still handled.  Thus,

+      in the following example the isUpper() predicate will be suppressed

+      by line #4 when hoisted from "bizarre" into "start", but will still

+      be present in "bizarre" in order to predict "stmt".

+

+        start    : (bizarre)* EOF ;     // #1

+                                        // #2

+        bizarre  : stmt                 // #3

+                 | A                    // #4

+                 ;

+

+        stmt     : cast

+                 | expr

+                 ;

+

+        cast     : <<isTypename(LATEXT(2))>>? LP ID RP ;

+

+        expr     : LP ID RP ;

+                 | <<isUpper(LATEXT(1))>>? A

+

+      Limitation (b) is illustrated by the following example of a

+      context guarded predicate:

+

+        rule : (A)? <<p>>?          // #1

+                     (A             // #2

+                     |B             // #3

+                     )              // #4

+             | <<q>> B              // #5

+             ;

+

+      Recall that this means that when the lookahead is NOT A then

+      the predicate "p" is ignored and it attempts to match "A|B".

+      Ideally, the "B" at line #3 should suppress predicate "q".

+      However, the current version does not attempt to look past

+      the guard predicate to find context which might suppress other

+      predicates.

+

+      In some cases -mrhoist will lead to the reporting of ambiguities

+      which were not visible before:

+

+        start   : (a)* "@";

+        a       : bc | d;

+        bc      : b  | c ;

+

+        b       : <<isUpper(LATEXT(1))>>? A;

+        c       : A ;

+

+        d       : A ;

+

+      In this case there is a true ambiguity in "a" between "bc" and "d"

+      which can both match "A".  Without -mrhoist the predicate in "b"

+      is hoisted into "a" and there is no ambiguity reported.  However,

+      with -mrhoist, the predicate in "b" is suppressed by "c" (as it

+      should be) making the ambiguity in "a" apparent.

+

+      The motivations for these changes were hoisting problems reported

+      by Reinier van den Born (reinier@vnet.ibm.com) and several others.

+

+#116. (Changed in 1.33MR10) C++ mode: tracein/traceout rule name is (const char *)

+

+      The prototype for C++ mode routine tracein (and traceout) has changed from

+      "char *" to "const char *".

+

+#115. (Changed in 1.33MR10) Using guess mode with exception handlers in C mode

+

+      The definition of the C mode macros zzmatch_wsig and zzsetmatch_wsig

+      neglected to consider guess mode.  When control passed to the rule's

+      parse exception handler the routine would exit without ever closing the

+      guess block. This would lead to unpredictable behavior.

+

+      In 1.33MR10 the behavior of exceptions in C mode and C++ mode should be

+      identical.

+

+#114. (Changed in 1.33MR10) difference in [zz]resynch() between C and C++ modes

+

+      There was a slight difference in the way C and C++ mode resynchronized

+      following a parsing error.  The C routine would sometimes skip an extra

+      token before attempting to resynchronize.

+

+      The C routine was changed to match the C++ routine.

+

+#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <<p>>? expr

+

+      The existing context guarded predicate:

+

+            rule : (guard)? => <<p>>? expr

+                 | next_alternative

+                 ;

+

+      generates code which resembles:

+

+            if (lookahead(expr) && (!guard || pred)) {

+              expr()

+            } else ....

+

+      This is not suitable for some applications because it allows

+      expr() to be invoked when the predicate is false.  This is

+      intentional because it is meant to mimic automatically computed

+      predicate context.

+

+      The new context guarded predicate uses the guard information

+      differently because it has a different goal.  Consider:

+

+            rule : (guard)? && <<p>>? expr

+                 | next_alternative

+                 ;

+

+      The new style of context guarded predicate is equivalent to:

+

+            rule : <<guard==true && pred>>? expr

+                 | next_alternative

+                 ;

+

+      It generates code which resembles:

+

+            if (lookahead(expr) && guard && pred) {

+                expr();

+            } else ...

+

+      Both forms of guarded predicates severely restrict the form of

+      the context guard: it can contain no rule references, no

+      (...)*, no (...)+, and no {...}.  It may contain token and

+      token class references, and alternation ("|").

+

+      Addition for 1.33MR11: in the token expression all tokens must

+      be at the same height of the token tree:

+

+            (A ( B | C))? && ...            is ok (all height 2)

+            (A ( B |  ))? && ...            is not ok (some 1, some 2)

+            (A B C D | E F G H)? && ...     is ok (all height 4)

+            (A B C D | E )? && ...          is not ok (some 4, some 1)

+

+      This restriction is required in order to properly compute the lookahead

+      set for expressions like:

+

+            rule1 : (A B C)? && <<pred>>? rule2 ;

+            rule2 : (A|X) (B|Y) (C|Z);

+

+      This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com)

+

+#112. (Changed in 1.33MR10) failed validation predicate in C guess mode

+

+      John Lilley (jlilley@empathy.com) suggested that failed validation

+      predicates abort a guess rather than reporting a failed error.

+      This was installed in C++ mode (Item #4).  Only now was it noticed

+      that the fix was never installed for C mode.

+

+#111. (Changed in 1.33MR10) moved zzTRACEIN to before init action

+

+      When the antlr -gd switch is present antlr generates calls to

+      zzTRACEIN at the start of a rule and zzTRACEOUT at the exit

+      from a rule.  Prior to 1.33MR10 Tthe call to zzTRACEIN was

+      after the init-action, which could cause confusion because the

+      init-actions were reported with the name of the enclosing rule,

+      rather than the active rule.

+

+#110. (Changed in 1.33MR10) antlr command line copied to generated file

+

+      The antlr command line is now copied to the generated file near

+      the start.

+

+#109. (Changed in 1.33MR10) improved trace information

+

+      The quality of the trace information provided by the "-gd"

+      switch has been improved significantly.  Here is an example

+      of the output from a test program.  It shows the rule name,

+      the first token of lookahead, the call depth, and the guess

+      status:

+

+        exit rule gusxx {"?"} depth 2

+        enter rule gusxx {"?"} depth 2

+        enter rule gus1 {"o"} depth 3 guessing

+        guess done - returning to rule gus1 {"o"} at depth 3

+                    (guess mode continues - an enclosing guess is still active)

+        guess done - returning to rule gus1 {"Z"} at depth 3

+                    (guess mode continues - an enclosing guess is still active)

+        exit rule gus1 {"Z"} depth 3 guessing

+        guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends)

+        enter rule gus1 {"o"} depth 3

+        guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends)

+        guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends)

+        exit rule gus1 {"Z"} depth 3

+        line 1: syntax error at "Z" missing SC

+            ...

+

+      Rule trace reporting is controlled by the value of the integer

+      [zz]traceOptionValue:  when it is positive tracing is enabled,

+      otherwise it is disabled.  Tracing during guess mode is controlled

+      by the value of the integer [zz]traceGuessOptionValue.  When

+      it is positive AND [zz]traceOptionValue is positive rule trace

+      is reported in guess mode.

+

+      The values of [zz]traceOptionValue and [zz]traceGuessOptionValue

+      can be adjusted by subroutine calls listed below.

+

+      Depending on the presence or absence of the antlr -gd switch

+      the variable [zz]traceOptionValueDefault is set to 0 or 1.  When

+      the parser is initialized or [zz]traceReset() is called the

+      value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue.

+      The value of [zz]traceGuessOptionValue is always initialzed to 1,

+      but, as noted earlier, nothing will be reported unless

+      [zz]traceOptionValue is also positive.

+

+      When the parser state is saved/restored the value of the trace

+      variables are also saved/restored.  If a restore causes a change in

+      reporting behavior from on to off or vice versa this will be reported.

+

+      When the -gd option is selected, the macro "#define zzTRACE_RULES"

+      is added to appropriate output files.

+

+        C++ mode

+        --------

+        int     traceOption(int delta)

+        int     traceGuessOption(int delta)

+        void    traceReset()

+        int     traceOptionValueDefault

+

+        C mode

+        --------

+        int     zzTraceOption(int delta)

+        int     zzTraceGuessOption(int delta)

+        void    zzTraceReset()

+        int     zzTraceOptionValueDefault

+

+      The argument "delta" is added to the traceOptionValue.  To

+      turn on trace when inside a particular rule one:

+

+        rule : <<traceOption(+1);>>

+               (

+                rest-of-rule

+               )

+               <<traceOption(-1);>>

+       ;  /* fail clause */ <<traceOption(-1);>>

+

+      One can use the same idea to turn *off* tracing within a

+      rule by using a delta of (-1).

+

+      An improvement in the rule trace was suggested by Sramji

+      Ramanathan (ps@kumaran.com).

+

+#108. A Note on Deallocation of Variables Allocated in Guess Mode

+

+                            NOTE

+        ------------------------------------------------------

+        This mechanism only works for heap allocated variables

+        ------------------------------------------------------

+

+      The rewrite of the trace provides the machinery necessary

+      to properly free variables or undo actions following a

+      failed guess.

+

+      The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded

+      as part of the zzGUESS macro.  When a guess is opened

+      the value of zzrv is 0.  When a longjmp() is executed to

+      undo the guess, the value of zzrv will be 1.

+

+      The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded

+      as part of the zzGUESS_DONE macro.  This is executed

+      whether the guess succeeds or fails as part of closing

+      the guess.

+

+      The guessSeq is a sequence number which is assigned to each

+      guess and is incremented by 1 for each guess which becomes

+      active.  It is needed by the user to associate the start of

+      a guess with the failure and/or completion (closing) of a

+      guess.

+

+      Guesses are nested.  They must be closed in the reverse

+      of the order that they are opened.

+

+      In order to free memory used by a variable during a guess

+      a user must write a routine which can be called to

+      register the variable along with the current guess sequence

+      number provided by the zzUSER_GUESS_HOOK macro. If the guess

+      fails, all variables tagged with the corresponding guess

+      sequence number should be released.  This is ugly, but

+      it would require a major rewrite of antlr 1.33 to use

+      some mechanism other than setjmp()/longjmp().

+

+      The order of calls for a *successful* guess would be:

+

+        zzUSER_GUESS_HOOK(guessSeq,0);

+        zzUSER_GUESS_DONE_HOOK(guessSeq);

+

+      The order of calls for a *failed* guess would be:

+

+        zzUSER_GUESS_HOOK(guessSeq,0);

+        zzUSER_GUESS_HOOK(guessSeq,1);

+        zzUSER_GUESS_DONE_HOOK(guessSeq);

+

+      The default definitions of these macros are empty strings.

+

+      Here is an example in C++ mode.  The zzUSER_GUESS_HOOK and

+      zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine

+      can be used without change in both C and C++ versions.

+

+      ----------------------------------------------------------------------

+        <<

+

+        #include "AToken.h"

+

+        typedef ANTLRCommonToken ANTLRToken;

+

+        #include "DLGLexer.h"

+

+        int main() {

+

+          {

+            DLGFileInput     in(stdin);

+            DLGLexer         lexer(&in,2000);

+            ANTLRTokenBuffer pipe(&lexer,1);

+            ANTLRCommonToken aToken;

+            P                parser(&pipe);

+

+            lexer.setToken(&aToken);

+            parser.init();

+            parser.start();

+          };

+

+          fclose(stdin);

+          fclose(stdout);

+          return 0;

+        }

+

+        >>

+

+        <<

+        char *s=NULL;

+

+        #undef zzUSER_GUESS_HOOK

+        #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv);

+        #undef zzUSER_GUESS_DONE_HOOK

+        #define zzUSER_GUESS_DONE_HOOK(guessSeq)   myGuessHook(guessSeq,2);

+

+        void myGuessHook(int guessSeq,int zzrv) {

+          if (zzrv == 0) {

+            fprintf(stderr,"User hook: starting guess #%d\n",guessSeq);

+          } else if (zzrv == 1) {

+            free (s);

+            s=NULL;

+            fprintf(stderr,"User hook: failed guess #%d\n",guessSeq);

+          } else if (zzrv == 2) {

+            free (s);

+            s=NULL;

+            fprintf(stderr,"User hook: ending guess #%d\n",guessSeq);

+          };

+        }

+

+        >>

+

+        #token A    "a"

+        #token      "[\t \ \n]"     <<skip();>>

+

+        class P {

+

+        start : (top)+

+              ;

+

+        top   : (which) ?   <<fprintf(stderr,"%s is a which\n",s); free(s); s=NULL; >>

+              | other       <<fprintf(stderr,"%s is an other\n",s); free(s); s=NULL; >>

+              ; <<if (s != NULL) free(s); s=NULL; >>

+

+        which : which2

+              ;

+

+        which2 : which3

+              ;

+        which3

+              : (label)?         <<fprintf(stderr,"%s is a label\n",s);>>

+              | (global)?        <<fprintf(stderr,"%s is a global\n",s);>>

+              | (exclamation)?   <<fprintf(stderr,"%s is an exclamation\n",s);>>

+              ;

+

+        label :       <<s=strdup(LT(1)->getText());>> A ":" ;

+

+        global :      <<s=strdup(LT(1)->getText());>> A "::" ;

+

+        exclamation : <<s=strdup(LT(1)->getText());>> A "!" ;

+

+        other :       <<s=strdup(LT(1)->getText());>> "other" ;

+

+        }

+      ----------------------------------------------------------------------

+

+      This is a silly example, but illustrates the idea.  For the input

+      "a ::" with tracing enabled the output begins:

+

+      ----------------------------------------------------------------------

+        enter rule "start" depth 1

+        enter rule "top" depth 2

+        User hook: starting guess #1

+        enter rule "which" depth 3 guessing

+        enter rule "which2" depth 4 guessing

+        enter rule "which3" depth 5 guessing

+        User hook: starting guess #2

+        enter rule "label" depth 6 guessing

+        guess failed

+        User hook: failed guess #2

+        guess done - returning to rule "which3" at depth 5 (guess mode continues

+                                                 - an enclosing guess is still active)

+        User hook: ending guess #2

+        User hook: starting guess #3

+        enter rule "global" depth 6 guessing

+        exit rule "global" depth 6 guessing

+        guess done - returning to rule "which3" at depth 5 (guess mode continues

+                                                 - an enclosing guess is still active)

+        User hook: ending guess #3

+        enter rule "global" depth 6 guessing

+        exit rule "global" depth 6 guessing

+        exit rule "which3" depth 5 guessing

+        exit rule "which2" depth 4 guessing

+        exit rule "which" depth 3 guessing

+        guess done - returning to rule "top" at depth 2 (guess mode ends)

+        User hook: ending guess #1

+        enter rule "which" depth 3

+        .....

+      ----------------------------------------------------------------------

+

+      Remember:

+

+        (a) Only init-actions are executed during guess mode.

+        (b) A rule can be invoked multiple times during guess mode.

+        (c) If the guess succeeds the rule will be called once more

+              without guess mode so that normal actions will be executed.

+            This means that the init-action might need to distinguish

+              between guess mode and non-guess mode using the variable

+              [zz]guessing.

+

+#107. (Changed in 1.33MR10) construction of ASTs in guess mode

+

+      Prior to 1.33MR10, when using automatic AST construction in C++

+      mode for a rule, an AST would be constructed for elements of the

+      rule even while in guess mode.  In MR10 this no longer occurs.

+

+#106. (Changed in 1.33MR10) guess variable confusion

+

+      In C++ mode a guess which failed always restored the parser state

+      using zzGUESS_DONE as part of zzGUESS_FAIL. Prior to 1.33MR10,

+      C mode required an explicit call to zzGUESS_DONE after the

+      call to zzGUESS_FAIL.

+

+      Consider:

+

+        rule : (alpha)? beta

+             | ...

+             ;

+

+      The generated code resembles:

+

+            zzGUESS

+            if (!zzrv && LA(1)==ID) {   <==== line #1

+                alpha

+                zzGUESS_DONE

+                beta

+            } else {

+              if (! zzrv) zzGUESS_DONE  <==== line #2a

+              ....

+

+      However, in some cases line #2 was rendered:

+

+              if (guessing) zzGUESS_DONE  <==== line #2b

+

+      This would work for simple test cases, but would fail in

+      some cases where there was a guess while another guess was active.

+      One kind of failure would be to match up the zzGUESS_DONE at line

+      #2b with the "outer" guess which was still active.  The outer

+      guess would "succeed" when only the inner guess should have

+      succeeded.

+

+      In 1.33MR10 the behavior of zzGUESS and zzGUESS_FAIL in C and

+      and C++ mode should be identical.

+

+      The same problem appears in 1.33 vanilla in some places.  For

+      example:

+

+            start : { (sub)? } ;

+

+      or:

+

+            start : (

+                       B

+                    |  ( sub )?

+                    |  C

+                    )+

+                    ;

+

+      generates incorrect code.

+

+      The general principle is:

+

+        (a) use [zz]guessing only when deciding between a call to zzFAIL

+              or zzGUESS_FAIL

+

+        (b) use zzrv in all other cases

+

+      This problem was discovered while testing changes to item #105.

+      I believe this is now fixed.  My apologies.

+

+#105. (Changed in 1.33MR10) guess block as single alt of (...)+

+

+      Prior to 1.33MR10 the following constructs:

+

+        rule_plus : (

+                       (sub)?

+                    )+

+                    ;

+

+        rule_star : (

+                      (sub)?

+                    )*

+                    ;

+

+      generated incorrect code for the guess block (which could result

+      in runtime errors) because of an incorrect optimization of a

+      block with only a single alternative.

+

+      The fix caused some changes to the fix described in Item #49

+      because there are now three code generation sequences for (...)+

+      blocks containing a guess block:

+

+        a. single alternative which is a guess block

+        b. multiple alternatives in which the last is a guess block

+        c. all other cases

+

+      Forms like "rule_star" can have unexpected behavior when there

+      is a syntax error: if the subrule "sub" is not matched *exactly*

+      then "rule_star" will consume no tokens.

+

+      Reported by Esa Pulkkinen (esap@cs.tut.fi).

+

+#104. (Changed in 1.33MR10) -o option for dlg

+

+      There was problem with the code added by item #74 to handle the

+      -o option of dlg.  This should fix it.

+

+#103. (Changed in 1.33MR10) ANDed semantic predicates

+

+      Rescinded.

+

+      The optimization was a mistake.

+      The resulting problem is described in Item #150.

+

+#102. (Changed in 1.33MR10) allow "class parser : .... {"

+

+      The syntax of the class statement ("class parser-name {")

+      has been extended to allow for the specification of base

+      classes.  An arbirtrary number of tokens may now appear

+      between the class name and the "{".  They are output

+      again when the class declaration is generated.  For

+      example:

+

+        class Parser : public MyBaseClassANTLRparser {

+

+      This was suggested by a user, but I don't have a record

+      of who it was.

+

+#101. (Changed in 1.33MR10) antlr -info command line switch

+

+        -info

+

+            p   - extra predicate information in generated file

+

+            t   - information about tnode use:

+                    at the end of each rule in generated file

+                    summary on stderr at end of program

+

+            m   - monitor progress

+                    prints name of each rule as it is started

+                    flushes output at start of each rule

+

+            f   - first/follow set information to stdout

+

+            0   - no operation (added in 1.33MR11)

+

+      The options may be combined and may appear in any order.

+      For example:

+

+        antlr -info ptm -CC -gt -mrhoist on mygrammar.g

+

+#100a. (Changed in 1.33MR10) Predicate tree simplification

+

+      When the same predicates can be referenced in more than one

+      alternative of a block large predicate trees can be formed.

+

+      The difference that these optimizations make is so dramatic

+      that I have decided to use it even when -mrhoist is not selected.

+

+      Consider the following grammar:

+

+        start : ( all )* ;

+

+        all   : a

+              | d

+              | e

+              | f

+              ;

+

+        a     : c A B

+              | c A C

+              ;

+

+        c     : <<AAA(LATEXT(2))>>?

+              ;

+

+        d     : <<BBB(LATEXT(2))>>? B C

+              ;

+

+        e     : <<CCC(LATEXT(2))>>? B C

+              ;

+

+        f     : e X Y

+              ;

+

+      In rule "a" there is a reference to rule "c" in both alternatives.

+      The length of the predicate AAA is k=2 and it can be followed in

+      alternative 1 only by (A B) while in alternative 2 it can be

+      followed only by (A C).  Thus they do not have identical context.

+

+      In rule "all" the alternatives which refer to rules "e" and "f" allow

+      elimination of the duplicate reference to predicate CCC.

+

+      The table below summarized the kind of simplification performed by

+      1.33MR10.  In the table, X and Y stand for single predicates

+      (not trees).

+

+        (OR X (OR Y (OR Z)))  => (OR X Y Z)

+        (AND X (AND Y (AND Z)))  => (AND X Y Z)

+

+        (OR X  (... (OR  X Y) ... ))     => (OR X (... Y ... ))

+        (AND X (... (AND X Y) ... ))     => (AND X (... Y ... ))

+        (OR X  (... (AND X Y) ... ))     => (OR X (...  ... ))

+        (AND X (... (OR  X Y) ... ))     => (AND X (...  ... ))

+

+        (AND X)               => X

+        (OR X)                => X

+

+      In a test with a complex grammar for a real application, a predicate

+      tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)".

+

+      In 1.33MR10 there is a greater effort to release memory used

+      by predicates once they are no longer in use.

+

+#100b. (Changed in 1.33MR10) Suppression of extra predicate tests

+

+      The following optimizations require that -mrhoist be selected.

+

+      It is relatively easy to optimize the code generated for predicate

+      gates when they are of the form:

+

+            (AND X Y Z ...)

+        or  (OR  X Y Z ...)

+

+      where X, Y, Z, and "..." represent individual predicates (leaves) not

+      predicate trees.

+

+      If the predicate is an AND the contexts of the X, Y, Z, etc. are

+      ANDed together to create a single Tree context for the group and

+      context tests for the individual predicates are suppressed:

+

+            --------------------------------------------------

+            Note: This was incorrect.  The contexts should be

+            ORed together.  This has been fixed.  A more 

+            complete description is available in item #152.

+            ---------------------------------------------------

+

+      Optimization 1:  (AND X Y Z ...)

+

+        Suppose the context for Xtest is LA(1)==LP and the context for

+        Ytest is LA(1)==LP && LA(2)==ID.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    !(LA(1)==LP && LA(1)==LP && LA(2)==ID) ||

+                        ( (! LA(1)==LP || Xtest) &&

+                          (! (LA(1)==LP || LA(2)==ID) || Xtest)

+                        )) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {...

+

+      Optimization 2: (OR X Y Z ...) with identical contexts

+

+        Suppose the context for Xtest is LA(1)==ID and for Ytest

+        the context is also LA(1)==ID.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==ID || LA(1)==ID) ||

+                        (LA(1)==ID && Xtest) ||

+                        (LA(1)==ID && Ytest) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    (! LA(1)==ID) || (Xtest || Ytest) {...

+

+      Optimization 3: (OR X Y Z ...) with distinct contexts

+

+        Suppose the context for Xtest is LA(1)==ID and for Ytest

+        the context is LA(1)==LP.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==ID || LA(1)==LP) ||

+                        (LA(1)==ID && Xtest) ||

+                        (LA(1)==LP && Ytest) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                        (zzpf=0,

+                            (LA(1)==ID && (zzpf=1) && Xtest) ||

+                            (LA(1)==LP && (zzpf=1) && Ytest) ||

+                            !zzpf) {

+

+            These may appear to be of similar complexity at first,

+            but the non-optimized version contains two tests of each

+            context while the optimized version contains only one

+            such test, as well as eliminating some of the inverted

+            logic (" !(...) || ").

+

+      Optimization 4: Computation of predicate gate trees

+

+        When generating code for the gates of predicate expressions

+        antlr 1.33 vanilla uses a recursive procedure to generate

+        "&&" and "||" expressions for testing the lookahead. As each

+        layer of the predicate tree is exposed a new set of "&&" and

+        "||" expressions on the lookahead are generated.  In many

+        cases the lookahead being tested has already been tested.

+

+        With -mrhoist a lookahead tree is computed for the entire

+        lookahead expression.  This means that predicates with identical

+        context or context which is a subset of another predicate's

+        context disappear.

+

+        This is especially important for predicates formed by rules

+        like the following:

+

+            uppperCaseVowel : <<isUpperCase(LATEXT(1))>>?  vowel;

+            vowel:          : <<isVowel(LATEXT(1))>>? LETTERS;

+

+        These predicates are combined using AND since both must be

+        satisfied for rule upperCaseVowel.  They have identical

+        context which makes this optimization very effective.

+

+      The affect of Items #100a and #100b together can be dramatic.  In

+      a very large (but real world) grammar one particular predicate

+      expression was reduced from an (unreadable) 50 predicate leaves,

+      195 LA(1) terms, and 5500 characters to an (easily comprehensible)

+      3 predicate leaves (all different) and a *single* LA(1) term.

+

+#99.  (Changed in 1.33MR10) Code generation for expression trees

+

+      Expression trees are used for k>1 grammars and predicates with

+      lookahead depth >1.  This optimization must be enabled using

+      "-mrhoist on".  (Clarification added for 1.33MR11).

+

+      In the processing of expression trees, antlr can generate long chains

+      of token comparisons.  Prior to 1.33MR10 there were many redundant

+      parenthesis which caused problems for compilers which could handle

+      expressions of only limited complexity.  For example, to test an

+      expression tree (root R A B C D), antlr would generate something

+      resembling:

+

+        (LA(1)==R && (LA(2)==A || (LA(2)==B || (LA(2)==C || LA(2)==D)))))

+

+      If there were twenty tokens to test then there would be twenty

+      parenthesis at the end of the expression.

+

+      In 1.33MR10 the generated code for tree expressions resembles:

+

+        (LA(1)==R && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D))

+

+      For "complex" expressions the output is indented to reflect the LA

+      number being tested:

+

+        (LA(1)==R

+            && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D

+               || LA(2)==E || LA(2)==F)

+        || LA(1)==S

+            && (LA(2)==G || LA(2)==H))

+

+

+      Suggested by S. Bochnak (S.Bochnak@@microTool.com.pl),

+

+#98.  (Changed in 1.33MR10) Option "-info p"

+

+      When the user selects option "-info p" the program will generate

+      detailed information about predicates.  If the user selects

+      "-mrhoist on" additional detail will be provided explaining

+      the promotion and suppression of predicates.  The output is part

+      of the generated file and sandwiched between #if 0/#endif statements.

+

+      Consider the following k=1 grammar:

+

+        start : ( all ) * ;

+

+        all   : ( a

+                | b

+                )

+                ;

+

+        a     : c B

+              ;

+

+        c     : <<LATEXT(1)>>?

+              | B

+              ;

+

+        b     : <<LATEXT(1)>>? X

+              ;

+

+      Below is an excerpt of the output for rule "start" for the three

+      predicate options (off, on, and maintenance release style hoisting).

+

+      For those who do not wish to use the "-mrhoist on" option for code

+      generation the option can be used in a "diagnostic" mode to provide

+      valuable information:

+

+            a. where one should insert null actions to inhibit hoisting

+            b. a chain of rule references which shows where predicates are

+               being hoisted

+

+      ======================================================================

+      Example of "-info p" with "-mrhoist on"

+      ======================================================================

+        #if 0

+

+        Hoisting of predicate suppressed by alternative without predicate.

+        The alt without the predicate includes all cases where the

+           predicate is false.

+

+           WITH predicate: line 11  v36.g

+           WITHOUT predicate: line 12  v36.g

+

+        The context set for the predicate:

+

+             B

+

+        The lookahead set for alt WITHOUT the semantic predicate:

+

+             B

+

+        The predicate:

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+               B

+            tree context: null

+

+        Chain of referenced rules:

+

+            #0  in rule start (line 1 v36.g) to rule all

+            #1  in rule all (line 3 v36.g) to rule a

+            #2  in rule a (line 8 v36.g) to rule c

+            #3  in rule c (line 11 v36.g)

+

+        #endif

+        &&

+        #if 0

+

+        pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+          set context:

+             X

+          tree context: null

+

+        #endif

+      ======================================================================

+      Example of "-info p"  with the default -prc setting ( "-prc off")

+      ======================================================================

+        #if 0

+

+        OR

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+              nil

+            tree context: null

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+            set context:

+              nil

+            tree context: null

+

+        #endif

+      ======================================================================

+      Example of "-info p" with "-prc on" and "-mrhoist off"

+      ======================================================================

+        #if 0

+

+        OR

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+               B

+            tree context: null

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+            set context:

+               X

+            tree context: null

+

+        #endif

+      ======================================================================

+

+#97.  (Fixed in 1.33MR10) "Predicate applied for more than one ... "

+

+      In 1.33 vanilla, the grammar listed below produced this message for

+      the first alternative (only) of rule "b":

+

+            warning: predicate applied for >1 lookahead 1-sequences

+                [you may only want one lookahead 1-sequence to apply.

+                Try using a context guard '(...)? =>'

+

+      In 1.33MR10 the message is issued for both alternatives.

+

+          top     : (a)*;

+          a       : b | c ;

+

+          b       : <<PPP(LATEXT(1))>>? ( AAA | BBB )

+                  | <<QQQ(LATEXT(1))>>? ( XXX | YYY )

+                  ;

+

+          c       : AAA | XXX;

+

+#96.  (Fixed in 1.33MR10) Guard predicates ignored when -prc off

+

+      Prior to 1.33MR10, guard predicate code was not generated unless

+      "-prc on" was selected.

+

+      This was incorrect, since "-prc off"  (the default) is supposed to

+      disable only AUTOMATIC computation of predicate context, not the

+      programmer specified context supplied by guard predicates.

+

+#95.  (Fixed in 1.33MR10) Predicate guard context length was k, not max(k,ck)

+

+      Prior to 1.33MR10, predicate guards were computed to k tokens rather

+      than max(k,ck).  Consider the following grammar:

+

+        a     : ( A B C)? => <<AAA(LATEXT(1))>>? (A|X) (B|Y) (C|Z) ;

+

+      The code generated by 1.33 vanilla with "-k 1 -ck 3 -prc on"

+      for the predicate in "a" resembles:

+

+        if ( (! LA(1)==A) || AAA(LATEXT(1))) {...

+

+      With 1.33MR10 and the same options the code resembles:

+

+        if ( (! (LA(1)==A && LA(2)==B && LA(3)==C) || AAA(LATEXT(1))) {...

+

+#94.  (Fixed in 1.33MR10) Predicates followed by rule references

+

+      Prior to 1.33MR10, a semantic predicate which referenced a token

+      which was off the end of the rule caused an incomplete context

+      to be computed (with "-prc on") for the predicate under some circum-

+      stances.  In some cases this manifested itself as illegal C code

+      (e.g. "LA(2)==[Ep](1)" in the k=2 examples below:

+

+          all     : ( a ) *;

+

+          a       : <<AAA(LATEXT(2))>>? ID X

+                  | <<BBB(LATEXT(2))>>? Y

+                  | Z

+                  ;

+

+      This might also occur when the semantic predicate was followed

+      by a rule reference which was shorter than the length of the

+      semantic predicate:

+

+        all       : ( a ) *;

+

+        a         : <<AAA(LATEXT(2))>>? ID X

+                  | <<BBB(LATEXT(2))>>? y

+                  | Z

+                  ;

+

+        y         : Y ;

+

+      Depending on circumstance, the resulting context might be too

+      generous because it was too short, or too restrictive because

+      of missing alternatives.

+

+#93.  (Changed in 1.33MR10) Definition of Purify macro

+

+      Ofer Ben-Ami (gremlin@cs.huji.ac.il) has supplied a definition

+      for the Purify macro:

+

+        #define PURIFY(r, s) memset((char *) &(r), '\0', (s));

+

+      Note: This may not be the right thing to do for C++ objects that

+      have constructors.  Reported by Bonny Rais (bonny@werple.net.au).

+

+      For those cases one should #define PURIFY to an empty macro in the

+      #header or #first actions.

+

+#92.  (Fixed in 1.33MR10) Guarded predicates and hoisting

+

+      When a guarded predicate participates in hoisting it is linked into

+      a predicate expression tree.  Prior to 1.33MR10 this link was never

+      cleared and the next time the guard was used to construct a new

+      tree the link could contain a spurious reference to another element

+      which had previosly been joined to it in the semantic predicate tree.

+

+      For example:

+

+        start  : ( all ) *;

+        all    : ( a | b ) ;

+

+        start2 : ( all2 ) *;

+        all2    : ( a ) ;

+

+        a     : (A)? => <<AAA(LATEXT(1))>>?  A ;

+        b     : (B)? => <<BBB(LATEXT(1))>>?  B ;

+

+      Prior to 1.33MR10 the code for "start2" would include a spurious

+      reference to the BBB predicate which was left from constructing

+      the predicate tree for rule "start" (i.e. or(AAA,BBB) ).

+

+      In 1.33MR10 this problem is avoided by cloning the original guard

+      each time it is linked into a predicate tree.

+

+#91.  (Changed in 1.33MR10) Extensive changes to semantic pred hoisting

+

+            ============================================

+            This has been rendered obsolete by Item #117

+            ============================================

+

+#90.  (Fixed in 1.33MR10) Semantic pred with LT(i) and i>max(k,ck)

+

+      There is a bug in antlr 1.33 vanilla and all maintenance releases

+      prior to 1.33MR10 which allows semantic predicates to reference

+      an LT(i) or LATEXT(i) where i is larger than max(k,ck).  When

+      this occurs antlr will attempt to mark the ith element of an array

+      in which there are only max(k,ck) elements.  The result cannot

+      be predicted.

+

+      Using LT(i) or LATEXT(i) for i>max(k,ck) is reported as an error

+      in 1.33MR10.

+

+#89.  Rescinded

+

+#88.  (Fixed in 1.33MR10) Tokens used in semantic predicates in guess mode

+

+        Consider the behavior of a semantic predicate during guess mode:

+

+            rule : a:A (

+                         <<test($a)>>? b:B

+                         | c:C

+                       );

+

+        Prior to MR10 the assignment of the token or attribute to

+        $a did not occur during guess mode, which would cause the

+        semantic predicate to misbehave because $a would be null.

+

+        In 1.33MR10 a semantic predicate with a reference to an

+        element label (such as $a) forces the assignment to take

+        place even in guess mode.

+

+        In order to work, this fix REQUIRES use of the $label format

+        for token pointers and attributes referenced in semantic

+        predicates.

+

+        The fix does not apply to semantic predicates using the

+        numeric form to refer to attributes (e.g. <<test($1)>>?).

+        The user will receive a warning for this case.

+

+        Reported by Rob Trout (trout@mcs.cs.kent.edu).

+

+#87.  (Fixed in 1.33MR10) Malformed guard predicates

+

+      Context guard predicates may contain only references to

+      tokens.  They may not contain references to (...)+ and

+      (...)* blocks.  This is now checked.  This replaces the

+      fatal error message in item #78 with an appropriate

+      (non-fatal) error messge.

+

+      In theory, context guards should be allowed to reference

+      rules.  However, I have not had time to fix this.

+      Evaluation of the guard takes place before all rules have

+      been read, making it difficult to resolve a forward reference

+      to rule "zzz" - it hasn't been read yet !  To postpone evaluation

+      of the guard until all rules have been read is too much

+      for the moment.

+

+#86.  (Fixed in 1.33MR10) Unequal set size in set_sub

+

+      Routine set_sub() in pccts/support/set/set.h  did not work

+      correctly when the sets were of unequal sizes.  Rewrote

+      set_equ to make it simpler and remove unnecessary and

+      expensive calls to set_deg().  This routine was not used

+      in 1.33 vanila.

+

+#85.  (Changed in 1.33MR10) Allow redefinition of MaxNumFiles

+

+      Raised the maximum number of input files to 99 from 20.

+      Put a #ifndef/#endif around the "#define MaxNumFiles 99".

+

+#84.  (Fixed in 1.33MR10) Initialize zzBadTok in macro zzRULE

+

+      Initialize zzBadTok to NULL in zzRULE macro of AParser.h.

+      in order to get rid of warning messages.

+

+#83.  (Fixed in 1.33MR10) False warnings with -w2 for #tokclass

+

+      When -w2 is selected antlr gives inappropriate warnings about

+      #tokclass names not having any associated regular expressions.

+      Since a #tokclass is not a "real" token it will never have an

+      associated regular expression and there should be no warning.

+

+      Reported by Derek Pappas (derek.pappas@eng.sun.com)

+

+#82.  (Fixed in 1.33MR10) Computation of follow sets with multiple cycles

+

+      Reinier van den Born (reinier@vnet.ibm.com) reported a problem

+      in the computation of follow sets by antlr.  The problem (bug)

+      exists in 1.33 vanilla and all maintenance releases prior to 1.33MR10.

+

+      The problem involves the computation of follow sets when there are

+      cycles - rules which have mutual references.  I believe the problem

+      is restricted to cases where there is  more than one cycle AND

+      elements of those cycles have rules in common.  Even when this

+      occurs it may not affect the code generated - but it might.  It

+      might also lead to undetected ambiguities.

+

+      There were no changes in antlr or dlg output from the revised version.

+

+      The following fragment demonstates the problem by giving different

+      follow sets (option -pa) for var_access when built with k=1 and ck=2 on

+      1.33 vanilla and 1.33MR10:

+

+        echo_statement : ECHO ( echo_expr )*

+                       ;

+

+        echo_expr      : ( command )?

+                       | expression

+                       ;

+

+        command        : IDENTIFIER

+                             { concat }

+                       ;

+

+        expression     : operand ( OPERATOR operand )*

+                       ;

+

+        operand        : value

+                       | START command END

+                       ;

+

+        value          : concat

+                       | TYPE operand

+                       ;

+

+        concat         : var_access { CONCAT value }

+                       ;

+

+        var_access     : IDENTIFIER { INDEX }

+

+                       ;

+#81.  (Changed in 1.33MR10) C mode use of attributes and ASTs

+

+       Reported by Isaac Clark (irclark@mindspring.com).

+

+       C mode code ignores attributes returned by rules which are

+       referenced using element labels when ASTs are enabled (-gt option).

+

+         1. start : r:rule t:Token <<$start=$r;>>

+

+                The $r refrence will not work when combined with

+                the -gt option.

+

+         2. start : t:Token         <<$start=$t;>>

+

+                The $t reference works in all cases.

+

+         3. start : rule            <<$0=$1;>>

+

+                Numeric labels work in all cases.

+

+       With MR10 the user will receive an error message for case 1 when

+       the -gt option is used.

+

+#80.  (Fixed in 1.33MR10) (...)? as last alternative of block

+

+        A construct like the following:

+

+            rule : a

+                 | (b)?

+                 ;

+

+        does not make sense because there is no alternative when

+        the guess block fails.  This is now reported as a warning

+        to the user.

+

+        Previously, there was a code generation error for this case:

+        the guess block was not "closed"  when the guess failed.

+        This could cause an infinite loop or other problems.  This

+        is now fixed.

+

+        Example problem:

+

+            #header<<

+            #include <stdio.h>

+            #include "charptr.h"

+            >>

+

+            <<

+            #include "charptr.c"

+            main ()

+            {

+             ANTLR(start(),stdin);

+            }

+            >>

+

+            #token "[\ \t]+"        << zzskip(); >>

+            #token "[\n]"           << zzline++; zzskip(); >>

+

+            #token Word     "[a-z]+"

+            #token Number   "[0-9]+"

+

+

+            start : (test1)?

+                  | (test2)?

+                  ;

+            test1 : (Word Word Word Word)?

+                  | (Word Word Word Number)?

+                  ;

+            test2 : (Word Word Number Word)?

+                  | (Word Word Number Number)?

+            ;

+

+        Test data which caused infinite loop:

+

+            a 1 a a

+

+#79.  (Changed in 1.33MR10) Use of -fh with multiple parsers

+

+        Previously, antlr always used the pre-processor symbol

+        STDPCCTS_H as a gate for the file stdpccts.h.  This

+        caused problems when there were multiple parsers defined

+        because they used the same gate symbol.

+

+        In 1.33MR10, the -fh filename is used to generate the

+        gate file for stdpccts.h.  For instance:

+

+            antlr -fh std_parser1.h

+

+        generates the pre-processor symbol "STDPCCTS_std_parser1_H".

+

+        Reported by Ramanathan Santhanam (ps@kumaran.com).

+

+#78.  (Changed in 1.33MR9) Guard predicates that refer to rules

+

+                ------------------------

+                Please refer to Item #87

+                ------------------------

+

+        Guard predicates are processed during an early phase

+        of antlr (during parsing) before all data structures

+        are completed.

+

+        There is an apparent bug in earlier versions of 1.33

+        which caused guard predicates which contained references

+        to rules (rather than tokens) to reference a structure

+        which hadn't yet been initialized.

+

+        In some cases (perhaps all cases) references to rules

+        in guard predicates resulted in the use of "garbage".

+

+#79.  (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)

+

+        Previously, the maximum length file name was set

+        arbitrarily to 300 characters in antlr, dlg, and sorcerer.

+

+        The config.h file now attempts to define the maximum length

+        filename using _MAX_PATH from stdlib.h before falling back

+        to using the value 300.

+

+#78.  (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)

+

+        Put #ifndef/#endif around definition of ZZLEXBUFSIZE in

+        antlr.

+

+#77.  (Changed in 1.33MR9) Arithmetic overflow for very large grammars

+

+        In routine HandleAmbiguities() antlr attempts to compute the

+        number of possible elements in a set that is order of

+        number-of-tokens raised to the number-of-lookahead-tokens power.

+        For large grammars or large lookahead (e.g. -ck 7) this can

+        cause arithmetic overflow.

+

+        With 1.33MR9, arithmetic overflow in this computation is reported

+        the first time it happens.  The program continues to run and

+        the program branches based on the assumption that the computed

+        value is larger than any number computed by counting actual cases

+        because 2**31 is larger than the number of bits in most computers.

+

+        Before 1.33MR9 overflow was not reported.  The behavior following

+        overflow is not predictable by anyone but the original author.

+

+                            NOTE

+

+            In 1.33MR10 the warning message is suppressed.

+            The code which detects the overflow allows the

+            computation to continue without an error.  The

+            error message itself made made users worry.

+

+#76.  (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)

+

+        Jeff Vincent has convinced me to make ANTLRCommonToken and

+        ANTLRCommonNoRefCountToken use variable length strings

+        allocated from the heap rather than fixed length strings.

+        By suitable definition of setText(), the copy constructor,

+        and operator =() it is possible to maintain "copy" semantics.

+        By "copy" semantics I mean that when a token is copied from

+        an existing token it receives its own, distinct, copy of the

+        text allocated from the heap rather than simply a pointer

+        to the original token's text.

+

+        ============================================================

+                        W * A * R * N * I * N * G

+        ============================================================

+

+        It is possible that this may cause problems for some users.

+        For those users I have included the old version of AToken.h as

+        pccts/h/AToken_traditional.h.

+

+#75.  (Changed in 1.33MR9) Bruce Guenter (bruceg@qcc.sk.ca)

+

+        Make DLGStringInput const correct.  Since this is infrequently

+        subclassed, it should affect few users, I hope.

+

+#74.  (Changed in 1.33MR9) -o (output directory) option

+

+        Antlr does not properly handle the -o output directory option

+        when the filename of the grammar contains a directory part.  For

+        example:

+

+            antlr -o outdir pccts_src/myfile.g

+

+        causes antlr create a file called "outdir/pccts_src/myfile.cpp.

+        It SHOULD create outdir/myfile.cpp

+

+        The suggested code fix has been installed in antlr, dlg, and

+        Sorcerer.

+

+#73.  (Changed in 1.33MR9) Hoisting of semantic predicates and -mrhoist

+

+            ============================================

+            This has been rendered obsolete by Item #117

+            ============================================

+

+#72.  (Changed in 1.33MR9) virtual saveState()/restoreState()/guess_XXX

+

+        The following methods in ANTLRParser were made virtual at

+        the request of S. Bochnak (S.Bochnak@microTool.com.pl):

+

+            saveState() and restoreState()

+            guess(), guess_fail(), and guess_done()

+

+#71.  (Changed in 1.33MR9) Access to omitted command line argument

+

+        If a switch requiring arguments is the last thing on the

+        command line, and the argument is omitted, antlr would core.

+

+            antlr test.g -prc

+

+        instead of

+

+            antlr test.g -prc off

+

+#70.  (Changed in 1.33MR9) Addition of MSVC .dsp and .mak build files

+

+        The following MSVC .dsp and .mak files for pccts and sorcerer

+        were contributed by Stanislaw Bochnak (S.Bochnak@microTool.com.pl)

+        and Jeff Vincent (JVincent@novell.com)

+

+        PCCTS Distribution Kit

+        ----------------------

+        pccts/PCCTSMSVC50.dsw

+

+        pccts/antlr/AntlrMSVC50.dsp

+        pccts/antlr/AntlrMSVC50.mak

+

+        pccts/dlg/DlgMSVC50.dsp

+        pccts/dlg/DlgMSVC50.mak

+

+        pccts/support/msvc.dsp

+

+        Sorcerer Distribution Kit

+        -------------------------

+        pccts/sorcerer/SorcererMSVC50.dsp

+        pccts/sorcerer/SorcererMSVC50.mak

+

+        pccts/sorcerer/lib/msvc.dsp

+

+#69.  (Changed in 1.33MR9) Change "unsigned int" to plain "int"

+

+       Declaration of max_token_num in misc.c as "unsigned int"

+       caused comparison between signed and unsigned ints giving

+       warning message without any special benefit.

+

+#68.  (Changed in 1.33MR9) Add void return for dlg internal_error()

+

+       Get rid of "no return value" message in internal_error()

+       in file dlg/support.c and dlg/dlg.h.

+

+#67.  (Changed in Sor) sor.g: lisp() has no return value

+

+       Added a "void" for the return type.

+

+#66.  (Added to Sor) sor.g: ZZLEXBUFSIZE enclosed in #ifndef/#endif

+

+       A user needed to be able to change the ZZLEXBUFSIZE for

+       sor. Put the definition of ZZLEXBUFSIZE inside #ifndef/#endif

+

+#65.  (Changed in 1.33MR9) PCCTSAST::deepCopy() and ast_dup() bug

+

+       Jeff Vincent (JVincent@novell.com) found that deepCopy()

+       made new copies of only the direct descendents.  No new

+       copies were made of sibling nodes,  Sibling pointers are

+       set to zero by shallowCopy().

+

+           PCCTS_AST::deepCopy() has been changed to make a

+           deep copy in the traditional sense.

+

+           The deepCopy() routine depends on the behavior of

+           shallowCopy().  In all sor examples I've found,

+           shallowCopy() zeroes the right and down pointers.

+

+       Original Tree       Original deepCopy()     Revised deepCopy

+       -------------       -------------------     ----------------

+            a->b->c         A                       A

+            |               |                       |

+            d->e->f         D                       D->E->F

+            |               |                       |

+            g->h->i         G                       G->H->I

+               |                                       |

+               j->k                                    J->K

+

+        While comparing deepCopy() for C++ mode with ast_dup for

+        C mode I found a problem with ast_dup().

+

+           Routine ast_dup() has been changed to make a deep copy

+           in the traditional sense.

+

+       Original Tree       Original ast_dup()      Revised ast_dup()

+       -------------       -------------------     ----------------

+            a->b->c         A->B->C                 A

+            |               |                       |

+            d->e->f         D->E->F                 D->E->F

+            |               |                       |

+            g->h->i         G->H->I                 G->H->I

+               |               |                       |

+               j->k            J->K                    J->K

+

+

+        I believe this affects transform mode sorcerer programs only.

+

+#64.  (Changed in 1.33MR9) anltr/hash.h prototype for killHashTable()

+

+#63.  (Changed in 1.33MR8) h/charptr.h does not zero pointer after free

+

+        The charptr.h routine now zeroes the pointer after free().

+

+        Reported by Jens Tingleff (jensting@imaginet.fr)

+

+#62.  (Changed in 1.33MR8) ANTLRParser::resynch had static variable

+

+        The static variable "consumed" in ANTLRParser::resynch was

+        changed into an instance variable of the class with the

+        name "resynchConsumed".

+

+        Reported by S.Bochnak@microTool.com.pl

+

+#61.  (Changed in 1.33MR8) Using rule>[i,j] when rule has no return values

+

+        Previously, the following code would cause antlr to core when

+        it tried to generate code for rule1 because rule2 had no return

+        values ("upward inheritance"):

+

+            rule1 : <<int i; int j>>

+                    rule2 > [i,j]

+                  ;

+

+            rule2 : Anything ;

+

+        Reported by S.Bochnak@microTool.com.pl

+

+        Verified correct operation of antlr MR8 when missing or extra

+        inheritance arguments for all combinations.  When there are

+        missing or extra arguments code will still be generated even

+        though this might cause the invocation of a subroutine with

+        the wrong number of arguments.

+

+#60.  (Changed in 1.33MR7) Major changes to exception handling

+

+        There were significant problems in the handling of exceptions

+        in 1.33 vanilla.  The general problem is that it can only

+        process one level of exception handler.  For example, a named

+        exception handler, an exception handler for an alternative, or

+        an exception for a subrule  always went to the rule's exception

+        handler if there was no "catch" which matched the exception.

+

+        In 1.33MR7 the exception handlers properly "nest".  If an

+        exception handler does not have a matching "catch" then the

+        nextmost outer exception handler is checked for an appropriate

+        "catch" clause, and so on until an exception handler with an

+        appropriate "catch" is found.

+

+        There are still undesirable features in the way exception

+        handlers are implemented, but I do not have time to fix them

+        at the moment:

+

+            The exception handlers for alternatives are outside the

+            block containing the alternative.  This makes it impossible

+            to access variables declared in a block or to resume the

+            parse by "falling through".  The parse can still be easily

+            resumed in other ways, but not in the most natural fashion.

+

+            This results in an inconsistentcy between named exception

+            handlers and exception handlers for alternatives.  When

+            an exception handler for an alternative "falls through"

+            it goes to the nextmost outer handler - not the "normal

+            action".

+

+        A major difference between 1.33MR7 and 1.33 vanilla is

+        the default action after an exception is caught:

+

+            1.33 Vanilla

+            ------------

+            In 1.33 vanilla the signal value is set to zero ("NoSignal")

+            and the code drops through to the code following the exception.

+            For named exception handlers this is the "normal action".

+            For alternative exception handlers this is the rule's handler.

+

+            1.33MR7

+            -------

+            In 1.33MR7 the signal value is NOT automatically set to zero.

+

+            There are two cases:

+

+                For named exception handlers: if the signal value has been

+                set to zero the code drops through to the "normal action".

+

+                For all other cases the code branches to the nextmost outer

+                exception handler until it reaches the handler for the rule.

+

+        The following macros have been defined for convenience:

+

+            C/C++ Mode Name

+            --------------------

+            (zz)suppressSignal

+                  set signal & return signal arg to 0 ("NoSignal")

+            (zz)setSignal(intValue)

+                  set signal & return signal arg to some value

+            (zz)exportSignal

+                  copy the signal value to the return signal arg

+

+        I'm not sure why PCCTS make a distinction between the local

+        signal value and the return signal argument, but I'm loathe

+        to change the code. The burden of copying the local signal

+        value to the return signal argument can be given to the

+        default signal handler, I suppose.

+

+#59.  (Changed in 1.33MR7) Prototypes for some functions

+

+        Added prototypes for the following functions to antlr.h

+

+            zzconsumeUntil()

+            zzconsumeUntilToken()

+

+#58.  (Changed in 1.33MR7) Added defintion of zzbufsize to dlgauto.h

+

+#57.  (Changed in 1.33MR7) Format of #line directive

+

+        Previously, the -gl directive for line 1234 would

+        resemble:  "# 1234 filename.g".  This caused problems

+        for some compilers/pre-processors.  In MR7 it generates

+        "#line 1234 filename.g".

+

+#56.  (Added in 1.33MR7) Jan Mikkelsen <janm@zeta.org.au>

+

+        Move PURIFY macro invocaton to after rule's init action.

+

+#55.  (Fixed in 1.33MR7) Unitialized variables in ANTLRParser

+

+        Member variables inf_labase and inf_last were not initialized.

+        (See item #50.)

+

+#54.  (Fixed in 1.33MR6) Brad Schick (schick@interacess.com)

+

+        Previously, the following constructs generated the same

+        code:

+

+        rule1 : (A B C)?

+              | something-else

+              ;

+

+        rule2 : (A B C)? ()

+              | something-else

+              ;

+

+        In all versions of pccts rule1 guesses (A B C) and then

+        consume all three tokens if the guess succeeds.  In MR6

+        rule2 guesses (A B C)  but consumes NONE of the tokens

+        when the guess succeeds because "()" matches epsilon.

+

+#53.  (Explanation for 1.33MR6) What happens after an exception is caught ?

+

+        The Book is silent about what happens after an exception

+        is caught.

+

+        The following code fragment prints "Error Action" followed

+        by "Normal Action".

+

+        test : Word ex:Number <<printf("Normal Action\n");>>

+                exception[ex]

+                   catch NoViableAlt:

+                        <<printf("Error Action\n");>>

+        ;

+

+        The reason for "Normal Action" is that the normal flow of the

+        program after a user-written exception handler is to "drop through".

+        In the case of an exception handler for a rule this results in

+        the exection of a "return" statement.  In the case of an

+        exception handler attached to an alternative, rule, or token

+        this is the code that would have executed had there been no

+        exception.

+

+        The user can achieve the desired result by using a "return"

+        statement.

+

+        test : Word ex:Number <<printf("Normal Action\n");>>

+                exception[ex]

+                   catch NoViableAlt:

+                        <<printf("Error Action\n"); return;>>

+        ;

+

+        The most powerful mechanism for recovery from parse errors

+        in pccts is syntactic predicates because they provide

+        backtracking.  Exceptions allow "return", "break",

+        "consumeUntil(...)", "goto _handler", "goto _fail", and

+        changing the _signal value.

+

+#52.  (Fixed in 1.33MR6) Exceptions without syntactic predicates

+

+        The following generates bad code in 1.33 if no syntactic

+        predicates are present in the grammar.

+

+        test : Word ex:Number <<printf("Normal Action\n");>>

+                exception[ex]

+                   catch NoViableAlt:

+                        <<printf("Error Action\n");>>

+

+        There is a reference to a guess variable.  In C mode

+        this causes a compiler error.  In C++ mode it generates

+        an extraneous check on member "guessing".

+

+        In MR6 correct code is generated for both C and C++ mode.

+

+#51.  (Added to 1.33MR6) Exception operator "@" used without exceptions

+

+        In MR6 added a warning when the exception operator "@" is

+        used and no exception group is defined.  This is probably

+        a case where "\@" or "@" is meant.

+

+#50.  (Fixed in 1.33MR6) Gunnar Rxnning (gunnar@candleweb.no)

+                                    http://www.candleweb.no/~gunnar/

+

+        Routines zzsave_antlr_state and zzrestore_antlr_state don't

+        save and restore all the data needed when switching states.

+

+        Suggested patch applied to antlr.h and err.h for MR6.

+

+#49.  (Fixed in 1.33MR6) Sinan Karasu (sinan@boeing.com)

+

+        Generated code failed to turn off guess mode when leaving a

+        (...)+ block which contained a guess block.  The result was

+        an infinite loop.  For example:

+

+                rule : (

+                         (x)?

+                         | y

+                       )+

+

+        Suggested code fix implemented in MR6.  Replaced

+

+            ... else if (zzcnt>1) break;

+

+        with:

+

+          C++ mode:

+              ... else if (zzcnt>1) {if (!zzrv) zzGUESS_DONE; break;};

+          C mode:

+              ... else if (zzcnt>1) {if (zzguessing) zzGUESS_DONE; break;};

+

+#48.  (Fixed in 1.33MR6) Invalid exception element causes core

+

+        A label attached to an invalid construct can cause

+        pccts to crash while processing the exception associated

+        with the label.  For example:

+

+        rule : t:(B C)

+                exception[t] catch MismatchedToken: <<printf(...);>>

+

+        Version MR6 generates the message:

+

+           reference in exception handler to undefined label 't'

+

+#47.  (Fixed in 1.33MR6) Manuel Ornato

+

+        Under some circumstances involving a k >1 or ck >1

+        grammar and a loop block (i.e.  (...)* ) pccts will

+        fail to detect a syntax error and loop indefinitely.

+        The problem did not exist in 1.20, but has existed

+        from 1.23 to the present.

+

+        Fixed in MR6.

+

+        ---------------------------------------------------

+        Complete test program

+        ---------------------------------------------------

+        #header<<

+        #include <stdio.h>

+        #include "charptr.h"

+        >>

+

+        <<

+        #include "charptr.c"

+        main ()

+        {

+         ANTLR(global(),stdin);

+        }

+        >>

+

+        #token "[\ \t]+"        << zzskip(); >>

+        #token "[\n]"           << zzline++; zzskip(); >>

+

+        #token B        "b"

+        #token C        "c"

+        #token D        "d"

+        #token E        "e"

+        #token LP       "\("

+        #token RP       "\)"

+

+        #token ANTLREOF "@"

+

+        global : (

+                   (E liste)

+                 | liste

+                 | listed

+                 )  ANTLREOF

+        ;

+

+        listeb : LP ( B ( B | C )* ) RP ;

+        listec : LP ( C ( B | C )* ) RP ;

+        listed : LP ( D ( B | C )* ) RP ;

+        liste : ( listeb | listec )* ;

+

+        ---------------------------------------------------

+        Sample data causing infinite loop

+        ---------------------------------------------------

+        e (d c)

+        ---------------------------------------------------

+

+#46.  (Fixed in 1.33MR6) Robert Richter

+                (Robert.Richter@infotech.tu-chemnitz.de)

+

+        This item from the list of known problems was

+        fixed by item #18 (below).

+

+#45.  (Fixed in 1.33MR6) Brad Schick (schick@interaccess.com)

+

+        The dependency scanner in VC++ mistakenly sees a

+        reference to an MPW #include file even though properly

+        #ifdef/#endif in config.h.  The suggested workaround

+        has been implemented:

+

+                #ifdef MPW

+                .....

+                #define MPW_CursorCtl_Header <CursorCtl.h>

+                #include MPW_CursorCtl_Header

+                .....

+                #endif

+

+#44.  (Fixed in 1.33MR6) cast malloc() to (char *) in charptr.c

+

+        Added (char *) cast for systems where malloc returns "void *".

+

+#43.  (Added to 1.33MR6) Bruce Guenter (bruceg@qcc.sk.ca)

+

+        Add setLeft() and setUp methods to ASTDoublyLinkedBase

+        for symmetry with setRight() and setDown() methods.

+

+#42.  (Fixed in 1.33MR6) Jeff Katcher (jkatcher@nortel.ca)

+

+        C++ style comment in antlr.c corrected.

+

+#41.  (Added in 1.33MR6) antlr -stdout

+

+        Using "antlr -stdout ..." forces the text that would

+        normally go to the grammar.c or grammar.cpp file to

+        stdout.

+

+#40.  (Added in 1.33MR6) antlr -tab to change tab stops

+

+        Using "antlr -tab number ..." changes the tab stops

+        for the grammar.c or grammar.cpp file.  The number

+        must be between 0 and 8.  Using 0 gives tab characters,

+        values between 1 and 8 give the appropriate number of

+        space characters.

+

+#39.  (Fixed in 1.33MR5) Jan Mikkelsen <janm@zeta.org.au>

+

+        Commas in function prototype still not correct under

+        some circumstances.  Suggested code fix installed.

+

+#38.  (Fixed in 1.33MR5) ANTLRTokenBuffer constructor

+

+        Have ANTLRTokenBuffer ctor initialize member "parser" to null.

+

+#37.  (Fixed in 1.33MR4) Bruce Guenter (bruceg@qcc.sk.ca)

+

+        In ANTLRParser::FAIL(int k,...) released memory pointed to by

+        f[i] (as well as f itself.  Should only free f itself.

+

+#36.  (Fixed in 1.33MR3) Cortland D. Starrett (cort@shay.ecn.purdue.edu)

+

+        Neglected to properly declare isDLGmaxToken() when fixing problem

+        reported by Andreas Magnusson.

+

+        Undo "_retv=NULL;" change which caused problems for return values

+        from rules whose return values weren't pointers.

+

+        Failed to create bin directory if it didn't exist.

+

+#35.  (Fixed in 1.33MR2) Andreas Magnusson

+(Andreas.Magnusson@mailbox.swipnet.se)

+

+        Repair bug introduced by 1.33MR1 for #tokdefs.  The original fix

+        placed "DLGmaxToken=9999" and "DLGminToken=0" in the TokenType enum

+        in order to fix a problem with an aggresive compiler assigning an 8

+        bit enum which might be too narrow.  This caused #tokdefs to assume

+        that there were 9999 real tokens.  The repair to the fix causes antlr to

+        ignore TokenTypes "DLGmaxToken" and "DLGminToken" in a #tokdefs file.

+

+#34.  (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue)

+

+        Previously there was no public function for changing the line

+        number maintained by the lexer.

+

+#33.  (Fixed in 1.33MR1) Franklin Chen   (chen@adi.com)

+

+        Accidental use of EXIT_FAILURE rather than PCCTS_EXIT_FAILURE

+        in pccts/h/AParser.cpp.

+

+#32.  (Fixed in 1.33MR1) Franklin Chen   (chen@adi.com)

+

+        In PCCTSAST.cpp lines 405 and 466:  Change

+

+                free (t)

+           to

+                free ( (char *)t );

+

+        to match prototype.

+

+#31.   (Added to 1.33MR1) Pointer to parser in ANTLRTokenBuffer

+                        Pointer to parser in DLGLexerBase

+

+        The ANTLRTokenBuffer class now contains a pointer to the

+        parser which is using it.  This is established by the

+        ANTLRParser constructor calling ANTLRTokenBuffer::

+        setParser(ANTLRParser *p).

+

+        When ANTLRTokenBuffer::setParser(ANTLRParser *p) is

+        called it saves the pointer to the parser and then

+        calls ANTLRTokenStream::setParser(ANTLRParser *p)

+        so that the lexer can also save a pointer to the

+        parser.

+

+        There is also a function getParser() in each class

+        with the obvious purpose.

+

+        It is possible that these functions will return NULL

+        under some circumstances (e.g. a non-DLG lexer is used).

+

+#30.   (Added to 1.33MR1) function tokenName(int token) standard

+

+        The generated parser class now includes the

+        function:

+

+          static const ANTLRChar * tokenName(int token)

+

+        which returns a pointer to the "name" corresponding

+        to the token.

+

+        The base class (ANTLRParser) always includes the

+        member function:

+

+          const ANTLRChar * parserTokenName(int token)

+

+        which can be accessed by objects which have a pointer

+        to an ANTLRParser, but do not know the name of the

+        parser class (e.g. ANTLRTokenBuffer and DLGLexerBase).

+

+#29.   (Added to 1.33MR1) Debugging DLG lexers

+

+        If the pre-processor symbol DEBUG_LEXER is defined

+        then DLexerBase will include code for printing out

+        key information about tokens which are recognized.

+

+        The debug feature of the lexer is controlled by:

+

+          int previousDebugValue=lexer.debugLexer(newValue);

+

+                        a value of 0 disables output

+                        a value of 1 enables output

+

+        Even if the lexer debug code is compiled into DLexerBase

+        it must be enabled before any output is generated.  For

+        example:

+

+           DLGFileInput         in(stdin);

+           MyDLG                lexer(&in,2000);

+

+           lexer.setToken(&aToken);

+

+           #if DEBUG_LEXER

+             lexer.debugLexer(1);       // enable debug information

+           #endif

+

+#28.   (Added to 1.33MR1) More control over DLG header

+

+        Version 1.33MR1 adds the following directives to PCCTS

+        for C++ mode:

+

+          #lexprefix  <<source code>>

+

+                Adds source code to the DLGLexer.h file

+                after the #include "DLexerBase.h" but

+                before the start of the class definition.

+

+          #lexmember  <<source code>>

+

+                Adds source code to the DLGLexer.h file

+                as part of the DLGLexer class body.  It

+                appears immediately after the start of

+                the class and a "public: statement.

+

+#27.   (Fixed in 1.33MR1) Comments in DLG actions

+

+        Previously, DLG would not recognize comments as a special case.

+        Thus, ">>" in the comments would cause errors.  This is fixed.

+

+#26.   (Fixed in 1.33MR1) Removed static variables from error routines

+

+        Previously, the existence of statically allocated variables

+        in some of the parser's member functions posed a danger when

+        there was more than one parser active.

+

+        Replaced with dynamically allocated/freed variables in 1.33MR1.

+

+#25.  (Fixed in 1.33MR1)  Use of string literals in semantic predicates

+

+        Previously, it was not possible to place a string literal in

+        a semantic predicate because it was not properly "stringized"

+        for the report of a failed predicate.

+

+#24.  (Fixed in 1.33MR1)  Continuation lines for semantic predicates

+

+        Previously, it was not possible to continue semantic

+        predicates across a line because it was not properly

+        "stringized" for the report of a failed predicate.

+

+                rule : <<ifXYZ()>>?[ a very

+                                        long statement ]

+

+#23.  (Fixed in 1.33MR1)  {...} envelope for failed semantic predicates

+

+        Previously, there was a code generation error for failed

+        semantic predicates:

+

+          rule : <<xyz()>>?[ stmt1; stmt2; ]

+

+        which generated code which resembled:

+

+          if (! xyz()) stmt1; stmt2;

+

+        It now puts the statements in a {...} envelope:

+

+          if (! xyz()) { stmt1; stmt2; };

+

+#22.  (Fixed in 1.33MR1)  Continuation of #token across lines using "\"

+

+        Previously, it was not possible to continue a #token regular

+        expression across a line.  The trailing "\" and newline caused

+        a newline to be inserted into the regular expression by DLG.

+

+        Fixed in 1.33MR1.

+

+#21.  (Fixed in 1.33MR1)  Use of ">>" (right shift operator in DLG actions

+

+        It is now possible to use the C++ right shift operator ">>"

+        in DLG actions by using the normal escapes:

+

+                #token "shift-right"     << value=value \>\> 1;>>

+

+#20.  (Version 1.33/19-Jan-97 Karl Eccleson <karle@microrobotics.co.uk>

+                            P.A. Keller (P.A.Keller@bath.ac.uk)

+

+        There is a problem due to using exceptions with the -gh option.

+

+        Suggested fix now in 1.33MR1.

+

+#19.  (Fixed in 1.33MR1)             Tom Piscotti and John Lilley

+

+        There were problems suppressing messages to stdin and stdout

+        when running in a window environment because some functions

+        which uses fprint were not virtual.

+

+        Suggested change now in 1.33MR1.

+

+        I believe all functions containing error messages (excluding those

+        indicating internal inconsistency) have been placed in functions

+        which are virtual.

+

+#18.  (Version 1.33/ 22-Nov-96)  John Bair (jbair@iftime.com)

+

+        Under some combination of options a required "return _retv" is

+        not generated.

+

+        Suggested fix now in 1.33MR1.

+

+#17.  (Version 1.33/3-Sep-96) Ron House  (house@helios.usq.edu.au)

+

+        The routine ASTBase::predorder_action omits two "tree->"

+        prefixes, which results in the preorder_action belonging

+        to the wrong node to be invoked.

+

+        Suggested fix now in 1.33MR1.

+

+#16.  (Version 1.33/7-Jun-96)       Eli Sternheim <eli@interhdl.com>

+

+        Routine consumeUntilToken() does not check for end-of-file

+        condition.

+

+        Suggested fix now in 1.33MR1.

+

+#15.  (Version 1.33/8 Apr 96)   Asgeir Olafsson <olafsson@cstar.ac.com>

+

+        Problem with tree duplication of doubly linked ASTs in ASTBase.cpp.

+

+        Suggested fix now in 1.33MR1.

+

+#14.  (Version 1.33/28-Feb-96)   Andreas.Magnusson@mailbox.swipnet.se

+

+        Problem with definition of operator = (const ANTLRTokenPtr rhs).

+

+        Suggested fix now in 1.33MR1.

+

+#13.  (Version 1.33/13-Feb-96) Franklin Chen (chen@adi.com)

+

+        Sun C++ Compiler 3.0.1 can't compile testcpp/1 due to goto in

+        block with destructors.

+

+        Apparently fixed. Can't locate "goto".

+

+#12.  (Version 1.33/10-Nov-95)  Minor problems with 1.33 code

+

+        The following items have been fixed in 1.33MR1:

+

+          1.  pccts/antlr/main.c line 142

+

+                "void" appears in classic C code

+

+          2.  no makefile in support/genmk

+

+          3.  EXIT_FAILURE/_SUCCESS instead of PCCTS_EXIT_FAILURE/_SUCCESS

+

+                pccts/h/PCCTSAST.cpp

+                pccts/h/DLexerBase.cpp

+                pccts/testcpp/6/test.g

+

+          4.  use of "signed int" isn't accepted by AT&T cfront

+

+                pccts/h/PCCTSAST.h line 42

+

+          5.  in call to ANTLRParser::FAIL the var arg err_k is passed as

+              "int" but is declared "unsigned int".

+

+          6.  I believe that a failed validation predicate still does not

+              get put in a "{...}" envelope, despite the release notes.

+

+          7. The #token ">>" appearing in the DLG grammar description

+             causes DLG to generate the string literal "\>\>" which

+             is non-conforming and will cause some compilers to

+             complain (scan.c function act10 line 143 of source code).

+

+#11.  (Version 1.32b6)  Dave Kuhlman     (dkuhlman@netcom.com)

+

+        Problem with file close in gen.c.  Already fixed in 1.33.

+

+#10.  (Version 1.32b6/29-Aug-95)

+

+        pccts/antlr/main.c contains a C++ style comments on lines 149

+        and 176 which causes problems for most C compilers.

+

+         Already fixed in 1.33.

+

+#9.   (Version 1.32b4/14-Mar-95) dlgauto.h #include "config.h"

+

+        The file pccts/h/dlgauto.h should probably contain a #include

+        "config.h" as it uses the #define symbol __USE_PROTOS.

+

+        Added to 1.33MR1.

+

+#8.   (Version 1.32b4/6-Mar-95)  Michael T. Richter (mtr@igs.net)

+

+        In C++ output mode anonymous tokens from in-line regular expressions

+        can create enum values which are too wide for the datatype of the enum

+        assigned by the C++ compiler.

+

+        Fixed in 1.33MR1.

+

+#7.   (Version 1.32b4/6-Mar-95)  C++ does not imply __STDC__

+

+        In err.h the combination of # directives assumes that a C++

+        compiler has __STDC__ defined.  This is not necessarily true.

+

+        This problem also appears in the use of __USE_PROTOS which

+        is appropriate for both Standard C and C++ in antlr/gen.c

+        and antlr/lex.c

+

+        Fixed in 1.33MR1.

+

+#6.   (Version 1.32 ?/15-Feb-95) Name conflict for "TokenType"

+

+        Already fixed in 1.33.

+

+#5.   (23-Jan-95)        Douglas_Cuthbertson.JTIDS@jtids_qmail.hanscom.af.mil

+

+        The fail action following a semantic predicate is not enclosed in

+        "{...}". This can lead to problems when the fail action contains

+        more than one statement.

+

+        Fixed in 1.33MR1.

+

+#4 .  (Version 1.33/31-Mar-96)   jlilley@empathy.com (John Lilley)

+

+        Put briefly, a semantic predicate ought to abort a guess if it fails.

+

+        Correction suggested by J. Lilley has been added to 1.33MR1.

+

+#3 .  (Version 1.33)             P.A.Keller@bath.ac.uk

+

+        Extra commas are placed in the K&R style argument list for rules

+        when using both exceptions and ASTs.

+

+        Fixed in 1.33MR1.

+

+#2.   (Version 1.32b6/2-Oct-95)  Brad Schick <schick@interaccess.com>

+

+        Construct #[] generates zzastnew() in C++ mode.

+

+        Already fixed in 1.33.

+

+#1.   (Version 1.33)     Bob Bailey (robert@oakhill.sps.mot.com)

+

+        Previously, config.h assumed that all PC systems required

+        "short" file names.  The user can now override that

+        assumption with "#define LONGFILENAMES".

+

+        Added to 1.33MR1.

diff --git a/Source/Pccts/CHANGES_SUMMARY.txt b/Source/Pccts/CHANGES_SUMMARY.txt
new file mode 100644
index 0000000..91defae
--- /dev/null
+++ b/Source/Pccts/CHANGES_SUMMARY.txt
@@ -0,0 +1,2049 @@
+======================================================================

+

+                       CHANGES_SUMMARY.TXT

+

+        A QUICK overview of changes from 1.33 in reverse order

+

+  A summary of additions rather than bug fixes and minor code changes.

+

+          Numbers refer to items in CHANGES_FROM_133*.TXT

+             which may contain additional information.

+

+                          DISCLAIMER

+

+ The software and these notes are provided "as is".  They may include

+ typographical or technical errors and their authors disclaims all

+ liability of any kind or nature for damages due to error, fault,

+ defect, or deficiency regardless of cause.  All warranties of any

+ kind, either express or implied, including, but not limited to, the

+ implied  warranties of merchantability and fitness for a particular

+ purpose are disclaimed.

+

+======================================================================

+

+#258. You can specify a user-defined base class for your parser

+

+    The base class must constructor must have a signature similar to

+    that of ANTLRParser.

+

+#253. Generation of block preamble (-preamble and -preamble_first)

+

+    The antlr option -preamble causes antlr to insert the code

+    BLOCK_PREAMBLE at the start of each rule and block.

+

+    The antlr option -preamble_first is similar, but inserts the

+    code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol

+    PreambleFirst_123 is equivalent to the first set defined by

+    the #FirstSetSymbol described in Item #248.

+

+#248. Generate symbol for first set of an alternative

+

+        rr : #FirstSetSymbol(rr_FirstSet)  ( Foo | Bar ) ;

+

+#216. Defer token fetch for C++ mode

+

+    When the ANTLRParser class is built with the pre-processor option 

+    ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred

+    until LA(i) or LT(i) is called. 

+

+#215. Use reset() to reset DLGLexerBase

+#188. Added pccts/h/DLG_stream_input.h

+#180. Added ANTLRParser::getEofToken()

+#173. -glms for Microsoft style filenames with -gl

+#170. Suppression for predicates with lookahead depth >1

+

+      Consider the following grammar with -ck 2 and the predicate in rule

+      "a" with depth 2:

+

+            r1  : (ab)* "@"

+                ;

+

+            ab  : a

+                | b

+                ;

+

+            a   : (A B)? => <<p(LATEXT(2))>>? A B C

+                ;

+

+            b   : A B C

+                ;

+

+      Normally, the predicate would be hoisted into rule r1 in order to

+      determine whether to call rule "ab".  However it should *not* be

+      hoisted because, even if p is false, there is a valid alternative

+      in rule b.  With "-mrhoistk on" the predicate will be suppressed.

+

+      If "-info p" command line option is present the following information

+      will appear in the generated code:

+

+                while ( (LA(1)==A)

+        #if 0

+

+        Part (or all) of predicate with depth > 1 suppressed by alternative

+            without predicate

+

+        pred  <<  p(LATEXT(2))>>?

+                  depth=k=2  ("=>" guard)  rule a  line 8  t1.g

+          tree context:

+            (root = A

+               B

+            )

+

+        The token sequence which is suppressed: ( A B )

+        The sequence of references which generate that sequence of tokens:

+

+           1 to ab          r1/1       line 1     t1.g

+           2 ab             ab/1       line 4     t1.g

+           3 to b           ab/2       line 5     t1.g

+           4 b              b/1        line 11    t1.g

+           5 #token A       b/1        line 11    t1.g

+           6 #token B       b/1        line 11    t1.g

+

+        #endif

+

+      A slightly more complicated example:

+

+            r1  : (ab)* "@"

+                ;

+

+            ab  : a

+                | b

+                ;

+

+            a   : (A B)? => <<p(LATEXT(2))>>? (A  B | D E)

+                ;

+

+            b   : <<q(LATEXT(2))>>? D E

+                ;

+

+

+      In this case, the sequence (D E) in rule "a" which lies behind

+      the guard is used to suppress the predicate with context (D E)

+      in rule b.

+

+                while ( (LA(1)==A || LA(1)==D)

+            #if 0

+

+            Part (or all) of predicate with depth > 1 suppressed by alternative

+                without predicate

+

+            pred  <<  q(LATEXT(2))>>?

+                              depth=k=2  rule b  line 11  t2.g

+              tree context:

+                (root = D

+                   E

+                )

+

+            The token sequence which is suppressed: ( D E )

+            The sequence of references which generate that sequence of tokens:

+

+               1 to ab          r1/1       line 1     t2.g

+               2 ab             ab/1       line 4     t2.g

+               3 to a           ab/1       line 4     t2.g

+               4 a              a/1        line 8     t2.g

+               5 #token D       a/1        line 8     t2.g

+               6 #token E       a/1        line 8     t2.g

+

+            #endif

+            &&

+            #if 0

+

+            pred  <<  p(LATEXT(2))>>?

+                              depth=k=2  ("=>" guard)  rule a  line 8  t2.g

+              tree context:

+                (root = A

+                   B

+                )

+

+            #endif

+

+            (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) )  {

+                ab();

+                ...

+

+#165. (Changed in MR13) option -newAST

+

+      To create ASTs from an ANTLRTokenPtr antlr usually calls

+      "new AST(ANTLRTokenPtr)".  This option generates a call

+      to "newAST(ANTLRTokenPtr)" instead.  This allows a user

+      to define a parser member function to create an AST object.

+

+#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h

+

+#158. (Changed in MR13) #header causes problem for pre-processors

+

+      A user who runs the C pre-processor on antlr source suggested

+      that another syntax be allowed.  With MR13 such directives

+      such as #header, #pragma, etc. may be written as "\#header",

+      "\#pragma", etc.  For escaping pre-processor directives inside

+      a #header use something like the following:

+

+            \#header

+            <<

+                \#include <stdio.h>

+            >>

+

+#155. (Changed in MR13) Context behind predicates can suppress

+

+      With -mrhoist enabled the context behind a guarded predicate can

+      be used to suppress other predicates.  Consider the following grammar:

+

+        r0 : (r1)+;

+

+        r1  : rp

+            | rq

+            ;

+        rp  : <<p LATEXT(1)>>? B ;

+        rq : (A)? => <<q LATEXT(1)>>? (A|B);

+

+      In earlier versions both predicates "p" and "q" would be hoisted into

+      rule r0. With MR12c predicate p is suppressed because the context which

+      follows predicate q includes "B" which can "cover" predicate "p".  In

+      other words, in trying to decide in r0 whether to call r1, it doesn't

+      really matter whether p is false or true because, either way, there is

+      a valid choice within r1.

+

+#154. (Changed in MR13) Making hoist suppression explicit using <<nohoist>>

+

+      A common error, even among experienced pccts users, is to code

+      an init-action to inhibit hoisting rather than a leading action.

+      An init-action does not inhibit hoisting.

+

+      This was coded:

+

+        rule1 : <<;>> rule2

+

+      This is what was meant:

+

+        rule1 : <<;>> <<;>> rule2

+

+      With MR13, the user can code:

+

+        rule1 : <<;>> <<nohoist>> rule2

+

+      The following will give an error message:

+

+        rule1 : <<nohoist>> rule2

+

+      If the <<nohoist>> appears as an init-action rather than a leading

+      action an error message is issued.  The meaning of an init-action

+      containing "nohoist" is unclear: does it apply to just one

+      alternative or to all alternatives ?

+

+#151a. Addition of ANTLRParser::getLexer(), ANTLRTokenStream::getLexer()

+

+      You must manually cast the ANTLRTokenStream to your program's

+      lexer class. Because the name of the lexer's class is not fixed.

+      Thus it is impossible to incorporate it into the DLGLexerBase

+      class.

+

+#151b.(Changed in MR12) ParserBlackBox member getLexer()

+

+#150. (Changed in MR12) syntaxErrCount and lexErrCount now public

+

+#149. (Changed in MR12) antlr option -info o (letter o for orphan)

+

+      If there is more than one rule which is not referenced by any

+      other rule then all such rules are listed.  This is useful for

+      alerting one to rules which are not used, but which can still

+      contribute to ambiguity.

+

+#148. (Changed in MR11) #token names appearing in zztokens,token_tbl

+

+      One can write:

+

+            #token Plus ("+")             "\+"

+            #token RP   ("(")             "\("

+            #token COM  ("comment begin") "/\*"

+

+      The string in parenthesis will be used in syntax error messages.

+

+#146. (Changed in MR11) Option -treport for locating "difficult" alts

+

+      It can be difficult to determine which alternatives are causing

+      pccts to work hard to resolve an ambiguity.  In some cases the

+      ambiguity is successfully resolved after much CPU time so there

+      is no message at all.

+

+      A rough measure of the amount of work being peformed which is

+      independent of the CPU speed and system load is the number of

+      tnodes created.  Using "-info t" gives information about the

+      total number of tnodes created and the peak number of tnodes.

+

+        Tree Nodes:  peak 1300k  created 1416k  lost 0

+

+      It also puts in the generated C or C++ file the number of tnodes

+      created for a rule (at the end of the rule).  However this

+      information is not sufficient to locate the alternatives within

+      a rule which are causing the creation of tnodes.

+

+      Using:

+

+             antlr -treport 100000 ....

+

+      causes antlr to list on stdout any alternatives which require the

+      creation of more than 100,000 tnodes, along with the lookahead sets

+      for those alternatives.

+

+      The following is a trivial case from the ansi.g grammar which shows

+      the format of the report.  This report might be of more interest

+      in cases where 1,000,000 tuples were created to resolve the ambiguity.

+

+      -------------------------------------------------------------------------

+        There were 0 tuples whose ambiguity could not be resolved

+             by full lookahead

+        There were 157 tnodes created to resolve ambiguity between:

+

+          Choice 1: statement/2  line 475  file ansi.g

+          Choice 2: statement/3  line 476  file ansi.g

+

+            Intersection of lookahead[1] sets:

+

+               IDENTIFIER

+

+            Intersection of lookahead[2] sets:

+

+               LPARENTHESIS     COLON            AMPERSAND        MINUS

+               STAR             PLUSPLUS         MINUSMINUS       ONESCOMPLEMENT

+               NOT              SIZEOF           OCTALINT         DECIMALINT

+               HEXADECIMALINT   FLOATONE         FLOATTWO         IDENTIFIER

+               STRING           CHARACTER

+      -------------------------------------------------------------------------

+

+#143. (Changed in MR11) Optional ";" at end of #token statement

+

+      Fixes problem of:

+

+            #token X "x"

+

+            <<

+                parser action

+            >>

+

+      Being confused with:

+

+            #token X "x" <<lexical action>>

+

+#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream

+

+      Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class

+      BufFileInput derived from DLGInputStream which provides a

+      function lookahead(char *string) to test characters in the

+      input stream more than one character ahead.

+      The class is located in pccts/h/BufFileInput.* of the kit.

+

+#140. #pred to define predicates

+

+      +---------------------------------------------------+

+      | Note: Assume "-prc on" for this entire discussion |

+      +---------------------------------------------------+

+

+      A problem with predicates is that each one is regarded as

+      unique and capable of disambiguating cases where two

+      alternatives have identical lookahead.  For example:

+

+        rule : <<pred(LATEXT(1))>>? A

+             | <<pred(LATEXT(1))>>? A

+             ;

+

+      will not cause any error messages or warnings to be issued

+      by earlier versions of pccts.  To compare the text of the

+      predicates is an incomplete solution.

+

+      In 1.33MR11 I am introducing the #pred statement in order to

+      solve some problems with predicates.  The #pred statement allows

+      one to give a symbolic name to a "predicate literal" or a

+      "predicate expression" in order to refer to it in other predicate

+      expressions or in the rules of the grammar.

+

+      The predicate literal associated with a predicate symbol is C

+      or C++ code which can be used to test the condition.  A

+      predicate expression defines a predicate symbol in terms of other

+      predicate symbols using "!", "&&", and "||".  A predicate symbol

+      can be defined in terms of a predicate literal, a predicate

+      expression, or *both*.

+

+      When a predicate symbol is defined with both a predicate literal

+      and a predicate expression, the predicate literal is used to generate

+      code, but the predicate expression is used to check for two

+      alternatives with identical predicates in both alternatives.

+

+      Here are some examples of #pred statements:

+

+        #pred  IsLabel       <<isLabel(LATEXT(1))>>?

+        #pred  IsLocalVar    <<isLocalVar(LATEXT(1))>>?

+        #pred  IsGlobalVar   <<isGlobalVar(LATEXT(1)>>?

+        #pred  IsVar         <<isVar(LATEXT(1))>>?       IsLocalVar || IsGlobalVar

+        #pred  IsScoped      <<isScoped(LATEXT(1))>>?    IsLabel || IsLocalVar

+

+      I hope that the use of EBNF notation to describe the syntax of the

+      #pred statement will not cause problems for my readers (joke).

+

+        predStatement : "#pred"

+                            CapitalizedName

+                              (

+                                  "<<predicate_literal>>?"

+                                | "<<predicate_literal>>?"  predOrExpr

+                                | predOrExpr

+                              )

+                      ;

+

+        predOrExpr    : predAndExpr ( "||" predAndExpr ) * ;

+

+        predAndExpr   : predPrimary ( "&&" predPrimary ) * ;

+

+        predPrimary   : CapitalizedName

+                      | "!" predPrimary

+                      | "(" predOrExpr ")"

+                      ;

+

+      What is the purpose of this nonsense ?

+

+      To understand how predicate symbols help, you need to realize that

+      predicate symbols are used in two different ways with two different

+      goals.

+

+        a. Allow simplification of predicates which have been combined

+           during predicate hoisting.

+

+        b. Allow recognition of identical predicates which can't disambiguate

+           alternatives with common lookahead.

+

+      First we will discuss goal (a).  Consider the following rule:

+

+            rule0: rule1

+                 | ID

+                 | ...

+                 ;

+

+            rule1: rule2

+                 | rule3

+                 ;

+

+            rule2: <<isX(LATEXT(1))>>? ID ;

+            rule3: <<!isX(LATEXT(1)>>? ID ;

+

+      When the predicates in rule2 and rule3 are combined by hoisting

+      to create a prediction expression for rule1 the result is:

+

+            if ( LA(1)==ID

+                && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ...

+

+      This is inefficient, but more importantly, can lead to false

+      assumptions that the predicate expression distinguishes the rule1

+      alternative with some other alternative with lookahead ID.  In

+      MR11 one can write:

+

+            #pred IsX     <<isX(LATEXT(1))>>?

+

+            ...

+

+            rule2: <<IsX>>? ID  ;

+            rule3: <<!IsX>>? ID ;

+

+      During hoisting MR11 recognizes this as a special case and

+      eliminates the predicates.  The result is a prediction

+      expression like the following:

+

+            if ( LA(1)==ID ) { rule1(); ...

+

+      Please note that the following cases which appear to be equivalent

+      *cannot* be simplified by MR11 during hoisting because the hoisting

+      logic only checks for a "!" in the predicate action, not in the

+      predicate expression for a predicate symbol.

+

+        *Not* equivalent and is not simplified during hoisting:

+

+            #pred IsX      <<isX(LATEXT(1))>>?

+            #pred NotX     <<!isX(LATEXT(1))>>?

+            ...

+            rule2: <<IsX>>? ID  ;

+            rule3: <<NotX>>? ID ;

+

+        *Not* equivalent and is not simplified during hoisting:

+

+            #pred IsX      <<isX(LATEXT(1))>>?

+            #pred NotX     !IsX

+            ...

+            rule2: <<IsX>>? ID  ;

+            rule3: <<NotX>>? ID ;

+

+      Now we will discuss goal (b).

+

+      When antlr discovers that there is a lookahead ambiguity between

+      two alternatives it attempts to resolve the ambiguity by searching

+      for predicates in both alternatives.  In the past any predicate

+      would do, even if the same one appeared in both alternatives:

+

+            rule: <<p(LATEXT(1))>>? X

+                | <<p(LATEXT(1))>>? X

+                ;

+

+      The #pred statement is a start towards solving this problem.

+      During ambiguity resolution (*not* predicate hoisting) the

+      predicates for the two alternatives are expanded and compared.

+      Consider the following example:

+

+            #pred Upper     <<isUpper(LATEXT(1))>>?

+            #pred Lower     <<isLower(LATEXT(1))>>?

+            #pred Alpha     <<isAlpha(LATEXT(1))>>?  Upper || Lower

+

+            rule0: rule1

+                 | <<Alpha>>? ID

+                 ;

+

+            rule1:

+                 | rule2

+                 | rule3

+                 ...

+                 ;

+

+            rule2: <<Upper>>? ID;

+            rule3: <<Lower>>? ID;

+

+      The definition of #pred Alpha expresses:

+

+            a. to test the predicate use the C code "isAlpha(LATEXT(1))"

+

+            b. to analyze the predicate use the information that

+               Alpha is equivalent to the union of Upper and Lower,

+

+      During ambiguity resolution the definition of Alpha is expanded

+      into "Upper || Lower" and compared with the predicate in the other

+      alternative, which is also "Upper || Lower".  Because they are

+      identical MR11 will report a problem.

+

+    -------------------------------------------------------------------------

+      t10.g, line 5: warning: the predicates used to disambiguate rule rule0

+             (file t10.g alt 1 line 5 and alt 2 line 6)

+             are identical when compared without context and may have no

+             resolving power for some lookahead sequences.

+    -------------------------------------------------------------------------

+

+      If you use the "-info p" option the output file will contain:

+

+    +----------------------------------------------------------------------+

+    |#if 0                                                                 |

+    |                                                                      |

+    |The following predicates are identical when compared without          |

+    |  lookahead context information.  For some ambiguous lookahead        |

+    |  sequences they may not have any power to resolve the ambiguity.     |

+    |                                                                      |

+    |Choice 1: rule0/1  alt 1  line 5  file t10.g                          |

+    |                                                                      |

+    |  The original predicate for choice 1 with available context          |

+    |    information:                                                      |

+    |                                                                      |

+    |    OR expr                                                           |

+    |                                                                      |

+    |      pred  <<  Upper>>?                                              |

+    |                        depth=k=1  rule rule2  line 14  t10.g         |

+    |        set context:                                                  |

+    |           ID                                                         |

+    |                                                                      |

+    |      pred  <<  Lower>>?                                              |

+    |                        depth=k=1  rule rule3  line 15  t10.g         |

+    |        set context:                                                  |

+    |           ID                                                         |

+    |                                                                      |

+    |  The predicate for choice 1 after expansion (but without context     |

+    |    information):                                                     |

+    |                                                                      |

+    |    OR expr                                                           |

+    |                                                                      |

+    |      pred  <<  isUpper(LATEXT(1))>>?                                 |

+    |                        depth=k=1  rule   line 1  t10.g               |

+    |                                                                      |

+    |      pred  <<  isLower(LATEXT(1))>>?                                 |

+    |                        depth=k=1  rule   line 2  t10.g               |

+    |                                                                      |

+    |                                                                      |

+    |Choice 2: rule0/2  alt 2  line 6  file t10.g                          |

+    |                                                                      |

+    |  The original predicate for choice 2 with available context          |

+    |    information:                                                      |

+    |                                                                      |

+    |  pred  <<  Alpha>>?                                                  |

+    |                    depth=k=1  rule rule0  line 6  t10.g              |

+    |    set context:                                                      |

+    |       ID                                                             |

+    |                                                                      |

+    |  The predicate for choice 2 after expansion (but without context     |

+    |    information):                                                     |

+    |                                                                      |

+    |  OR expr                                                             |

+    |                                                                      |

+    |    pred  <<  isUpper(LATEXT(1))>>?                                   |

+    |                      depth=k=1  rule   line 1  t10.g                 |

+    |                                                                      |

+    |    pred  <<  isLower(LATEXT(1))>>?                                   |

+    |                      depth=k=1  rule   line 2  t10.g                 |

+    |                                                                      |

+    |                                                                      |

+    |#endif                                                                |

+    +----------------------------------------------------------------------+

+

+      The comparison of the predicates for the two alternatives takes

+      place without context information, which means that in some cases

+      the predicates will be considered identical even though they operate

+      on disjoint lookahead sets.  Consider:

+

+            #pred Alpha

+

+            rule1: <<Alpha>>? ID

+                 | <<Alpha>>? Label

+                 ;

+

+      Because the comparison of predicates takes place without context

+      these will be considered identical.  The reason for comparing

+      without context is that otherwise it would be necessary to re-evaluate

+      the entire predicate expression for each possible lookahead sequence.

+      This would require more code to be written and more CPU time during

+      grammar analysis, and it is not yet clear whether anyone will even make

+      use of the new #pred facility.

+

+      A temporary workaround might be to use different #pred statements

+      for predicates you know have different context.  This would avoid

+      extraneous warnings.

+

+      The above example might be termed a "false positive".  Comparison

+      without context will also lead to "false negatives".  Consider the

+      following example:

+

+            #pred Alpha

+            #pred Beta

+

+            rule1: <<Alpha>>? A

+                 | rule2

+                 ;

+

+            rule2: <<Alpha>>? A

+                 | <<Beta>>?  B

+                 ;

+

+      The predicate used for alt 2 of rule1 is (Alpha || Beta).  This

+      appears to be different than the predicate Alpha used for alt1.

+      However, the context of Beta is B.  Thus when the lookahead is A

+      Beta will have no resolving power and Alpha will be used for both

+      alternatives.  Using the same predicate for both alternatives isn't

+      very helpful, but this will not be detected with 1.33MR11.

+

+      To properly handle this the predicate expression would have to be

+      evaluated for each distinct lookahead context.

+

+      To determine whether two predicate expressions are identical is

+      difficult.  The routine may fail to identify identical predicates.

+

+      The #pred feature also compares predicates to see if a choice between

+      alternatives which is resolved by a predicate which makes the second

+      choice unreachable.  Consider the following example:

+

+            #pred A         <<A(LATEXT(1)>>?

+            #pred B         <<B(LATEXT(1)>>?

+            #pred A_or_B    A || B

+

+            r   : s

+                | t

+                ;

+            s   : <<A_or_B>>? ID

+                ;

+            t   : <<A>>? ID

+                ;

+

+        ----------------------------------------------------------------------------

+        t11.g, line 5: warning: the predicate used to disambiguate the

+               first choice of  rule r

+             (file t11.g alt 1 line 5 and alt 2 line 6)

+             appears to "cover" the second predicate when compared without context.

+             The second predicate may have no resolving power for some lookahead

+               sequences.

+        ----------------------------------------------------------------------------

+

+#132. (Changed in 1.33MR11) Recognition of identical predicates in alts

+

+      Prior to 1.33MR11, there would be no ambiguity warning when the

+      very same predicate was used to disambiguate both alternatives:

+

+        test: ref B

+            | ref C

+            ;

+

+        ref : <<pred(LATEXT(1)>>? A

+

+      In 1.33MR11 this will cause the warning:

+

+        warning: the predicates used to disambiguate rule test

+            (file v98.g alt 1 line 1 and alt 2 line 2)

+             are identical and have no resolving power

+

+        -----------------  Note  -----------------

+

+          This is different than the following case

+

+                test: <<pred(LATEXT(1))>>? A B

+                    | <<pred(LATEXT(1)>>?  A C

+                    ;

+

+          In this case there are two distinct predicates

+          which have exactly the same text.  In the first

+          example there are two references to the same

+          predicate.  The problem represented by this

+          grammar will be addressed later.

+

+

+#127. (Changed in 1.33MR11)

+

+                    Count Syntax Errors     Count DLG Errors

+                    -------------------     ----------------

+

+       C++ mode     ANTLRParser::           DLGLexerBase::

+                      syntaxErrCount          lexErrCount

+       C mode       zzSyntaxErrCount        zzLexErrCount

+

+       The C mode variables are global and initialized to 0.

+       They are *not* reset to 0 automatically when antlr is

+       restarted.

+

+       The C++ mode variables are public.  They are initialized

+       to 0 by the constructors.  They are *not* reset to 0 by the

+       ANTLRParser::init() method.

+

+       Suggested by Reinier van den Born (reinier@vnet.ibm.com).

+

+#126. (Changed in 1.33MR11) Addition of #first <<...>>

+

+       The #first <<...>> inserts the specified text in the output

+       files before any other #include statements required by pccts.

+       The only things before the #first text are comments and

+       a #define ANTLR_VERSION.

+

+       Requested by  and Esa Pulkkinen (esap@cs.tut.fi) and Alexin

+       Zoltan (alexin@inf.u-szeged.hu).

+

+#124. A Note on the New "&&" Style Guarded Predicates

+

+        I've been asked several times, "What is the difference between

+        the old "=>" style guard predicates and the new style "&&" guard

+        predicates, and how do you choose one over the other" ?

+

+        The main difference is that the "=>" does not apply the

+        predicate if the context guard doesn't match, whereas

+        the && form always does.  What is the significance ?

+

+        If you have a predicate which is not on the "leading edge"

+        it is cannot be hoisted.  Suppose you need a predicate that

+        looks at LA(2).  You must introduce it manually.  The

+        classic example is:

+

+            castExpr :

+                     LP typeName RP

+                     | ....

+                     ;

+

+            typeName : <<isTypeName(LATEXT(1))>>?  ID

+                     | STRUCT ID

+                     ;

+

+        The problem  is that isTypeName() isn't on the leading edge

+        of typeName, so it won't be hoisted into castExpr to help

+        make a decision on which production to choose.

+

+        The *first* attempt to fix it is this:

+

+            castExpr :

+                     <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+        Unfortunately, this won't work because it ignores

+        the problem of STRUCT.  The solution is to apply

+        isTypeName() in castExpr if LA(2) is an ID and

+        don't apply it when LA(2) is STRUCT:

+

+            castExpr :

+                     (LP ID)? => <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+        In conclusion, the "=>" style guarded predicate is

+        useful when:

+

+            a. the tokens required for the predicate

+               are not on the leading edge

+            b. there are alternatives in the expression

+               selected by the predicate for which the

+               predicate is inappropriate

+

+        If (b) were false, then one could use a simple

+        predicate (assuming "-prc on"):

+

+            castExpr :

+                     <<isTypeName(LATEXT(2))>>?

+                                        LP typeName RP

+                     | ....

+                     ;

+

+            typeName : <<isTypeName(LATEXT(1))>>?  ID

+                     ;

+

+        So, when do you use the "&&" style guarded predicate ?

+

+        The new-style "&&" predicate should always be used with

+        predicate context.  The context guard is in ADDITION to

+        the automatically computed context.  Thus it useful for

+        predicates which depend on the token type for reasons

+        other than context.

+

+        The following example is contributed by Reinier van den Born

+        (reinier@vnet.ibm.com).

+

+ +-------------------------------------------------------------------------+

+ | This grammar has two ways to call functions:                            |

+ |                                                                         |

+ |  - a "standard" call syntax with parens and comma separated args        |

+ |  - a shell command like syntax (no parens and spacing separated args)   |

+ |                                                                         |

+ | The former also allows a variable to hold the name of the function,     |

+ | the latter can also be used to call external commands.                  |

+ |                                                                         |

+ | The grammar (simplified) looks like this:                               |

+ |                                                                         |

+ |   fun_call   :     ID "(" { expr ("," expr)* } ")"                      |

+ |                                  /* ID is function name */              |

+ |              | "@" ID "(" { expr ("," expr)* } ")"                      |

+ |                                  /* ID is var containing fun name */    |

+ |              ;                                                          |

+ |                                                                         |

+ |   command    : ID expr*          /* ID is function name */              |

+ |              | path expr*        /* path is external command name */    |

+ |              ;                                                          |

+ |                                                                         |

+ |   path       : ID                /* left out slashes and such */        |

+ |              | "@" ID            /* ID is environment var */            |

+ |              ;                                                          |

+ |                                                                         |

+ |   expr       : ....                                                     |

+ |              | "(" expr ")";                                            |

+ |                                                                         |

+ |   call       : fun_call                                                 |

+ |              | command                                                  |

+ |              ;                                                          |

+ |                                                                         |

+ | Obviously the call is wildly ambiguous. This is more or less how this   |

+ | is to be resolved:                                                      |

+ |                                                                         |

+ |    A call begins with an ID or an @ followed by an ID.                  |

+ |                                                                         |

+ |    If it is an ID and if it is an ext. command name  -> command         |

+ |                       if followed by a paren         -> fun_call        |

+ |                       otherwise                      -> command         |

+ |                                                                         |

+ |    If it is an @  and if the ID is a var name        -> fun_call        |

+ |                       otherwise                      -> command         |

+ |                                                                         |

+ | One can implement these rules quite neatly using && predicates:         |

+ |                                                                         |

+ |   call       : ("@" ID)? && <<isVarName(LT(2))>>? fun_call              |

+ |              | (ID)?     && <<isExtCmdName>>?     command               |

+ |              | (ID "(")?                          fun_call              |

+ |              |                                    command               |

+ |              ;                                                          |

+ |                                                                         |

+ | This can be done better, so it is not an ideal example, but it          |

+ | conveys the principle.                                                  |

+ +-------------------------------------------------------------------------+

+

+#122. (Changed in 1.33MR11)  Member functions to reset DLG in C++ mode

+

+         void DLGFileReset(FILE *f) { input = f; found_eof = 0; }

+         void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; }

+

+        Supplied by R.A. Nelson (cowboy@VNET.IBM.COM)

+

+#119. (Changed in 1.33MR11) Ambiguity aid for grammars

+

+      The user can ask for additional information on ambiguities reported

+      by antlr to stdout.  At the moment, only one ambiguity report can

+      be created in an antlr run.

+

+      This feature is enabled using the "-aa" (Ambiguity Aid)  option.

+

+      The following options control the reporting of ambiguities:

+

+          -aa ruleName       Selects reporting by name of rule

+          -aa lineNumber     Selects reporting by line number

+                               (file name not compared)

+

+          -aam               Selects "multiple" reporting for a token

+                             in the intersection set of the

+                             alternatives.

+

+                             For instance, the token ID may appear dozens

+                             of times in various paths as the program

+                             explores the rules which are reachable from

+                             the point of an ambiguity. With option -aam

+                             every possible path the search program

+                             encounters is reported.

+

+                             Without -aam only the first encounter is

+                             reported.  This may result in incomplete

+                             information, but the information may be

+                             sufficient and much shorter.

+

+          -aad depth         Selects the depth of the search.

+                             The default value is 1.

+

+                             The number of paths to be searched, and the

+                             size of the report can grow geometrically

+                             with the -ck value if a full search for all

+                             contributions to the source of the ambiguity

+                             is explored.

+

+                             The depth represents the number of tokens

+                             in the lookahead set which are matched against

+                             the set of ambiguous tokens.  A depth of 1

+                             means that the search stops when a lookahead

+                             sequence of just one token is matched.

+

+                             A k=1 ck=6 grammar might generate 5,000 items

+                             in a report if a full depth 6 search is made

+                             with the Ambiguity Aid.  The source of the

+                             problem may be in the first token and obscured

+                             by the volume of data - I hesitate to call

+                             it information.

+

+                             When the user selects a depth > 1, the search

+                             is first performed at depth=1 for both

+                             alternatives, then depth=2 for both alternatives,

+                             etc.

+

+      Sample output for rule grammar in antlr.g itself:

+

+  +---------------------------------------------------------------------+

+  | Ambiguity Aid                                                       |

+  |                                                                     |

+  |   Choice 1: grammar/70                 line 632  file a.g           |

+  |   Choice 2: grammar/82                 line 644  file a.g           |

+  |                                                                     |

+  |   Intersection of lookahead[1] sets:                                |

+  |                                                                     |

+  |      "\}"             "class"          "#errclass"      "#tokclass" |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:1  ("#errclass")                        |

+  |  1 in (...)* block                grammar/70       line 632   a.g   |

+  |  2 to error                       grammar/73       line 635   a.g   |

+  |  3 error                          error/1          line 894   a.g   |

+  |  4 #token "#errclass"             error/2          line 895   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:2  ("#tokclass")                        |

+  |  2 to tclass                      grammar/74       line 636   a.g   |

+  |  3 tclass                         tclass/1         line 937   a.g   |

+  |  4 #token "#tokclass"             tclass/2         line 938   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:3  ("class")                            |

+  |  2 to class_def                   grammar/75       line 637   a.g   |

+  |  3 class_def                      class_def/1      line 669   a.g   |

+  |  4 #token "class"                 class_def/3      line 671   a.g   |

+  |                                                                     |

+  |    Choice:1  Depth:1  Group:4  ("\}")                               |

+  |  2 #token "\}"                    grammar/76       line 638   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:5  ("#errclass")                        |

+  |  1 in (...)* block                grammar/83       line 645   a.g   |

+  |  2 to error                       grammar/93       line 655   a.g   |

+  |  3 error                          error/1          line 894   a.g   |

+  |  4 #token "#errclass"             error/2          line 895   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:6  ("#tokclass")                        |

+  |  2 to tclass                      grammar/94       line 656   a.g   |

+  |  3 tclass                         tclass/1         line 937   a.g   |

+  |  4 #token "#tokclass"             tclass/2         line 938   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:7  ("class")                            |

+  |  2 to class_def                   grammar/95       line 657   a.g   |

+  |  3 class_def                      class_def/1      line 669   a.g   |

+  |  4 #token "class"                 class_def/3      line 671   a.g   |

+  |                                                                     |

+  |    Choice:2  Depth:1  Group:8  ("\}")                               |

+  |  2 #token "\}"                    grammar/96       line 658   a.g   |

+  +---------------------------------------------------------------------+

+

+      For a linear lookahead set ambiguity (where k=1 or for k>1 but

+      when all lookahead sets [i] with i<k all have degree one) the

+      reports appear in the following order:

+

+        for (depth=1 ; depth <= "-aad depth" ; depth++) {

+          for (alternative=1; alternative <=2 ; alternative++) {

+            while (matches-are-found) {

+              group++;

+              print-report

+            };

+          };

+       };

+

+      For reporting a k-tuple ambiguity, the reports appear in the

+      following order:

+

+        for (depth=1 ; depth <= "-aad depth" ; depth++) {

+          while (matches-are-found) {

+            for (alternative=1; alternative <=2 ; alternative++) {

+              group++;

+              print-report

+            };

+          };

+       };

+

+      This is because matches are generated in different ways for

+      linear lookahead and k-tuples.

+

+#117. (Changed in 1.33MR10) new EXPERIMENTAL predicate hoisting code

+

+      The hoisting of predicates into rules to create prediction

+      expressions is a problem in antlr.  Consider the following

+      example (k=1 with -prc on):

+

+        start   : (a)* "@" ;

+        a       : b | c ;

+        b       : <<isUpper(LATEXT(1))>>? A ;

+        c       : A ;

+

+      Prior to 1.33MR10 the code generated for "start" would resemble:

+

+        while {

+            if (LA(1)==A &&

+                    (!LA(1)==A || isUpper())) {

+              a();

+            }

+        };

+

+      This code is wrong because it makes rule "c" unreachable from

+      "start".  The essence of the problem is that antlr fails to

+      recognize that there can be a valid alternative within "a" even

+      when the predicate <<isUpper(LATEXT(1))>>? is false.

+

+      In 1.33MR10 with -mrhoist the hoisting of the predicate into

+      "start" is suppressed because it recognizes that "c" can

+      cover all the cases where the predicate is false:

+

+        while {

+            if (LA(1)==A) {

+              a();

+            }

+        };

+

+      With the antlr "-info p" switch the user will receive information

+      about the predicate suppression in the generated file:

+

+      --------------------------------------------------------------

+        #if 0

+

+        Hoisting of predicate suppressed by alternative without predicate.

+        The alt without the predicate includes all cases where

+            the predicate is false.

+

+           WITH predicate: line 7  v1.g

+           WITHOUT predicate: line 7  v1.g

+

+        The context set for the predicate:

+

+             A

+

+        The lookahead set for the alt WITHOUT the semantic predicate:

+

+             A

+

+        The predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 9  v1.g

+            set context:

+               A

+            tree context: null

+

+        Chain of referenced rules:

+

+            #0  in rule start (line 5 v1.g) to rule a

+            #1  in rule a (line 7 v1.g)

+

+        #endif

+      --------------------------------------------------------------

+

+      A predicate can be suppressed by a combination of alternatives

+      which, taken together, cover a predicate:

+

+        start   : (a)* "@" ;

+

+        a       : b | ca | cb | cc ;

+

+        b       : <<isUpper(LATEXT(1))>>? ( A | B | C ) ;

+

+        ca      : A ;

+        cb      : B ;

+        cc      : C ;

+

+      Consider a more complex example in which "c" covers only part of

+      a predicate:

+

+        start   : (a)* "@" ;

+

+        a       : b

+                | c

+                ;

+

+        b       : <<isUpper(LATEXT(1))>>?

+                    ( A

+                    | X

+                    );

+

+        c       : A

+                ;

+

+      Prior to 1.33MR10 the code generated for "start" would resemble:

+

+        while {

+            if ( (LA(1)==A || LA(1)==X) &&

+                    (! (LA(1)==A || LA(1)==X) || isUpper()) {

+              a();

+            }

+        };

+

+      With 1.33MR10 and -mrhoist the predicate context is restricted to

+      the non-covered lookahead.  The code resembles:

+

+        while {

+            if ( (LA(1)==A || LA(1)==X) &&

+                  (! (LA(1)==X) || isUpper()) {

+              a();

+            }

+        };

+

+      With the antlr "-info p" switch the user will receive information

+      about the predicate restriction in the generated file:

+

+      --------------------------------------------------------------

+        #if 0

+

+        Restricting the context of a predicate because of overlap

+          in the lookahead set between the alternative with the

+          semantic predicate and one without

+        Without this restriction the alternative without the predicate

+          could not be reached when input matched the context of the

+          predicate and the predicate was false.

+

+           WITH predicate: line 11  v4.g

+           WITHOUT predicate: line 12  v4.g

+

+        The original context set for the predicate:

+

+             A                X

+

+        The lookahead set for the alt WITHOUT the semantic predicate:

+

+             A

+

+        The intersection of the two sets

+

+             A

+

+        The original predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 15  v4.g

+            set context:

+               A                X

+            tree context: null

+

+        The new (modified) form of the predicate:

+

+          pred <<  isUpper(LATEXT(1))>>?

+                          depth=k=1  rule b  line 15  v4.g

+            set context:

+               X

+            tree context: null

+

+        #endif

+      --------------------------------------------------------------

+

+      The bad news about -mrhoist:

+

+        (a) -mrhoist does not analyze predicates with lookahead

+            depth > 1.

+

+        (b) -mrhoist does not look past a guarded predicate to

+            find context which might cover other predicates.

+

+      For these cases you might want to use syntactic predicates.

+      When a semantic predicate fails during guess mode the guess

+      fails and the next alternative is tried.

+

+      Limitation (a) is illustrated by the following example:

+

+        start    : (stmt)* EOF ;

+

+        stmt     : cast

+                 | expr

+                 ;

+        cast     : <<isTypename(LATEXT(2))>>? LP ID RP ;

+

+        expr     : LP ID RP ;

+

+      This is not much different from the first example, except that

+      it requires two tokens of lookahead context to determine what

+      to do.  This predicate is NOT suppressed because the current version

+      is unable to handle predicates with depth > 1.

+

+      A predicate can be combined with other predicates during hoisting.

+      In those cases the depth=1 predicates are still handled.  Thus,

+      in the following example the isUpper() predicate will be suppressed

+      by line #4 when hoisted from "bizarre" into "start", but will still

+      be present in "bizarre" in order to predict "stmt".

+

+        start    : (bizarre)* EOF ;     // #1

+                                        // #2

+        bizarre  : stmt                 // #3

+                 | A                    // #4

+                 ;

+

+        stmt     : cast

+                 | expr

+                 ;

+

+        cast     : <<isTypename(LATEXT(2))>>? LP ID RP ;

+

+        expr     : LP ID RP ;

+                 | <<isUpper(LATEXT(1))>>? A

+

+      Limitation (b) is illustrated by the following example of a

+      context guarded predicate:

+

+        rule : (A)? <<p>>?          // #1

+                     (A             // #2

+                     |B             // #3

+                     )              // #4

+             | <<q>> B              // #5

+             ;

+

+      Recall that this means that when the lookahead is NOT A then

+      the predicate "p" is ignored and it attempts to match "A|B".

+      Ideally, the "B" at line #3 should suppress predicate "q".

+      However, the current version does not attempt to look past

+      the guard predicate to find context which might suppress other

+      predicates.

+

+      In some cases -mrhoist will lead to the reporting of ambiguities

+      which were not visible before:

+

+        start   : (a)* "@";

+        a       : bc | d;

+        bc      : b  | c ;

+

+        b       : <<isUpper(LATEXT(1))>>? A;

+        c       : A ;

+

+        d       : A ;

+

+      In this case there is a true ambiguity in "a" between "bc" and "d"

+      which can both match "A".  Without -mrhoist the predicate in "b"

+      is hoisted into "a" and there is no ambiguity reported.  However,

+      with -mrhoist, the predicate in "b" is suppressed by "c" (as it

+      should be) making the ambiguity in "a" apparent.

+

+      The motivations for these changes were hoisting problems reported

+      by Reinier van den Born (reinier@vnet.ibm.com) and several others.

+

+#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <<p>>? expr

+

+      The existing context guarded predicate:

+

+            rule : (guard)? => <<p>>? expr

+                 | next_alternative

+                 ;

+

+      generates code which resembles:

+

+            if (lookahead(expr) && (!guard || pred)) {

+              expr()

+            } else ....

+

+      This is not suitable for some applications because it allows

+      expr() to be invoked when the predicate is false.  This is

+      intentional because it is meant to mimic automatically computed

+      predicate context.

+

+      The new context guarded predicate uses the guard information

+      differently because it has a different goal.  Consider:

+

+            rule : (guard)? && <<p>>? expr

+                 | next_alternative

+                 ;

+

+      The new style of context guarded predicate is equivalent to:

+

+            rule : <<guard==true && pred>>? expr

+                 | next_alternative

+                 ;

+

+      It generates code which resembles:

+

+            if (lookahead(expr) && guard && pred) {

+                expr();

+            } else ...

+

+      Both forms of guarded predicates severely restrict the form of

+      the context guard: it can contain no rule references, no

+      (...)*, no (...)+, and no {...}.  It may contain token and

+      token class references, and alternation ("|").

+

+      Addition for 1.33MR11: in the token expression all tokens must

+      be at the same height of the token tree:

+

+            (A ( B | C))? && ...            is ok (all height 2)

+            (A ( B |  ))? && ...            is not ok (some 1, some 2)

+            (A B C D | E F G H)? && ...     is ok (all height 4)

+            (A B C D | E )? && ...          is not ok (some 4, some 1)

+

+      This restriction is required in order to properly compute the lookahead

+      set for expressions like:

+

+            rule1 : (A B C)? && <<pred>>? rule2 ;

+            rule2 : (A|X) (B|Y) (C|Z);

+

+      This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com)

+

+#109. (Changed in 1.33MR10) improved trace information

+

+      The quality of the trace information provided by the "-gd"

+      switch has been improved significantly.  Here is an example

+      of the output from a test program.  It shows the rule name,

+      the first token of lookahead, the call depth, and the guess

+      status:

+

+        exit rule gusxx {"?"} depth 2

+        enter rule gusxx {"?"} depth 2

+        enter rule gus1 {"o"} depth 3 guessing

+        guess done - returning to rule gus1 {"o"} at depth 3

+                    (guess mode continues - an enclosing guess is still active)

+        guess done - returning to rule gus1 {"Z"} at depth 3

+                    (guess mode continues - an enclosing guess is still active)

+        exit rule gus1 {"Z"} depth 3 guessing

+        guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends)

+        enter rule gus1 {"o"} depth 3

+        guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends)

+        guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends)

+        exit rule gus1 {"Z"} depth 3

+        line 1: syntax error at "Z" missing SC

+            ...

+

+      Rule trace reporting is controlled by the value of the integer

+      [zz]traceOptionValue:  when it is positive tracing is enabled,

+      otherwise it is disabled.  Tracing during guess mode is controlled

+      by the value of the integer [zz]traceGuessOptionValue.  When

+      it is positive AND [zz]traceOptionValue is positive rule trace

+      is reported in guess mode.

+

+      The values of [zz]traceOptionValue and [zz]traceGuessOptionValue

+      can be adjusted by subroutine calls listed below.

+

+      Depending on the presence or absence of the antlr -gd switch

+      the variable [zz]traceOptionValueDefault is set to 0 or 1.  When

+      the parser is initialized or [zz]traceReset() is called the

+      value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue.

+      The value of [zz]traceGuessOptionValue is always initialzed to 1,

+      but, as noted earlier, nothing will be reported unless

+      [zz]traceOptionValue is also positive.

+

+      When the parser state is saved/restored the value of the trace

+      variables are also saved/restored.  If a restore causes a change in

+      reporting behavior from on to off or vice versa this will be reported.

+

+      When the -gd option is selected, the macro "#define zzTRACE_RULES"

+      is added to appropriate output files.

+

+        C++ mode

+        --------

+        int     traceOption(int delta)

+        int     traceGuessOption(int delta)

+        void    traceReset()

+        int     traceOptionValueDefault

+

+        C mode

+        --------

+        int     zzTraceOption(int delta)

+        int     zzTraceGuessOption(int delta)

+        void    zzTraceReset()

+        int     zzTraceOptionValueDefault

+

+      The argument "delta" is added to the traceOptionValue.  To

+      turn on trace when inside a particular rule one:

+

+        rule : <<traceOption(+1);>>

+               (

+                rest-of-rule

+               )

+               <<traceOption(-1);>>

+       ;  /* fail clause */ <<traceOption(-1);>>

+

+      One can use the same idea to turn *off* tracing within a

+      rule by using a delta of (-1).

+

+      An improvement in the rule trace was suggested by Sramji

+      Ramanathan (ps@kumaran.com).

+

+#108. A Note on Deallocation of Variables Allocated in Guess Mode

+

+                            NOTE

+        ------------------------------------------------------

+        This mechanism only works for heap allocated variables

+        ------------------------------------------------------

+

+      The rewrite of the trace provides the machinery necessary

+      to properly free variables or undo actions following a

+      failed guess.

+

+      The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded

+      as part of the zzGUESS macro.  When a guess is opened

+      the value of zzrv is 0.  When a longjmp() is executed to

+      undo the guess, the value of zzrv will be 1.

+

+      The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded

+      as part of the zzGUESS_DONE macro.  This is executed

+      whether the guess succeeds or fails as part of closing

+      the guess.

+

+      The guessSeq is a sequence number which is assigned to each

+      guess and is incremented by 1 for each guess which becomes

+      active.  It is needed by the user to associate the start of

+      a guess with the failure and/or completion (closing) of a

+      guess.

+

+      Guesses are nested.  They must be closed in the reverse

+      of the order that they are opened.

+

+      In order to free memory used by a variable during a guess

+      a user must write a routine which can be called to

+      register the variable along with the current guess sequence

+      number provided by the zzUSER_GUESS_HOOK macro. If the guess

+      fails, all variables tagged with the corresponding guess

+      sequence number should be released.  This is ugly, but

+      it would require a major rewrite of antlr 1.33 to use

+      some mechanism other than setjmp()/longjmp().

+

+      The order of calls for a *successful* guess would be:

+

+        zzUSER_GUESS_HOOK(guessSeq,0);

+        zzUSER_GUESS_DONE_HOOK(guessSeq);

+

+      The order of calls for a *failed* guess would be:

+

+        zzUSER_GUESS_HOOK(guessSeq,0);

+        zzUSER_GUESS_HOOK(guessSeq,1);

+        zzUSER_GUESS_DONE_HOOK(guessSeq);

+

+      The default definitions of these macros are empty strings.

+

+      Here is an example in C++ mode.  The zzUSER_GUESS_HOOK and

+      zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine

+      can be used without change in both C and C++ versions.

+

+      ----------------------------------------------------------------------

+        <<

+

+        #include "AToken.h"

+

+        typedef ANTLRCommonToken ANTLRToken;

+

+        #include "DLGLexer.h"

+

+        int main() {

+

+          {

+            DLGFileInput     in(stdin);

+            DLGLexer         lexer(&in,2000);

+            ANTLRTokenBuffer pipe(&lexer,1);

+            ANTLRCommonToken aToken;

+            P                parser(&pipe);

+

+            lexer.setToken(&aToken);

+            parser.init();

+            parser.start();

+          };

+

+          fclose(stdin);

+          fclose(stdout);

+          return 0;

+        }

+

+        >>

+

+        <<

+        char *s=NULL;

+

+        #undef zzUSER_GUESS_HOOK

+        #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv);

+        #undef zzUSER_GUESS_DONE_HOOK

+        #define zzUSER_GUESS_DONE_HOOK(guessSeq)   myGuessHook(guessSeq,2);

+

+        void myGuessHook(int guessSeq,int zzrv) {

+          if (zzrv == 0) {

+            fprintf(stderr,"User hook: starting guess #%d\n",guessSeq);

+          } else if (zzrv == 1) {

+            free (s);

+            s=NULL;

+            fprintf(stderr,"User hook: failed guess #%d\n",guessSeq);

+          } else if (zzrv == 2) {

+            free (s);

+            s=NULL;

+            fprintf(stderr,"User hook: ending guess #%d\n",guessSeq);

+          };

+        }

+

+        >>

+

+        #token A    "a"

+        #token      "[\t \ \n]"     <<skip();>>

+

+        class P {

+

+        start : (top)+

+              ;

+

+        top   : (which) ?   <<fprintf(stderr,"%s is a which\n",s); free(s); s=NULL; >>

+              | other       <<fprintf(stderr,"%s is an other\n",s); free(s); s=NULL; >>

+              ; <<if (s != NULL) free(s); s=NULL; >>

+

+        which : which2

+              ;

+

+        which2 : which3

+              ;

+        which3

+              : (label)?         <<fprintf(stderr,"%s is a label\n",s);>>

+              | (global)?        <<fprintf(stderr,"%s is a global\n",s);>>

+              | (exclamation)?   <<fprintf(stderr,"%s is an exclamation\n",s);>>

+              ;

+

+        label :       <<s=strdup(LT(1)->getText());>> A ":" ;

+

+        global :      <<s=strdup(LT(1)->getText());>> A "::" ;

+

+        exclamation : <<s=strdup(LT(1)->getText());>> A "!" ;

+

+        other :       <<s=strdup(LT(1)->getText());>> "other" ;

+

+        }

+      ----------------------------------------------------------------------

+

+      This is a silly example, but illustrates the idea.  For the input

+      "a ::" with tracing enabled the output begins:

+

+      ----------------------------------------------------------------------

+        enter rule "start" depth 1

+        enter rule "top" depth 2

+        User hook: starting guess #1

+        enter rule "which" depth 3 guessing

+        enter rule "which2" depth 4 guessing

+        enter rule "which3" depth 5 guessing

+        User hook: starting guess #2

+        enter rule "label" depth 6 guessing

+        guess failed

+        User hook: failed guess #2

+        guess done - returning to rule "which3" at depth 5 (guess mode continues

+                                                 - an enclosing guess is still active)

+        User hook: ending guess #2

+        User hook: starting guess #3

+        enter rule "global" depth 6 guessing

+        exit rule "global" depth 6 guessing

+        guess done - returning to rule "which3" at depth 5 (guess mode continues

+                                                 - an enclosing guess is still active)

+        User hook: ending guess #3

+        enter rule "global" depth 6 guessing

+        exit rule "global" depth 6 guessing

+        exit rule "which3" depth 5 guessing

+        exit rule "which2" depth 4 guessing

+        exit rule "which" depth 3 guessing

+        guess done - returning to rule "top" at depth 2 (guess mode ends)

+        User hook: ending guess #1

+        enter rule "which" depth 3

+        .....

+      ----------------------------------------------------------------------

+

+      Remember:

+

+        (a) Only init-actions are executed during guess mode.

+        (b) A rule can be invoked multiple times during guess mode.

+        (c) If the guess succeeds the rule will be called once more

+              without guess mode so that normal actions will be executed.

+            This means that the init-action might need to distinguish

+              between guess mode and non-guess mode using the variable

+              [zz]guessing.

+

+#101. (Changed in 1.33MR10) antlr -info command line switch

+

+        -info

+

+            p   - extra predicate information in generated file

+

+            t   - information about tnode use:

+                    at the end of each rule in generated file

+                    summary on stderr at end of program

+

+            m   - monitor progress

+                    prints name of each rule as it is started

+                    flushes output at start of each rule

+

+            f   - first/follow set information to stdout

+

+            0   - no operation (added in 1.33MR11)

+

+      The options may be combined and may appear in any order.

+      For example:

+

+        antlr -info ptm -CC -gt -mrhoist on mygrammar.g

+

+#100a. (Changed in 1.33MR10) Predicate tree simplification

+

+      When the same predicates can be referenced in more than one

+      alternative of a block large predicate trees can be formed.

+

+      The difference that these optimizations make is so dramatic

+      that I have decided to use it even when -mrhoist is not selected.

+

+      Consider the following grammar:

+

+        start : ( all )* ;

+

+        all   : a

+              | d

+              | e

+              | f

+              ;

+

+        a     : c A B

+              | c A C

+              ;

+

+        c     : <<AAA(LATEXT(2))>>?

+              ;

+

+        d     : <<BBB(LATEXT(2))>>? B C

+              ;

+

+        e     : <<CCC(LATEXT(2))>>? B C

+              ;

+

+        f     : e X Y

+              ;

+

+      In rule "a" there is a reference to rule "c" in both alternatives.

+      The length of the predicate AAA is k=2 and it can be followed in

+      alternative 1 only by (A B) while in alternative 2 it can be

+      followed only by (A C).  Thus they do not have identical context.

+

+      In rule "all" the alternatives which refer to rules "e" and "f" allow

+      elimination of the duplicate reference to predicate CCC.

+

+      The table below summarized the kind of simplification performed by

+      1.33MR10.  In the table, X and Y stand for single predicates

+      (not trees).

+

+        (OR X (OR Y (OR Z)))  => (OR X Y Z)

+        (AND X (AND Y (AND Z)))  => (AND X Y Z)

+

+        (OR X  (... (OR  X Y) ... ))     => (OR X (... Y ... ))

+        (AND X (... (AND X Y) ... ))     => (AND X (... Y ... ))

+        (OR X  (... (AND X Y) ... ))     => (OR X (...  ... ))

+        (AND X (... (OR  X Y) ... ))     => (AND X (...  ... ))

+

+        (AND X)               => X

+        (OR X)                => X

+

+      In a test with a complex grammar for a real application, a predicate

+      tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)".

+

+      In 1.33MR10 there is a greater effort to release memory used

+      by predicates once they are no longer in use.

+

+#100b. (Changed in 1.33MR10) Suppression of extra predicate tests

+

+      The following optimizations require that -mrhoist be selected.

+

+      It is relatively easy to optimize the code generated for predicate

+      gates when they are of the form:

+

+            (AND X Y Z ...)

+        or  (OR  X Y Z ...)

+

+      where X, Y, Z, and "..." represent individual predicates (leaves) not

+      predicate trees.

+

+      If the predicate is an AND the contexts of the X, Y, Z, etc. are

+      ANDed together to create a single Tree context for the group and

+      context tests for the individual predicates are suppressed:

+

+            --------------------------------------------------

+            Note: This was incorrect.  The contexts should be

+            ORed together.  This has been fixed.  A more 

+            complete description is available in item #152.

+            ---------------------------------------------------

+

+      Optimization 1:  (AND X Y Z ...)

+

+        Suppose the context for Xtest is LA(1)==LP and the context for

+        Ytest is LA(1)==LP && LA(2)==ID.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    !(LA(1)==LP && LA(1)==LP && LA(2)==ID) ||

+                        ( (! LA(1)==LP || Xtest) &&

+                          (! (LA(1)==LP || LA(2)==ID) || Xtest)

+                        )) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {...

+

+      Optimization 2: (OR X Y Z ...) with identical contexts

+

+        Suppose the context for Xtest is LA(1)==ID and for Ytest

+        the context is also LA(1)==ID.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==ID || LA(1)==ID) ||

+                        (LA(1)==ID && Xtest) ||

+                        (LA(1)==ID && Ytest) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    (! LA(1)==ID) || (Xtest || Ytest) {...

+

+      Optimization 3: (OR X Y Z ...) with distinct contexts

+

+        Suppose the context for Xtest is LA(1)==ID and for Ytest

+        the context is LA(1)==LP.

+

+            Without the optimization the code would resemble:

+

+                if (lookaheadContext &&

+                    ! (LA(1)==ID || LA(1)==LP) ||

+                        (LA(1)==ID && Xtest) ||

+                        (LA(1)==LP && Ytest) {...

+

+            With the -mrhoist optimization the code would resemble:

+

+                if (lookaheadContext &&

+                        (zzpf=0,

+                            (LA(1)==ID && (zzpf=1) && Xtest) ||

+                            (LA(1)==LP && (zzpf=1) && Ytest) ||

+                            !zzpf) {

+

+            These may appear to be of similar complexity at first,

+            but the non-optimized version contains two tests of each

+            context while the optimized version contains only one

+            such test, as well as eliminating some of the inverted

+            logic (" !(...) || ").

+

+      Optimization 4: Computation of predicate gate trees

+

+        When generating code for the gates of predicate expressions

+        antlr 1.33 vanilla uses a recursive procedure to generate

+        "&&" and "||" expressions for testing the lookahead. As each

+        layer of the predicate tree is exposed a new set of "&&" and

+        "||" expressions on the lookahead are generated.  In many

+        cases the lookahead being tested has already been tested.

+

+        With -mrhoist a lookahead tree is computed for the entire

+        lookahead expression.  This means that predicates with identical

+        context or context which is a subset of another predicate's

+        context disappear.

+

+        This is especially important for predicates formed by rules

+        like the following:

+

+            uppperCaseVowel : <<isUpperCase(LATEXT(1))>>?  vowel;

+            vowel:          : <<isVowel(LATEXT(1))>>? LETTERS;

+

+        These predicates are combined using AND since both must be

+        satisfied for rule upperCaseVowel.  They have identical

+        context which makes this optimization very effective.

+

+      The affect of Items #100a and #100b together can be dramatic.  In

+      a very large (but real world) grammar one particular predicate

+      expression was reduced from an (unreadable) 50 predicate leaves,

+      195 LA(1) terms, and 5500 characters to an (easily comprehensible)

+      3 predicate leaves (all different) and a *single* LA(1) term.

+

+#98.  (Changed in 1.33MR10) Option "-info p"

+

+      When the user selects option "-info p" the program will generate

+      detailed information about predicates.  If the user selects

+      "-mrhoist on" additional detail will be provided explaining

+      the promotion and suppression of predicates.  The output is part

+      of the generated file and sandwiched between #if 0/#endif statements.

+

+      Consider the following k=1 grammar:

+

+        start : ( all ) * ;

+

+        all   : ( a

+                | b

+                )

+                ;

+

+        a     : c B

+              ;

+

+        c     : <<LATEXT(1)>>?

+              | B

+              ;

+

+        b     : <<LATEXT(1)>>? X

+              ;

+

+      Below is an excerpt of the output for rule "start" for the three

+      predicate options (off, on, and maintenance release style hoisting).

+

+      For those who do not wish to use the "-mrhoist on" option for code

+      generation the option can be used in a "diagnostic" mode to provide

+      valuable information:

+

+            a. where one should insert null actions to inhibit hoisting

+            b. a chain of rule references which shows where predicates are

+               being hoisted

+

+      ======================================================================

+      Example of "-info p" with "-mrhoist on"

+      ======================================================================

+        #if 0

+

+        Hoisting of predicate suppressed by alternative without predicate.

+        The alt without the predicate includes all cases where the

+           predicate is false.

+

+           WITH predicate: line 11  v36.g

+           WITHOUT predicate: line 12  v36.g

+

+        The context set for the predicate:

+

+             B

+

+        The lookahead set for alt WITHOUT the semantic predicate:

+

+             B

+

+        The predicate:

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+               B

+            tree context: null

+

+        Chain of referenced rules:

+

+            #0  in rule start (line 1 v36.g) to rule all

+            #1  in rule all (line 3 v36.g) to rule a

+            #2  in rule a (line 8 v36.g) to rule c

+            #3  in rule c (line 11 v36.g)

+

+        #endif

+        &&

+        #if 0

+

+        pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+          set context:

+             X

+          tree context: null

+

+        #endif

+      ======================================================================

+      Example of "-info p"  with the default -prc setting ( "-prc off")

+      ======================================================================

+        #if 0

+

+        OR

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+              nil

+            tree context: null

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+            set context:

+              nil

+            tree context: null

+

+        #endif

+      ======================================================================

+      Example of "-info p" with "-prc on" and "-mrhoist off"

+      ======================================================================

+        #if 0

+

+        OR

+          pred <<  LATEXT(1)>>?  depth=k=1  rule c  line 11  v36.g

+

+            set context:

+               B

+            tree context: null

+

+          pred <<  LATEXT(1)>>?  depth=k=1  rule b  line 15  v36.g

+

+            set context:

+               X

+            tree context: null

+

+        #endif

+      ======================================================================

+

+#60.  (Changed in 1.33MR7) Major changes to exception handling

+

+        There were significant problems in the handling of exceptions

+        in 1.33 vanilla.  The general problem is that it can only

+        process one level of exception handler.  For example, a named

+        exception handler, an exception handler for an alternative, or

+        an exception for a subrule  always went to the rule's exception

+        handler if there was no "catch" which matched the exception.

+

+        In 1.33MR7 the exception handlers properly "nest".  If an

+        exception handler does not have a matching "catch" then the

+        nextmost outer exception handler is checked for an appropriate

+        "catch" clause, and so on until an exception handler with an

+        appropriate "catch" is found.

+

+        There are still undesirable features in the way exception

+        handlers are implemented, but I do not have time to fix them

+        at the moment:

+

+            The exception handlers for alternatives are outside the

+            block containing the alternative.  This makes it impossible

+            to access variables declared in a block or to resume the

+            parse by "falling through".  The parse can still be easily

+            resumed in other ways, but not in the most natural fashion.

+

+            This results in an inconsistentcy between named exception

+            handlers and exception handlers for alternatives.  When

+            an exception handler for an alternative "falls through"

+            it goes to the nextmost outer handler - not the "normal

+            action".

+

+        A major difference between 1.33MR7 and 1.33 vanilla is

+        the default action after an exception is caught:

+

+            1.33 Vanilla

+            ------------

+            In 1.33 vanilla the signal value is set to zero ("NoSignal")

+            and the code drops through to the code following the exception.

+            For named exception handlers this is the "normal action".

+            For alternative exception handlers this is the rule's handler.

+

+            1.33MR7

+            -------

+            In 1.33MR7 the signal value is NOT automatically set to zero.

+

+            There are two cases:

+

+                For named exception handlers: if the signal value has been

+                set to zero the code drops through to the "normal action".

+

+                For all other cases the code branches to the nextmost outer

+                exception handler until it reaches the handler for the rule.

+

+        The following macros have been defined for convenience:

+

+            C/C++ Mode Name

+            --------------------

+            (zz)suppressSignal

+                  set signal & return signal arg to 0 ("NoSignal")

+            (zz)setSignal(intValue)

+                  set signal & return signal arg to some value

+            (zz)exportSignal

+                  copy the signal value to the return signal arg

+

+        I'm not sure why PCCTS make a distinction between the local

+        signal value and the return signal argument, but I'm loathe

+        to change the code. The burden of copying the local signal

+        value to the return signal argument can be given to the

+        default signal handler, I suppose.

+

+#53.  (Explanation for 1.33MR6) What happens after an exception is caught ?

+

+        The Book is silent about what happens after an exception

+        is caught.

+

+        The following code fragment prints "Error Action" followed

+        by "Normal Action".

+

+        test : Word ex:Number <<printf("Normal Action\n");>>

+                exception[ex]

+                   catch NoViableAlt:

+                        <<printf("Error Action\n");>>

+        ;

+

+        The reason for "Normal Action" is that the normal flow of the

+        program after a user-written exception handler is to "drop through".

+        In the case of an exception handler for a rule this results in

+        the exection of a "return" statement.  In the case of an

+        exception handler attached to an alternative, rule, or token

+        this is the code that would have executed had there been no

+        exception.

+

+        The user can achieve the desired result by using a "return"

+        statement.

+

+        test : Word ex:Number <<printf("Normal Action\n");>>

+                exception[ex]

+                   catch NoViableAlt:

+                        <<printf("Error Action\n"); return;>>

+        ;

+

+        The most powerful mechanism for recovery from parse errors

+        in pccts is syntactic predicates because they provide

+        backtracking.  Exceptions allow "return", "break",

+        "consumeUntil(...)", "goto _handler", "goto _fail", and

+        changing the _signal value.

+

+#41.  (Added in 1.33MR6) antlr -stdout

+

+        Using "antlr -stdout ..." forces the text that would

+        normally go to the grammar.c or grammar.cpp file to

+        stdout.

+

+#40.  (Added in 1.33MR6) antlr -tab to change tab stops

+

+        Using "antlr -tab number ..." changes the tab stops

+        for the grammar.c or grammar.cpp file.  The number

+        must be between 0 and 8.  Using 0 gives tab characters,

+        values between 1 and 8 give the appropriate number of

+        space characters.

+

+#34.  (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue)

+

+        Previously there was no public function for changing the line

+        number maintained by the lexer.

+

+#28.   (Added to 1.33MR1) More control over DLG header

+

+        Version 1.33MR1 adds the following directives to PCCTS

+        for C++ mode:

+

+          #lexprefix  <<source code>>

+

+                Adds source code to the DLGLexer.h file

+                after the #include "DLexerBase.h" but

+                before the start of the class definition.

+

+          #lexmember  <<source code>>

+

+                Adds source code to the DLGLexer.h file

+                as part of the DLGLexer class body.  It

+                appears immediately after the start of

+                the class and a "public: statement.

+

diff --git a/Source/Pccts/KNOWN_PROBLEMS.txt b/Source/Pccts/KNOWN_PROBLEMS.txt
new file mode 100644
index 0000000..5a9b22e
--- /dev/null
+++ b/Source/Pccts/KNOWN_PROBLEMS.txt
@@ -0,0 +1,241 @@
+

+    =======================================================

+    Known Problems In PCCTS - Last revised 14 November 1998

+    =======================================================

+

+#17. The dlg fix for handling characters up to 255 is incorrect.

+

+    See item #207.

+

+    Reported by Frank Hartmann.

+        

+#16. A note about "&&" predicates (Mike Dimmick)

+

+    Mike Dimmick has pointed out a potential pitfall in the use of the

+    "&&" style predicate.  Consider:

+    

+         r0: (g)? => <<P>>?  r1

+             | ...

+             ;

+         r1: A | B;

+         

+    If the context guard g is not a subset of the lookahead context for r1

+    (in other words g is neither A nor B) then the code may execute r1 

+    even when the lookahead context is not satisfied.  This is an error

+    by the person coding the grammer, and the error should be reported to

+    the user, but it isn't. expect.  Some examples I've run seem to

+    indicate that such an error actually results in the rule becoming

+    unreachable.

+    

+    When g is properly coded the code is correct, the problem is when g

+    is not properly coded.

+    

+    A second problem reported by Mike Dimmick is that the test for a

+    failed validation predicate is equivalent to a test on the predicate

+    along.  In other words, if the "&&" has not been hoisted then it may

+    falsely report a validation error.

+

+#15. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions

+

+    An bug (or at least an oddity) is that a reference to LT(1), LA(1),

+    or LATEXT(1) in an action which immediately follows a token match

+    in a rule refers to the token matched, not the token which is in

+    the lookahead buffer.  Consider:

+

+        r : abc <<action alpha>> D <<action beta>> E;

+

+    In this case LT(1) in action alpha will refer to the next token in

+    the lookahead buffer ("D"), but LT(1) in action beta will refer to

+    the token matched by D - the preceding token.

+

+    A warning has been added which warns users about this when an action

+    following a token match contains a reference to LT(1), LA(1), or LATEXT(1).

+

+    This behavior should be changed, but it appears in too many programs

+    now.  Another problem, perhaps more significant, is that the obvious

+    fix (moving the consume() call to before the action) could change the 

+    order in which input is requested and output appears in existing programs.

+

+    This problem was reported, along with a fix by Benjamin Mandel

+    (beny@sd.co.il).  However, I felt that changing the behavior was too

+    dangerous for existing code.

+

+#14. Parsing bug in dlg

+

+    THM: I have been unable to reproduce this problem.

+

+    Reported by Rick Howard Mijenix Corporation (rickh@mijenix.com).

+

+    The regular expression parser (in rexpr.c) fails while

+    trying to parse the following regular expression:

+

+            {[a-zA-Z]:}(\\\\[a-zA-Z0-9]*)+

+

+    See my comment in the following excerpt from rexpr.c:

+

+    /*

+     * <regExpr>        ::= <andExpr> ( '|' {<andExpr>} )*

+     *

+     * Return -1 if syntax error

+     * Return  0 if none found

+     * Return  1 if a regExrp was found

+     */

+	static

+	regExpr(g)

+	GraphPtr g;

+	{

+	    Graph g1, g2;

+	

+	    if ( andExpr(&g1) == -1 )

+	    {

+	        return -1;

+	    }

+	

+	    while ( token == '|' )

+	    {

+	        int a;

+	        next();

+	        a = andExpr(&g2);

+	        if ( a == -1 ) return -1;   /* syntax error below */

+	        else if ( !a ) return 1;    /* empty alternative */

+	        g1 = BuildNFA_AorB(g1, g2);

+	    }

+	

+	    if ( token!='\0' ) return -1;

+	*****

+	***** It appears to fail here becuause token is 125 - the closing '}'

+	***** If I change it to:

+	*****    if ( token!='\0' && token!='}' && token!= ')' ) return -1;

+	*****

+	***** It succeeds, but I'm not sure this is the corrrect approach.

+	*****

+	    *g = g1;

+	    return 1;

+	}

+

+#13. dlg reports an invalid range for: [\0x00-\0xff]

+

+    Diagnosed by Piotr Eljasiak (eljasiak@no-spam.zt.gdansk.tpsa.pl):

+

+    Fixed in MR16.

+

+#12. Strings containing comment actions

+

+     Sequences that looked like C style comments appearing in string

+     literals are improperly parsed by antlr/dlg.

+

+        << fprintf(out," /* obsolete */ ");

+

+     For this case use:

+

+        << fprintf(out," \/\* obsolete \*\/ ");

+

+     Reported by K.J. Cummings (cummings@peritus.com).

+

+#11. User hook for deallocation of variables on guess fail

+

+     The mechanism outlined in Item #108 works only for

+     heap allocated variables.

+

+#10. Label re-initialization in ( X {y:Y} )*

+

+     If a label assignment is optional and appears in a

+     (...)* or (...)+ block it will not be reset to NULL

+     when it is skipped by a subsequent iteration.

+

+     Consider the example:

+

+            ( X { y:Y })* Z

+

+     with input:

+

+            X Y X Z

+

+     The first time through the block Y will be matched and

+     y will be set to point to the token.  On the second

+     iteration of the (...)* block there is no match for Y.

+     But y will not be reset to NULL, as the user might

+     expect, it will contain a reference to the Y that was

+     matched in the first iteration.

+

+     The work-around is to manually reset y:

+

+            ( X << y = NULL; >> { y:Y } )* Z

+

+        or

+

+            ( X ( y:Y | << y = NULL; >> /* epsilon */ ) )* Z

+

+     Reported by Jeff Vincent (JVincent@novell.com).

+

+#9. PCCTAST.h PCCTSAST::setType() is a noop

+

+#8. #tokdefs with ~Token and .

+

+    THM: I have been unable to reproduce this problem.

+

+    When antlr uses #tokdefs to define tokens the fields of

+    #errclass and #tokclass do not get properly defined.

+    When it subsequently attempts to take the complement of

+    the set of tokens (using ~Token or .) it can refer to

+    tokens which don't have names, generating a fatal error.

+

+#7. DLG crashes on some invalid inputs

+

+    THM:  In MR20 have fixed the most common cases.

+

+    The following token defintion will cause DLG to crash.

+

+        #token "()"

+

+    Reported by  Mengue Olivier (dolmen@bigfoot.com).

+

+#6. On MS systems \n\r is treated as two new lines

+

+    Fixed.

+

+#5. Token expressions in #tokclass

+

+    #errclass does not support TOK1..TOK2 or ~TOK syntax.

+    #tokclass does not support ~TOKEN syntax

+

+    A workaround for #errclass TOK1..TOK2 is to use a

+    #tokclass.

+

+    Reported by Dave Watola (dwatola@amtsun.jpl.nasa.gov)

+

+#4. A #tokdef must appear "early" in the grammar file.

+

+    The "early" section of the grammar file is the only

+    place where the following directives may appear:

+

+        #header

+        #first

+        #tokdefs

+        #parser

+

+    Any other kind of statement signifiies the end of the

+    "early" section.

+

+#3. Use of PURIFY macro for C++ mode

+

+    Item #93 of the CHANGES_FROM_1.33 describes the use of

+    the PURIFY macro to zero arguments to be passed by

+    upward inheritance.

+

+        #define PURIFY(r, s) memset((char *) &(r), '\0', (s));

+

+    This may not be the right thing to do for C++ objects that

+    have constructors.  Reported by Bonny Rais (bonny@werple.net.au).

+

+    For those cases one should #define PURIFY to be an empty macro

+    in the #header or #first actions.

+

+#2. Fixed in 1.33MR10 - See CHANGES_FROM_1.33 Item #80.

+

+#1. The quality of support for systems with 8.3 file names leaves

+    much to be desired.  Since the kit is distributed using the

+    long file names and the make file uses long file names it requires

+    some effort to generate.  This will probably not be changed due

+    to the large number of systems already written using the long

+    file names.

diff --git a/Source/Pccts/MPW_Read_Me b/Source/Pccts/MPW_Read_Me
new file mode 100644
index 0000000..70a9d1b
--- /dev/null
+++ b/Source/Pccts/MPW_Read_Me
@@ -0,0 +1,21 @@
+

+1. You can control the creator type of generated files by changing a value of

+   #if control statement.

+

+

+   pccts:h:pcctscfg.h

+

+   line 225-231

+

+	#if 0

+	#define MAC_FILE_CREATOR 'MPS '   /* MPW Text files */

+	#endif

+	#if 0

+	#define MAC_FILE_CREATOR 'KAHL'   /* THINK C/Symantec C++ Text files */

+	#endif

+	#if 0

+	#define MAC_FILE_CREATOR 'CWIE'   /* Metrowerks C/C++ Text files */

+	#endif

+

+2.  If you want to build 68K version. You must convert all source files to Macintosh

+    format before compile.

diff --git a/Source/Pccts/NOTES.bcc b/Source/Pccts/NOTES.bcc
new file mode 100644
index 0000000..1ac05b1
--- /dev/null
+++ b/Source/Pccts/NOTES.bcc
@@ -0,0 +1,184 @@
+March 95

+Version 1.32 of pccts

+ 

+At the moment this file is available via anonymous FTP at

+ 

+        Node: marvin.ecn.purdue.edu

+        File: pub/pccts/1.32/NOTES.BCC

+ 

+Mail corrections or additions to David Seidel <71333.1575@compuserve.com>

+===============================================================================

+Notes on Building PCCTS 1.32 with Borland C++

+ 

+David Seidel, Innovative Data Concepts Incorporated

+CompuServe: 71333,1575

+Internet:   71333.1575@compuserve.com

+            dseidel@delphi.com

+ 

+I have gotten ANTLR and DLG to succesfully build with BCC 4.0, but have found

+from experience that ANTLR, in particular, is likely to run out of memory

+with grammars over a certain size, or with larger values for the -k and -ck

+options.  Now that BCC 4.02 and the new Borland Power Pack for DOS is now

+available, I feel that there is no excuse not to build these tools as

+32-bit executables, as they ought to be.

+ 

+For people without the Power Pack, the makefiles below should be fairly easily

+modified to build 16-bit real-mode executables, but I don't really recommend

+it.  As an alternative, you might consider the highly regarded DJGPP compiler

+(a DOS port of the Gnu GCC compiler, with a DOS extender included).  Hopefully

+some other PCCTS who has DJGPP can provode whatever advice is necessary.  The

+Watcom compiler is also an excellent possibility (albeit a commercial one),

+and I hope to make available Watcom makefiles in the near future.

+ 

+Here are the makefiles I am using.  Both makefiles use a compiler configuration

+file that contains compiler switches such as optimization settings.  I call

+this file bor32.cfg and keep a copy in both the ANTLR and DLG subdirectories.

+ 

+==== File: bor32.cfg (cut here) ===============================================

+-w-

+-RT-

+-x-

+-N-

+-k-

+-d

+-O2-e-l

+-Z

+-D__STDC__=1

+==== End of file bor32.cfg (cut here) =========================================

+ 

+==== File: antlr\bor32.mak (cut here) =========================================

+#

+#  ANTLR 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by

+#  David Seidel

+#  Innovative Data Concepts Incorporated

+#  71333.1575@compuserve.com (or) dseidel@delphi.com

+#

+#  Notes:   1. Compiler switches (optimization etc.) are contained in the

+#              file bor32.cfg.

+#           2. This makefile requires Borland C++ 4.02 or greater with

+#              the DOS Power Pack add-on package.

+#           3. Change the BCCDIR macro below to the topmost directory in

+#              which BCC is installed on your system.

+#

+ 

+BCCDIR   =  d:\bc4

+CC       =  bcc32

+SET      =  ..\support\set

+PCCTS_H  =  ..\h

+ANTLR    =  ..\bin\antlr

+DLG      =  ..\bin\dlg

+CFLAGS   =  -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \

+ +bor32.cfg

+LIBS     =  dpmi32 cw32

+OBJ_EXT  =  obj

+OBJS     =  antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj fset.obj \

+ gen.obj globals.obj hash.obj lex.obj main.obj misc.obj pred.obj dialog.obj \

+ set.obj

+ 

+.c.obj:

+      $(CC) -c $(CFLAGS) {$&.c }

+ 

+antlr.exe: $(OBJS)

+   tlink32 @&&|

+-Tpe -ax -c -s -L$(BCCDIR)\lib +

+$(BCCDIR)\lib\c0x32 $**

+$@

+ 

+$(LIBS)

+;

+|

+   copy *.exe ..\bin

+ 

+ 

+# *********** Target list of PC machines ***********

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+ 

+# leave this commented out for initial build!

+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+#   $(ANTLR) antlr.g

+ 

+antlr.$(OBJ_EXT): antlr.c mode.h tokens.h

+ 

+scan.$(OBJ_EXT): scan.c mode.h tokens.h

+ 

+# leave this commented out for initial build!

+#scan.c mode.h: parser.dlg

+#   $(DLG) -C2 parser.dlg scan.c

+ 

+set.$(OBJ_EXT): $(SET)\set.c

+   $(CC) -c $(CFLAGS) $(SET)\set.c

+ 

+==== End of file antlr\bor32.mak (cut here) ===================================

+ 

+==== File: dlg\bor32.mak (cut here) ===========================================

+#

+#  DLG 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by

+#  David Seidel

+#  Innovative Data Concepts Incorporated

+#  71333.1575@compuserve.com (or) dseidel@delphi.com

+#

+#  Notes:   1. Compiler switches (optimization etc.) are contained in the

+#              file bor32.cfg.

+#           2. This makefile requires Borland C++ 4.02 or greater with

+#              the DOS Power Pack add-on package.

+#           3. Change the BCCDIR macro below to the topmost directory in

+#              which BCC is installed on your system.

+#

+ 

+ 

+BCCDIR   =  d:\bc4

+CC       =  bcc32

+SET      =  ..\support\set

+PCCTS_H  =  ..\h

+ANTLR    =  ..\bin\antlr

+DLG      =  ..\bin\dlg

+CFLAGS   =  -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \

+ +bor32.cfg

+LIBS     =  dpmi32 cw32

+OBJ_EXT  =  obj

+OBJS     =  dlg_p.obj dlg_a.obj main.obj err.obj support.obj \

+ output.obj relabel.obj automata.obj set.obj

+ 

+.c.obj:

+      $(CC) -c $(CFLAGS) {$&.c }

+ 

+dlg.exe : $(OBJS)

+   tlink32 @&&|

+-Tpe -ax -c -s -L$(BCCDIR)\lib +

+c0x32 $**

+$@

+ 

+$(LIBS)

+;

+|

+   copy *.exe ..\bin

+ 

+dlg_p.obj:  dlg_p.c

+ 

+dlg_a.obj:  dlg_a.c

+ 

+main.obj:   main.c

+ 

+err.obj:    err.c

+ 

+support.obj:   support.c

+ 

+output.obj: output.c

+ 

+relabel.obj:   relabel.c

+ 

+automata.obj:  automata.c

+ 

+set.$(OBJ_EXT): $(SET)\set.c

+   $(CC) -c $(CFLAGS) $(SET)\set.c

+ 

+==== End of file dlg\bor32.mak (cut here) =====================================

+ 

+ 

+ 

+

+

+

diff --git a/Source/Pccts/NOTES.msvc b/Source/Pccts/NOTES.msvc
new file mode 100644
index 0000000..86f8ed6
--- /dev/null
+++ b/Source/Pccts/NOTES.msvc
@@ -0,0 +1,189 @@
+

+                        Microsoft Visual C Stuff

+

+

+[Tom Moog 2-Oct-98

+

+    Users of Microsoft Visual C++ should download a separate

+    ready-to-run zip file from my web site.  It contains 

+    binaries, static library, and a sample project.

+]

+

+[

+  Two notes added by Tom Moog 23-Sep-97.  I believe the *.dsp and

+  *.mak files that were once at the end of this file are now obsolete.

+  

+  The following MSVC .dsp and .mak files for pccts and sorcerer

+  were contributed by Stanislaw Bochnak (S.Bochnak@microtool.com.pl)

+  and Jeff Vincent (jvincent@novell.com)

+

+        PCCTS Distribution Kit

+        ----------------------

+        pccts/antlr/AntlrMSVC50.dsp

+        pccts/antlr/AntlrMSVC50.mak

+

+        pccts/dlg/DlgMSVC50.dsp

+        pccts/dlg/DlgMSVC50.mak

+

+        pccts/support/genmk/watgenmk.mak

+        pccts/support/msvc.dsp

+

+        Sorcerer Distribution Kit

+        -------------------------

+        pccts/sorcerer/SorcererMSVC50.dsp

+        pccts/sorcerer/SorcererMSVC50.mak

+

+        pccts/sorcerer/lib/msvc.dsp

+

+  I do not have an MS based computer.  If you discover problems

+  please report them so as to save trouble for others in the future.

+]

+

+[

+ Modified by Terence Parr (September 1995) to change .C to .cpp

+]

+

+[

+ This file contains notes on MSVC for Windows NT console execs by Dave

+ Seidel and an explanation of flags etc.. by John Hall; good luck,

+ Terence

+]

+

+===============================================================================

+Date: Sat, 31 Dec 1994 11:40:36 -0500 (EST)

+From: David Seidel <75342.2034@compuserve.com>

+

+I've succesfully build 1.31b3 with djgpp for DOS and MSVC 2.0 for Windows 

+NT.  The only (minor) problem I had was that GNU make (version 3.71, in the 

+djgpp port) complained about "multiple targets" in both the antlr and dlg 

+makefiles.  I got around the error by, in each makefile, commenting out the 

+$(SRC) dependency, for example:

+

+   antlr: $(OBJ) #$(SRC)

+

+I don't know why this is happenning, since you haven't changed that part of 

+the makefile at all, and I think this used to work ok...

+

+Here are the makefiles I built from within the MSVC 2.0 environment for antlr 

+and dlg and Windows NT console executables.  Please feel free to pass them 

+on.  Of course, as soon as 1.31 "goes gold", I will send you nice new 

+binaries.  I'm not going to bother to keep doing both Borland and djgpp for 

+DOS however.  Instead, I'll just keep the djgpp version up to date and also 

+provide WinNT binaries.

+

+Dave

+===============================================================================

+

+         How to port PCCTS 1.10 (and 1.32 hopefully) to Visual C++

+

+                                   By

+

+                       John Hall <jhall@ivy.wpi.edu>

+

+Here is how to compile an ANTLR grammar in Visual C++.  These steps

+describe how to have your ANTLR grammar parse the input file the user

+selects when they choose File Open in your Windows application.  (Even

+if you aren't using Visual C++, the steps should be portable enough to

+other compilers.)

+

+ * Make sure that ANTLR and DLG generate ANSI code (use the -ga

+   switch).

+

+ * Set the following compiler flags in Visual C++ (these are in the

+   Memory Model category of the compiler options in the Project

+   Options menu):

+

+   FLAG MEANING

+   ==== ==============================================================

+   /AL  Large memory model (multiple data segments; data items must be

+    smaller than 64K).

+

+   /Gtn Allocates all items whose size is greater than or equal to n

+    in a new data segment.  (I let n be 256: /Gt256.)

+

+   /Gx- All references to data items are done with far addressing in

+    case they are placed in a far segment.

+

+ * Add the following member variable to the attributes section of your

+   derived CDocument class (you will need to make sure you also

+   include stdio.h):

+

+   FILE *fp;

+

+ * Add the following method to your derived CDocument class:

+

+   BOOL CAppDoc::OnOpenDocument(const char* pszPathName)

+   {

+       // Call CDocument's OnOpenDocument to do housekeeping for us

+       // DON'T add anything to the loading section of Serialize

+       if (!CDocument::OnOpenDocument(pszPathName))

+           return FALSE;

+   

+       // Open input file

+       if ((fp = fopen(pszPathName, "r")) == NULL)

+           return FALSE;

+   

+       // Parse input file

+       ANTLR(start(), fp);

+   

+       // Close input file

+       fclose(fp);

+       return TRUE;

+   }

+

+   (Note: additional code may be necessary, depending on your parser.

+   For example, if your parser uses PCCTS's symbol table library, you

+   will need to insert calls to zzs_init and zzs_done.)

+

+ * Compile the generated C files as C++ files.  (I renamed the files

+   to have a .CPP extension to fool Visual C++ into thinking they were

+   C++ files.  One might also use the /Tp switch, but that switch

+   requires you separately include the filename.)  [I used this step

+   as an easy out for all the external linking errors I was getting

+   that I couldn't fix by declaring things extern "C".]

+

+ * Make sure the __STDC__ portion of the generated files gets

+   compiled.  (Either define __STDC__ yourself or else change all

+   occurrences of __STDC__ to __cplusplus in the generated files.  You

+   can define __STDC__ in the Preprocessor category of the compiler

+   options.)

+

+        ================================================================

+        = Note 23-Sep-97: This is probably not necessary any more.     =

+        = With 1.33MRxxx the use of __STDC__ was replaced with the     =

+        = macro __USE_PROTOS to control the compilation of prototypes. =

+        ================================================================

+                        

+That last step is important for Visual C++, but may not apply to other

+compilers.  For C++ compilers, whether __STDC__ is defined is

+implementation dependent (ARM, page 379).  Apparently, Visual C++ does

+not to define it; it also does not support "old style" C function

+definitions (which is okay, according to page 404 of the ARM).  Those

+two things together caused problems when trying to port the code.

+When it saw this:

+

+#ifdef __STDC__

+void

+globals(AST **_root)

+#else

+globals(_root)

+AST **_root;

+#endif

+

+it skipped the __STDC__ section and tried to process the "old style"

+function definition, where it choked.

+

+When you finally get your parser to compile and link without error,

+you may get General Protection Fault errors at run time.  The problem

+I had was that a NULL was passed to a variable argument function

+without an explicit cast.  The function grabbed a pointer (32-bits)

+off the stack using va_arg, but the NULL was passed silently as the

+integer 0 (16 bits), making the resulting pointer was invalid.  (This

+was in PCCTS's sample C parser.)

+

+There is one other thing I might suggest to help you avoid a run-time

+error.  Make sure you redefine the default error reporting function,

+zzsyn.  To do this, put "#define USER_ZZSYN" in your #header section

+and put your own zzsyn somewhere.  You can then pop up a MessageBox or

+print the error to some output window.

+===============================================================================

diff --git a/Source/Pccts/README b/Source/Pccts/README
new file mode 100644
index 0000000..d089b63
--- /dev/null
+++ b/Source/Pccts/README
@@ -0,0 +1,159 @@
+

+                          Parr Research Corporation

+                                    with

+                  Purdue University Electrical Engineering

+                                    and

+                       University of Minnesota, AHPCRC

+

+                                Terence Parr

+                                Russell Quong

+                                 Will Cohen

+                                 Hank Dietz

+

+

+A central place for information about PCCTS 1.33 is:

+

+        http://www.polhode.com/pccts.html

+

+The maintenance release is available from:

+

+        http://www.polhode.com/pccts133mr.zip

+

+There is a ready-to-run version for win32 for Microsoft Visual Studio

+at the same site.  It is available from:

+

+        http://www.polhode.com/win32.zip

+

+New users should visit http://www.polhode.com/pccts.html in

+order to get the following document:

+

+        "Notes For New Users of PCCTS"

+

+This is a Postscript file of about 40 pages which is extremely 

+useful for someone starting out. It is a based on 1.33mr21

+

+When you have a little more experience, be sure to review the

+following documents in the distribution kit:

+

+            CHANGES_FROM_133.txt

+            CHANGES_FROM_133_BEFORE_MR13.txt

+            KNOWN_PROBLEMS.txt

+

+-------------------------------------------------------------------------

+                      INSTALLATION (Unix)

+-------------------------------------------------------------------------

+0. Download http://www.polhode.com/pccts133mr.zip

+

+1. Unzip the distribution kit to your preferred location.  

+   If there are newline problems try using zip -a ...

+

+2. cd to the main pccts directory.

+

+3. make

+

+   This will create:

+

+        antlr

+        dlg

+        sorcerer

+        genmk

+

+4. Copy to /usr/local/bin or /usr/local/bin if you like.  If you

+   don't wish to then add pccts/bin to your path.

+

+5. To get an up-to-date list of program options execute the

+   program with no command line options.  To get up-to-date

+   documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt

+   at:

+

+           http://www.polhode.com/pccts.html

+

+6. You need not create a library.  The makefile created by genmk

+   assumes that the files are not part of a library. 

+

+   If you wish to create a library from elements of pccts/h:

+

+   If the first letter of the filename is lowercase (uppercase) it is

+   related to the code generated using the pccts C mode (C++ mode).

+   Some of the .c and .cpp files in the h directory are not meant to

+   be placed in a library and will not compile because they are meant

+   to be #include in pccts generated files which are grammar specific.

+

+   For C++ users place the following elements in the library:

+

+        AParser.cpp

+        ASTBase.cpp

+        ATokenBuffer.cpp

+        BufFileInput.cpp (optional)

+        DLexerBase.cpp

+        PCCTSAST.cpp

+        SList.cpp

+

+-------------------------------------------------------------------------

+                    INSTALLATION (Win32)

+-------------------------------------------------------------------------

+

+I've tried to keep the win32 kit to the minimum necessary to get 

+up and running.  The complete kit contains additional information

+(some historical), source code, and DevStudio projects for 

+rebuilding pccts from the source code.

+

+The kit is now distributed with both MSVC 5 and MSVC6 style projects.

+

+0. Download http://www.polhode.com/win32.zip.

+

+   You may also wish to download:

+

+        http://www.polhode.com/CHANGES_FROM_133.txt

+        http://www.polhode.com/CHANGES_FROM_133_BEFORE_MR13.txt

+        http://www.polhode.com/KNOWN_PROBLEMS.txt

+

+1. Unzip the distribution kit to your preferred location.

+

+   This will create:

+

+         a pccts directory tree

+            pccts/bin/*.exe

+            pccts/lib/*.lib

+            pccts/h/*

+            sorcerer/lib/*

+            sorcerer/h/*

+

+         an example directory tree

+            pccts\example\calcAST\*

+            pccts\example\simple\*

+

+2. Define the environment variable PCCTS to point to the main

+   pccts directory.

+

+3. Try building the simple project: pccts\example\simple\simple50.dsw

+   or simple60.dsw.

+

+4. Try building the complex project: pccts\example\calcAST\calcAST50.dsw

+   or calcAST60.dsw.

+

+-------------------------------------------------------------------------

+                      INSTALLATION (DEC/VMS)

+-------------------------------------------------------------------------

+

+DEC/VMS support added by Piéronne Jean-François (jfp@altavista.net)

+

+0. Download http://www.polhode.com/pccts133mr.zip

+

+1. Unzip the distribution kit to your preferred location.

+

+2. set default to the main pccts directory.

+

+3. @makefile.vms

+

+   This will create in directory [.bin]:

+

+        antlr.exe

+        dlg.exe

+        sorcerer.exe

+        genmk.exe

+

+5. To get an up-to-date list of program options execute the

+   program with no command line options.  To get up-to-date

+   documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt

+   at http://www.polhode.com/pccts.html.

diff --git a/Source/Pccts/RIGHTS b/Source/Pccts/RIGHTS
new file mode 100644
index 0000000..9db175f
--- /dev/null
+++ b/Source/Pccts/RIGHTS
@@ -0,0 +1,26 @@
+

+SOFTWARE RIGHTS

+

+We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+company may do whatever they wish with source code distributed with

+PCCTS or the code generated by PCCTS, including the incorporation of

+PCCTS, or its output, into commerical software.

+

+We encourage users to develop software with PCCTS.  However, we do ask

+that credit is given to us for developing PCCTS.  By "credit", we mean

+that if you incorporate our source code into one of your programs

+(commercial product, research project, or otherwise) that you

+acknowledge this fact somewhere in the documentation, research report,

+etc...  If you like PCCTS and have developed a nice tool with the

+output, please mention that you developed it using PCCTS.  In

+addition, we ask that this header remain intact in our source code.

+As long as these guidelines are kept, we expect to continue enhancing

+this system and expect to make other tools available as they are

+completed.

+

+ANTLR 1.33

+Terence Parr

+Parr Research Corporation

+with Purdue University and AHPCRC, University of Minnesota

+1989-1995

diff --git a/Source/Pccts/antlr/AntlrMS.mak b/Source/Pccts/antlr/AntlrMS.mak
new file mode 100644
index 0000000..7342d99
--- /dev/null
+++ b/Source/Pccts/antlr/AntlrMS.mak
@@ -0,0 +1,233 @@
+# PCCTS directory

+

+# You will need to set the LIB variable similar to this.

+# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib"

+

+# PCCTS_HOME=<your PCCTS_HOME>

+PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts

+ANTLR_SRC=$(PCCTS_HOME)\antlr

+PCCTS_H=$(PCCTS_HOME)\h

+

+

+# Support directories

+SET=$(PCCTS_HOME)\support\set

+

+

+# Compiler stuff

+CC = cl

+CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \

+        -D "ZZLEXBUFSIZE=65536"  /D "LONGFILENAMES" /Zi /W3 -D__USE_PROTOS /wd4700

+

+ANTLR_OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+            fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+            misc.obj pred.obj egman.obj mrhoist.obj fcache.obj

+

+SUPPORT_OBJS = set.obj

+

+# Dependencies

+

+$(WORKSPACE)\Tools\bin\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS)

+    $(CC) $(CFLAGS) -o antlr.exe $(ANTLR_OBJS) $(SUPPORT_OBJS)

+    del *.obj

+		move antlr.exe $(WORKSPACE)\Tools\bin

+

+

+antlr.obj: $(ANTLR_SRC)\antlr.c \

+	                $(PCCTS_H)\antlr.h \

+                	$(PCCTS_H)\config.h \

+	                $(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\mode.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+					$(ANTLR_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\antlr.c

+

+scan.obj: $(ANTLR_SRC)\scan.c \

+	                $(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgauto.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\mode.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+					$(ANTLR_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\scan.c

+

+err.obj: $(ANTLR_SRC)\err.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(PCCTS_H)\err.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+					$(ANTLR_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\err.c

+

+bits.obj: $(ANTLR_SRC)\bits.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\bits.c

+

+build.obj: $(ANTLR_SRC)\build.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\build.c

+

+fset2.obj: $(ANTLR_SRC)\fset2.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset2.c

+

+fset.obj: $(ANTLR_SRC)\fset.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset.c

+

+gen.obj: $(ANTLR_SRC)\gen.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\gen.c

+

+globals.obj: $(ANTLR_SRC)\globals.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\globals.c

+

+hash.obj: $(ANTLR_SRC)\hash.c \

+					$(PCCTS_H)\config.h \

+					$(ANTLR_SRC)\hash.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\hash.c

+

+lex.obj: $(ANTLR_SRC)\lex.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\lex.c

+

+main.obj: $(ANTLR_SRC)\main.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\mode.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\stdpccts.h \

+					$(ANTLR_SRC)\syn.h \

+					$(ANTLR_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\main.c

+

+misc.obj: $(ANTLR_SRC)\misc.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\misc.c

+

+pred.obj: $(ANTLR_SRC)\pred.c \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\pred.c

+

+egman.obj: $(ANTLR_SRC)\egman.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\egman.c

+

+mrhoist.obj: $(ANTLR_SRC)\mrhoist.c \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\mrhoist.c

+

+fcache.obj: $(ANTLR_SRC)\fcache.c \

+					$(ANTLR_SRC)\generic.h \

+					$(ANTLR_SRC)\hash.h \

+					$(ANTLR_SRC)\proto.h \

+					$(ANTLR_SRC)\syn.h \

+

+    $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fcache.c

+

+set.obj: $(SET)\set.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+

+    $(CC) -c $(CFLAGS) $(SET)\set.c

+

+clean:	

+    del *.obj

+

+distclean:

+    del *.obj

+    del $(WORKSPACE)\Tools\bin\antlr.exe

diff --git a/Source/Pccts/antlr/AntlrPPC.mak b/Source/Pccts/antlr/AntlrPPC.mak
new file mode 100644
index 0000000..9ede60d
--- /dev/null
+++ b/Source/Pccts/antlr/AntlrPPC.mak
@@ -0,0 +1,101 @@
+#   Target:     antlrPPC

+#   Sources:    ::support:set:set.c

+#               antlr.c

+#               bits.c

+#               build.c

+#               egman.c

+#               err.c

+#               fcache.c

+#               fset2.c

+#               fset.c

+#               gen.c

+#               globals.c

+#               hash.c

+#               lex.c

+#               main.c

+#               misc.c

+#               mrhoist.c

+#               pred.c

+#               scan.c

+#   Created:    Sunday, May 17, 1998 10:24:53 PM

+#	Author:		Kenji Tanaka

+MAKEFILE     = antlrPPC.make

+¥MondoBuild¥ = {MAKEFILE}  # Make blank to avoid rebuilds when makefile is modified

+Includes     = ¶

+		-i "::h:" ¶

+		-i "::support:set:"

+Sym¥PPC      = 

+ObjDir¥PPC   = :Obj:

+PPCCOptions  = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN

+Objects¥PPC  = ¶

+		"{ObjDir¥PPC}set.c.x" ¶

+		"{ObjDir¥PPC}antlr.c.x" ¶

+		"{ObjDir¥PPC}bits.c.x" ¶

+		"{ObjDir¥PPC}build.c.x" ¶

+		"{ObjDir¥PPC}egman.c.x" ¶

+		"{ObjDir¥PPC}err.c.x" ¶

+		"{ObjDir¥PPC}fcache.c.x" ¶

+		"{ObjDir¥PPC}fset2.c.x" ¶

+		"{ObjDir¥PPC}fset.c.x" ¶

+		"{ObjDir¥PPC}gen.c.x" ¶

+		"{ObjDir¥PPC}globals.c.x" ¶

+		"{ObjDir¥PPC}hash.c.x" ¶

+		"{ObjDir¥PPC}lex.c.x" ¶

+		"{ObjDir¥PPC}main.c.x" ¶

+		"{ObjDir¥PPC}misc.c.x" ¶

+		"{ObjDir¥PPC}mrhoist.c.x" ¶

+		"{ObjDir¥PPC}pred.c.x" ¶

+		"{ObjDir¥PPC}scan.c.x"

+antlrPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC}

+	PPCLink ¶

+		-o {Targ} {Sym¥PPC} ¶

+		{Objects¥PPC} ¶

+		-t 'MPST' ¶

+		-c 'MPS ' ¶

+		"{SharedLibraries}InterfaceLib" ¶

+		"{SharedLibraries}StdCLib" ¶

+		#"{SharedLibraries}MathLib" ¶

+		"{PPCLibraries}StdCRuntime.o" ¶

+		"{PPCLibraries}PPCCRuntime.o" ¶

+		"{PPCLibraries}PPCToolLibs.o"

+"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c"

+	{PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}antlr.c.x" Ä {¥MondoBuild¥} antlr.c

+	{PPCC} antlr.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}bits.c.x" Ä {¥MondoBuild¥} bits.c

+	{PPCC} bits.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}build.c.x" Ä {¥MondoBuild¥} build.c

+	{PPCC} build.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}egman.c.x" Ä {¥MondoBuild¥} egman.c

+	{PPCC} egman.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c

+	{PPCC} err.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}fcache.c.x" Ä {¥MondoBuild¥} fcache.c

+	{PPCC} fcache.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}fset2.c.x" Ä {¥MondoBuild¥} fset2.c

+	{PPCC} fset2.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}fset.c.x" Ä {¥MondoBuild¥} fset.c

+	{PPCC} fset.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}gen.c.x" Ä {¥MondoBuild¥} gen.c

+	{PPCC} gen.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}globals.c.x" Ä {¥MondoBuild¥} globals.c

+	{PPCC} globals.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}hash.c.x" Ä {¥MondoBuild¥} hash.c

+	{PPCC} hash.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}lex.c.x" Ä {¥MondoBuild¥} lex.c

+	{PPCC} lex.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c

+	{PPCC} main.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}misc.c.x" Ä {¥MondoBuild¥} misc.c

+	{PPCC} misc.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}mrhoist.c.x" Ä {¥MondoBuild¥} mrhoist.c

+	{PPCC} mrhoist.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}pred.c.x" Ä {¥MondoBuild¥} pred.c

+	{PPCC} pred.c -o {Targ} {PPCCOptions}

+"{ObjDir¥PPC}scan.c.x" Ä {¥MondoBuild¥} scan.c

+	{PPCC} scan.c -o {Targ} {PPCCOptions}

+

+antlrPPC ÄÄ antlr.r

+	Rez antlr.r -o antlrPPC -a

+Install  Ä antlrPPC

+	Duplicate -y antlrPPC "{MPW}"Tools:antlr

diff --git a/Source/Pccts/antlr/README b/Source/Pccts/antlr/README
new file mode 100644
index 0000000..d7fc959
--- /dev/null
+++ b/Source/Pccts/antlr/README
@@ -0,0 +1,19 @@
+                            ANTLR 1.33

+

+This directory contains the files necessary to build ANTLR.

+

+If you do a "make scrub", ANTLR will have to run on antlr.g and DLG

+will have to run on parser.dlg.  Either

+

+(1)     ANTLR uses the previous antlr in that directory to rebuild itself

+(2)     Needs to find antlr on the search path

+

+You will find that running "antlr -gh antlr.g" will result in about

+10 ambiguity warnings.  These are normal.  Don't worry.

+

+If you do a "make clean" right after installation, ANTLR and DLG should

+not need to run; only the C files will compile.

+

+Don't forget to go into the makefile to uncomment the appropriate

+definitions for your OS/architecture/compiler or see the appropriate

+NOTES.?? file.

diff --git a/Source/Pccts/antlr/antlr.1 b/Source/Pccts/antlr/antlr.1
new file mode 100644
index 0000000..acfa85b
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.1
@@ -0,0 +1,209 @@
+.TH ANTLR 1 "September 1995" "ANTLR" "PCCTS Manual Pages"

+.SH NAME

+antlr \- ANother Tool for Language Recognition

+.SH SYNTAX

+.LP

+\fBantlr\fR [\fIoptions\fR] \fIgrammar_files\fR

+.SH DESCRIPTION

+.PP

+\fIAntlr\fP converts an extended form of context-free grammar into a

+set of C functions which directly implement an efficient form of

+deterministic recursive-descent LL(k) parser.  Context-free grammars

+may be augmented with predicates to allow semantics to influence

+parsing; this allows a form of context-sensitive parsing.  Selective

+backtracking is also available to handle non-LL(k) and even

+non-LALR(k) constructs.  \fIAntlr\fP also produces a definition of a

+lexer which can be automatically converted into C code for a DFA-based

+lexer by \fIdlg\fR.  Hence, \fIantlr\fR serves a function much like

+that of \fIyacc\fR, however, it is notably more flexible and is more

+integrated with a lexer generator (\fIantlr\fR directly generates

+\fIdlg\fR code, whereas \fIyacc\fR and \fIlex\fR are given independent

+descriptions).  Unlike \fIyacc\fR which accepts LALR(1) grammars,

+\fIantlr\fR accepts LL(k) grammars in an extended BNF notation \(em

+which eliminates the need for precedence rules.

+.PP

+Like \fIyacc\fR grammars, \fIantlr\fR grammars can use

+automatically-maintained symbol attribute values referenced as dollar

+variables.  Further, because \fIantlr\fR generates top-down parsers,

+arbitrary values may be inherited from parent rules (passed like

+function parameters).  \fIAntlr\fP also has a mechanism for creating

+and manipulating abstract-syntax-trees.

+.PP

+There are various other niceties in \fIantlr\fR, including the ability to

+spread one grammar over multiple files or even multiple grammars in a single

+file, the ability to generate a version of the grammar with actions stripped

+out (for documentation purposes), and lots more.

+.SH OPTIONS

+.IP "\fB-ck \fIn\fR"

+Use up to \fIn\fR symbols of lookahead when using compressed (linear

+approximation) lookahead.  This type of lookahead is very cheap to

+compute and is attempted before full LL(k) lookahead, which is of

+exponential complexity in the worst case.  In general, the compressed

+lookahead can be much deeper (e.g, \f(CW-ck 10\fP) than the full

+lookahead (which usually must be less than 4).

+.IP \fB-CC\fP

+Generate C++ output from both ANTLR and DLG.

+.IP \fB-cr\fP

+Generate a cross-reference for all rules.  For each rule, print a list

+of all other rules that reference it.

+.IP \fB-e1\fP

+Ambiguities/errors shown in low detail (default).

+.IP \fB-e2\fP

+Ambiguities/errors shown in more detail.

+.IP \fB-e3\fP

+Ambiguities/errors shown in excruciating detail.

+.IP "\fB-fe\fP file"

+Rename \fBerr.c\fP to file.

+.IP "\fB-fh\fP file"

+Rename \fBstdpccts.h\fP header (turns on \fB-gh\fP) to file.

+.IP "\fB-fl\fP file"

+Rename lexical output, \fBparser.dlg\fP, to file.

+.IP "\fB-fm\fP file"

+Rename file with lexical mode definitions, \fBmode.h\fP, to file.

+.IP "\fB-fr\fP file"

+Rename file which remaps globally visible symbols, \fBremap.h\fP, to file.

+.IP "\fB-ft\fP file"

+Rename \fBtokens.h\fP to file.

+.IP \fB-ga\fP

+Generate ANSI-compatible code (default case).  This has not been

+rigorously tested to be ANSI XJ11 C compliant, but it is close.  The

+normal output of \fIantlr\fP is currently compilable under both K&R,

+ANSI C, and C++\(emthis option does nothing because \fIantlr\fP

+generates a bunch of #ifdef's to do the right thing depending on the

+language.

+.IP \fB-gc\fP

+Indicates that \fIantlr\fP should generate no C code, i.e., only

+perform analysis on the grammar.

+.IP \fB-gd\fP

+C code is inserted in each of the \fIantlr\fR generated parsing functions to

+provide for user-defined handling of a detailed parse trace.  The inserted

+code consists of calls to the user-supplied macros or functions called

+\fBzzTRACEIN\fR and \fBzzTRACEOUT\fP.  The only argument is a

+\fIchar *\fR pointing to a C-style string which is the grammar rule

+recognized by the current parsing function.  If no definition is given

+for the trace functions, upon rule entry and exit, a message will be

+printed indicating that a particular rule as been entered or exited.

+.IP \fB-ge\fP

+Generate an error class for each non-terminal.

+.IP \fB-gh\fP

+Generate \fBstdpccts.h\fP for non-ANTLR-generated files to include.

+This file contains all defines needed to describe the type of parser

+generated by \fIantlr\fP (e.g. how much lookahead is used and whether

+or not trees are constructed) and contains the \fBheader\fP action

+specified by the user.

+.IP \fB-gk\fP

+Generate parsers that delay lookahead fetches until needed.  Without

+this option, \fIantlr\fP generates parsers which always have \fIk\fP

+tokens of lookahead available.

+.IP \fB-gl\fP

+Generate line info about grammar actions in C parser of the form

+\fB#\ \fIline\fP\ "\fIfile\fP"\fR which makes error messages from

+the C/C++ compiler make more sense as they will \*Qpoint\*U into the

+grammar file not the resulting C file.  Debugging is easier as well,

+because you will step through the grammar not C file.

+.IP \fB-gs\fR

+Do not generate sets for token expression lists; instead generate a

+\fB||\fP-separated sequence of \fBLA(1)==\fItoken_number\fR.  The

+default is to generate sets.

+.IP \fB-gt\fP

+Generate code for Abstract-Syntax Trees.

+.IP \fB-gx\fP

+Do not create the lexical analyzer files (dlg-related).  This option

+should be given when the user wishes to provide a customized lexical

+analyzer.  It may also be used in \fImake\fR scripts to cause only the

+parser to be rebuilt when a change not affecting the lexical structure

+is made to the input grammars.

+.IP "\fB-k \fIn\fR"

+Set k of LL(k) to \fIn\fR; i.e. set tokens of look-ahead (default==1).

+.IP "\fB-o\fP dir

+Directory where output files should go (default=".").  This is very

+nice for keeping the source directory clear of ANTLR and DLG spawn.

+.IP \fB-p\fP

+The complete grammar, collected from all input grammar files and

+stripped of all comments and embedded actions, is listed to

+\fBstdout\fP.  This is intended to aid in viewing the entire grammar

+as a whole and to eliminate the need to keep actions concisely stated

+so that the grammar is easier to read.  Hence, it is preferable to

+embed even complex actions directly in the grammar, rather than to

+call them as subroutines, since the subroutine call overhead will be

+saved.

+.IP \fB-pa\fP

+This option is the same as \fB-p\fP except that the output is

+annotated with the first sets determined from grammar analysis.

+.IP "\fB-prc on\fR

+Turn on the computation and hoisting of predicate context.

+.IP "\fB-prc off\fR

+Turn off the computation and hoisting of predicate context.  This

+option makes 1.10 behave like the 1.06 release with option \fB-pr\fR

+on.  Context computation is off by default.

+.IP "\fB-rl \fIn\fR

+Limit the maximum number of tree nodes used by grammar analysis to

+\fIn\fP.  Occasionally, \fIantlr\fP is unable to analyze a grammar

+submitted by the user.  This rare situation can only occur when the

+grammar is large and the amount of lookahead is greater than one.  A

+nonlinear analysis algorithm is used by PCCTS to handle the general

+case of LL(k) parsing.  The average complexity of analysis, however, is

+near linear due to some fancy footwork in the implementation which

+reduces the number of calls to the full LL(k) algorithm.  An error

+message will be displayed, if this limit is reached, which indicates

+the grammar construct being analyzed when \fIantlr\fP hit a

+non-linearity.  Use this option if \fIantlr\fP seems to go out to

+lunch and your disk start thrashing; try \fIn\fP=10000 to start.  Once

+the offending construct has been identified, try to remove the

+ambiguity that \fIantlr\fP was trying to overcome with large lookahead

+analysis.  The introduction of (...)? backtracking blocks eliminates

+some of these problems\ \(em \fIantlr\fP does not analyze alternatives

+that begin with (...)? (it simply backtracks, if necessary, at run

+time).

+.IP \fB-w1\fR

+Set low warning level.  Do not warn if semantic predicates and/or

+(...)? blocks are assumed to cover ambiguous alternatives.

+.IP \fB-w2\fR

+Ambiguous parsing decisions yield warnings even if semantic predicates

+or (...)? blocks are used.  Warn if predicate context computed and

+semantic predicates incompletely disambiguate alternative productions.

+.IP \fB-\fR

+Read grammar from standard input and generate \fBstdin.c\fP as the

+parser file.

+.SH "SPECIAL CONSIDERATIONS"

+.PP

+\fIAntlr\fP works...  we think.  There is no implicit guarantee of

+anything.  We reserve no \fBlegal\fP rights to the software known as

+the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the

+public domain.  An individual or company may do whatever they wish

+with source code distributed with PCCTS or the code generated by

+PCCTS, including the incorporation of PCCTS, or its output, into

+commercial software.  We encourage users to develop software with

+PCCTS.  However, we do ask that credit is given to us for developing

+PCCTS.  By "credit", we mean that if you incorporate our source code

+into one of your programs (commercial product, research project, or

+otherwise) that you acknowledge this fact somewhere in the

+documentation, research report, etc...  If you like PCCTS and have

+developed a nice tool with the output, please mention that you

+developed it using PCCTS.  As long as these guidelines are followed,

+we expect to continue enhancing this system and expect to make other

+tools available as they are completed.

+.SH FILES

+.IP *.c

+output C parser.

+.IP *.cpp

+output C++ parser when C++ mode is used.

+.IP \fBparser.dlg\fP

+output \fIdlg\fR lexical analyzer.

+.IP \fBerr.c\fP

+token string array, error sets and error support routines.  Not used in

+C++ mode.

+.IP \fBremap.h\fP

+file that redefines all globally visible parser symbols.  The use of

+the #parser directive creates this file.  Not used in

+C++ mode.

+.IP \fBstdpccts.h\fP

+list of definitions needed by C files, not generated by PCCTS, that

+reference PCCTS objects.  This is not generated by default.  Not used in

+C++ mode.

+.IP \fBtokens.h\fP

+output \fI#defines\fR for tokens used and function prototypes for

+functions generated for rules.

+.SH "SEE ALSO"

+.LP

+dlg(1), pccts(1)

diff --git a/Source/Pccts/antlr/antlr.c b/Source/Pccts/antlr/antlr.c
new file mode 100644
index 0000000..8aaef79
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.c
@@ -0,0 +1,3564 @@
+/*

+ * A n t l r  T r a n s l a t i o n  H e a d e r

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ *

+ *   ..\bin\antlr -gh antlr.g

+ *

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include "pcctscfg.h"

+#include "set.h"

+#include <ctype.h>

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#define zzcr_attr(attr,tok,t)

+#define zzSET_SIZE 20

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "mode.h"

+

+/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */

+

+#ifndef PCCTS_PURIFY

+#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s));

+#endif

+

+ANTLR_INFO

+

+

+/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */

+#if defined(__TURBOC__)

+#pragma warn -aus  /* unused assignment of 'xxx' */

+#endif

+

+

+#ifdef __USE_PROTOS

+static void chkToken(char *, char *, char *, int);

+#else

+static void chkToken();

+#endif

+

+#ifdef __USE_PROTOS

+static int isDLGmaxToken(char *Token);				     /* MR3 */

+#else

+static int isDLGmaxToken();				                             /* MR3 */

+#endif

+

+static int class_nest_level = 0;

+

+/* MR20 G. Hobbelt extern definitions moved to antlr.h */

+

+  

+

+void

+#ifdef __USE_PROTOS

+grammar(void)

+#else

+grammar()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  Graph g;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    for (;;) {

+      if ( !((setwd1[LA(1)]&0x1))) break;

+      if ( (LA(1)==94) ) {

+        zzmatch(94); zzCONSUME;

+        zzmatch(Action);

+        

+        if ( HdrAction==NULL ) {

+          HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+          require(HdrAction!=NULL, "rule grammar: cannot allocate header action");

+          strcpy(HdrAction, LATEXT(1));

+        }

+        else warn("additional #header statement ignored");

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==95) ) {

+          zzmatch(95); zzCONSUME;

+          zzmatch(Action);

+          

+          if ( FirstAction==NULL ) {

+            FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+            require(FirstAction!=NULL, "rule grammar: cannot allocate #first action");

+            strcpy(FirstAction, LATEXT(1));

+          } else {

+            warn("additional #first statement ignored");

+          };

+ zzCONSUME;

+

+        }

+        else {

+          if ( (LA(1)==96) ) {

+            zzmatch(96); zzCONSUME;

+            zzmatch(QuotedTerm);

+            

+            if ( GenCC ) {

+              warn("#parser meta-op incompatible with -CC; ignored");

+            }

+            else {

+              if ( strcmp(ParserName,"zzparser")==0 ) {

+                ParserName=StripQuotes(mystrdup(LATEXT(1)));

+                if ( RulePrefix[0]!='\0' )

+                {

+                  warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");

+                  RulePrefix[0]='\0';

+                }

+              }

+              else warn("additional #parser statement ignored");

+            }

+ zzCONSUME;

+

+          }

+          else {

+            if ( (LA(1)==97) ) {

+              zzmatch(97); zzCONSUME;

+              zzmatch(QuotedTerm);

+              {

+                char *fname;

+                zzantlr_state st; FILE *f; struct zzdlg_state dst;

+                UserTokenDefsFile = mystrdup(LATEXT(1));

+                zzsave_antlr_state(&st);

+                zzsave_dlg_state(&dst);

+                fname = mystrdup(LATEXT(1));

+                f = fopen(StripQuotes(fname), "r");

+                if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));}

+                else {

+                  ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE);

+                  UserDefdTokens = 1;

+                }

+                zzrestore_antlr_state(&st);

+                zzrestore_dlg_state(&dst);

+              }

+ zzCONSUME;

+

+            }

+            else break; /* MR6 code for exiting loop "for sure" */

+          }

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    for (;;) {

+      if ( !((setwd1[LA(1)]&0x2))) break;

+      if ( (LA(1)==Action) ) {

+        zzmatch(Action);

+        {

+          UserAction *ua = newUserAction(LATEXT(1));

+          ua->file = action_file; ua->line = action_line;

+          if ( class_nest_level>0 ) list_add(&class_before_actions, ua);

+          else list_add(&BeforeActions, ua);

+        }

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==108) ) {

+          laction();

+        }

+        else {

+          if ( (LA(1)==109) ) {

+            lmember();

+          }

+          else {

+            if ( (LA(1)==110) ) {

+              lprefix();

+            }

+            else {

+              if ( (LA(1)==116) ) {

+                aLexclass();

+              }

+              else {

+                if ( (LA(1)==120) ) {

+                  token();

+                }

+                else {

+                  if ( (LA(1)==117) ) {

+                    error();

+                  }

+                  else {

+                    if ( (LA(1)==118) ) {

+                      tclass();

+                    }

+                    else {

+                      if ( (LA(1)==111) ) {

+                        aPred();

+                      }

+                      else {

+                        if ( (LA(1)==133) ) {

+                          default_exception_handler();

+                        }

+                        else {

+                          if ( (LA(1)==99) ) {

+                            class_def();

+                          }

+                          else {

+                            if ( (LA(1)==98) ) {

+                              zzmatch(98);

+                              

+                              if ( class_nest_level==0 )

+                              warn("missing class definition for trailing '}'");

+                              class_nest_level--;

+ zzCONSUME;

+

+                            }

+                            else break; /* MR6 code for exiting loop "for sure" */

+                          }

+                        }

+                      }

+                    }

+                  }

+                }

+              }

+            }

+          }

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  rule();

+  g=zzaArg(zztasp1,3); SynDiag = (Junction *) zzaArg(zztasp1,3 ).left;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    for (;;) {

+      if ( !((setwd1[LA(1)]&0x4))) break;

+      if ( (LA(1)==NonTerminal) ) {

+        rule();

+        if ( zzaArg(zztasp2,1 ).left!=NULL ) {

+          g.right = NULL;

+          

+/* MR21a */             /*  Avoid use of a malformed graph when CannotContinue */

+          /* MR21a */             /*  is already set                                     */

+          /* MR21a */

+          /* MR21a */             if (! (CannotContinue && g.left == NULL)) {

+            /* MR21a */               g = Or(g, zzaArg(zztasp2,1));

+            /* MR21a */             }

+          /* MR21a */		      }

+      }

+      else {

+        if ( (LA(1)==116) ) {

+          aLexclass();

+        }

+        else {

+          if ( (LA(1)==120) ) {

+            token();

+          }

+          else {

+            if ( (LA(1)==117) ) {

+              error();

+            }

+            else {

+              if ( (LA(1)==118) ) {

+                tclass();

+              }

+              else {

+                if ( (LA(1)==111) ) {

+                  aPred();

+                }

+                else {

+                  if ( (LA(1)==99) ) {

+                    class_def();

+                  }

+                  else {

+                    if ( (LA(1)==98) ) {

+                      zzmatch(98);

+                      

+                      if ( class_nest_level==0 )

+                      warn("missing class definition for trailing '}'");

+                      class_nest_level--;

+ zzCONSUME;

+

+                    }

+                    else break; /* MR6 code for exiting loop "for sure" */

+                  }

+                }

+              }

+            }

+          }

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    for (;;) {

+      if ( !((setwd1[LA(1)]&0x8))) break;

+      if ( (LA(1)==Action) ) {

+        zzmatch(Action);

+        {

+          UserAction *ua = newUserAction(LATEXT(1));

+          ua->file = action_file; ua->line = action_line;

+          if ( class_nest_level>0 ) list_add(&class_after_actions, ua);

+          else list_add(&AfterActions, ua);

+        }

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==108) ) {

+          laction();

+        }

+        else {

+          if ( (LA(1)==109) ) {

+            lmember();

+          }

+          else {

+            if ( (LA(1)==110) ) {

+              lprefix();

+            }

+            else {

+              if ( (LA(1)==117) ) {

+                error();

+              }

+              else {

+                if ( (LA(1)==118) ) {

+                  tclass();

+                }

+                else {

+                  if ( (LA(1)==99) ) {

+                    class_def();

+                  }

+                  else {

+                    if ( (LA(1)==111) ) {

+                      aPred();

+                    }

+                    else {

+                      if ( (LA(1)==98) ) {

+                        zzmatch(98);

+                        

+                        if ( class_nest_level==0 )

+                        warn("missing class definition for trailing '}'");

+                        class_nest_level--;

+ zzCONSUME;

+

+                      }

+                      else break; /* MR6 code for exiting loop "for sure" */

+                    }

+                  }

+                }

+              }

+            }

+          }

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(Eof); zzCONSUME;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x10);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+class_def(void)

+#else

+class_def()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  int go=1; char name[MaxRuleName+1];

+  zzmatch(99); zzCONSUME;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==NonTerminal) ) {

+      zzmatch(NonTerminal);

+      if(go) strncpy(name,LATEXT(1),MaxRuleName);

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==TokenTerm) ) {

+        zzmatch(TokenTerm);

+        if(go) strncpy(name,LATEXT(1),MaxRuleName);

+ zzCONSUME;

+

+      }

+      else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0

+  && GenCC ) {

+    err("only one grammar class allowed in this release");

+    go = 0;

+  }

+  else strcpy(CurrentClassName, name);

+  if ( !GenCC ) { err("class meta-op used without C++ option"); }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (setwd1[LA(1)]&0x20) ) {

+      zzsetmatch(zzerr2, zzerr3);

+      if (ClassDeclStuff == NULL) {

+        /* MR10 */                   ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char));

+        /* MR10 */              };

+      /* MR10 */              strncat(ClassDeclStuff," ",MaxClassDeclStuff);

+      /* MR10 */              strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff);

+      /* MR22 */              do {

+        /* MR22 */                if (0 == strcmp(LATEXT(1),"public")) break;

+        /* MR22 */                if (0 == strcmp(LATEXT(1),"private")) break;

+        /* MR22 */                if (0 == strcmp(LATEXT(1),"protected")) break;

+        /* MR22 */                if (0 == strcmp(LATEXT(1),"virtual")) break;

+        /* MR22 */                if (0 == strcmp(LATEXT(1),",")) break;

+        /* MR22 */                if (0 == strcmp(LATEXT(1),":")) break;

+        /* MR22 */                if (BaseClassName != NULL) break;

+        /* MR22 */                BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char));

+        /* MR22 */                require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name");

+        /* MR22 */				  strcpy(BaseClassName,LATEXT(1));

+        /* MR22 */              } while (0);

+      /* MR10 */

+ zzCONSUME;

+

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(102);

+  

+  no_classes_found = 0;

+  if ( class_nest_level>=1 ) {warn("cannot have nested classes");}

+  else class_nest_level++;

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x40);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+rule(void)

+#else

+rule()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  

+  

+			ExceptionGroup *eg;

+  RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;

+  set toksrefd, rulesrefd;

+  char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;

+  CurExGroups = NULL;

+  CurElementLabels = NULL;

+  CurAstLabelsInActions = NULL; /* MR27 */

+  /* We want a new element label hash table for each rule */

+  if ( Elabel!=NULL ) killHashTable(Elabel);

+  Elabel = newHashTable();

+  attribsRefdFromAction = empty;

+  zzmatch(NonTerminal);

+  q=NULL;

+  if ( hash_get(Rname, LATEXT(1))!=NULL ) {

+    err(eMsg1("duplicate rule definition: '%s'",LATEXT(1)));

+    CannotContinue=TRUE;

+  }

+  else

+  {

+    q = (RuleEntry *)hash_add(Rname,

+    LATEXT(1),

+    (Entry *)newRuleEntry(LATEXT(1)));

+    CurRule = q->str;

+  }

+  CurRuleNode = q;

+  f = CurFile; l = zzline;

+  NumRules++;

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==103) ) {

+      zzmatch(103);

+      if ( q!=NULL ) q->noAST = TRUE;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd1[LA(1)]&0x80) ) {

+      }

+      else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    ;

+    if ( (setwd2[LA(1)]&0x1) ) {

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==104) ) {

+          zzmatch(104); zzCONSUME;

+        }

+        else {

+          if ( (LA(1)==PassAction) ) {

+          }

+          else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      zzmatch(PassAction);

+      pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(pdecl!=NULL, "rule rule: cannot allocate param decl");

+      strcpy(pdecl, LATEXT(1));

+      CurParmDef = pdecl;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd2[LA(1)]&0x2) ) {

+      }

+      else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==105) ) {

+      zzmatch(105); zzCONSUME;

+      zzmatch(PassAction);

+      ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(ret!=NULL, "rule rule: cannot allocate ret type");

+      strcpy(ret, LATEXT(1));

+      CurRetDef = ret;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd2[LA(1)]&0x4) ) {

+      }

+      else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==QuotedTerm) ) {

+      zzmatch(QuotedTerm);

+      if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==106) ) {

+      }

+      else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  if ( GenEClasseForRules && q!=NULL ) {

+    e = newECnode;

+    require(e!=NULL, "cannot allocate error class node");

+    if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}

+    else a = q->egroup;

+    if ( Tnum( a ) == 0 )

+    {

+      e->tok = addTname( a );

+      list_add(&eclasses, (char *)e);

+      if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);

+      /* refers to itself */

+      list_add(&(e->elist), mystrdup(q->str));

+    }

+    else {

+      warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a));

+      if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);

+      free((char *)e);

+    }

+  }

+  BlkLevel++;

+  if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");

+  /* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;

+  /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;

+  zzmatch(106);

+  inAlt=1;

+ zzCONSUME;

+

+  block( &toksrefd, &rulesrefd );

+  r = makeBlk(zzaArg(zztasp1,7),0, NULL /* pFirstSetSymbol */ );

+  CurRuleBlk = (Junction *)r.left;

+  CurRuleBlk->blockid = CurBlockID;

+  CurRuleBlk->jtype = RuleBlk;

+  if ( q!=NULL ) CurRuleBlk->rname = q->str;

+  CurRuleBlk->file = f;

+  CurRuleBlk->line = l;

+  CurRuleBlk->pdecl = pdecl;

+  CurRuleBlk->ret = ret;

+  CurRuleBlk->lock = makelocks();

+  CurRuleBlk->pred_lock = makelocks();

+  CurRuleBlk->tokrefs = toksrefd;

+  CurRuleBlk->rulerefs = rulesrefd;

+  p = newJunction();	/* add EndRule Node */

+  ((Junction *)r.right)->p1 = (Node *)p;

+  r.right = (Node *) p;

+  p->jtype = EndRule;

+  p->lock = makelocks();

+  p->pred_lock = makelocks();

+  CurRuleBlk->end = p;

+  if ( q!=NULL ) q->rulenum = NumRules;

+  zzaArg(zztasp1,7) = r;

+  

+  /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+  /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+  --BlkLevel;

+  altFixup();leFixup();egFixup();

+  zzmatch(107);

+  inAlt=0;

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==Action) ) {

+      zzmatch(Action);

+      a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(a!=NULL, "rule rule: cannot allocate error action");

+      strcpy(a, LATEXT(1));

+      CurRuleBlk->erraction = a;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd2[LA(1)]&0x8) ) {

+      }

+      else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==133) ) {

+       eg  = exception_group();

+

+      if ( eg!=NULL ) {

+        list_add(&CurExGroups, (void *)eg);

+        if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1;

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  if ( q==NULL ) zzaArg(zztasp1,0 ).left = NULL; else zzaArg(zztasp1,0) = zzaArg(zztasp1,7);

+  CurRuleBlk->exceptions = CurExGroups;

+  CurRuleBlk->el_labels = CurElementLabels;

+  CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions;

+  CurRuleNode = NULL;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x10);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+laction(void)

+#else

+laction()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *a;

+  zzmatch(108); zzCONSUME;

+  zzmatch(Action);

+  

+  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+  require(a!=NULL, "rule laction: cannot allocate action");

+  strcpy(a, LATEXT(1));

+  list_add(&LexActions, a);

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x20);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+lmember(void)

+#else

+lmember()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *a;

+  zzmatch(109); zzCONSUME;

+  zzmatch(Action);

+  

+  /* MR1 */		if (! GenCC) {

+    /* MR1 */		  err("Use #lexmember only in C++ mode (to insert code in DLG class header");

+    /* MR1 */	        } else {

+    /* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+    /* MR1 */		  require(a!=NULL, "rule lmember: cannot allocate action");

+    /* MR1 */		  strcpy(a, LATEXT(1));

+    /* MR1 */		  list_add(&LexMemberActions, a);

+    /* MR1 */		};

+  /* MR1 */

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x40);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+lprefix(void)

+#else

+lprefix()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *a;

+  zzmatch(110); zzCONSUME;

+  zzmatch(Action);

+  

+  /* MR1 */		if (! GenCC) {

+    /* MR1 */		  err("Use #lexprefix only in C++ mode (to insert code in DLG class header");

+    /* MR1 */	        } else {

+    /* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+    /* MR1 */		  require(a!=NULL, "rule lprefix: cannot allocate action");

+    /* MR1 */		  strcpy(a, LATEXT(1));

+    /* MR1 */		  list_add(&LexPrefixActions, a);

+    /* MR1 */		};

+  /* MR1 */

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x80);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+aPred(void)

+#else

+aPred()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  PredEntry     *predEntry=NULL;

+  char          *name=NULL;

+  Predicate     *predExpr=NULL;

+  char          *predLiteral=NULL;

+  int           save_file;

+  int           save_line;

+  int           predExprPresent=0;

+  zzmatch(111);

+  

+  MR_usingPredNames=1;      /* will need to use -mrhoist version of genPredTree */

+ zzCONSUME;

+

+  zzmatch(TokenTerm);

+  name=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+  

+  /* don't free - referenced in predicates */

+  

+            CurPredName=(char *)calloc(1,strlen(name) + 10);

+  strcat(CurPredName,"#pred ");

+  strcat(CurPredName,name);

+  

+            predEntry=(PredEntry *) hash_get(Pname,name);

+  if (predEntry != NULL) {

+  warnFL(eMsg1("#pred %s previously defined - ignored",name),

+  FileStr[action_file],action_line);

+  name=NULL;

+};

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==Pred) ) {

+      zzmatch(Pred);

+      predLiteral=mystrdup(LATEXT(1));

+      save_line=action_line;

+      save_file=action_file;

+ zzCONSUME;

+

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (setwd3[LA(1)]&0x1) ) {

+           predExpr  = predOrExpr();

+

+          predExprPresent=1;

+        }

+        else {

+          if ( (setwd3[LA(1)]&0x2) ) {

+          }

+          else {zzFAIL(1,zzerr10,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      if (predLiteral != NULL && name != NULL) {

+        

+                      /*

+        *  predExpr may be NULL due to syntax errors

+        *    or simply omitted by the user

+        */

+        

+                      predEntry=newPredEntry(name);

+        predEntry->file=save_file;

+        predEntry->line=save_line;

+        predExpr=MR_predFlatten(predExpr);

+        predEntry->predLiteral=predLiteral;

+        if (! predExprPresent || predExpr == NULL) {

+          predExpr=new_pred();

+          predExpr->expr=predLiteral;

+          predExpr->source=newActionNode();

+          predExpr->source->action=predExpr->expr;

+          predExpr->source->rname=CurPredName;

+          predExpr->source->line=action_line;

+          predExpr->source->file=action_file;

+          predExpr->source->is_predicate=1;

+          predExpr->k=predicateLookaheadDepth(predExpr->source);

+        };

+        predEntry->pred=predExpr;

+        hash_add(Pname,name,(Entry *)predEntry);

+        predExpr=NULL;

+      };

+      predicate_free(predExpr);

+    }

+    else {

+      if ( (setwd3[LA(1)]&0x4) ) {

+        save_line=zzline; save_file=CurFile;

+         predExpr  = predOrExpr();

+

+        if (predExpr != NULL && name != NULL) {

+          predEntry=newPredEntry(name);

+          predEntry->file=CurFile;

+          predEntry->line=zzline;

+          predExpr=MR_predFlatten(predExpr);

+          predEntry->pred=predExpr;

+          hash_add(Pname,name,(Entry *)predEntry);

+          predExpr=NULL;

+        };

+        predicate_free(predExpr);

+      }

+      else {zzFAIL(1,zzerr11,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==107) ) {

+      zzmatch(107); zzCONSUME;

+    }

+    else {

+      if ( (setwd3[LA(1)]&0x8) ) {

+      }

+      else {zzFAIL(1,zzerr12,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  predicate_free(predExpr);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x10);

+  }

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+predOrExpr(void)

+#else

+predOrExpr()

+#endif

+{

+  Predicate *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(Predicate *  ))

+  zzMake0;

+  {

+  Predicate     *ORnode;

+  Predicate     *predExpr;

+  Predicate     **tail=NULL;

+   predExpr  = predAndExpr();

+

+  

+  ORnode=new_pred();

+  ORnode->expr=PRED_OR_LIST;

+  if (predExpr != NULL) {

+    ORnode->down=predExpr;

+    tail=&predExpr->right;

+  };

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==112) ) {

+      zzmatch(112); zzCONSUME;

+       predExpr  = predAndExpr();

+

+      

+      if (predExpr != NULL) {

+        *tail=predExpr;

+        tail=&predExpr->right;

+      };

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  _retv=ORnode;

+  ORnode=NULL;

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  predicate_free(ORnode);  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x20);

+  return _retv;

+  }

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+predAndExpr(void)

+#else

+predAndExpr()

+#endif

+{

+  Predicate *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(Predicate *  ))

+  zzMake0;

+  {

+  Predicate     *ANDnode;

+  Predicate     *predExpr;

+  Predicate     **tail=NULL;

+   predExpr  = predPrimary();

+

+  

+  ANDnode=new_pred();

+  ANDnode->expr=PRED_AND_LIST;

+  if (predExpr != NULL) {

+    ANDnode->down=predExpr;

+    tail=&predExpr->right;

+  };

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==113) ) {

+      zzmatch(113); zzCONSUME;

+       predExpr  = predPrimary();

+

+      

+      if (predExpr != NULL) {

+        *tail=predExpr;

+        tail=&predExpr->right;

+      };

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  _retv=ANDnode;

+  ANDnode=NULL;

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  predicate_free(ANDnode);  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x40);

+  return _retv;

+  }

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+predPrimary(void)

+#else

+predPrimary()

+#endif

+{

+  Predicate *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(Predicate *  ))

+  zzMake0;

+  {

+  

+  char          *name=NULL;

+  PredEntry     *predEntry=NULL;

+  Predicate     *predExpr=NULL;

+  if ( (LA(1)==TokenTerm) ) {

+    zzmatch(TokenTerm);

+    name=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+    

+    predEntry=(PredEntry *) hash_get(Pname,name);

+    if (predEntry == NULL) {

+      warnFL(eMsg1("no previously defined #pred with name \"%s\"",name),

+      FileStr[CurFile],zzline);

+      name=NULL;

+      _retv=NULL;

+    } else {

+      predExpr=predicate_dup(predEntry->pred);

+      predExpr->predEntry=predEntry;

+      _retv=predExpr;

+    };

+  }

+  else {

+    if ( (LA(1)==114) ) {

+      zzmatch(114); zzCONSUME;

+       predExpr  = predOrExpr();

+

+      zzmatch(115);

+      

+      _retv=predExpr;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==103) ) {

+        zzmatch(103); zzCONSUME;

+         predExpr  = predPrimary();

+

+        

+        predExpr->inverted=!predExpr->inverted;

+        _retv=predExpr;

+      }

+      else {zzFAIL(1,zzerr13,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+  }

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  

+  predicate_free(predExpr);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x80);

+  return _retv;

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+aLexclass(void)

+#else

+aLexclass()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  zzmatch(116); zzCONSUME;

+  zzmatch(TokenTerm);

+  lexclass(mystrdup(LATEXT(1)));

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd4, 0x1);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+error(void)

+#else

+error()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *t=NULL; ECnode *e; int go=1; TermEntry *p;

+  zzmatch(117); zzCONSUME;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    ;

+    if ( (LA(1)==TokenTerm) ) {

+      zzmatch(TokenTerm);

+      t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==QuotedTerm) ) {

+        zzmatch(QuotedTerm);

+        t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+      }

+      else {zzFAIL(1,zzerr14,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  e = newECnode;

+  require(e!=NULL, "cannot allocate error class node");

+  e->lexclass = CurrentLexClass;

+  if ( Tnum( (t=StripQuotes(t)) ) == 0 )

+  {

+    if ( hash_get(Texpr, t) != NULL )

+    warn(eMsg1("errclass name conflicts with regular expression  '%s'",t));

+    e->tok = addTname( t );

+    set_orel(e->tok, &imag_tokens);

+    require((p=(TermEntry *)hash_get(Tname, t)) != NULL,

+    "hash table mechanism is broken");

+    p->classname = 1;	/* entry is errclass name, not token */

+    list_add(&eclasses, (char *)e);

+  }

+  else

+  {

+  warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t));

+  free( (char *)e );

+  go=0;

+}

+  zzmatch(102); zzCONSUME;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==NonTerminal) ) {

+      zzmatch(NonTerminal);

+      if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==TokenTerm) ) {

+        zzmatch(TokenTerm);

+        if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==QuotedTerm) ) {

+          zzmatch(QuotedTerm);

+          if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+        }

+        else {zzFAIL(1,zzerr15,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+      }

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  if ( go ) list_add(&(e->elist), t);

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (setwd4[LA(1)]&0x2) ) {

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==NonTerminal) ) {

+          zzmatch(NonTerminal);

+          if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+        }

+        else {

+          if ( (LA(1)==TokenTerm) ) {

+            zzmatch(TokenTerm);

+            if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+          }

+          else {

+            if ( (LA(1)==QuotedTerm) ) {

+              zzmatch(QuotedTerm);

+              if ( go ) t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+            }

+            else {zzFAIL(1,zzerr16,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      if ( go ) list_add(&(e->elist), t);

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(98); zzCONSUME;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd4, 0x4);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+tclass(void)

+#else

+tclass()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm;

+  char *akaString=NULL; int save_file; int save_line;

+  char *totext=NULL;

+  zzmatch(118); zzCONSUME;

+  zzmatch(TokenTerm);

+  t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+  e = newTCnode;

+  require(e!=NULL, "cannot allocate token class node");

+  e->lexclass = CurrentLexClass;

+  if ( Tnum( t ) == 0 )

+  {

+    e->tok = addTname( t );

+    set_orel(e->tok, &imag_tokens);

+    set_orel(e->tok, &tokclasses);

+    require((p=(TermEntry *)hash_get(Tname, t)) != NULL,

+    "hash table mechanism is broken");

+    p->classname = 1;	/* entry is class name, not token */

+    p->tclass = e;		/* save ptr to this tclass def */

+    list_add(&tclasses, (char *)e);

+  }

+  else

+  {

+  warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t));

+  free( (char *)e );

+  go=0;

+}

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==114) ) {

+      zzmatch(114); zzCONSUME;

+      zzmatch(QuotedTerm);

+      akaString=mystrdup(StripQuotes(LATEXT(1)));

+      /* MR11 */                   save_file=CurFile;save_line=zzline;

+      /* MR23 */

+ zzCONSUME;

+

+      zzmatch(115); zzCONSUME;

+    }

+    else {

+      if ( (LA(1)==102) ) {

+      }

+      else {zzFAIL(1,zzerr17,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  /* MR23 */         if (p!= NULL && akaString != NULL) {

+    /* MR23 */           if (p->akaString != NULL) {

+      /* MR23 */             if (strcmp(p->akaString,akaString) != 0) {

+        /* MR23 */                warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement",

+        /* MR23 */                              t,p->akaString),

+        /* MR23 */			                    FileStr[save_file],save_line);

+        /* MR23 */             };

+      /* MR23 */            } else {

+      /* MR23 */              p->akaString=akaString;

+      /* MR23 */            };

+    /* MR23 */          };

+  /* MR23 */

+  zzmatch(102); zzCONSUME;

+  {

+    zzBLOCK(zztasp2);

+    int zzcnt=1;

+    zzMake0;

+    {

+    do {

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==TokenTerm) ) {

+          zzmatch(TokenTerm);

+          if ( go ) {

+            term = (TermEntry *) hash_get(Tname, LATEXT(1));

+            if ( term==NULL && UserDefdTokens ) {

+              err("implicit token definition not allowed with #tokdefs");

+              go = 0;

+            }

+            else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));}

+          }

+ zzCONSUME;

+

+          {

+            zzBLOCK(zztasp4);

+            zzMake0;

+            {

+            if ( (LA(1)==119) ) {

+              zzmatch(119); zzCONSUME;

+              zzmatch(TokenTerm);

+              if ( go ) {

+                toterm = (TermEntry *) hash_get(Tname, LATEXT(1));

+                if ( toterm==NULL && UserDefdTokens ) {

+                  err("implicit token definition not allowed with #tokdefs");

+                  go = 0;

+                } else {

+                  totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1));

+                }

+              }

+ zzCONSUME;

+

+            }

+            else {

+              if ( (setwd4[LA(1)]&0x8) ) {

+              }

+              else {zzFAIL(1,zzerr18,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp4);

+            }

+          }

+        }

+        else {

+          if ( (LA(1)==QuotedTerm) ) {

+            zzmatch(QuotedTerm);

+            if ( go ) {

+              term = (TermEntry *) hash_get(Texpr, LATEXT(1));

+              if ( term==NULL && UserDefdTokens ) {

+                err("implicit token definition not allowed with #tokdefs");

+                go = 0;

+              }

+              else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));}

+            }

+ zzCONSUME;

+

+          }

+          else {zzFAIL(1,zzerr19,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      if ( go ) {

+        if (totext == NULL) {

+          list_add(&(e->tlist), t);

+        } else {

+          list_add(&(e->tlist),"..");

+          list_add(&(e->tlist),t);

+          list_add(&(e->tlist),totext);

+        }

+        totext=NULL;

+      }

+      zzLOOP(zztasp2);

+    } while ( (setwd4[LA(1)]&0x10) );

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(98); zzCONSUME;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd4, 0x20);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+token(void)

+#else

+token()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  char *t=NULL, *e=NULL, *a=NULL; int tnum=0;

+  char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0;

+  zzmatch(120);

+  tokenActionActive=1;

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==TokenTerm) ) {

+      zzmatch(TokenTerm);

+      t=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==114) ) {

+          zzmatch(114); zzCONSUME;

+          zzmatch(QuotedTerm);

+          akaString=mystrdup(StripQuotes(LATEXT(1)));

+          /* MR11 */                   save_file=CurFile;save_line=zzline;

+          /* MR11 */

+ zzCONSUME;

+

+          zzmatch(115); zzCONSUME;

+        }

+        else {

+          if ( (setwd4[LA(1)]&0x40) ) {

+          }

+          else {zzFAIL(1,zzerr20,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==121) ) {

+          zzmatch(121); zzCONSUME;

+          zzmatch(122);

+          tnum = atoi(LATEXT(1));

+ zzCONSUME;

+

+        }

+        else {

+          if ( (setwd4[LA(1)]&0x80) ) {

+          }

+          else {zzFAIL(1,zzerr21,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+    }

+    else {

+      if ( (setwd5[LA(1)]&0x1) ) {

+      }

+      else {zzFAIL(1,zzerr22,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==QuotedTerm) ) {

+      zzmatch(QuotedTerm);

+      e=mystrdup(LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd5[LA(1)]&0x2) ) {

+      }

+      else {zzFAIL(1,zzerr23,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==Action) ) {

+      zzmatch(Action);

+      

+      a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(a!=NULL, "rule token: cannot allocate action");

+      strcpy(a, LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd5[LA(1)]&0x4) ) {

+      }

+      else {zzFAIL(1,zzerr24,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==107) ) {

+      zzmatch(107); zzCONSUME;

+    }

+    else {

+      if ( (setwd5[LA(1)]&0x8) ) {

+      }

+      else {zzFAIL(1,zzerr25,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  chkToken(t, e, a, tnum);

+  if (t != NULL) {

+    te=(TermEntry *)hash_get(Tname,t);

+    if (te != NULL && akaString != NULL) {

+      if (te->akaString != NULL) {

+        if (strcmp(te->akaString,akaString) != 0) {

+          warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement",

+          t,te->akaString),

+          FileStr[save_file],save_line);

+        };

+      } else {

+        te->akaString=akaString;

+      };

+    };

+  };

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd5, 0x10);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+block(set * toksrefd,set * rulesrefd)

+#else

+block(toksrefd,rulesrefd)

+ set *toksrefd;

+set *rulesrefd ;

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  

+  Graph g, b;

+  set saveblah;

+  int saveinalt = inAlt;

+  ExceptionGroup *eg;

+  * toksrefd = empty;

+  * rulesrefd = empty;

+  set_clr(AST_nodes_refd_in_actions);

+  CurBlockID++;

+  /* MR23 */      CurBlockID_array[BlkLevel] = CurBlockID;

+  CurAltNum = 1;

+  /* MR23 */      CurAltNum_array[BlkLevel] = CurAltNum;                

+  saveblah = attribsRefdFromAction;

+  attribsRefdFromAction = empty;

+  alt( toksrefd,rulesrefd );

+  b = g = zzaArg(zztasp1,1);

+  

+  if ( ((Junction *)g.left)->p1->ntype == nAction )

+  {

+    ActionNode *actionNode=(ActionNode *)

+    ( ( (Junction *)g.left) ->p1);

+    if (!actionNode->is_predicate )

+    {

+      actionNode->init_action = TRUE;

+      /* MR12c */  		if (actionNode->noHoist) {

+        /* MR12c */           errFL("<<nohoist>> appears as init-action - use <<>> <<nohoist>>",

+        /* MR12c */                       FileStr[actionNode->file],actionNode->line);

+        /* MR12c */         };

+    }

+  }

+  ((Junction *)g.left)->blockid = CurBlockID;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==133) ) {

+       eg  = exception_group();

+

+      

+      if ( eg!=NULL ) {

+        /* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/

+        /* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/

+        list_add(&CurExGroups, (void *)eg);

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  CurAltNum++;

+  /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==123) ) {

+      zzmatch(123);

+      inAlt=1;

+ zzCONSUME;

+

+      alt( toksrefd,rulesrefd );

+      g = Or(g, zzaArg(zztasp2,2));

+      

+      ((Junction *)g.left)->blockid = CurBlockID;

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        while ( (LA(1)==133) ) {

+           eg  = exception_group();

+

+          

+          if ( eg!=NULL ) {

+            /* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/

+            /* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/

+            list_add(&CurExGroups, (void *)eg);

+          }

+          zzLOOP(zztasp3);

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      CurAltNum++;

+      /* MR23 */        CurAltNum_array[BlkLevel] = CurAltNum;

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzaArg(zztasp1,0) = b;

+  attribsRefdFromAction = saveblah; inAlt = saveinalt;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd5, 0x20);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+alt(set * toksrefd,set * rulesrefd)

+#else

+alt(toksrefd,rulesrefd)

+ set *toksrefd;

+set *rulesrefd ;

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif;

+  int first_on_line = 1, use_def_MT_handler = 0;

+  g.left=NULL; g.right=NULL;

+  

+			CurAltStart = NULL;

+  elems = empty;

+  inAlt = 1;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==88) ) {

+      zzmatch(88);

+      use_def_MT_handler = 1;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd5[LA(1)]&0x40) ) {

+      }

+      else {zzFAIL(1,zzerr26,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    ;

+    while ( (setwd5[LA(1)]&0x80) ) {

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        old_not=0;

+        if ( (LA(1)==124) ) {

+          zzmatch(124);

+          old_not=1;

+ zzCONSUME;

+

+        }

+        else {

+          if ( (setwd6[LA(1)]&0x1) ) {

+          }

+          else {zzFAIL(1,zzerr27,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+       node  = element( old_not, first_on_line, use_def_MT_handler );

+

+      if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;

+      

+      if ( zzaArg(zztasp2,2 ).left!=NULL ) {

+        g = Cat(g, zzaArg(zztasp2,2));

+        n++;

+        if ( node!=NULL ) {

+          if ( node->ntype!=nAction ) e_num++;

+          /* record record number of all rule and token refs */

+          if ( node->ntype==nToken ) {

+            TokNode *tk = (TokNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1;

+            tk->elnum = e_num;

+            set_orel(e_num, &elems);

+          }

+          else if ( node->ntype==nRuleRef ) {

+            RuleRefNode *rn = (RuleRefNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1;

+            rn->elnum = e_num;

+            set_orel(e_num,  rulesrefd);

+          }

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  if ( n == 0 ) g = emptyAlt();

+  zzaArg(zztasp1,0) = g;

+  /* We want to reduce number of LT(i) calls and the number of

+  * local attribute variables in C++ mode (for moment, later we'll

+  * do for C also).  However, if trees are being built, they

+  * require most of the attrib variables to create the tree nodes

+  * with; therefore, we gen a token ptr for each token ref in C++

+  */

+  if ( GenCC && !GenAST )

+  {

+  /* This now free's the temp set -ATG 5/6/95 */

+  set temp;

+  temp = set_and(elems, attribsRefdFromAction);

+  set_orin( toksrefd, temp);

+  set_free(temp);

+}

+else set_orin( toksrefd, elems);

+if ( GenCC ) {

+  dif = set_dif(attribsRefdFromAction, elems);

+  if ( set_deg(dif)>0 )

+  err("one or more $i in action(s) refer to non-token elements");

+  set_free(dif);

+}

+set_free(elems);

+set_free(attribsRefdFromAction);

+inAlt = 0;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd6, 0x2);

+  }

+}

+

+LabelEntry *

+#ifdef __USE_PROTOS

+element_label(void)

+#else

+element_label()

+#endif

+{

+  LabelEntry *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(LabelEntry *  ))

+  zzMake0;

+  {

+  TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;

+  zzmatch(LABEL);

+  lab = mystrdup(LATEXT(1));

+ zzCONSUME;

+

+  

+  UsedNewStyleLabel = 1;

+  if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i");

+  t = (TermEntry *) hash_get(Tname, lab);

+  if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab);

+  if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab);

+  if ( t!=NULL ) {

+    err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab));

+    _retv = NULL;

+  }

+  else if ( r!=NULL ) {

+    err(eMsg1("label definition clashes with rule definition: '%s'", lab));

+    _retv = NULL;

+  }

+  else {

+    /* we don't clash with anybody else */

+    l = (LabelEntry *) hash_get(Elabel, lab);

+    if ( l==NULL ) {	/* ok to add new element label */

+    l = (LabelEntry *)hash_add(Elabel,

+    lab,

+    (Entry *)newLabelEntry(lab));

+    /* add to list of element labels for this rule */

+    list_add(&CurElementLabels, (void *)lab);

+    /* MR7 */       leAdd(l);  /* list of labels waiting for exception group definitions */

+    _retv = l;

+  }

+  else {

+  err(eMsg1("label definitions must be unique per rule: '%s'", lab));

+  _retv = NULL;

+}

+}

+  zzmatch(106); zzCONSUME;

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd6, 0x4);

+  return _retv;

+  }

+}

+

+Node *

+#ifdef __USE_PROTOS

+element(int old_not,int first_on_line,int use_def_MT_handler)

+#else

+element(old_not,first_on_line,use_def_MT_handler)

+ int old_not;

+int first_on_line;

+int use_def_MT_handler ;

+#endif

+{

+  Node *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(Node *  ))

+  zzMake0;

+  {

+  

+  Attrib blk;

+  Predicate *pred = NULL;

+  int local_use_def_MT_handler=0;

+  ActionNode *act;

+  RuleRefNode *rr;

+  set toksrefd, rulesrefd;

+  TermEntry *term;

+  TokNode *p=NULL; RuleRefNode *q; int approx=0;

+  LabelEntry *label=NULL;

+  int predMsgDone=0;

+  int semDepth=0;

+  int   ampersandStyle;

+  int   height;         /* MR11 */

+  int   equal_height;   /* MR11 */

+  

+          char* pFirstSetSymbol = NULL; /* MR21 */

+  

+		  _retv = NULL;

+  if ( (setwd6[LA(1)]&0x8) ) {

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      if ( (LA(1)==LABEL) ) {

+         label  = element_label();

+

+      }

+      else {

+        if ( (setwd6[LA(1)]&0x10) ) {

+        }

+        else {zzFAIL(1,zzerr28,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      if ( (LA(1)==TokenTerm) ) {

+        zzmatch(TokenTerm);

+        

+        term = (TermEntry *) hash_get(Tname, LATEXT(1));

+        if ( term==NULL && UserDefdTokens ) {

+          err("implicit token definition not allowed with #tokdefs");

+          zzaRet.left = zzaRet.right = NULL;

+        }

+        else {

+          zzaRet = buildToken(LATEXT(1));

+          p=((TokNode *)((Junction *)zzaRet.left)->p1);

+          term = (TermEntry *) hash_get(Tname, LATEXT(1));

+          require( term!= NULL, "hash table mechanism is broken");

+          p->tclass = term->tclass;

+          p->complement =  old_not;

+          if ( label!=NULL ) {

+            p->el_label = label->str;

+            label->elem = (Node *)p;

+          }

+        }

+ zzCONSUME;

+

+        {

+          zzBLOCK(zztasp3);

+          zzMake0;

+          {

+          if ( (LA(1)==119) ) {

+            zzmatch(119); zzCONSUME;

+            {

+              zzBLOCK(zztasp4);

+              zzMake0;

+              {

+              if ( (LA(1)==QuotedTerm) ) {

+                zzmatch(QuotedTerm);

+                if ( p!=NULL ) setUpperRange(p, LATEXT(1));

+ zzCONSUME;

+

+              }

+              else {

+                if ( (LA(1)==TokenTerm) ) {

+                  zzmatch(TokenTerm);

+                  if ( p!=NULL ) setUpperRange(p, LATEXT(1));

+ zzCONSUME;

+

+                }

+                else {zzFAIL(1,zzerr29,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+              }

+              zzEXIT(zztasp4);

+              }

+            }

+          }

+          else {

+            if ( (setwd6[LA(1)]&0x20) ) {

+            }

+            else {zzFAIL(1,zzerr30,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+          zzEXIT(zztasp3);

+          }

+        }

+        

+        if ( p!=NULL && (p->upper_range!=0 || p->tclass ||  old_not) )

+        list_add(&MetaTokenNodes, (void *)p);

+        {

+          zzBLOCK(zztasp3);

+          zzMake0;

+          {

+          if ( (LA(1)==125) ) {

+            zzmatch(125);

+            if ( p!=NULL ) p->astnode=ASTroot;

+ zzCONSUME;

+

+          }

+          else {

+            if ( (setwd6[LA(1)]&0x40) ) {

+              if ( p!=NULL ) p->astnode=ASTchild;

+            }

+            else {

+              if ( (LA(1)==103) ) {

+                zzmatch(103);

+                if ( p!=NULL ) p->astnode=ASTexclude;

+ zzCONSUME;

+

+              }

+              else {zzFAIL(1,zzerr31,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+          }

+          zzEXIT(zztasp3);

+          }

+        }

+        {

+          zzBLOCK(zztasp3);

+          zzMake0;

+          {

+          if ( (LA(1)==88) ) {

+            zzmatch(88);

+            local_use_def_MT_handler = 1;

+ zzCONSUME;

+

+          }

+          else {

+            if ( (setwd6[LA(1)]&0x80) ) {

+            }

+            else {zzFAIL(1,zzerr32,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+          zzEXIT(zztasp3);

+          }

+        }

+        

+        if ( p!=NULL &&  first_on_line ) {

+          CurAltStart = (Junction *)zzaRet.left;

+          altAdd(CurAltStart);                                 /* MR7 */

+          p->altstart = CurAltStart;

+        }

+        if ( p!=NULL )

+        p->use_def_MT_handler =  use_def_MT_handler || local_use_def_MT_handler;

+        _retv = (Node *)p;

+      }

+      else {

+        if ( (LA(1)==QuotedTerm) ) {

+          zzmatch(QuotedTerm);

+          

+          term = (TermEntry *) hash_get(Texpr, LATEXT(1));

+          if ( term==NULL && UserDefdTokens ) {

+            err("implicit token definition not allowed with #tokdefs");

+            zzaRet.left = zzaRet.right = NULL;

+          }

+          else {

+            zzaRet = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1);

+            p->complement =  old_not;

+            if ( label!=NULL ) {

+              p->el_label = label->str;

+              label->elem = (Node *)p;

+            }

+          }

+ zzCONSUME;

+

+          {

+            zzBLOCK(zztasp3);

+            zzMake0;

+            {

+            if ( (LA(1)==119) ) {

+              zzmatch(119); zzCONSUME;

+              {

+                zzBLOCK(zztasp4);

+                zzMake0;

+                {

+                if ( (LA(1)==QuotedTerm) ) {

+                  zzmatch(QuotedTerm);

+                  if ( p!=NULL ) setUpperRange(p, LATEXT(1));

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (LA(1)==TokenTerm) ) {

+                    zzmatch(TokenTerm);

+                    if ( p!=NULL ) setUpperRange(p, LATEXT(1));

+ zzCONSUME;

+

+                  }

+                  else {zzFAIL(1,zzerr33,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+                zzEXIT(zztasp4);

+                }

+              }

+            }

+            else {

+              if ( (setwd7[LA(1)]&0x1) ) {

+              }

+              else {zzFAIL(1,zzerr34,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp3);

+            }

+          }

+          {

+            zzBLOCK(zztasp3);

+            zzMake0;

+            {

+            if ( (LA(1)==125) ) {

+              zzmatch(125);

+              if ( p!=NULL ) p->astnode=ASTroot;

+ zzCONSUME;

+

+            }

+            else {

+              if ( (setwd7[LA(1)]&0x2) ) {

+                if ( p!=NULL ) p->astnode=ASTchild;

+              }

+              else {

+                if ( (LA(1)==103) ) {

+                  zzmatch(103);

+                  if ( p!=NULL ) p->astnode=ASTexclude;

+ zzCONSUME;

+

+                }

+                else {zzFAIL(1,zzerr35,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+              }

+            }

+            zzEXIT(zztasp3);

+            }

+          }

+          {

+            zzBLOCK(zztasp3);

+            zzMake0;

+            {

+            if ( (LA(1)==88) ) {

+              zzmatch(88);

+              local_use_def_MT_handler = 1;

+ zzCONSUME;

+

+            }

+            else {

+              if ( (setwd7[LA(1)]&0x4) ) {

+              }

+              else {zzFAIL(1,zzerr36,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp3);

+            }

+          }

+          

+          if ( p!=NULL && (p->upper_range!=0 || p->tclass ||  old_not) )

+          list_add(&MetaTokenNodes, (void *)p);

+          

+          if (  first_on_line ) {

+            CurAltStart = (Junction *)zzaRet.left;

+            altAdd(CurAltStart);                                 /* MR7 */

+            p->altstart = CurAltStart;

+          }

+          if ( p!=NULL )

+          p->use_def_MT_handler =  use_def_MT_handler || local_use_def_MT_handler;

+          _retv = (Node *)p;

+        }

+        else {

+          if ( (LA(1)==WildCard) ) {

+            if (  old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");

+            zzmatch(WildCard);

+            zzaRet = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1);

+ zzCONSUME;

+

+            {

+              zzBLOCK(zztasp3);

+              zzMake0;

+              {

+              if ( (LA(1)==125) ) {

+                zzmatch(125);

+                p->astnode=ASTroot;

+ zzCONSUME;

+

+              }

+              else {

+                if ( (setwd7[LA(1)]&0x8) ) {

+                  p->astnode=ASTchild;

+                }

+                else {

+                  if ( (LA(1)==103) ) {

+                    zzmatch(103);

+                    p->astnode=ASTexclude;

+ zzCONSUME;

+

+                  }

+                  else {zzFAIL(1,zzerr37,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+              }

+              zzEXIT(zztasp3);

+              }

+            }

+            list_add(&MetaTokenNodes, (void *)p);

+            

+            if (  first_on_line ) {

+              CurAltStart = (Junction *)zzaRet.left;

+              altAdd(CurAltStart);                                 /* MR7 */

+              p->altstart = CurAltStart;

+              if ( label!=NULL ) {

+                p->el_label = label->str;

+                label->elem = (Node *)p;

+              }

+            }

+            _retv = (Node *)p;

+          }

+          else {

+            if ( (LA(1)==NonTerminal) ) {

+              if (  old_not ) warn("~ NONTERMINAL is an undefined operation");

+              zzmatch(NonTerminal);

+              zzaRet = buildRuleRef(LATEXT(1));

+ zzCONSUME;

+

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                if ( (LA(1)==103) ) {

+                  zzmatch(103);

+                  q = (RuleRefNode *) ((Junction *)zzaRet.left)->p1;

+                  q->astnode=ASTexclude;

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (setwd7[LA(1)]&0x10) ) {

+                  }

+                  else {zzFAIL(1,zzerr38,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                if ( (setwd7[LA(1)]&0x20) ) {

+                  {

+                    zzBLOCK(zztasp4);

+                    zzMake0;

+                    {

+                    if ( (LA(1)==104) ) {

+                      zzmatch(104); zzCONSUME;

+                    }

+                    else {

+                      if ( (LA(1)==PassAction) ) {

+                      }

+                      else {zzFAIL(1,zzerr39,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                    }

+                    zzEXIT(zztasp4);

+                    }

+                  }

+                  zzmatch(PassAction);

+                  addParm(((Junction *)zzaRet.left)->p1, LATEXT(1));

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (setwd7[LA(1)]&0x40) ) {

+                  }

+                  else {zzFAIL(1,zzerr40,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+              rr=(RuleRefNode *) ((Junction *)zzaRet.left)->p1;

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                char *a;

+                if ( (LA(1)==105) ) {

+                  zzmatch(105); zzCONSUME;

+                  zzmatch(PassAction);

+                  

+                  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+                  require(a!=NULL, "rule element: cannot allocate assignment");

+                  strcpy(a, LATEXT(1));

+                  rr->assign = a;

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (setwd7[LA(1)]&0x80) ) {

+                  }

+                  else {zzFAIL(1,zzerr41,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+              

+              if ( label!=NULL ) {

+                rr->el_label = label->str;

+                label->elem = (Node *)rr;

+              }

+              if (  first_on_line ) {

+                CurAltStart = (Junction *)zzaRet.left;

+                altAdd(CurAltStart);                                 /* MR7 */

+                ((RuleRefNode *)((Junction *)zzaRet.left)->p1)->altstart = CurAltStart;

+              }

+              _retv = (Node *)rr;

+            }

+            else {zzFAIL(1,zzerr42,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+        }

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+  }

+  else {

+    if ( (LA(1)==Action) ) {

+      if (  old_not )	warn("~ ACTION is an undefined operation");

+      zzmatch(Action);

+      zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 0);

+ zzCONSUME;

+

+      if (  first_on_line ) {                                /* MR7 */

+        CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left;                   /* MR7 */

+        altAdd(CurAltStart);                                 /* MR7 */

+      };

+      _retv = (Node *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1;

+    }

+    else {

+      if ( (LA(1)==Pred) ) {

+        if (  old_not )	warn("~ SEMANTIC-PREDICATE is an undefined operation");

+        zzmatch(Pred);

+        zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 1);

+ zzCONSUME;

+

+        act = (ActionNode *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1;

+        if (numericActionLabel) {             /* MR10 */

+          list_add(&NumericPredLabels,act);   /* MR10 */

+          numericActionLabel=0;               /* MR10 */

+        };                                    /* MR10 */

+        {

+          zzBLOCK(zztasp2);

+          zzMake0;

+          {

+          char *a;

+          if ( (LA(1)==PassAction) ) {

+            zzmatch(PassAction);

+            

+            a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+            require(a!=NULL, "rule element: cannot allocate predicate fail action");

+            strcpy(a, LATEXT(1));

+            act->pred_fail = a;

+ zzCONSUME;

+

+          }

+          else {

+            if ( (setwd8[LA(1)]&0x1) ) {

+            }

+            else {zzFAIL(1,zzerr43,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+          zzEXIT(zztasp2);

+          }

+        }

+        if (  first_on_line ) {                                /* MR7 */

+          CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left;                   /* MR7 */

+          altAdd(CurAltStart);                                 /* MR7 */

+        };

+        _retv = (Node *)act;

+      }

+      else {

+        if ( (setwd8[LA(1)]&0x2) ) {

+          if (  old_not )	warn("~ BLOCK is an undefined operation");

+          BlkLevel++;

+          if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");

+          /* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;

+          /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;

+          {

+            zzBLOCK(zztasp2);

+            zzMake0;

+            {

+            if ( (LA(1)==Pragma) ) {

+              zzmatch(Pragma); zzCONSUME;

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                if ( (LA(1)==126) ) {

+                  zzmatch(126);

+                  approx=LL_k;

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (LA(1)==127) ) {

+                    zzmatch(127);

+                    approx = 1;

+ zzCONSUME;

+

+                  }

+                  else {

+                    if ( (LA(1)==128) ) {

+                      zzmatch(128);

+                      approx = 2;

+ zzCONSUME;

+

+                    }

+                    else {zzFAIL(1,zzerr44,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                  }

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+            }

+            else {

+              if ( (setwd8[LA(1)]&0x4) ) {

+              }

+              else {zzFAIL(1,zzerr45,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp2);

+            }

+          }

+          {

+            zzBLOCK(zztasp2);

+            zzMake0;

+            {

+            if ( (LA(1)==FirstSetSymbol) ) {

+              zzmatch(FirstSetSymbol); zzCONSUME;

+              zzmatch(114); zzCONSUME;

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                if ( (LA(1)==NonTerminal) ) {

+                  zzmatch(NonTerminal);

+                  

+                  /* MR21 */                     pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,

+                  /* MR21 */                                                    sizeof(char));

+                  /* MR21 */                          require(pFirstSetSymbol!=NULL,

+                  /* MR21 */                                  "cannot allocate first set name");

+                  /* MR21 */                          strcpy(pFirstSetSymbol, LATEXT(1));

+                  /* MR21 */

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (LA(1)==TokenTerm) ) {

+                    zzmatch(TokenTerm);

+                    

+                    /* MR21 */                      pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,

+                    /* MR21 */                                                        sizeof(char));

+                    /* MR21 */                      require(pFirstSetSymbol!=NULL,

+                    /* MR21 */                              "cannot allocate first set name");

+                    /* MR21 */                      strcpy(pFirstSetSymbol, LATEXT(1));

+                    /* MR21 */

+ zzCONSUME;

+

+                  }

+                  else {zzFAIL(1,zzerr46,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+              zzmatch(115); zzCONSUME;

+            }

+            else {

+              if ( (setwd8[LA(1)]&0x8) ) {

+              }

+              else {zzFAIL(1,zzerr47,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp2);

+            }

+          }

+          {

+            zzBLOCK(zztasp2);

+            zzMake0;

+            {

+            if ( (LA(1)==114) ) {

+              zzmatch(114); zzCONSUME;

+              block( &toksrefd,&rulesrefd );

+              zzmatch(115);

+              blk = zzaRet = zzaArg(zztasp2,2);

+              /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+              /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+              --BlkLevel;

+ zzCONSUME;

+

+              {

+                zzBLOCK(zztasp3);

+                zzMake0;

+                {

+                if ( (LA(1)==129) ) {

+                  zzmatch(129);

+                  zzaRet = makeLoop(zzaRet,approx,pFirstSetSymbol);

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (LA(1)==130) ) {

+                    zzmatch(130);

+                    zzaRet = makePlus(zzaRet,approx,pFirstSetSymbol);

+ zzCONSUME;

+

+                  }

+                  else {

+                    if ( (LA(1)==131) ) {

+                      zzmatch(131); zzCONSUME;

+                      {

+                        zzBLOCK(zztasp4);

+                        zzMake0;

+                        {

+                        if ( (setwd8[LA(1)]&0x10) ) {

+                          {

+                            zzBLOCK(zztasp5);

+                            zzMake0;

+                            {

+                            if ( (LA(1)==132) ) {

+                              zzmatch(132);

+                              ampersandStyle=0;

+ zzCONSUME;

+

+                            }

+                            else {

+                              if ( (LA(1)==113) ) {

+                                zzmatch(113);

+                                ampersandStyle=1;

+ zzCONSUME;

+

+                              }

+                              else {zzFAIL(1,zzerr48,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                            }

+                            zzEXIT(zztasp5);

+                            }

+                          }

+                          zzmatch(Pred);

+                          zzaRet = buildAction(LATEXT(1),action_file,action_line,1);

+ zzCONSUME;

+

+                          act = (ActionNode *) ((Junction *)zzaRet.left)->p1;

+                          semDepth=predicateLookaheadDepth(act);

+                          if (numericActionLabel) {             /* MR10 */

+                            list_add(&NumericPredLabels,act);   /* MR10 */

+                            numericActionLabel=0;               /* MR10 */

+                          };                                    /* MR10 */

+                          {

+                            zzBLOCK(zztasp5);

+                            zzMake0;

+                            {

+                            char *a;

+                            if ( (LA(1)==PassAction) ) {

+                              zzmatch(PassAction);

+                              

+                              a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char));

+                              require(a!=NULL, "rule element: cannot allocate predicate fail action");

+                              strcpy(a, LATEXT(1));

+                              act->pred_fail = a;

+ zzCONSUME;

+

+                            }

+                            else {

+                              if ( (setwd8[LA(1)]&0x20) ) {

+                              }

+                              else {zzFAIL(1,zzerr49,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                            }

+                            zzEXIT(zztasp5);

+                            }

+                          }

+                          if ( first_on_line) {                      /* MR7 */

+                            CurAltStart=(Junction *)zzaRet.left;         /* MR7 */

+                            altAdd(CurAltStart);                     /* MR7 */

+                          };

+                          _retv = (Node *)act;

+                          

+                          pred = computePredFromContextGuard(blk,&predMsgDone);           /* MR10 */

+                          if ( pred==NULL) {                                              /* MR10 */

+                            if ( !predMsgDone) err("invalid or missing context guard");   /* MR10 */

+                            predMsgDone=1;                                                /* MR10 */

+                          } else {                                                        /* MR10 */

+                            act->guardNodes=(Junction *)blk.left;                       /* MR11 */

+                            pred->expr = act->action;

+                            pred->source = act;

+                            /* MR10 */                  pred->ampersandStyle = ampersandStyle;  /* 0 means (g)? => ... 1 means (g)? && ... */

+                            /* MR13 */                  if (pred->tcontext != NULL) {

+                              /* MR13 */                    height=MR_max_height_of_tree(pred->tcontext);

+                              /* MR13 */                    equal_height=MR_all_leaves_same_height(pred->tcontext,height);

+                              /* MR13 */                    if (! equal_height) {

+                                /* MR13 */                       errFL("in guarded predicates all tokens in the guard must be at the same height",

+                                /* MR13 */                              FileStr[act->file],act->line);

+                                /* MR13 */                    };

+                              /* MR13 */                  }

+                            /* MR10 */                  if (ampersandStyle) {

+                              /* MR10 */			  		  act->ampersandPred = pred;

+                              /* MR11 */                    if (! HoistPredicateContext) {

+                                /* MR11 */                      errFL("without \"-prc on\" (guard)? && <<pred>>? ... doesn't make sense",

+                                /* MR11 */                              FileStr[act->file],act->line);

+                                /* MR11 */                    };

+                              /* MR10 */                  } else {

+                              /* MR10 */			  		  act->guardpred = pred;

+                              /* MR10 */                  };

+                            /* MR10 */                  if (pred->k != semDepth) {

+                              /* MR10 */                     warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)",

+                              /* MR10 */                                  pred->k,semDepth));

+                              /* MR10 */                  };

+                          }

+                        }

+                        else {

+                          if ( (setwd8[LA(1)]&0x40) ) {

+                            zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol);

+                            FoundGuessBlk = 1;

+                            ((Junction *) ((Junction *)zzaRet.left)->p1)->guess=1;

+                            if ( ! first_on_line ) {

+                              err("(...)? predicate must be first element of production");

+                            }

+                          }

+                          else {zzFAIL(1,zzerr50,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                        }

+                        zzEXIT(zztasp4);

+                        }

+                      }

+                    }

+                    else {

+                      if ( (setwd8[LA(1)]&0x80) ) {

+                        zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol);

+                      }

+                      else {zzFAIL(1,zzerr51,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                    }

+                  }

+                }

+                zzEXIT(zztasp3);

+                }

+              }

+              

+              if ( pred==NULL && !predMsgDone) {                                      /* MR10 */

+                ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID;

+                ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd;

+                ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd;

+                if (  first_on_line ) {                         /* MR7 */

+                  CurAltStart = (Junction *)((Junction *)((Junction *)zzaRet.left)->p1);  /* MR7 */

+                  altAdd(CurAltStart);                         /* MR7 */

+                };                                              /* MR7 */

+                _retv = (Node *) ((Junction *)zzaRet.left)->p1;

+              }

+            }

+            else {

+              if ( (LA(1)==102) ) {

+                zzmatch(102); zzCONSUME;

+                block( &toksrefd,&rulesrefd );

+                zzaRet = makeOpt(zzaArg(zztasp2,2),approx,pFirstSetSymbol);

+                /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+                /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+                --BlkLevel;

+                zzmatch(98);

+                

+                ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID;

+                ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd;

+                ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd;

+ zzCONSUME;

+

+                if (  first_on_line ) {                            /* MR7 */

+                  CurAltStart = (Junction *) ((Junction *)((Junction *)zzaRet.left)->p1);  /* MR7 */

+                  altAdd(CurAltStart);                             /* MR7 */

+                };

+                _retv = (Node *) ((Junction *)zzaRet.left)->p1;

+              }

+              else {zzFAIL(1,zzerr52,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp2);

+            }

+          }

+        }

+        else {

+          if ( (LA(1)==129) ) {

+            zzmatch(129);

+            warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;

+ zzCONSUME;

+

+          }

+          else {

+            if ( (LA(1)==130) ) {

+              zzmatch(130);

+              warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;

+ zzCONSUME;

+

+            }

+            else {

+              if ( (LA(1)==105) ) {

+                zzmatch(105);

+                warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;

+ zzCONSUME;

+

+              }

+              else {

+                if ( (LA(1)==PassAction) ) {

+                  zzmatch(PassAction);

+                  warn("[...] out of context 'rule > [...]'");

+                  CannotContinue=TRUE;

+ zzCONSUME;

+

+                }

+                else {zzFAIL(1,zzerr53,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+              }

+            }

+          }

+        }

+      }

+    }

+  }

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd9, 0x1);

+  return _retv;

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+default_exception_handler(void)

+#else

+default_exception_handler()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+   DefaultExGroup  = exception_group();

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd9, 0x2);

+  }

+}

+

+ExceptionGroup *

+#ifdef __USE_PROTOS

+exception_group(void)

+#else

+exception_group()

+#endif

+{

+  ExceptionGroup *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(ExceptionGroup *  ))

+  zzMake0;

+  {

+  ExceptionHandler *h; LabelEntry *label=NULL;	  /* MR6 */

+  FoundException = 1; FoundExceptionGroup = 1;

+  zzmatch(133);

+  _retv = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    char *p;

+    if ( (LA(1)==PassAction) ) {

+      zzmatch(PassAction);

+      

+      p = LATEXT(1)+1;

+      p[strlen(p)-1] = '\0';		/* kill trailing space */

+      label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1);

+      if ( label==NULL )

+      {

+        err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1));

+      }

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd9[LA(1)]&0x4) ) {

+      }

+      else {zzFAIL(1,zzerr54,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==135) ) {

+       h  = exception_handler();

+

+      list_add(&(_retv->handlers), (void *)h);

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==134) ) {

+      zzmatch(134); zzCONSUME;

+      zzmatch(106); zzCONSUME;

+      zzmatch(Action);

+      {

+        ExceptionHandler *eh = (ExceptionHandler *)

+        calloc(1, sizeof(ExceptionHandler));

+        char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+        require(eh!=NULL, "exception: cannot allocate handler");

+        require(a!=NULL, "exception: cannot allocate action");

+        strcpy(a, LATEXT(1));

+        eh->action = a;

+        eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char));

+        require(eh->signalname!=NULL, "exception: cannot allocate sig name");

+        strcpy(eh->signalname, "default");

+        list_add(&(_retv->handlers), (void *)eh);

+      }

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd9[LA(1)]&0x8) ) {

+      }

+      else {zzFAIL(1,zzerr55,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  if ( label!=NULL ) {

+    /* Record ex group in sym tab for this label */

+    if ( label->ex_group!=NULL ) {

+      err(eMsg1("duplicate exception handler for label '%s'",label->str));

+    } else {

+      label->ex_group = _retv;

+      /* Label the exception group itself */

+      _retv->label = label->str;

+      /* Make the labelled element pt to the exception also */

+      /* MR6 */	  if (label->elem == NULL) {

+        /* MR6 */	     err(eMsg1("reference in exception handler to undefined label '%s'",label->str));

+        /* MR6 */	  } else {

+        switch ( label->elem->ntype ) {

+          case nRuleRef :

+          {

+            RuleRefNode *r = (RuleRefNode *)label->elem;

+            r->ex_group = _retv;

+            break;

+          }

+          case nToken :

+          {

+            TokNode *t = (TokNode *)label->elem;

+            t->ex_group = _retv;

+            break;

+          }

+        } /* end switch */

+        /* MR6 */	  }; /* end test on label->elem */

+    } /* end test on label->ex_group */

+    

+		} /* end test on exception label */

+  

+/* MR7 */

+  /* MR7 */   if (BlkLevel == 1 && label == NULL) {

+    /* MR7 */     _retv->forRule=1;

+    /* MR7 */   } else if (label == NULL) {

+    /* MR7 */     _retv->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]);

+    /* MR7 */     egAdd(_retv);

+    /* MR7 */   } else {

+    /* MR7 */     _retv->labelEntry=label;

+    /* MR7 */   };

+  /* MR7 */

+  /* MR7 */	    /* You may want to remove this exc from the rule list  */

+  /* MR7 */		/* and handle at the labeled element site.             */

+  /* MR7 */

+  /* MR7 */   if (label != NULL) {

+    /* MR7 */     _retv = NULL;

+    /* MR7 */   };

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd9, 0x10);

+  return _retv;

+  }

+}

+

+ExceptionHandler *

+#ifdef __USE_PROTOS

+exception_handler(void)

+#else

+exception_handler()

+#endif

+{

+  ExceptionHandler *   _retv;

+  zzRULE;

+  zzBLOCK(zztasp1);

+  PCCTS_PURIFY(_retv,sizeof(ExceptionHandler *  ))

+  zzMake0;

+  {

+  ;

+  zzmatch(135);

+  

+  _retv = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler));

+  require(_retv!=NULL, "exception: cannot allocate handler");

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==NonTerminal) ) {

+      zzmatch(NonTerminal);

+      

+      _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(_retv->signalname!=NULL, "exception: cannot allocate sig name");

+      strcpy(_retv->signalname, LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==TokenTerm) ) {

+        zzmatch(TokenTerm);

+        

+        _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+        require(_retv->signalname!=NULL, "exception: cannot allocate sig name");

+        strcpy(_retv->signalname, LATEXT(1));

+ zzCONSUME;

+

+      }

+      else {zzFAIL(1,zzerr56,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(106); zzCONSUME;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    _retv->action = NULL;

+    if ( (LA(1)==Action) ) {

+      zzmatch(Action);

+      

+      _retv->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+      require(_retv->action!=NULL, "exception: cannot allocate action");

+      strcpy(_retv->action, LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd9[LA(1)]&0x20) ) {

+      }

+      else {zzFAIL(1,zzerr57,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return _retv;

+fail:

+  zzEXIT(zztasp1);

+  CannotContinue=TRUE;  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd9, 0x40);

+  return _retv;

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+enum_file(char * fname)

+#else

+enum_file(fname)

+ char *fname ;

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  if ( (setwd9[LA(1)]&0x80) ) {

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      if ( (LA(1)==143) ) {

+        zzmatch(143); zzCONSUME;

+        zzmatch(ID); zzCONSUME;

+        {

+          zzBLOCK(zztasp3);

+          zzMake0;

+          {

+          if ( (LA(1)==149) ) {

+            zzmatch(149); zzCONSUME;

+            zzmatch(ID); zzCONSUME;

+          }

+          else {

+            if ( (setwd10[LA(1)]&0x1) ) {

+            }

+            else {zzFAIL(1,zzerr58,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+          zzEXIT(zztasp3);

+          }

+        }

+      }

+      else {

+        if ( (setwd10[LA(1)]&0x2) ) {

+        }

+        else {zzFAIL(1,zzerr59,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      if ( (LA(1)==151) ) {

+        {

+          zzBLOCK(zztasp3);

+          int zzcnt=1;

+          zzMake0;

+          {

+          do {

+            enum_def(  fname );

+            zzLOOP(zztasp3);

+          } while ( (LA(1)==151) );

+          zzEXIT(zztasp3);

+          }

+        }

+      }

+      else {

+        if ( (LA(1)==149) ) {

+          defines(  fname );

+        }

+        else {zzFAIL(1,zzerr60,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+  }

+  else {

+    if ( (LA(1)==Eof) ) {

+    }

+    else {zzFAIL(1,zzerr61,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd10, 0x4);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+defines(char * fname)

+#else

+defines(fname)

+ char *fname ;

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  int v; int maxt=(-1); char *t;

+  {

+    zzBLOCK(zztasp2);

+    int zzcnt=1;

+    zzMake0;

+    {

+    do {

+      zzmatch(149); zzCONSUME;

+      zzmatch(ID);

+      t = mystrdup(LATEXT(1));

+ zzCONSUME;

+

+      zzmatch(INT);

+      

+      v = atoi(LATEXT(1));

+      /*			fprintf(stderr, "#token %s=%d\n", t, v);*/

+      

+	/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */

+      /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */

+      /* MR2 Don't let #tokdefs be confused by 			*/

+      /* MR2   DLGminToken and DLGmaxToken     			*/

+      

+			if ( ! isDLGmaxToken(t)) {		/* MR2 */

+      TokenNum = v;

+      if ( v>maxt ) maxt=v;

+      if ( Tnum( t ) == 0 ) {

+      addForcedTname( t, v );

+    } else {

+    warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);

+  };

+};

+ zzCONSUME;

+

+      zzLOOP(zztasp2);

+    } while ( (LA(1)==149) );

+    zzEXIT(zztasp2);

+    }

+  }

+  TokenNum = maxt + 1;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd10, 0x8);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+enum_def(char * fname)

+#else

+enum_def(fname)

+ char *fname ;

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  int v= 0; int maxt=(-1); char *t;

+  zzmatch(151); zzCONSUME;

+  zzmatch(ID); zzCONSUME;

+  zzmatch(152); zzCONSUME;

+  zzmatch(ID);

+  t = mystrdup(LATEXT(1));

+ zzCONSUME;

+

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==153) ) {

+      zzmatch(153); zzCONSUME;

+      zzmatch(INT);

+      v=atoi(LATEXT(1));

+ zzCONSUME;

+

+    }

+    else {

+      if ( (setwd10[LA(1)]&0x10) ) {

+        v++;

+      }

+      else {zzFAIL(1,zzerr62,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  

+  /*			fprintf(stderr, "#token %s=%d\n", t, v);*/

+  TokenNum = v;

+  if ( v>maxt ) maxt=v;				/* MR3 */

+  if ( Tnum( t ) == 0 ) addForcedTname( t, v );

+  else {

+    warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);

+  }

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==154) ) {

+      zzmatch(154); zzCONSUME;

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==ID)&&(isDLGmaxToken(LATEXT(1))) ) {

+          if (!(isDLGmaxToken(LATEXT(1)))            ) {zzfailed_pred("  isDLGmaxToken(LATEXT(1))",0 /* report */, { 0; /* no user action */ } );}

+          zzmatch(ID); zzCONSUME;

+          {

+            zzBLOCK(zztasp4);

+            zzMake0;

+            {

+            if ( (LA(1)==153) ) {

+              zzmatch(153); zzCONSUME;

+              zzmatch(INT); zzCONSUME;

+            }

+            else {

+              if ( (setwd10[LA(1)]&0x20) ) {

+              }

+              else {zzFAIL(1,zzerr63,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+            }

+            zzEXIT(zztasp4);

+            }

+          }

+        }

+        else {

+          if ( (LA(1)==ID) ) {

+            zzmatch(ID);

+            t = mystrdup(LATEXT(1));

+ zzCONSUME;

+

+            {

+              zzBLOCK(zztasp4);

+              zzMake0;

+              {

+              if ( (LA(1)==153) ) {

+                zzmatch(153); zzCONSUME;

+                zzmatch(INT);

+                v=atoi(LATEXT(1));

+ zzCONSUME;

+

+              }

+              else {

+                if ( (setwd10[LA(1)]&0x40) ) {

+                  v++;

+                }

+                else {zzFAIL(1,zzerr64,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+              }

+              zzEXIT(zztasp4);

+              }

+            }

+            

+            /*					fprintf(stderr, "#token %s=%d\n", t, v);*/

+            TokenNum = v;

+            if ( v>maxt ) maxt=v;				/* MR3 */

+            if ( Tnum( t ) == 0 ) addForcedTname( t, v );

+            else {

+              warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);

+            }

+          }

+          else {

+            if ( (setwd10[LA(1)]&0x80) ) {

+            }

+            else {zzFAIL(1,zzerr65,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+          }

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(155); zzCONSUME;

+  zzmatch(156);

+  TokenNum = maxt + 1;

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd11, 0x1);

+  }

+}

+

+

+/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */

+/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */

+/* MR2 Don't let #tokdefs be confused by 			*/

+/* MR2   DLGminToken and DLGmaxToken     			*/

+

+/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */

+

+#ifdef __USE_PROTOS

+static int isDLGmaxToken(char *Token)

+#else

+static int isDLGmaxToken(Token)

+char *	Token;

+#endif

+{

+static char checkStr1[] = "DLGmaxToken";

+static char checkStr2[] = "DLGminToken";

+

+   if (strcmp(Token, checkStr1) == 0)

+return 1;

+else if (strcmp(Token, checkStr2) == 0)

+return 1;

+else

+return 0;

+}

+

+/* semantics of #token */

+static void

+#ifdef __USE_PROTOS

+chkToken(char *t, char *e, char *a, int tnum)

+#else

+chkToken(t,e,a,tnum)

+char *t, *e, *a;

+int tnum;

+#endif

+{

+TermEntry *p;

+

+	/* check to see that they don't try to redefine a token as a token class */

+if ( t!=NULL ) {

+p = (TermEntry *) hash_get(Tname, t);

+if ( p!=NULL && p->classname ) {

+  err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t));

+  if ( a!=NULL ) free((char *)a);

+  return;

+}

+}

+

+	if ( t==NULL && e==NULL ) {			/* none found */

+err("#token requires at least token name or rexpr");

+}

+else if ( t!=NULL && e!=NULL ) {	/* both found */

+if ( UserDefdTokens ) {			/* if #tokdefs, must not define new */

+  p = (TermEntry *) hash_get(Tname, t);

+  if ( p == NULL) {

+    err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));

+    return;

+  };

+}

+Tklink(t, e);

+if ( a!=NULL ) {

+  if ( hasAction(e) ) {

+    err(eMsg1("redefinition of action for %s; ignored",e));

+  }

+  else setHasAction(e, a);

+}

+}

+else if ( t!=NULL ) {				/* only one found */

+if ( UserDefdTokens ) {

+  p = (TermEntry *) hash_get(Tname, t);

+  if (p == NULL) {

+    err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));

+  };

+  return;

+}

+if ( Tnum( t ) == 0 ) addTname( t );

+else {

+  err(eMsg1("redefinition of token %s; ignored",t));

+}

+if ( a!=NULL ) {

+  err(eMsg1("action cannot be attached to a token name (%s); ignored",t));

+  free((char *)a);

+}

+}

+else if ( e!=NULL ) {

+if ( Tnum( e ) == 0 ) addTexpr( e );

+else {

+  if ( hasAction(e) ) {

+    err(eMsg1("redefinition of action for expr %s; ignored",e));

+  }

+  else if ( a==NULL ) {

+    err(eMsg1("redefinition of expr %s; ignored",e));

+  }

+}

+if ( a!=NULL ) setHasAction(e, a);

+}

+

+	/* if a token type number was specified, then add the token ID and 'tnum'

+* pair to the ForcedTokens list.  (only applies if an id was given)

+*/

+if ( t!=NULL && tnum>0 )

+{

+if ( set_el(tnum, reserved_positions) )

+{

+  err(eMsgd("a token has already been forced to token number %d; ignored", tnum));

+}

+else

+{

+  list_add(&ForcedTokens, newForcedToken(t,tnum));

+  set_orel(tnum, &reserved_positions);

+}

+}

+}

+

+static int

+#ifdef __USE_PROTOS

+match_token(char *s, char **nxt)

+#else

+match_token(s,nxt)

+char *s;

+char **nxt;

+#endif

+{

+  if ( !(*s>='A' && *s<='Z') ) return 0;

+  s++;

+  while ( (*s>='a' && *s<='z') ||

+  (*s>='A' && *s<='Z') ||

+  (*s>='0' && *s<='9') ||

+  *s=='_' )

+  {

+    s++;

+  }

+  if ( *s!=' ' && *s!='}' ) return 0;

+  *nxt = s;

+  return 1;

+}

+

+static int

+#ifdef __USE_PROTOS

+match_rexpr(char *s, char **nxt)

+#else

+match_rexpr(s,nxt)

+char *s;

+char **nxt;

+#endif

+{

+  if ( *s!='"' ) return 0;

+  s++;

+  while ( *s!='"' )

+  {

+    if ( *s=='\n' || *s=='\r' )                   /* MR13 */

+    warn("eoln found in regular expression");

+    if ( *s=='\\' ) s++;

+    s++;

+  }

+  *nxt = s+1;

+  return 1;

+}

+

+/*

+* Walk a string "{ A .. Z }" where A..Z is a space separated list

+* of token references (either labels or reg exprs).  Return a

+* string "inlineX_set" for some unique integer X.  Basically,

+* we pretend as if we had seen "#tokclass inlineX { A .. Z }"

+* on the input stream outside of an action.

+*/

+char *

+#ifdef __USE_PROTOS

+inline_set(char *s)

+#else

+inline_set(s)

+char *s;

+#endif

+{

+  char *nxt;

+  fprintf(stderr, "found consumeUntil( {...} )\n");

+  while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+  if ( *s!='{' )

+  {

+    err("malformed consumeUntil( {...} ); missing '{'");

+    return "bad_set";

+  }

+  s++;

+  while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+  while ( *s!='}' )

+  {

+    if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s);

+    else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s);

+    else {

+      err("invalid element in consumeUntil( {...} )");

+      return "bad_set";

+    }

+    s = nxt;

+    while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+  }

+  return "inlineX_set";

+}

+

+/* ANTLR-specific syntax error message generator

+* (define USER_ZZSYN when compiling so don't get 2 definitions)

+*/

+void

+#ifdef __USE_PROTOS

+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok,

+int k, char *bad_text)

+#else

+zzsyn(text, tok, egroup, eset, etok, k, bad_text)

+char *text, *egroup, *bad_text;

+int tok;

+int etok;

+int k;

+SetWordType *eset;

+#endif

+{

+fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);

+fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);

+if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}

+if ( k==1 ) fprintf(stderr, " missing");

+else

+{

+fprintf(stderr, "; \"%s\" not", bad_text);

+if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");

+}

+if ( zzset_deg(eset)>0 ) zzedecode(eset);

+else fprintf(stderr, " %s", zztokens[etok]);

+if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);

+fprintf(stderr, "\n");

+}

diff --git a/Source/Pccts/antlr/antlr.g b/Source/Pccts/antlr/antlr.g
new file mode 100644
index 0000000..e6eda60
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.g
@@ -0,0 +1,2586 @@
+/*

+ * antlr.g	--	PCCTS Version 1.xx ANTLR

+ *

+ * Parse an antlr input grammar and build a syntax-diagram.

+ *

+ * Written in itself (needs at least 1.06 to work)

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-1995

+ */

+

+/* MR1									*/

+/* MR1 10-Apr-97 MR1	Replace #if logic with #include "pcctscfg.h"	*/

+/* MR1									*/

+

+#header <<

+	#include "pcctscfg.h"

+	#include "set.h"

+	#include <ctype.h>

+	#include "syn.h"

+	#include "hash.h"

+	#include "generic.h"

+	#define zzcr_attr(attr,tok,t)

+	>>

+

+<<

+

+/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */

+#if defined(__TURBOC__)

+#pragma warn -aus  /* unused assignment of 'xxx' */

+#endif

+

+

+#ifdef __USE_PROTOS

+static void chkToken(char *, char *, char *, int);

+#else

+static void chkToken();

+#endif

+

+#ifdef __USE_PROTOS

+static int isDLGmaxToken(char *Token);				     /* MR3 */

+#else

+static int isDLGmaxToken();				                             /* MR3 */

+#endif

+

+static int class_nest_level = 0;

+

+/* MR20 G. Hobbelt extern definitions moved to antlr.h */

+

+>>

+

+#lexaction <<

+/* maintained, but not used for now */

+set AST_nodes_refd_in_actions = set_init;

+int inAlt = 0;

+set attribsRefdFromAction = set_init; /* MR20 */

+int UsedOldStyleAttrib = 0;

+int UsedNewStyleLabel = 0;

+#ifdef __USE_PROTOS

+char *inline_set(char *);

+#else

+char *inline_set();

+#endif

+

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	    */

+/* MR1					in DLG action			                    */

+

+int tokenActionActive=0;                                            /* MR1 */

+

+>>

+

+#lexclass STRINGS

+#token QuotedTerm "\""		<< zzmode(START); >>

+#token "\n|\r|\r\n"     	<<

+							zzline++;

+							warn("eoln found in string");

+							zzskip();

+							>>

+#token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>

+#token "\\~[]"				<< zzmore(); >>

+#token "~[\n\r\"\\]+"		<< zzmore(); >>

+

+#lexclass ACTION_STRINGS

+#token "\""					<< zzmode(ACTIONS); zzmore(); >>

+#token "\n|\r|\r\n"			<<

+							zzline++;

+							warn("eoln found in string (in user action)");

+							zzskip();

+							>>

+#token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>

+#token "\\~[]"				<< zzmore(); >>

+#token "~[\n\r\"\\]+"			<< zzmore(); >>

+

+#lexclass ACTION_CHARS

+#token "'"					<< zzmode(ACTIONS); zzmore(); >>

+#token "\n|\r|\r\n"			<<

+							zzline++;

+							warn("eoln found in char literal (in user action)");

+							zzskip();

+							>>

+#token "\\~[]"				<< zzmore(); >>

+#token "~[\n\r'\\]+"		<< zzmore(); >>

+

+#lexclass ACTION_COMMENTS

+#token "\*/"				<< zzmode(ACTIONS); zzmore(); >>

+#token "\*"					<< zzmore(); >>

+#token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>

+#token "~[\n\r\*]+"			<< zzmore(); >>

+

+#lexclass TOK_DEF_COMMENTS

+#token "\*/"				<< zzmode(PARSE_ENUM_FILE);

+                              zzmore(); >>

+#token "\*"					<< zzmore(); >>

+#token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>

+#token "~[\n\r\*]+"			<< zzmore(); >>

+

+#lexclass TOK_DEF_CPP_COMMENTS

+#token "\n|\r|\r\n"			<< zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >>

+#token "~[\n\r]+"			<< zzskip(); >>

+

+#lexclass ACTION_CPP_COMMENTS

+#token "\n|\r|\r\n"			<< zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >>

+#token "~[\n\r]+"			<< zzmore(); >>

+

+#lexclass CPP_COMMENTS

+#token "\n|\r|\r\n"			<< zzline++; zzmode(START); zzskip(); DAWDLE; >>

+#token "~[\n\r]+"			<< zzskip(); >>

+

+#lexclass COMMENTS

+#token "\*/"				<< zzmode(START); zzskip(); >>

+#token "\*"					<< zzskip(); >>

+#token "\n|\r|\r\n"			<< zzline++; zzskip(); DAWDLE; >>

+#token "~[\n\r\*]+"			<< zzskip(); >>

+

+/*

+ * This lexical class accepts actions of type [..] and <<..>>

+ *

+ * It translates the following special items for C:

+ *

+ * $j		--> "zzaArg(current zztasp, j)"

+ * $i.j		--> "zzaArg(zztaspi, j)"

+ * $i.nondigit> "zzaArg(current zztasp, i).nondigit"

+ * $$		--> "zzaRet"

+ * $alnum	--> "alnum"			(used to ref parameters)

+ * $rule	--> "zzaRet"

+ * $retval	--> "_retv.retval" if > 1 return values else "_retv"

+ * $[token, text] --> "zzconstr_attr(token, text)"

+ * $[]		--> "zzempty_attr()"

+ *

+ * It translates the following special items for C++:

+ * (attributes are now stored with 'Token' and $i's are only

+ *  pointers to the Tokens.  Rules don't have attributes now.)

+ *

+ * $j		--> "_tbj" where b is the block level

+ * $i.j		--> "_tij"

+ * $j->nondigit> "_tbj->nondigit"

+ * $$		--> "$$"

+ * $alnum	--> "alnum"			(used to ref parameters)

+ * $rule	--> "$rule"

+ * $retval	--> "_retv.retval" if > 1 return values else "_retv"

+ * $[token, text] --> invalid

+ * $[]		--> invalid

+ *

+ * And, for trees:

+ *

+ * #0		-->	"(*_root)"

+ * #i		--> "zzastArg(i)"

+ * #[args]	--> "zzmk_ast(zzastnew(), args)"

+ * #[]		--> "zzastnew()"

+ * #( root, child1, ..., childn )

+ *			--> "zztmake(root, child1, ...., childn, NULL)"

+ * #()		--> "NULL"

+ *

+ * For C++, ...

+ *

+ * #0		-->	"(*_root)"

+ * #i		--> "_astbi" where b is the block level

+ * #alnum	--> "alnum_ast"	(used to ref #label)

+ * #[args]	--> "new AST(args)"

+ * #[]		--> "new AST"

+ * #( root, child1, ..., childn )

+ *			--> "AST::tmake(root, child1, ...., childn, NULL)"

+ * #()		--> "NULL"

+ *

+ * To escape,

+ *

+ * \]		--> ]

+ * \)		--> )

+ * \$		--> $

+ * \#		--> #

+ *

+ * A stack is used to nest action terminators because they can be nested

+ * like crazy:  << #[$[..],..] >>

+ */

+#lexclass ACTIONS

+#token Action "\>\>"        << /* these do not nest */

+                              zzmode(START);

+                              NLATEXT[0] = ' ';

+                              NLATEXT[1] = ' ';

+                              zzbegexpr[0] = ' ';

+                              zzbegexpr[1] = ' ';

+							  if ( zzbufovf ) {

+								err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));

+							  }

+

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/

+/* MR1					in DLG action			*/

+/* MR1			Doesn't matter what kind of action it is - reset*/

+

+			      tokenActionActive=0;		 /* MR1 */

+                            >>

+#token Pred "\>\>?"			<< /* these do not nest */

+                              zzmode(START);

+                              NLATEXT[0] = ' ';

+                              NLATEXT[1] = ' ';

+                              zzbegexpr[0] = '\0';

+							  if ( zzbufovf ) {

+								err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));

+							  };

+#ifdef __cplusplus__

+/* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __STDC__

+/* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __USE_PROTOS

+/* MRxx */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+/* MR10 */                    list_apply(CurActionLabels,mark_label_used_in_sem_pred);

+#endif

+#endif

+#endif

+                            >>

+#token PassAction "\]"		<< if ( topint() == ']' ) {

+								  popint();

+								  if ( istackempty() )	/* terminate action */

+								  {

+									  zzmode(START);

+									  NLATEXT[0] = ' ';

+									  zzbegexpr[0] = ' ';

+									  if ( zzbufovf ) {

+										err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));

+									  }

+								  }

+								  else {

+									  /* terminate $[..] and #[..] */

+									  if ( GenCC ) zzreplstr("))");

+									  else zzreplstr(")");

+									  zzmore();

+								  }

+							   }

+							   else if ( topint() == '|' ) { /* end of simple [...] */

+								  popint();

+								  zzmore();

+							   }

+							   else zzmore();

+							>>

+#token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)"

+   							<<

+   							zzmore();

+							zzreplstr(inline_set(zzbegexpr+

+									  strlen("consumeUntil(")));

+							>>

+#token "consumeUntil\( ~[\)]+ \)"

+							<< zzmore(); >>

+#token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>

+#token "\>"					<< zzmore(); >>

+#token "$"					<< zzmore(); >>

+#token "$$"					<< if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}

+							   else err("$$ use invalid in C++ mode"); >>

+

+#token "$\[\]"				<< if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}

+							   else err("$[] use invalid in C++ mode"); >>

+#token "$\["				<<

+							pushint(']');

+							if ( !GenCC ) zzreplstr("zzconstr_attr(");

+							else err("$[..] use invalid in C++ mode");

+							zzmore();

+							>>

+#token "$[0-9]+"			<<{

+							static char buf[100];

+                            numericActionLabel=1;       /* MR10 */

+							if ( strlen(zzbegexpr)>(size_t)85 )

+								fatal("$i attrib ref too big");

+							set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",

+										BlkLevel-1,zzbegexpr+1);

+							else sprintf(buf,"_t%d%s",

+										BlkLevel-1,zzbegexpr+1);

+							zzreplstr(buf);

+							zzmore();

+							UsedOldStyleAttrib = 1;

+							if ( UsedNewStyleLabel )

+								err("cannot mix old-style $i with new-style labels");

+							}

+							>>

+#token "$[0-9]+."			<<{

+							static char buf[100];

+                            numericActionLabel=1;       /* MR10 */

+							if ( strlen(zzbegexpr)>(size_t)85 )

+								fatal("$i.field attrib ref too big");

+							zzbegexpr[strlen(zzbegexpr)-1] = ' ';

+							set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",

+										BlkLevel-1,zzbegexpr+1);

+							else sprintf(buf,"_t%d%s.",

+										BlkLevel-1,zzbegexpr+1);

+							zzreplstr(buf);

+							zzmore();

+							UsedOldStyleAttrib = 1;

+							if ( UsedNewStyleLabel )

+								err("cannot mix old-style $i with new-style labels");

+							}

+							>>

+#token "$[0-9]+.[0-9]+"		<<{

+							static char buf[100];

+							static char i[20], j[20];

+							char *p,*q;

+                            numericActionLabel=1;       /* MR10 */

+							if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");

+							for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {

+								if ( q == &i[20] )

+									 fatalFL("i of $i.j attrib ref too big",

+											 FileStr[CurFile], zzline );

+								*q++ = *p;

+							}

+							*q = '\0';

+							for (p++, q= &j[0]; *p!='\0'; p++) {

+								if ( q == &j[20] )

+									fatalFL("j of $i.j attrib ref too big",

+											FileStr[CurFile], zzline );

+								*q++ = *p;

+							}

+							*q = '\0';

+							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);

+							else sprintf(buf,"_t%s%s",i,j);

+							zzreplstr(buf);

+							zzmore();

+							UsedOldStyleAttrib = 1;

+							if ( UsedNewStyleLabel )

+								err("cannot mix old-style $i with new-style labels");

+							}

+							>>

+#token "$[_a-zA-Z][_a-zA-Z0-9]*"

+							<<{ static char buf[300]; LabelEntry *el;

+							zzbegexpr[0] = ' ';

+							if ( CurRule != NULL &&

+								 strcmp(CurRule, &zzbegexpr[1])==0 ) {

+								if ( !GenCC ) zzreplstr("zzaRet");

+							}

+							else if ( CurRetDef != NULL &&

+									  strmember(CurRetDef, &zzbegexpr[1])) {

+								 if ( hasMultipleOperands( CurRetDef ) ) {

+									require (strlen(zzbegexpr)<=(size_t)285,

+											 "$retval attrib ref too big");

+									sprintf(buf,"_retv.%s",&zzbegexpr[1]);

+									zzreplstr(buf);

+								}

+								else zzreplstr("_retv");

+							}

+							else if ( CurParmDef != NULL &&

+									  strmember(CurParmDef, &zzbegexpr[1])) {

+								;

+							}

+							else if ( Elabel==NULL ) {

+								{ err("$-variables in actions outside of rules are not allowed"); }

+							} else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {

+/* MR10 */

+/* MR10 */                      /* element labels might exist without an elem when */

+/* MR10 */                      /*  it is a forward reference (to a rule)          */

+/* MR10 */

+/* MR10 */						if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )

+/* MR10 */							{ err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }

+/* MR10 */

+/* MR10 */						if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {

+/* MR10 */                          err("You can no longer use attributes returned by rules when also using ASTs");

+/* MR10 */                          err("   Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")");

+/* MR10 */                      };

+/* MR10 */

+/* MR10 */                      /* keep track of <<... $label ...>> for semantic predicates in guess mode */

+/* MR10 */                      /* element labels contain pointer to the owners node                      */

+/* MR10 */

+/* MR10 */                      if (el->elem != NULL && el->elem->ntype == nToken) {

+/* MR10 */                        list_add(&CurActionLabels,el);

+/* MR10 */                      };

+							}

+							else

+								warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));

+							}

+							zzmore();

+							>>

+#token "#0"					<< zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >>

+#token "#\[\]"				<< if ( GenCC ) {

+                                    if (NewAST) zzreplstr("(newAST)");

+                                        else zzreplstr("(new AST)");}

+							   else {zzreplstr("zzastnew()");} zzmore();

+							   chkGTFlag();

+							>>

+#token "#\(\)"				<< zzreplstr("NULL"); zzmore(); chkGTFlag(); >>

+#token "#[0-9]+"			<<{

+							static char buf[100];

+							if ( strlen(zzbegexpr)>(size_t)85 )

+								fatal("#i AST ref too big");

+							if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);

+							else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);

+							zzreplstr(buf);

+							zzmore();

+							set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);

+							chkGTFlag();

+ 							}

+							>>

+

+/* MR14 Arpad Beszedes  26-May-98

+        Add support for #line directives when antlr source is pre-processed

+        #lexclass ACTIONS

+*/

+

+#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"

+        <<

+        zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+        getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+        >>

+

+#token "#line ~[\n\r]* (\n|\r|\r\n)"

+        <<

+        zzline++; zzmore();

+        >>

+

+/* MR14 end of a block to support #line in antlr source code */

+

+#token "#[_a-zA-Z][_a-zA-Z0-9]*"

+							<<

+							if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||

+								 strcmp(zzbegexpr, "#if")==0 ||

+								 strcmp(zzbegexpr, "#else")==0 ||

+								 strcmp(zzbegexpr, "#endif")==0 ||

+								 strcmp(zzbegexpr, "#ifndef")==0 ||

+								 strcmp(zzbegexpr, "#define")==0 ||

+								 strcmp(zzbegexpr, "#pragma")==0 ||

+								 strcmp(zzbegexpr, "#undef")==0 ||

+								 strcmp(zzbegexpr, "#import")==0 ||

+								 strcmp(zzbegexpr, "#line")==0 ||

+								 strcmp(zzbegexpr, "#include")==0 ||

+								 strcmp(zzbegexpr, "#error")==0) )

+							{

+								static char buf[100];

+								sprintf(buf, "%s_ast", zzbegexpr+1);

+/* MR27 */						list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));

+								zzreplstr(buf);

+								chkGTFlag();

+							}

+							zzmore();

+							>>

+#token "#\["				<<

+							pushint(']');

+							if ( GenCC ) {

+                                if (NewAST) zzreplstr("(newAST(");

+                                    else zzreplstr("(new AST("); }

+							else zzreplstr("zzmk_ast(zzastnew(),");

+							zzmore();

+							chkGTFlag();

+							>>

+#token "#\("				<<

+							pushint('}');

+							if ( GenCC ) {

+								if (tmakeInParser) {

+									zzreplstr("tmake(");

+								}

+								else {

+									zzreplstr("ASTBase::tmake(");

+								}

+							}

+							else {

+								zzreplstr("zztmake(");

+							}

+							zzmore();

+							chkGTFlag();

+							>>

+#token "#"					<< zzmore(); >>

+#token "\)"					<<

+							if ( istackempty() )

+								zzmore();

+							else if ( topint()==')' ) {

+								popint();

+							}

+							else if ( topint()=='}' ) {

+								popint();

+								/* terminate #(..) */

+								zzreplstr(", NULL)");

+							}

+							zzmore();

+							>>

+#token "\["					<<

+							pushint('|');	/* look for '|' to terminate simple [...] */

+							zzmore();

+							>>

+#token "\("					<<

+							pushint(')');

+							zzmore();

+							>>

+

+#token "\\\]"				<< zzreplstr("]");  zzmore(); >>

+#token "\\\)"				<< zzreplstr(")");  zzmore(); >>

+

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/

+/* MR1					in DLG action			*/

+

+#token "\\>"	<< if (! tokenActionActive) zzreplstr(">");	 /* MR1 */

+		   zzmore();				         /* MR1 */

+		>>					         /* MR1	*/

+

+

+#token "'"					<< zzmode(ACTION_CHARS); zzmore();>>

+#token "\""					<< zzmode(ACTION_STRINGS); zzmore();>>

+#token "\\$"				<< zzreplstr("$");  zzmore(); >>

+#token "\\#"				<< zzreplstr("#");  zzmore(); >>

+#token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>

+#token "\\~[\]\)>$#]"		<< zzmore(); >> /* escaped char, always ignore */

+#token "/"					<< zzmore(); >>

+#token "/\*"				<< zzmode(ACTION_COMMENTS); zzmore(); >>

+#token "\*/"				<< warn("Missing /*; found dangling */ in action"); zzmore(); >>

+#token "//"					<< zzmode(ACTION_CPP_COMMENTS); zzmore(); >>

+#token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >>

+

+#lexclass START

+#token "[\t\ ]+"			<< zzskip(); >>				/* Ignore White */

+#token "\n|\r|\r\n"	   		<< zzline++; zzskip(); >>	/* Track Line # */

+#token "\["                 << zzmode(ACTIONS); zzmore();

+                               istackreset();

+                               pushint(']'); >>

+#token "\<\<"               << action_file=CurFile; action_line=zzline;

+                               zzmode(ACTIONS); zzmore();

+                               list_free(&CurActionLabels,0);       /* MR10 */

+                               numericActionLabel=0;                /* MR10 */

+                               istackreset();

+                               pushint('>'); >>

+#token "\""					<< zzmode(STRINGS); zzmore(); >>

+#token "/\*"				<< zzmode(COMMENTS); zzskip(); >>

+#token "\*/"				<< warn("Missing /*; found dangling */"); zzskip(); >>

+#token "//"					<< zzmode(CPP_COMMENTS); zzskip(); >>

+

+/* MR14 Arpad Beszedes  26-May-98

+        Add support for #line directives when antlr source is pre-processed

+        #lexclass START

+*/

+

+#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"

+        <<

+        zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+        getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+        >>

+

+#token "#line ~[\n\r]* (\n|\r|\r\n)"

+        <<

+        zzline++; zzmore();

+        >>

+

+/* MR14 end of a block to support #line in antlr source code */

+

+/*                                                                          */

+/*  8-Apr-97	Regularize escape sequence for ">>"                         */

+/*			appearing in string literals                                    */

+/*                                                                          */

+

+#token "\>\>"			<< warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */

+#token WildCard "."

+#token "\@"			<<FoundException = 1;		/* MR6 */

+    				  FoundAtOperator = 1;>>	/* MR6 */

+#token Eof					"@"

+							<<	/* L o o k  F o r  A n o t h e r  F i l e */

+							{

+							FILE *new_input;

+							new_input = NextFile();

+							if ( new_input == NULL ) { NLA=Eof; return; }

+							fclose( input );

+							input = new_input;

+							zzrdstream( input );

+							zzskip();	/* Skip the Eof (@) char i.e continue */

+							}

+							>>

+

+#token LABEL

+

+#errclass "grammar-element" { element }

+#errclass "meta-symbol"		{ "\}" "!" ";" "\|" "\~" "^" "\)" }

+

+#token Pragma			"{\\}#pragma"			/* MR21 */

+#token FirstSetSymbol	"{\\}#FirstSetSymbol"	/* MR21 */

+/*

+ * Get a grammar -- Build a list of rules like:

+ *

+ *	o-->Rule1--o

+ *	|

+ *	o-->Rule2--o

+ *	|

+ *	...

+ *	|

+ *	o-->RuleN--o

+ */

+

+/* rule grammar */

+

+grammar :	<<Graph g;>>

+			(	"{\\}#header" Action    /* MR13 */

+				<<

+				if ( HdrAction==NULL ) {

+				HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+				require(HdrAction!=NULL, "rule grammar: cannot allocate header action");

+				strcpy(HdrAction, LATEXT(1));

+				}

+				else warn("additional #header statement ignored");

+				>>

+            |   "{\\}#first" Action

+				<<

+    				if ( FirstAction==NULL ) {

+        				FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+        				require(FirstAction!=NULL, "rule grammar: cannot allocate #first action");

+        				strcpy(FirstAction, LATEXT(1));

+    				} else {

+                        warn("additional #first statement ignored");

+                    };

+				>>

+

+			|	"{\\}#parser" QuotedTerm

+				<<

+				if ( GenCC ) {

+					warn("#parser meta-op incompatible with -CC; ignored");

+				}

+				else {

+					if ( strcmp(ParserName,"zzparser")==0 ) {

+						ParserName=StripQuotes(mystrdup(LATEXT(1)));

+						if ( RulePrefix[0]!='\0' )

+						{

+							warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");

+							RulePrefix[0]='\0';

+						}

+					}

+					else warn("additional #parser statement ignored");

+				}

+				>>

+			|	"{\\}#tokdefs" QuotedTerm

+				<<{

+				char *fname;

+				zzantlr_state st; FILE *f; struct zzdlg_state dst;

+				UserTokenDefsFile = mystrdup(LATEXT(1));

+				zzsave_antlr_state(&st);

+				zzsave_dlg_state(&dst);

+				fname = mystrdup(LATEXT(1));

+				f = fopen(StripQuotes(fname), "r");

+				if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));}

+				else {

+					ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE);

+					UserDefdTokens = 1;

+				}

+				zzrestore_antlr_state(&st);

+				zzrestore_dlg_state(&dst);

+				}>>

+			)*

+			(	Action

+				<<{

+				UserAction *ua = newUserAction(LATEXT(1));

+				ua->file = action_file; ua->line = action_line;

+				if ( class_nest_level>0 ) list_add(&class_before_actions, ua);

+				else list_add(&BeforeActions, ua);

+				}>>

+			|	laction

+			|	lmember				/* MR1 */

+			|	lprefix				/* MR1 */

+			|	aLexclass

+			|	token

+			|	error

+			|	tclass

+            |   aPred               /* MR11 */

+			|	default_exception_handler

+			|	class_def

+			|	"\}"

+				<<

+				if ( class_nest_level==0 )

+					warn("missing class definition for trailing '}'");

+				class_nest_level--;

+				>>

+			)*

+            

+			rule		<<g=$3; SynDiag = (Junction *) $3.left;>>

+			(	rule

+

+                	<<if ( $1.left!=NULL ) {

+                        g.right = NULL;

+

+/* MR21a */             /*  Avoid use of a malformed graph when CannotContinue */

+/* MR21a */             /*  is already set                                     */

+/* MR21a */

+/* MR21a */             if (! (CannotContinue && g.left == NULL)) {

+/* MR21a */               g = Or(g, $1);

+/* MR21a */             }

+/* MR21a */		      }

+                    >>

+

+			|	aLexclass

+			|	token

+			|	error

+			|	tclass

+            |   aPred               /* MR11 */

+			|	class_def

+			|	"\}"

+				<<

+				if ( class_nest_level==0 )

+					warn("missing class definition for trailing '}'");

+				class_nest_level--;

+				>>

+			)*

+			(	Action

+				<<{

+				UserAction *ua = newUserAction(LATEXT(1));

+				ua->file = action_file; ua->line = action_line;

+				if ( class_nest_level>0 ) list_add(&class_after_actions, ua);

+				else list_add(&AfterActions, ua);

+				}>>

+			|	laction

+			|	lmember				/* MR1 */

+			|	lprefix				/* MR1 */

+			|	error

+			|	tclass

+			|	class_def

+            |   aPred               /* MR11 */

+			|	"\}"

+				<<

+				if ( class_nest_level==0 )

+					warn("missing class definition for trailing '}'");

+				class_nest_level--;

+				>>

+			)*

+			Eof

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule class_def */

+

+class_def

+	:	<<int go=1; char name[MaxRuleName+1];>>

+		"class"

+		(	NonTerminal		<<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>

+		|	TokenTerm		<<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>

+		)

+		<<

+		if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0

+			 && GenCC ) {

+			err("only one grammar class allowed in this release");

+			go = 0;

+		}

+		else strcpy(CurrentClassName, name);

+		>>

+		<<if ( !GenCC ) { err("class meta-op used without C++ option"); }>>

+

+/* MR10 */  (~ "\{"

+/* MR10 */            <<if (ClassDeclStuff == NULL) {

+/* MR10 */                   ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char));

+/* MR10 */              };

+/* MR10 */              strncat(ClassDeclStuff," ",MaxClassDeclStuff);

+/* MR10 */              strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff);

+/* MR22 */              do {

+/* MR22 */                if (0 == strcmp(LATEXT(1),"public")) break;

+/* MR22 */                if (0 == strcmp(LATEXT(1),"private")) break;

+/* MR22 */                if (0 == strcmp(LATEXT(1),"protected")) break;

+/* MR22 */                if (0 == strcmp(LATEXT(1),"virtual")) break;

+/* MR22 */                if (0 == strcmp(LATEXT(1),",")) break;

+/* MR22 */                if (0 == strcmp(LATEXT(1),":")) break;

+/* MR22 */                if (BaseClassName != NULL) break;

+/* MR22 */                BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char));

+/* MR22 */                require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name");

+/* MR22 */				  strcpy(BaseClassName,LATEXT(1));

+/* MR22 */              } while (0);

+/* MR10 */            >>

+/* MR10 */  )*

+

+		"\{"

+		<<

+		no_classes_found = 0;

+		if ( class_nest_level>=1 ) {warn("cannot have nested classes");}

+		else class_nest_level++;

+		>>

+	;

+	<<CannotContinue=TRUE;>>

+

+/*

+ * Build -o-->o-R-o-->o-	where -o-R-o- is the block from rule 'block'.

+ * Construct the RuleBlk front and EndRule node on the end of the

+ * block.  This is used to add FOLLOW pointers to the rule end.  Add the

+ * new rule name to the Rname hash table and sets its rulenum.

+ * Store the parameter definitions if any are found.

+ *

+ * Note that locks are required on the RuleBlk and EndRule nodes to thwart

+ * infinite recursion.

+ *

+ * Return the left graph pointer == NULL to indicate error/dupl rule def.

+ */

+

+/* rule rule */

+

+rule	:	<<

+

+			ExceptionGroup *eg;

+			RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;

+			set toksrefd, rulesrefd;

+			char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;

+			CurExGroups = NULL;

+			CurElementLabels = NULL;

+			CurAstLabelsInActions = NULL; /* MR27 */

+			/* We want a new element label hash table for each rule */

+			if ( Elabel!=NULL ) killHashTable(Elabel);

+			Elabel = newHashTable();

+			attribsRefdFromAction = empty;

+			>>

+			NonTerminal

+			<<q=NULL;

+			  if ( hash_get(Rname, LATEXT(1))!=NULL ) {

+				  err(eMsg1("duplicate rule definition: '%s'",LATEXT(1)));

+				  CannotContinue=TRUE;

+			  }

+			  else

+			  {

+			  	  q = (RuleEntry *)hash_add(Rname,

+											LATEXT(1),

+											(Entry *)newRuleEntry(LATEXT(1)));

+			      CurRule = q->str;

+			  }

+			  CurRuleNode = q;

+			  f = CurFile; l = zzline;

+			  NumRules++;

+			>>

+			{	"!"  <<if ( q!=NULL ) q->noAST = TRUE;>> }

+			{	<<;>>

+				{"\<"}

+				PassAction

+				<<	pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+					require(pdecl!=NULL, "rule rule: cannot allocate param decl");

+					strcpy(pdecl, LATEXT(1));

+					CurParmDef = pdecl;

+				>>

+			}

+			{	"\>"

+				PassAction

+				<<	ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+				    require(ret!=NULL, "rule rule: cannot allocate ret type");

+					strcpy(ret, LATEXT(1));

+ 					CurRetDef = ret;

+				>>

+			}

+			{ QuotedTerm <<if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));>> }

+			<<

+			if ( GenEClasseForRules && q!=NULL ) {

+				e = newECnode;

+				require(e!=NULL, "cannot allocate error class node");

+				if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}

+				else a = q->egroup;

+				if ( Tnum( a ) == 0 )

+				{

+					e->tok = addTname( a );

+					list_add(&eclasses, (char *)e);

+					if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);

+					/* refers to itself */

+					list_add(&(e->elist), mystrdup(q->str));

+				}

+				else {

+					warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a));

+					if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);

+					free((char *)e);

+				}

+			}

+			>>

+			<<BlkLevel++;

+              if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");

+/* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;

+/* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;                

+            >>

+

+			":" <<inAlt=1;>>

+			block[&toksrefd, &rulesrefd]

+			<<r = makeBlk($7,0, NULL /* pFirstSetSymbol */ );

+			  CurRuleBlk = (Junction *)r.left;

+			  CurRuleBlk->blockid = CurBlockID;

+			  CurRuleBlk->jtype = RuleBlk;

+			  if ( q!=NULL ) CurRuleBlk->rname = q->str;

+			  CurRuleBlk->file = f;

+			  CurRuleBlk->line = l;

+			  CurRuleBlk->pdecl = pdecl;

+			  CurRuleBlk->ret = ret;

+			  CurRuleBlk->lock = makelocks();

+			  CurRuleBlk->pred_lock = makelocks();

+			  CurRuleBlk->tokrefs = toksrefd;

+			  CurRuleBlk->rulerefs = rulesrefd;

+			  p = newJunction();	/* add EndRule Node */

+			  ((Junction *)r.right)->p1 = (Node *)p;

+			  r.right = (Node *) p;

+			  p->jtype = EndRule;

+			  p->lock = makelocks();

+			  p->pred_lock = makelocks();

+			  CurRuleBlk->end = p;

+			  if ( q!=NULL ) q->rulenum = NumRules;

+			  $7 = r;

+			>>

+			<<

+                /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+                /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+                --BlkLevel;

+            >>

+            <<altFixup();leFixup();egFixup();>>                      /* MR7 */

+			";" <<inAlt=0;>>

+			{	Action

+				<<	a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+					require(a!=NULL, "rule rule: cannot allocate error action");

+					strcpy(a, LATEXT(1));

+					CurRuleBlk->erraction = a;

+				>>

+			}

+			(	exception_group > [eg]

+				<<if ( eg!=NULL ) {

+					list_add(&CurExGroups, (void *)eg);

+					if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1;

+			    }

+				>>

+			)*

+			<<if ( q==NULL ) $0.left = NULL; else $0 = $7;>>

+			<<CurRuleBlk->exceptions = CurExGroups;>>

+			<<CurRuleBlk->el_labels = CurElementLabels;>>

+			<<CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */

+			<<CurRuleNode = NULL;>> /* MR27 Moved */

+		;

+		<<CannotContinue=TRUE;>>

+

+/*

+ * pragma	:	"{\\}#pragma" "dup\-labeled\-tokens"

+ *			<<Pragma_DupLabeledTokens=1;>>

+ *		;

+ */

+

+/* rule laction */

+

+laction	:	<<char *a;>>

+

+			"{\\}#lexaction"

+			Action

+			<<

+			a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+			require(a!=NULL, "rule laction: cannot allocate action");

+			strcpy(a, LATEXT(1));

+			list_add(&LexActions, a);

+			>>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* MR1									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+/* MR1			  via #lexmember <<....>> & #lexprefix <<...>>      */

+/* MR1									    */

+

+/* rule lmember */

+

+lmember:	<<char *a;>>					     /* MR1 */

+

+/* MR1 */		"{\\}#lexmember"

+/* MR1 */		Action

+/* MR1 */		<<

+/* MR1 */		if (! GenCC) {

+/* MR1 */		  err("Use #lexmember only in C++ mode (to insert code in DLG class header");

+/* MR1 */	        } else {

+/* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+/* MR1 */		  require(a!=NULL, "rule lmember: cannot allocate action");

+/* MR1 */		  strcpy(a, LATEXT(1));

+/* MR1 */		  list_add(&LexMemberActions, a);

+/* MR1 */		};

+/* MR1 */		>>

+/* MR1 */	;

+/* MR1 */	<<CannotContinue=TRUE;>>

+

+/* rule lprefix */

+

+lprefix:	<<char *a;>>					     /* MR1 */

+

+/* MR1 */		"{\\}#lexprefix"

+/* MR1 */		Action

+/* MR1 */		<<

+/* MR1 */		if (! GenCC) {

+/* MR1 */		  err("Use #lexprefix only in C++ mode (to insert code in DLG class header");

+/* MR1 */	        } else {

+/* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+/* MR1 */		  require(a!=NULL, "rule lprefix: cannot allocate action");

+/* MR1 */		  strcpy(a, LATEXT(1));

+/* MR1 */		  list_add(&LexPrefixActions, a);

+/* MR1 */		};

+/* MR1 */		>>

+/* MR1 */	;

+/* MR1 */	<<CannotContinue=TRUE;>>

+

+/*

+ * #pred upper        <<isupper()>>?            predicate literal

+ * #pred lower        <<islower()>>?            predicate literal

+ * #pred up_or_low    upper || lower            predicate expression

+ *                                                concealed interdependence

+ * #pred up_or_low_2  <<isletter()>>?  A || B   predicate literal equals predicate expr

+ *                                                analyze using lower||upper

+ *                                                generate using isLetter()

+ */

+

+/* rule aPref */

+

+aPred:  <<PredEntry     *predEntry=NULL;

+          char          *name=NULL;

+          Predicate     *predExpr=NULL;

+          char          *predLiteral=NULL;

+          int           save_file;

+          int           save_line;

+          int           predExprPresent=0;

+        >>

+

+        "{\\}#pred"

+

+        <<

+          MR_usingPredNames=1;      /* will need to use -mrhoist version of genPredTree */

+        >>

+

+                                    /* used to allow NonTerminal but it caused problems

+                                       when a rule name immediately followed a #pred statement */

+

+        TokenTerm     <<name=mystrdup(LATEXT(1));>>

+

+          <<

+            /* don't free - referenced in predicates */

+

+            CurPredName=(char *)calloc(1,strlen(name) + 10);

+            strcat(CurPredName,"#pred ");

+            strcat(CurPredName,name);

+

+            predEntry=(PredEntry *) hash_get(Pname,name);

+            if (predEntry != NULL) {

+              warnFL(eMsg1("#pred %s previously defined - ignored",name),

+                                              FileStr[action_file],action_line);

+              name=NULL;

+            };

+          >>

+

+        (

+

+            Pred    <<predLiteral=mystrdup(LATEXT(1));

+                      save_line=action_line;

+                      save_file=action_file;

+                    >>

+

+              {

+                    predOrExpr>[predExpr]   <<predExprPresent=1;>>

+              }

+

+              <<if (predLiteral != NULL && name != NULL) {

+

+                      /*

+                       *  predExpr may be NULL due to syntax errors

+                       *    or simply omitted by the user

+                      */

+

+                      predEntry=newPredEntry(name);

+                      predEntry->file=save_file;

+                      predEntry->line=save_line;

+                      predExpr=MR_predFlatten(predExpr);

+                      predEntry->predLiteral=predLiteral;

+                      if (! predExprPresent || predExpr == NULL) {

+                        predExpr=new_pred();

+                        predExpr->expr=predLiteral;

+                        predExpr->source=newActionNode();

+                        predExpr->source->action=predExpr->expr;

+                        predExpr->source->rname=CurPredName;

+                        predExpr->source->line=action_line;

+                        predExpr->source->file=action_file;

+                        predExpr->source->is_predicate=1;

+                        predExpr->k=predicateLookaheadDepth(predExpr->source);

+                      };

+                      predEntry->pred=predExpr;

+                      hash_add(Pname,name,(Entry *)predEntry);

+                      predExpr=NULL;

+                };

+                predicate_free(predExpr);

+              >>

+

+            |

+               <<save_line=zzline; save_file=CurFile;>>

+

+                predOrExpr>[predExpr]

+

+              <<if (predExpr != NULL && name != NULL) {

+                  predEntry=newPredEntry(name);

+                  predEntry->file=CurFile;

+                  predEntry->line=zzline;

+                  predExpr=MR_predFlatten(predExpr);

+                  predEntry->pred=predExpr;

+                  hash_add(Pname,name,(Entry *)predEntry);

+                  predExpr=NULL;

+                };

+                predicate_free(predExpr);

+              >>

+        )

+        {";"}

+;

+

+/* fail */

+

+<<predicate_free(predExpr);

+>>

+

+/* rule predOrExpr */

+

+predOrExpr>[Predicate *result] :

+            <<Predicate     *ORnode;

+              Predicate     *predExpr;

+              Predicate     **tail=NULL;

+            >>

+        predAndExpr>[predExpr]

+            <<

+                ORnode=new_pred();

+                ORnode->expr=PRED_OR_LIST;

+                if (predExpr != NULL) {

+                    ORnode->down=predExpr;

+                    tail=&predExpr->right;

+                };

+            >>

+        ( "\|\|"  predAndExpr>[predExpr]

+            <<

+                if (predExpr != NULL) {

+                    *tail=predExpr;

+                    tail=&predExpr->right;

+                };

+            >>

+        )*

+        <<

+            $result=ORnode;

+            ORnode=NULL;

+        >>

+;

+

+/* fail */

+

+<<predicate_free(ORnode);>>

+

+/* rule predAndExpr */

+

+predAndExpr>[Predicate *result] :

+            <<Predicate     *ANDnode;

+              Predicate     *predExpr;

+              Predicate     **tail=NULL;

+            >>

+        predPrimary>[predExpr]

+            <<

+                ANDnode=new_pred();

+                ANDnode->expr=PRED_AND_LIST;

+                if (predExpr != NULL) {

+                    ANDnode->down=predExpr;

+                    tail=&predExpr->right;

+                };

+            >>

+        ( "&&"  predPrimary>[predExpr]

+            <<

+                if (predExpr != NULL) {

+                    *tail=predExpr;

+                    tail=&predExpr->right;

+                };

+            >>

+        )*

+        <<

+            $result=ANDnode;

+            ANDnode=NULL;

+        >>

+;

+

+/* fail */

+

+<<predicate_free(ANDnode);>>

+

+

+/* rule predPrimary */

+

+predPrimary>[Predicate *result] :

+            <<

+              char          *name=NULL;

+              PredEntry     *predEntry=NULL;

+              Predicate     *predExpr=NULL;

+            >>

+

+        TokenTerm            <<name=mystrdup(LATEXT(1));>>

+

+            <<

+                predEntry=(PredEntry *) hash_get(Pname,name);

+                if (predEntry == NULL) {

+                  warnFL(eMsg1("no previously defined #pred with name \"%s\"",name),

+                        FileStr[CurFile],zzline);

+                  name=NULL;

+                  $result=NULL;

+                } else {

+                  predExpr=predicate_dup(predEntry->pred);

+                  predExpr->predEntry=predEntry;

+                  $result=predExpr;

+                };

+            >>

+

+        | "\(" predOrExpr>[predExpr] "\)"

+            <<

+                $result=predExpr;

+            >>

+

+        | "!" predPrimary>[predExpr]

+            <<

+                predExpr->inverted=!predExpr->inverted;

+                $result=predExpr;

+            >>

+;

+

+/* fail */  <<

+              predicate_free(predExpr);

+            >>

+

+/* rule aLexclass */

+

+aLexclass:	"{\\}#lexclass" TokenTerm <<lexclass(mystrdup(LATEXT(1)));>>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule error */

+

+error	:	<<char *t=NULL; ECnode *e; int go=1; TermEntry *p;>>

+			"{\\}#errclass"

+			(<<;>>	TokenTerm  <<t=mystrdup(LATEXT(1));>>

+			|		QuotedTerm <<t=mystrdup(LATEXT(1));>>

+			)

+			<<e = newECnode;

+			  require(e!=NULL, "cannot allocate error class node");

+			  e->lexclass = CurrentLexClass;

+			  if ( Tnum( (t=StripQuotes(t)) ) == 0 )

+			  {

+				if ( hash_get(Texpr, t) != NULL )

+					warn(eMsg1("errclass name conflicts with regular expression  '%s'",t));

+			  	e->tok = addTname( t );

+				set_orel(e->tok, &imag_tokens);

+				require((p=(TermEntry *)hash_get(Tname, t)) != NULL,

+						"hash table mechanism is broken");

+				p->classname = 1;	/* entry is errclass name, not token */

+				list_add(&eclasses, (char *)e);

+			  }

+			  else

+			  {

+			  	warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t));

+				free( (char *)e );

+				go=0;

+			  }

+			>>

+			"\{"

+				( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>

+				| TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>

+				| QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>

+				)

+				<<if ( go ) list_add(&(e->elist), t);>>

+				(

+					( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>

+					| TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>

+					| QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>

+					)

+					<<if ( go ) list_add(&(e->elist), t);>>

+				)*

+			"\}"

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule tclass */

+

+tclass	:	<<char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm;>>

+            <<char *akaString=NULL; int save_file; int save_line;>>

+            <<char *totext=NULL; >>

+			"{\\}#tokclass" TokenTerm <<t=mystrdup(LATEXT(1));>>

+			<<e = newTCnode;

+			  require(e!=NULL, "cannot allocate token class node");

+			  e->lexclass = CurrentLexClass;

+			  if ( Tnum( t ) == 0 )

+			  {

+			  	e->tok = addTname( t );

+				set_orel(e->tok, &imag_tokens);

+				set_orel(e->tok, &tokclasses);

+				require((p=(TermEntry *)hash_get(Tname, t)) != NULL,

+						"hash table mechanism is broken");

+				p->classname = 1;	/* entry is class name, not token */

+				p->tclass = e;		/* save ptr to this tclass def */

+				list_add(&tclasses, (char *)e);

+			  }

+			  else

+			  {

+			  	warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t));

+				free( (char *)e );

+				go=0;

+			  }

+			>>

+/* MR23 */      {

+/* MR23 */          "\("

+/* MR23 */          QuotedTerm

+/* MR23 */                 <<akaString=mystrdup(StripQuotes(LATEXT(1)));

+/* MR11 */                   save_file=CurFile;save_line=zzline;

+/* MR23 */                 >>

+/* MR23 */          "\)"

+/* MR23 */      }

+/* MR23 */

+/* MR23 */

+/* MR23 */		<<

+/* MR23 */         if (p!= NULL && akaString != NULL) {

+/* MR23 */           if (p->akaString != NULL) {

+/* MR23 */             if (strcmp(p->akaString,akaString) != 0) {

+/* MR23 */                warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement",

+/* MR23 */                              t,p->akaString),

+/* MR23 */			                    FileStr[save_file],save_line);

+/* MR23 */             };

+/* MR23 */            } else {

+/* MR23 */              p->akaString=akaString;

+/* MR23 */            };

+/* MR23 */          };

+/* MR23 */		>>

+

+			"\{"

+				(

+    				( TokenTerm

+    				  <<if ( go ) {

+    					term = (TermEntry *) hash_get(Tname, LATEXT(1));

+    					if ( term==NULL && UserDefdTokens ) {

+    						err("implicit token definition not allowed with #tokdefs");

+    						go = 0;

+    					}

+    					else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));}

+    					}>>

+

+                        {

+                            ".."

+                            TokenTerm

+

+            				  <<if ( go ) {

+                					toterm = (TermEntry *) hash_get(Tname, LATEXT(1));

+                					if ( toterm==NULL && UserDefdTokens ) {

+                						err("implicit token definition not allowed with #tokdefs");

+                						go = 0;

+                					} else {

+                                        totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1));

+                                    }

+            				    }

+                              >>

+                        }

+

+    				| QuotedTerm

+    				  <<if ( go ) {

+    					term = (TermEntry *) hash_get(Texpr, LATEXT(1));

+    					if ( term==NULL && UserDefdTokens ) {

+    						err("implicit token definition not allowed with #tokdefs");

+    						go = 0;

+        					}

+    					else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));}

+    					}>>

+    				)

+    				<<if ( go ) {

+                        if (totext == NULL) {

+                            list_add(&(e->tlist), t);

+                        } else {

+                            list_add(&(e->tlist),"..");

+                            list_add(&(e->tlist),t);

+                            list_add(&(e->tlist),totext);

+                        }

+                        totext=NULL;

+                      }

+                    >>

+				)+  // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+")

+			"\}"

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule token */

+

+token	:	<<char *t=NULL, *e=NULL, *a=NULL; int tnum=0;>>

+            <<char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0;>>           /* MR11 */

+			"{\\}#token"

+

+/* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions		   */

+/* MR1			Danger when parser feedback to lexer		           */

+/* MR1	                                                               */

+

+			<<tokenActionActive=1;>>		                    /* MR1 */

+			{	TokenTerm  <<t=mystrdup(LATEXT(1));>>

+

+/* MR11 */      {

+/* MR11 */          "\("

+/* MR11 */          QuotedTerm

+/* MR11 */                 <<akaString=mystrdup(StripQuotes(LATEXT(1)));

+/* MR11 */                   save_file=CurFile;save_line=zzline;

+/* MR11 */                 >>

+/* MR11 */          "\)"

+/* MR11 */      }

+

+				{	"=" "[0-9]+"		/* define the token type number */

+					<<tnum = atoi(LATEXT(1));>>

+				}

+			}

+			{ QuotedTerm <<e=mystrdup(LATEXT(1));>> }

+			{	Action

+				<<

+					a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+					require(a!=NULL, "rule token: cannot allocate action");

+					strcpy(a, LATEXT(1));

+				>>

+			}

+

+            { ";" }     /* MR11 */

+

+			<<chkToken(t, e, a, tnum);>>

+

+            <<if (t != NULL) {

+                te=(TermEntry *)hash_get(Tname,t);

+                if (te != NULL && akaString != NULL) {

+                  if (te->akaString != NULL) {

+                    if (strcmp(te->akaString,akaString) != 0) {

+                      warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement",

+                                    t,te->akaString),

+                        FileStr[save_file],save_line);

+                    };

+                  } else {

+                    te->akaString=akaString;

+                  };

+                };

+              };

+            >>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule block */

+

+block[set *toksrefd, set *rulesrefd]

+		:	<<

+    			Graph g, b;

+    			set saveblah;

+    			int saveinalt = inAlt;

+    			ExceptionGroup *eg;

+    			*$toksrefd = empty;

+    			*$rulesrefd = empty;

+    			set_clr(AST_nodes_refd_in_actions);

+    			CurBlockID++;

+/* MR23 */      CurBlockID_array[BlkLevel] = CurBlockID;

+    			CurAltNum = 1;

+/* MR23 */      CurAltNum_array[BlkLevel] = CurAltNum;                

+    			saveblah = attribsRefdFromAction;

+    			attribsRefdFromAction = empty;

+			>>

+

+			alt[toksrefd,rulesrefd]		<<b = g = $1;>>

+

+			<<

+			if ( ((Junction *)g.left)->p1->ntype == nAction )

+			{

+                ActionNode *actionNode=(ActionNode *)

+                                         ( ( (Junction *)g.left) ->p1);

+				if (!actionNode->is_predicate )

+				{

+					actionNode->init_action = TRUE;

+/* MR12c */  		if (actionNode->noHoist) {

+/* MR12c */           errFL("<<nohoist>> appears as init-action - use <<>> <<nohoist>>",

+/* MR12c */                       FileStr[actionNode->file],actionNode->line);

+/* MR12c */         };

+				}

+			}

+			((Junction *)g.left)->blockid = CurBlockID;

+			>>

+

+			(	exception_group > [eg]

+				<<

+				if ( eg!=NULL ) {

+/* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/

+/* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/

+					list_add(&CurExGroups, (void *)eg);

+				}

+				>>

+			)*

+			<<CurAltNum++;

+/* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;

+            >>

+

+			(	"\|" <<inAlt=1;>>

+				alt[toksrefd,rulesrefd]		<<g = Or(g, $2);>>

+				<<

+				((Junction *)g.left)->blockid = CurBlockID;

+				>>

+

+				(	exception_group > [eg]

+					<<

+					if ( eg!=NULL ) {

+/* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/

+/* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/

+						list_add(&CurExGroups, (void *)eg);

+					}

+					>>

+				)*

+

+				<<CurAltNum++;

+/* MR23 */        CurAltNum_array[BlkLevel] = CurAltNum;                

+                >>

+

+			)*

+			<<$0 = b;>>

+			<<attribsRefdFromAction = saveblah; inAlt = saveinalt;>>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule alt */

+

+alt[set *toksrefd, set *rulesrefd]

+		:	<<int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif;

+			int first_on_line = 1, use_def_MT_handler = 0;

+			g.left=NULL; g.right=NULL;

+

+			CurAltStart = NULL;

+			elems = empty;

+			inAlt = 1;

+			>>

+			{	"\@"	/* handle MismatchedToken signals with default handler */

+				<<use_def_MT_handler = 1;>>

+			}

+

+			(	<<;>>       /* MR9 Removed unreferenced variable "tok" */

+				{ <<old_not=0;>> "\~" <<old_not=1;>> }

+				element[old_not, first_on_line, use_def_MT_handler] > [node]

+				<<if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;>>

+				<<

+				if ( $2.left!=NULL ) {

+					g = Cat(g, $2);

+					n++;

+					if ( node!=NULL ) {

+						if ( node->ntype!=nAction ) e_num++;

+						/* record record number of all rule and token refs */

+						if ( node->ntype==nToken ) {

+							TokNode *tk = (TokNode *)((Junction *)$2.left)->p1;

+							tk->elnum = e_num;

+							set_orel(e_num, &elems);

+						}

+						else if ( node->ntype==nRuleRef ) {

+							RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1;

+							rn->elnum = e_num;

+							set_orel(e_num, $rulesrefd);

+						}

+					}

+				}

+				>>

+			)*

+			<<if ( n == 0 ) g = emptyAlt();

+			  $0 = g;

+			  /* We want to reduce number of LT(i) calls and the number of

+			   * local attribute variables in C++ mode (for moment, later we'll

+			   * do for C also).  However, if trees are being built, they

+			   * require most of the attrib variables to create the tree nodes

+			   * with; therefore, we gen a token ptr for each token ref in C++

+			   */

+			  if ( GenCC && !GenAST )

+			  {

+				  /* This now free's the temp set -ATG 5/6/95 */

+				  set temp;

+				  temp = set_and(elems, attribsRefdFromAction);

+				  set_orin($toksrefd, temp);

+				  set_free(temp);

+			  }

+			  else set_orin($toksrefd, elems);

+			  if ( GenCC ) {

+				dif = set_dif(attribsRefdFromAction, elems);

+			  	if ( set_deg(dif)>0 )

+					err("one or more $i in action(s) refer to non-token elements");

+				set_free(dif);

+			  }

+			  set_free(elems);

+			  set_free(attribsRefdFromAction);

+			  inAlt = 0;

+   			>>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule element_label */

+

+element_label > [LabelEntry *label]

+	:	<<TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;>>

+		LABEL	<<lab = mystrdup(LATEXT(1));>>

+		<<

+		UsedNewStyleLabel = 1;

+		if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i");

+		t = (TermEntry *) hash_get(Tname, lab);

+		if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab);

+		if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab);

+		if ( t!=NULL ) {

+			err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab));

+			$label = NULL;

+		}

+		else if ( r!=NULL ) {

+			err(eMsg1("label definition clashes with rule definition: '%s'", lab));

+			$label = NULL;

+		}

+		else {

+			/* we don't clash with anybody else */

+			l = (LabelEntry *) hash_get(Elabel, lab);

+ 			if ( l==NULL ) {	/* ok to add new element label */

+				l = (LabelEntry *)hash_add(Elabel,

+										   lab,

+										   (Entry *)newLabelEntry(lab));

+				/* add to list of element labels for this rule */

+				list_add(&CurElementLabels, (void *)lab);

+/* MR7 */       leAdd(l);  /* list of labels waiting for exception group definitions */

+				$label = l;

+			}

+			else {

+				err(eMsg1("label definitions must be unique per rule: '%s'", lab));

+				$label = NULL;

+			}

+		}

+		>>

+		":"

+	;

+

+/* rule element */

+

+element[int old_not, int first_on_line, int use_def_MT_handler] > [Node *node]

+		: <<

+		  Attrib blk;

+		  Predicate *pred = NULL;

+		  int local_use_def_MT_handler=0;

+		  ActionNode *act;

+		  RuleRefNode *rr;

+		  set toksrefd, rulesrefd;

+		  TermEntry *term;

+		  TokNode *p=NULL; RuleRefNode *q; int approx=0;

+		  LabelEntry *label=NULL;

+          int predMsgDone=0;

+          int semDepth=0;

+          int   ampersandStyle;

+          int   height;         /* MR11 */

+          int   equal_height;   /* MR11 */

+

+          char* pFirstSetSymbol = NULL; /* MR21 */

+

+		  $node = NULL;

+		  >>

+		  {element_label>[label]}

+		  ( TokenTerm

+			<<

+			term = (TermEntry *) hash_get(Tname, LATEXT(1));

+			if ( term==NULL && UserDefdTokens ) {

+				err("implicit token definition not allowed with #tokdefs");

+				$$.left = $$.right = NULL;

+			}

+			else {

+				$$ = buildToken(LATEXT(1));

+				p=((TokNode *)((Junction *)$$.left)->p1);

+				term = (TermEntry *) hash_get(Tname, LATEXT(1));

+				require( term!= NULL, "hash table mechanism is broken");

+				p->tclass = term->tclass;

+				p->complement = $old_not;

+				if ( label!=NULL ) {

+					p->el_label = label->str;

+					label->elem = (Node *)p;

+				}

+			}

+			>>

+			{	".."

+				(	QuotedTerm

+					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>

+				|	TokenTerm

+					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>

+				)

+			}

+			<<

+			if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )

+				list_add(&MetaTokenNodes, (void *)p);

+			>>

+			(	"^"	<<if ( p!=NULL ) p->astnode=ASTroot;>>

+			|		<<if ( p!=NULL ) p->astnode=ASTchild;>>

+			|	"!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>

+			)

+			{ "\@" <<local_use_def_MT_handler = 1;>> }

+			<<

+			if ( p!=NULL && $first_on_line ) {

+				CurAltStart = (Junction *)$$.left;

+                altAdd(CurAltStart);                                 /* MR7 */

+				p->altstart = CurAltStart;

+			}

+   			if ( p!=NULL )

+				p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;

+			$node = (Node *)p;

+			>>

+		  | QuotedTerm

+			<<

+			term = (TermEntry *) hash_get(Texpr, LATEXT(1));

+			if ( term==NULL && UserDefdTokens ) {

+				err("implicit token definition not allowed with #tokdefs");

+				$$.left = $$.right = NULL;

+			}

+			else {

+				$$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);

+				p->complement = $old_not;

+				if ( label!=NULL ) {

+					p->el_label = label->str;

+	   				label->elem = (Node *)p;

+				}

+			}

+			>>

+			{	".."

+				(	QuotedTerm

+					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>

+				|	TokenTerm

+					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>

+				)

+			}

+			(	"^"	<<if ( p!=NULL ) p->astnode=ASTroot;>>

+			|		<<if ( p!=NULL ) p->astnode=ASTchild;>>

+			|	"!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>

+			)

+			{ "\@" <<local_use_def_MT_handler = 1;>> }

+			<<

+			if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )

+				list_add(&MetaTokenNodes, (void *)p);

+			>>

+			<<

+			if ( $first_on_line ) {

+				CurAltStart = (Junction *)$$.left;

+                altAdd(CurAltStart);                                 /* MR7 */

+				p->altstart = CurAltStart;

+			}

+   			if ( p!=NULL )

+				p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;

+			$node = (Node *)p;

+			>>

+

+		  | <<if ( $old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");>>

+			"."

+			<<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>>

+			(	"^"	<<p->astnode=ASTroot;>>

+			|		<<p->astnode=ASTchild;>>

+			|	"!" <<p->astnode=ASTexclude;>>

+			)

+			<<list_add(&MetaTokenNodes, (void *)p);>>

+			<<

+			if ( $first_on_line ) {

+				CurAltStart = (Junction *)$$.left;

+                altAdd(CurAltStart);                                 /* MR7 */

+				p->altstart = CurAltStart;

+				if ( label!=NULL ) {

+					p->el_label = label->str;

+					label->elem = (Node *)p;

+				}

+			}

+			$node = (Node *)p;

+			>>

+

+		  | <<if ( $old_not ) warn("~ NONTERMINAL is an undefined operation");>>

+			NonTerminal

+			<<$$ = buildRuleRef(LATEXT(1));>>

+			{ "!" <<q = (RuleRefNode *) ((Junction *)$$.left)->p1;

+					q->astnode=ASTexclude;>>

+			}

+			{	{"\<"}

+				PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>>

+			}

+			<<rr=(RuleRefNode *) ((Junction *)$$.left)->p1;>>

+			{	<<char *a;>>

+				"\>"

+				PassAction

+				<<

+					a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+					require(a!=NULL, "rule element: cannot allocate assignment");

+					strcpy(a, LATEXT(1));

+					rr->assign = a;

+				>>

+			}

+			<<

+			if ( label!=NULL ) {

+				rr->el_label = label->str;

+				label->elem = (Node *)rr;

+			}

+			if ( $first_on_line ) {

+				CurAltStart = (Junction *)$$.left;

+                altAdd(CurAltStart);                                 /* MR7 */

+				((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart;

+			}

+			$node = (Node *)rr;

+			>>

+		  )

+

+		|	<<if ( $old_not )	warn("~ ACTION is an undefined operation");>>

+			Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>>

+			<<if ( $first_on_line ) {                                /* MR7 */

+                CurAltStart = (Junction *)$0.left;                   /* MR7 */

+                altAdd(CurAltStart);                                 /* MR7 */

+              };>>                                                   /* MR7 */

+			<<$node = (Node *) ((Junction *)$0.left)->p1;>>

+

+		|	<<if ( $old_not )	warn("~ SEMANTIC-PREDICATE is an undefined operation");>>

+			Pred   <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>>

+			<<act = (ActionNode *) ((Junction *)$0.left)->p1;>>

+            <<if (numericActionLabel) {             /* MR10 */

+                list_add(&NumericPredLabels,act);   /* MR10 */

+                numericActionLabel=0;               /* MR10 */

+              };                                    /* MR10 */

+            >>

+			{	<<char *a;>>

+				PassAction

+				<<

+				a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+				require(a!=NULL, "rule element: cannot allocate predicate fail action");

+				strcpy(a, LATEXT(1));

+				act->pred_fail = a;

+				>>

+			}

+			<<if ( $first_on_line ) {                                /* MR7 */

+                CurAltStart = (Junction *)$0.left;                   /* MR7 */

+                altAdd(CurAltStart);                                 /* MR7 */

+              };>>                                                   /* MR7 */

+			<<$node = (Node *)act;>>

+

+		|	<<if ( $old_not )	warn("~ BLOCK is an undefined operation");>>

+			<<BlkLevel++;

+              if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");

+/* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;

+/* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;                

+            >>

+			{	Pragma

+				(	"approx" <<approx=LL_k;>>

+				|	"LL\(1\)"  <<approx = 1;>>  /* MR20 */

+				|	"LL\(2\)"  <<approx = 2;>>  /* MR20 */

+                )

+            }

+

+/* MR21 */  {  FirstSetSymbol

+/* MR21 */     "\("

+/* MR21 */    		(	NonTerminal

+/* MR21 */                <<

+/* MR21 */                     pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,

+/* MR21 */                                                    sizeof(char));

+/* MR21 */                          require(pFirstSetSymbol!=NULL,

+/* MR21 */                                  "cannot allocate first set name");

+/* MR21 */                          strcpy(pFirstSetSymbol, LATEXT(1));

+/* MR21 */                      >>

+/* MR21 */          |    TokenTerm

+/* MR21 */                  <<

+/* MR21 */                      pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,

+/* MR21 */                                                        sizeof(char));

+/* MR21 */                      require(pFirstSetSymbol!=NULL,

+/* MR21 */                              "cannot allocate first set name");

+/* MR21 */                      strcpy(pFirstSetSymbol, LATEXT(1));

+/* MR21 */                  >>

+/* MR21 */          )

+/* MR21 */      "\)"

+/* MR21 */  }

+

+            (

+

+        	"\(" block[&toksrefd,&rulesrefd] "\)"

+				<<blk = $$ = $2;

+                        /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+                        /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+                  --BlkLevel;

+            >>

+

+				(	"\*"		<<$$ = makeLoop($$,approx,pFirstSetSymbol);>>

+				|	"\+"		<<$$ = makePlus($$,approx,pFirstSetSymbol);>>

+				|	"?"

+					(	

+                        ( "=>" <<ampersandStyle=0;>>

+                        | "&&" <<ampersandStyle=1;>>  /* MR10 (g)? && <<p>>? */

+                        )

+                        Pred	/* generalized predicate */

+						/* first make into a predicate */

+					    <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>>

+					    <<act = (ActionNode *) ((Junction *)$$.left)->p1;>>

+                        <<semDepth=predicateLookaheadDepth(act);>>  /* MR10 */

+                        <<if (numericActionLabel) {             /* MR10 */

+                            list_add(&NumericPredLabels,act);   /* MR10 */

+                            numericActionLabel=0;               /* MR10 */

+                          };                                    /* MR10 */

+                        >>

+						{	<<char *a;>>

+							PassAction

+							<<

+							a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char));

+							require(a!=NULL, "rule element: cannot allocate predicate fail action");

+							strcpy(a, LATEXT(1));

+							act->pred_fail = a;

+							>>

+						}

+						<<if ($first_on_line) {                      /* MR7 */

+                            CurAltStart=(Junction *)$$.left;         /* MR7 */

+                            altAdd(CurAltStart);                     /* MR7 */

+                          };>>

+						<<$node = (Node *)act;>>

+

+						/* for now, just snag context */

+						<<

+						pred = computePredFromContextGuard(blk,&predMsgDone);           /* MR10 */

+						if ( pred==NULL) {                                              /* MR10 */

+                          if ( !predMsgDone) err("invalid or missing context guard");   /* MR10 */

+                          predMsgDone=1;                                                /* MR10 */

+						} else {                                                        /* MR10 */

+                            act->guardNodes=(Junction *)blk.left;                       /* MR11 */

+							pred->expr = act->action;

+							pred->source = act;

+/* MR10 */                  pred->ampersandStyle = ampersandStyle;  /* 0 means (g)? => ... 1 means (g)? && ... */

+/* MR13 */                  if (pred->tcontext != NULL) {

+/* MR13 */                    height=MR_max_height_of_tree(pred->tcontext);

+/* MR13 */                    equal_height=MR_all_leaves_same_height(pred->tcontext,height);

+/* MR13 */                    if (! equal_height) {

+/* MR13 */                       errFL("in guarded predicates all tokens in the guard must be at the same height",

+/* MR13 */                              FileStr[act->file],act->line);

+/* MR13 */                    };

+/* MR13 */                  }

+/* MR10 */                  if (ampersandStyle) {

+/* MR10 */			  		  act->ampersandPred = pred;

+/* MR11 */                    if (! HoistPredicateContext) {

+/* MR11 */                      errFL("without \"-prc on\" (guard)? && <<pred>>? ... doesn't make sense",

+/* MR11 */                              FileStr[act->file],act->line);

+/* MR11 */                    };

+/* MR10 */                  } else {

+/* MR10 */			  		  act->guardpred = pred;

+/* MR10 */                  };

+/* MR10 */                  if (pred->k != semDepth) {

+/* MR10 */                     warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)",

+/* MR10 */                                  pred->k,semDepth));

+/* MR10 */                  };

+						}

+						>>

+					|	<<$$ = makeBlk($$,approx,pFirstSetSymbol);

+						  FoundGuessBlk = 1;

+						  ((Junction *) ((Junction *)$$.left)->p1)->guess=1;

+						  if ( !$first_on_line ) {

+							err("(...)? predicate must be first element of production");

+						  }

+						>>

+					)

+				|	<<$$ = makeBlk($$,approx,pFirstSetSymbol);>>

+				)

+				<<

+				if ( pred==NULL && !predMsgDone) {                                      /* MR10 */

+					((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;

+					((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;

+					((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;

+					if ( $first_on_line ) {                         /* MR7 */

+					   CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1);  /* MR7 */

+                       altAdd(CurAltStart);                         /* MR7 */

+                    };                                              /* MR7 */

+					$node = (Node *) ((Junction *)$$.left)->p1;

+				}

+				>>

+

+			|	"\{"	block[&toksrefd,&rulesrefd]

+						<<$$ = makeOpt($2,approx,pFirstSetSymbol);

+                                /* MR23 */      CurBlockID_array[BlkLevel] = (-1);

+                                /* MR23 */      CurAltNum_array[BlkLevel] = (-1);                

+                                --BlkLevel;

+                        >>

+				"\}"

+				<<

+				((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;

+				((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;

+				((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;

+				>>

+				<<if ( $first_on_line ) {                            /* MR7 */

+					CurAltStart = (Junction *) ((Junction *)((Junction *)$$.left)->p1);  /* MR7 */

+                    altAdd(CurAltStart);                             /* MR7 */

+                  };

+				>>

+				<<$node = (Node *) ((Junction *)$$.left)->p1;>>

+

+			)

+

+/* Error catching alternatives */

+		|	"\*"	<<warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;>>

+		|	"\+"	<<warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;>>

+		|	"\>"	<<warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;>>

+		|	PassAction <<warn("[...] out of context 'rule > [...]'");

+						 CannotContinue=TRUE;>>

+		;

+		<<CannotContinue=TRUE;>>

+

+/* rule default_exception_handler */

+

+default_exception_handler

+	:	exception_group > [DefaultExGroup]

+	;

+

+/* rule exception_group */

+

+exception_group > [ExceptionGroup *eg]

+	:	<<ExceptionHandler *h; LabelEntry *label=NULL;	  /* MR6 */

+		  FoundException = 1; FoundExceptionGroup = 1;>>  /* MR6 */

+

+		"exception"	 <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>>

+		{	<<char *p;>>

+			PassAction		/* did they attach a label? */

+			<<

+			p = LATEXT(1)+1;

+			p[strlen(p)-1] = '\0';		/* kill trailing space */

+			label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1);

+			if ( label==NULL )

+			{

+				err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1));

+			}

+			>>

+		}

+		(	exception_handler > [h]

+			<<list_add(&($eg->handlers), (void *)h);>>

+		)*

+		{	"default" ":" Action

+			<<{

+			ExceptionHandler *eh = (ExceptionHandler *)

+				calloc(1, sizeof(ExceptionHandler));

+			char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+			require(eh!=NULL, "exception: cannot allocate handler");

+			require(a!=NULL, "exception: cannot allocate action");

+			strcpy(a, LATEXT(1));

+			eh->action = a;

+			eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char));

+			require(eh->signalname!=NULL, "exception: cannot allocate sig name");

+			strcpy(eh->signalname, "default");

+			list_add(&($eg->handlers), (void *)eh);

+			}>>

+		}

+

+		<<

+		if ( label!=NULL ) {

+            	/* Record ex group in sym tab for this label */

+		   if ( label->ex_group!=NULL ) {

+		      err(eMsg1("duplicate exception handler for label '%s'",label->str));

+		   } else {

+			  label->ex_group = $eg;

+				/* Label the exception group itself */

+			  $eg->label = label->str;

+				/* Make the labelled element pt to the exception also */

+/* MR6 */	  if (label->elem == NULL) {

+/* MR6 */	     err(eMsg1("reference in exception handler to undefined label '%s'",label->str));

+/* MR6 */	  } else {

+			   	 switch ( label->elem->ntype ) {

+				    case nRuleRef :

+                        {

+    					    RuleRefNode *r = (RuleRefNode *)label->elem;

+    					    r->ex_group = $eg;

+    				    	break;

+                        }

+     	            case nToken :

+				        {

+					        TokNode *t = (TokNode *)label->elem;

+					        t->ex_group = $eg;

+					        break;

+				        }

+				 } /* end switch */

+/* MR6 */	  }; /* end test on label->elem */

+		    } /* end test on label->ex_group */

+

+		} /* end test on exception label */

+

+/* MR7 */

+/* MR7 */   if (BlkLevel == 1 && label == NULL) {

+/* MR7 */     $eg->forRule=1;

+/* MR7 */   } else if (label == NULL) {

+/* MR7 */     $eg->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]);

+/* MR7 */     egAdd($eg);

+/* MR7 */   } else {

+/* MR7 */     $eg->labelEntry=label;

+/* MR7 */   };

+/* MR7 */

+/* MR7 */	    /* You may want to remove this exc from the rule list  */

+/* MR7 */		/* and handle at the labeled element site.             */

+/* MR7 */

+/* MR7 */   if (label != NULL) {

+/* MR7 */     $eg = NULL;

+/* MR7 */   };

+

+		>>

+	;

+	<<CannotContinue=TRUE;>>

+

+/* rule exception_handler */

+

+exception_handler > [ExceptionHandler *eh]

+	:	<<;>>                               /* MR9 Removed unreferenced variable "a" */

+		"catch"

+		<<

+		$eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler));

+		require($eh!=NULL, "exception: cannot allocate handler");

+		>>

+		(	NonTerminal

+			<<

+			$eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+			require($eh->signalname!=NULL, "exception: cannot allocate sig name");

+			strcpy($eh->signalname, LATEXT(1));

+			>>

+		|	TokenTerm

+			<<

+			$eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+			require($eh->signalname!=NULL, "exception: cannot allocate sig name");

+			strcpy($eh->signalname, LATEXT(1));

+			>>

+		)

+		":"

+		{	<<$eh->action = NULL;>>

+			Action

+			<<

+			$eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+			require($eh->action!=NULL, "exception: cannot allocate action");

+			strcpy($eh->action, LATEXT(1));

+			>>

+		}

+	;

+	<<CannotContinue=TRUE;>>

+

+#token NonTerminal		"[a-z] [A-Za-z0-9_]*"

+							<<

+							while ( zzchar==' ' || zzchar=='\t' ) {

+								zzadvance();

+							}

+							if ( zzchar == ':' && inAlt ) NLA = LABEL;

+							>>

+#token TokenTerm		"[A-Z] [A-Za-z0-9_]*"

+							<<

+							while ( zzchar==' ' || zzchar=='\t' ) {

+								zzadvance();

+							}

+							if ( zzchar == ':' && inAlt ) NLA = LABEL;

+							>>

+#token "{\\}#[A-Za-z0-9_]*"	<<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>

+

+#lexclass PARSE_ENUM_FILE

+

+#token "[\t\ ]+"			<< zzskip(); >>				/* Ignore White */

+#token "\n|\r|\r\n"			<< zzline++; zzskip(); >>	/* Track Line # */

+#token "//"					<< zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >>

+#token "/\*"				<< zzmode(TOK_DEF_COMMENTS); zzskip(); >>

+#token "#ifdef"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "#if"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "#ifndef"			<< ; >>

+#token "#else"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "#endif"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "#undef"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "#import"			<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>

+#token "@"					<< ; >>

+

+/* rule enum_file */

+

+enum_file[char *fname]

+	:	{	"#ifndef" ID

+			{	"#define" ID /* ignore if it smells like a gate */

+				/* First #define after the first #ifndef (if any) is ignored */

+			}

+		}

+		(	( enum_def[$fname] )+

+		|	defines[$fname]

+		)

+	|

+	;

+

+/* rule defines */

+

+defines[char *fname]

+	:	<<int v; int maxt=(-1); char *t;>>		/* MR3 */

+		(

+			"#define" ID

+			<<t = mystrdup(LATEXT(1));>>

+			INT

+			<<

+			v = atoi(LATEXT(1));

+/*			fprintf(stderr, "#token %s=%d\n", t, v);*/

+

+	/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */

+	/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */

+	/* MR2 Don't let #tokdefs be confused by 			*/

+	/* MR2   DLGminToken and DLGmaxToken     			*/

+

+			if ( ! isDLGmaxToken(t)) {		/* MR2 */

+			  TokenNum = v;

+			  if ( v>maxt ) maxt=v;

+			  if ( Tnum( t ) == 0 ) {

+			    addForcedTname( t, v );

+			  } else {

+			    warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);

+			  };

+	                };

+			>>

+		)+

+		<<TokenNum = maxt + 1;>>

+	;

+

+/* rule enum_def */

+

+enum_def[char *fname]

+	:	<<int v= 0; int maxt=(-1); char *t;>>			/* MR3 */

+		"enum" ID

+		"\{"

+			ID

+			<<t = mystrdup(LATEXT(1));>>

+			(	"=" INT	<<v=atoi(LATEXT(1));>>

+			|			<<v++;>>

+			)

+			<<

+/*			fprintf(stderr, "#token %s=%d\n", t, v);*/

+			TokenNum = v;

+			if ( v>maxt ) maxt=v;				/* MR3 */

+			if ( Tnum( t ) == 0 ) addForcedTname( t, v );

+			else {

+				warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);

+			}

+			>>

+			(	","

+

+				/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */

+				/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */

+				/* MR2 Don't let #tokdefs be confused by 			*/

+				/* MR2   DLGminToken and DLGmaxToken     			*/

+

+				{

+				  <<isDLGmaxToken(LATEXT(1))>>? ID { "=" INT }		/* MR2 */

+				| ID					                /* MR2 */

+					<<t = mystrdup(LATEXT(1));>>

+					(	"=" INT	<<v=atoi(LATEXT(1));>>

+					|			<<v++;>>

+					)

+					<<

+/*					fprintf(stderr, "#token %s=%d\n", t, v);*/

+					TokenNum = v;

+					if ( v>maxt ) maxt=v;				/* MR3 */

+					if ( Tnum( t ) == 0 ) addForcedTname( t, v );

+					else {

+						warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);

+					}

+					>>

+				}

+			)*

+		"\}"

+		";"

+		<<TokenNum = maxt + 1;>>					/* MR3 */

+	;

+

+#token INT	"[0-9]+"

+#token ID	"[a-zA-Z_][_a-zA-Z0-9]*"

+

+#lexclass START

+

+/* MR14 Arpad Beszedes  26-May-98

+        Add support for #line directives when antlr source is pre-processed

+*/

+

+#lexaction

+<<

+

+static char *

+#ifdef __USE_PROTOS

+getFileNameFromTheLineInfo(char *toStr, char *fromStr)

+#else

+getFileNameFromTheLineInfo(toStr, fromStr)

+char *toStr, *fromStr;

+#endif

+{

+  int i, j, k;

+

+  if (!fromStr || !toStr) return toStr;

+

+  /* find the first " */

+

+  for (i=0;

+        (i<MaxFileName) &&

+        (fromStr[i] != '\n') &&

+        (fromStr[i] != '\r') &&

+        (fromStr[i] != '\"');

+      i++) /* nothing */ ;

+

+  if ( (i == MaxFileName) ||

+       (fromStr[i] == '\n') ||

+       (fromStr[i] == '\r') ) {

+    return toStr;

+  }

+

+  /* find the second " */

+

+  for (j=i+1;

+        (j<MaxFileName) &&

+        (fromStr[j] != '\n') &&

+        (fromStr[j] != '\r') &&

+        (fromStr[j] != '\"');

+       j++) /* nothing */ ;

+

+  if ((j == MaxFileName) ||

+      (fromStr[j] == '\n') ||

+      (fromStr[j] == '\r') ) {

+    return toStr;

+  }

+

+  /* go back until the last / or \ */

+

+  for (k=j-1;

+        (fromStr[k] != '\"') &&

+        (fromStr[k] != '/') &&

+        (fromStr[k] != '\\');

+       k--) /* nothing */ ;

+

+  /* copy the string after " / or \ into toStr */

+

+  for (i=k+1; fromStr[i] != '\"'; i++) {

+    toStr[i-k-1] = fromStr[i];

+  }

+

+  toStr[i-k-1] = '\0';

+

+  return toStr;

+}

+

+/* MR14 end of a block to support #line in antlr source code */

+

+>>

+

+<<

+

+/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */

+/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */

+/* MR2 Don't let #tokdefs be confused by 			*/

+/* MR2   DLGminToken and DLGmaxToken     			*/

+

+/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */

+

+#ifdef __USE_PROTOS

+static int isDLGmaxToken(char *Token)

+#else

+static int isDLGmaxToken(Token)

+  char *	Token;

+#endif

+{

+   static char checkStr1[] = "DLGmaxToken";

+   static char checkStr2[] = "DLGminToken";

+

+   if (strcmp(Token, checkStr1) == 0)

+      return 1;

+   else if (strcmp(Token, checkStr2) == 0)

+      return 1;

+   else

+      return 0;

+}

+

+/* semantics of #token */

+static void

+#ifdef __USE_PROTOS

+chkToken(char *t, char *e, char *a, int tnum)

+#else

+chkToken(t,e,a,tnum)

+char *t, *e, *a;

+int tnum;

+#endif

+{

+	TermEntry *p;

+

+	/* check to see that they don't try to redefine a token as a token class */

+	if ( t!=NULL ) {

+		p = (TermEntry *) hash_get(Tname, t);

+		if ( p!=NULL && p->classname ) {

+			err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t));

+			if ( a!=NULL ) free((char *)a);

+			return;

+		}

+	}

+

+	if ( t==NULL && e==NULL ) {			/* none found */

+		err("#token requires at least token name or rexpr");

+	}

+	else if ( t!=NULL && e!=NULL ) {	/* both found */

+		if ( UserDefdTokens ) {			/* if #tokdefs, must not define new */

+			p = (TermEntry *) hash_get(Tname, t);

+			if ( p == NULL) {

+err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));

+	    		return;

+            };

+		}

+		Tklink(t, e);

+		if ( a!=NULL ) {

+			if ( hasAction(e) ) {

+				err(eMsg1("redefinition of action for %s; ignored",e));

+			}

+			else setHasAction(e, a);

+		}

+	}

+	else if ( t!=NULL ) {				/* only one found */

+		if ( UserDefdTokens ) {

+			p = (TermEntry *) hash_get(Tname, t);

+            if (p == NULL) {

+err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));

+            };

+   		    return;

+		}

+		if ( Tnum( t ) == 0 ) addTname( t );

+		else {

+			err(eMsg1("redefinition of token %s; ignored",t));

+		}

+		if ( a!=NULL ) {

+			err(eMsg1("action cannot be attached to a token name (%s); ignored",t));

+			free((char *)a);

+		}

+	}

+	else if ( e!=NULL ) {

+		if ( Tnum( e ) == 0 ) addTexpr( e );

+		else {

+			if ( hasAction(e) ) {

+				err(eMsg1("redefinition of action for expr %s; ignored",e));

+			}

+			else if ( a==NULL ) {

+				err(eMsg1("redefinition of expr %s; ignored",e));

+			}

+		}

+		if ( a!=NULL ) setHasAction(e, a);

+	}

+

+	/* if a token type number was specified, then add the token ID and 'tnum'

+	 * pair to the ForcedTokens list.  (only applies if an id was given)

+	 */

+	if ( t!=NULL && tnum>0 )

+	{

+		if ( set_el(tnum, reserved_positions) )

+		{

+			err(eMsgd("a token has already been forced to token number %d; ignored", tnum));

+		}

+		else

+		{

+			list_add(&ForcedTokens, newForcedToken(t,tnum));

+			set_orel(tnum, &reserved_positions);

+		}

+	}

+}

+>>

+

+<<

+static int

+#ifdef __USE_PROTOS

+match_token(char *s, char **nxt)

+#else

+match_token(s,nxt)

+char *s;

+char **nxt;

+#endif

+{

+    if ( !(*s>='A' && *s<='Z') ) return 0;

+	s++;

+    while ( (*s>='a' && *s<='z') ||

+		    (*s>='A' && *s<='Z') ||

+		    (*s>='0' && *s<='9') ||

+		    *s=='_' )

+    {

+	   s++;

+	}

+	if ( *s!=' ' && *s!='}' ) return 0;

+	*nxt = s;

+	return 1;

+}

+

+static int

+#ifdef __USE_PROTOS

+match_rexpr(char *s, char **nxt)

+#else

+match_rexpr(s,nxt)

+char *s;

+char **nxt;

+#endif

+{

+    if ( *s!='"' ) return 0;

+	s++;

+    while ( *s!='"' )

+    {

+	   if ( *s=='\n' || *s=='\r' )                   /* MR13 */

+		  warn("eoln found in regular expression");

+	   if ( *s=='\\' ) s++;

+	   s++;

+	}

+	*nxt = s+1;

+	return 1;

+}

+

+/*

+ * Walk a string "{ A .. Z }" where A..Z is a space separated list

+ * of token references (either labels or reg exprs).  Return a

+ * string "inlineX_set" for some unique integer X.  Basically,

+ * we pretend as if we had seen "#tokclass inlineX { A .. Z }"

+ * on the input stream outside of an action.

+ */

+char *

+#ifdef __USE_PROTOS

+inline_set(char *s)

+#else

+inline_set(s)

+char *s;

+#endif

+{

+	char *nxt;

+    fprintf(stderr, "found consumeUntil( {...} )\n");

+	while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+	if ( *s!='{' )

+	{

+	   err("malformed consumeUntil( {...} ); missing '{'");

+	   return "bad_set";

+	}

+	s++;

+	while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+	while ( *s!='}' )

+	{

+	    if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s);

+		else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s);

+		else {

+		    err("invalid element in consumeUntil( {...} )");

+			return "bad_set";

+		}

+		s = nxt;

+		while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}

+	}

+	return "inlineX_set";

+}

+>>

+

+<<

+/* ANTLR-specific syntax error message generator

+ * (define USER_ZZSYN when compiling so don't get 2 definitions)

+ */

+void

+#ifdef __USE_PROTOS

+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok,

+int k, char *bad_text)

+#else

+zzsyn(text, tok, egroup, eset, etok, k, bad_text)

+char *text, *egroup, *bad_text;

+int tok;

+int etok;

+int k;

+SetWordType *eset;

+#endif

+{

+	fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);

+	fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);

+	if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}

+	if ( k==1 ) fprintf(stderr, " missing");

+	else

+	{

+		fprintf(stderr, "; \"%s\" not", bad_text);

+		if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");

+	}

+	if ( zzset_deg(eset)>0 ) zzedecode(eset);

+	else fprintf(stderr, " %s", zztokens[etok]);

+	if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);

+	fprintf(stderr, "\n");

+}

+>>

+

+#lexaction <<

+#ifdef __USE_PROTOS

+void mark_label_used_in_sem_pred(LabelEntry *le)              /* MR10 */

+#else

+void mark_label_used_in_sem_pred(le)                          /* MR10 */

+  LabelEntry    *le;

+#endif

+{

+  TokNode   *tn;

+  require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");

+  tn=(TokNode *)le->elem;

+  require (tn->label != 0,"mark_label_used... TokNode has no label");

+  tn->label_used_in_semantic_pred=1;

+}

+>>

diff --git a/Source/Pccts/antlr/antlr.r b/Source/Pccts/antlr/antlr.r
new file mode 100644
index 0000000..e3de387
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.r
@@ -0,0 +1,787 @@
+/*

+	File:		antlrMPW.r

+	Target:		antlr 133MR

+	Created:    Monday, June 15, 1998 4:41:11 AM

+	Author:		Kenji Tanaka (kentar@osa.att.ne.jp)

+*/

+

+#include "cmdo.r"

+

+resource 'cmdo' (128, "Antlr") {

+	{	/* array dialogs: 5 elements */

+		/* [1] */

+		295,

+		"ANTLR -- Purdue Compiler Construction To"

+		"ol Set (PCCTS) LL(k) parser generator.",

+		{	/* array itemArray: 12 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{18, 23, 33, 223},

+				"Read grammar from stdin",

+				"-",

+				"Read grammar from stdin."

+			},

+			/* [2] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{38, 23, 53, 310},

+				"Send grammar.c/grammar.cpp to stdout",

+				"-stdout",

+				"Send grammar.c/grammar.cpp to stdout."

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			MultiFiles {

+				"Grammar File(s)É",

+				"Choose the grammar specification files y"

+				"ou wish to have ANTLR process.",

+				{79, 22, 98, 152},

+				"Grammar specification:",

+				"",

+				MultiInputFiles {

+					{	/* array MultiTypesArray: 1 elements */

+						/* [1] */

+						text

+					},

+					".g",

+					"Files ending in .g",

+					"All text files"

+				}

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			Files {

+				DirOnly,

+				OptionalFile {

+					{58, 168, 74, 298},

+					{79, 169, 98, 299},

+					"Output Directory",

+					":",

+					"-o",

+					"",

+					"Choose the directory where ANTLR will pu"

+					"t its output.",

+					dim,

+					"Output DirectoryÉ",

+					"",

+					""

+				},

+				NoMore {

+

+				}

+			},

+			/* [5] */

+			NotDependent {

+

+			},

+			Redirection {

+				StandardOutput,

+				{126, 27}

+			},

+			/* [6] */

+			NotDependent {

+

+			},

+			Redirection {

+				DiagnosticOutput,

+				{126, 178}

+			},

+			/* [7] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{117, 20, 167, 300},

+				"Redirection"

+			},

+			/* [8] */

+			NotDependent {

+

+			},

+			NestedDialog {

+				5,

+				{20, 324, 40, 460},

+				"Parse OptionsÉ",

+				"Parse control options may be set with th"

+				"is button."

+			},

+			/* [9] */

+			NotDependent {

+

+			},

+			NestedDialog {

+				2,

+				{50, 324, 70, 460},

+				"Generate OptionsÉ",

+				"Various command line options may be set "

+				"with this button."

+			},

+			/* [10] */

+			NotDependent {

+

+			},

+			NestedDialog {

+				3,

+				{78, 324, 98, 460},

+				"More OptionsÉ",

+				"Antlr has ALOT of options. There are eve"

+				"n more to be found with this button."

+			},

+			/* [11] */

+			NotDependent {

+

+			},

+			NestedDialog {

+				4,

+				{106, 324, 126, 460},

+				"Rename OptionsÉ",

+				"Options for renaming output files may be"

+				" set with this button."

+			},

+			/* [12] */

+			NotDependent {

+

+			},

+			VersionDialog {

+				VersionString {

+					"1.33MR"

+				},

+				"PCCTS was written by Terence Parr, Russe"

+				"ll Quong, Will Cohen, and Hank Dietz: 19"

+				"89-1998. MPW port by Scott Haney.",

+				noDialog

+			}

+		},

+		/* [2] */

+		295,

+		"Use this dialog to specify command line "

+		"Generate Options.",

+		{	/* array itemArray: 15 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{18, 25, 33, 225},

+				"Generate C++ code",

+				"-CC",

+				"Generate C++ output from both ANTLR and "

+				"DLG."

+			},

+			/* [2] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{38, 25, 53, 225},

+				"Generate ASTs",

+				"-gt",

+				"Generate code for Abstract-Syntax-Trees "

+				"(ASTs)."

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{58, 25, 73, 225},

+				"Generate line info",

+				"-gl",

+				"If this option is checked, ANTLR will ge"

+				"nerate line info about grammaractions, t"

+				"hereby making debugging easier since com"

+				"pile errors will point to the grammar fi"

+				"le."

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{78, 25, 93, 225},

+				"Generate error classes",

+				"-ge",

+				"If this option is checked, ANTLR will ge"

+				"nerate an error class foreach non-termin"

+				"al."

+			},

+			/* [5] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{98, 25, 113, 225},

+				"Don't generate Code",

+				"-gc",

+				"If this option is checked, ANTLR will ge"

+				"nerate no code, i.e. it will only perfor"

+				"m analysis on the grammar."

+			},

+			/* [6] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{118, 25, 133, 225},

+				"Delay lookahead fetches",

+				"-gk",

+				"If this option is checked, ANTLR will ge"

+				"nerate a parser that delays lookahead fe"

+				"tches until needed."

+			},

+			/* [7] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{138, 25, 153, 225},

+				"Use newAST(...)",

+				"-newAST",

+				"In C++ mode use \"newAST(...)\" rather tha"

+				"n \"new AST(...)\""

+			},

+			/* [8] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{18, 235, 33, 435},

+				"Support parse traces",

+				"-gd",

+				"If this option is checked, ANTLR inserts"

+				" code in each parsing function to provid"

+				"e for user-defined handling of a detaile"

+				"d parse trace. The code consists of call"

+				"s to zzTRACEIN and zzTRACEOUT."

+			},

+			/* [9] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{38, 235, 53, 435},

+				"Generate cross-references",

+				"-cr",

+				"If this option is checked, ANTLR will ge"

+				"nerate a cross reference for all rules. "

+				"For each rule it will print a list of al"

+				"l other rules that refrence it."

+			},

+			/* [10] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{58, 235, 73, 435},

+				"Don't create Lexer files",

+				"-gx",

+				"If this option is checked, ANTLR will no"

+				"t generate DLG-related output files. Thi"

+				"s option should be used if one wants a c"

+				"ustom lexical analyzer or if one has mad"

+				"e changes to the grammar not affecting t"

+				"he lexical structure."

+			},

+			/* [11] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{78, 235, 93, 460},

+				"Don't generate token expr sets",

+				"-gs",

+				"If this option is checked, ANTLR will no"

+				"t generate sets for token expression set"

+				"s; instead, it will generate a || separa"

+				"ted sequence of LA(1)==token #. "

+			},

+			/* [12] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{98, 235, 113, 460},

+				"Generate ANSI-compatible",

+				"-ga",

+				"Generate ANSI-compatible code (default=F"

+				"ALSE)"

+			},

+			/* [13] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{118, 235, 133, 460},

+				"Don't generate tokens.h",

+				"-gxt",

+				"Do not generate tokens.h (default=FALSE)"

+			},

+			/* [13] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{138, 235, 153, 460},

+				"Provide \"(alpha)? beta\" info",

+				"-alpha",

+				"Provide additional information for \"(alpha)? beta\" error messages"

+			},

+			/* [14] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Tabs(1 to 8):",

+				{162, 23, 177, 117},

+				{163, 125, 179, 196},

+				"",

+				keepCase,

+				"-tab",

+				"Width of tabs (1 to 8) for grammar.c/gra"

+				"mmar.cpp files."

+			},

+			/* [15] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Function Prefix:",

+				{161, 236, 177, 342},

+				{162, 345, 177, 454},

+				"",

+				keepCase,

+				"-gp",

+				"Prefix all generated rule functions with"

+				" a string."

+			}

+		},

+		/* [3] */

+		295,

+		"Use this dialog to specify still more co"

+		"mmand line options.",

+		{	/* array itemArray: 12 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			RadioButtons {

+				{	/* array radioArray: 3 elements */

+					/* [1] */

+					{38, 25, 53, 85}, "None", "", Set, "When this option is selected, ANTLR will"

+					" not print the grammar to stdout.",

+					/* [2] */

+					{38, 100, 53, 160}, "Yes", "-p", NotSet, "When this option is selected, ANTLR will"

+					" print the grammar, stripped of all acti"

+					"ons and comments, to stdout.",

+					/* [3] */

+					{38, 175, 53, 235}, "More", "-pa", NotSet, "When this option is selected, ANTLR will"

+					" print the grammar, stripped of all acti"

+					"ons and comments, to stdout. It will als"

+					"o annotate the output with the first set"

+					"s determined from grammar analysis."

+				}

+			},

+			/* [2] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{28, 15, 60, 250},

+				"Grammar Printing"

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			RadioButtons {

+				{	/* array radioArray: 3 elements */

+					/* [1] */

+					{88, 25, 103, 85}, "Low", "", Set, "When this option is selected, ANTLR will"

+					" show ambiguities/errors in low detail.",

+					/* [2] */

+					{88, 100, 103, 160}, "Medium", "-e2", NotSet, "When this option is selected, ANTLR will"

+					" show ambiguities/errors in more detail.",

+					/* [3] */

+					{88, 175, 103, 235}, "High", "-e3", NotSet, "When this option is selected, ANTLR will"

+					" show ambiguities/errors in excruciating"

+					" detail."

+				}

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{78, 15, 110, 250},

+				"Error reporting"

+			},

+			/* [5] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{130, 22, 145, 222},

+				"More warnings",

+				"-w2",

+				"If this option is checked, ANTLR will wa"

+				"rn if semantic predicates and/or (É)? bl"

+				"ocks are assumed to cover ambiguous alte"

+				"rnatives."

+			},

+			/* [6] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Report when tnode usage exceeds:",

+				{162, 23, 180, 253},

+				{162, 255, 178, 326},

+				"",

+				keepCase,

+				"-treport",

+				"Report when tnode usage exceeds value du"

+				"ring ambiguity resolution."

+			},

+			/* [7] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{40, 292, 55, 431},

+				"Predicate",

+				"-info p",

+				"With the antlr \"-info p\" switch the user"

+				" will receive information about the pred"

+				"icate suppression in the generated file."

+			},

+			/* [8] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{60, 292, 75, 430},

+				"Tree Nodes",

+				"-info t",

+				"Using \"-info t\" gives information about "

+				"the total number of tnodes created and t"

+				"he peak number of tnodes."

+			},

+			/* [9] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{80, 292, 95, 425},

+				"First/follow",

+				"-info f",

+				"first/follow set information."

+			},

+			/* [10] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{100, 292, 115, 425},

+				"Monitor progress",

+				"-info m",

+				"prints name of each rule as it is starte"

+				"d and flushes output at start of each rule."

+			},

+			/* [11] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{120, 292, 135, 416},

+				"Orphan rules",

+				"-info o",

+				"If there is more than one rule which is "

+				"not referenced by any other rule then al"

+				"l such rules are listed."

+			},

+			/* [12] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{28, 279, 147, 451},

+				"Extra info"

+			}

+		},

+		/* [4] */

+		295,

+		"Use this dialog to specify command line "

+		"options relating to renaming output file"

+		"s.",

+		{	/* array itemArray: 7 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Errors file name:",

+				{35, 25, 50, 205},

+				{35, 205, 51, 300},

+				"err.c",

+				keepCase,

+				"-fe",

+				"This entry specifies the name ANTLR uses"

+				" for the errors file."

+			},

+			/* [2] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Lexical output name:",

+				{60, 25, 75, 205},

+				{60, 205, 76, 300},

+				"parser.dlg",

+				keepCase,

+				"-fl",

+				"This entry specifies the name ANTLR uses"

+				" for the lexical output file."

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Lexical modes name:",

+				{85, 25, 100, 205},

+				{85, 205, 101, 300},

+				"mode.h",

+				keepCase,

+				"-fm",

+				"This entry specifies the name ANTLR uses"

+				" for the lexical mode definitions file."

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Remap file name:",

+				{110, 25, 125, 205},

+				{110, 205, 126, 300},

+				"remap.h",

+				keepCase,

+				"-fr",

+				"This entry specifies the name ANTLR uses"

+				" for the file that remaps globally visib"

+				"le symbols."

+			},

+			/* [5] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Tokens file name:",

+				{135, 25, 150, 205},

+				{135, 205, 151, 300},

+				"tokens.h",

+				keepCase,

+				"-ft",

+				"This entry specifies the name ANTLR uses"

+				" for the tokens file."

+			},

+			/* [6] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{160, 25, 175, 175},

+				"Create std header",

+				"-gh",

+				"If this option is checked, ANTLR will cr"

+				"eate a standard header file named, by de"

+				"fault 'stdpccts.h'. This name can be alt"

+				"ered using the entry right next door."

+			},

+			/* [7] */

+			Or {

+				{	/* array OrArray: 1 elements */

+					/* [1] */

+					6

+				}

+			},

+			RegularEntry {

+				"Std header file name:",

+				{160, 175, 175, 355},

+				{160, 355, 176, 450},

+				"stdpccts.h",

+				keepCase,

+				"-fh",

+				"This entry specifies the name ANTLR uses"

+				" for the standard header file."

+			}

+		},

+		/* [5] */

+		295,

+		"Use this dialog to specify parse options"

+		".",

+		{	/* array itemArray: 9 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Lookahead:",

+				{23, 27, 38, 152},

+				{46, 29, 62, 154},

+				"1",

+				keepCase,

+				"-k",

+				"This entry specifies the number of token"

+				"s of lookahead."

+			},

+			/* [2] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Compr lookahead:",

+				{22, 167, 37, 292},

+				{46, 172, 62, 297},

+				"",

+				keepCase,

+				"-ck",

+				"This entry specifies the number of token"

+				"s of lookahead when using compressed (li"

+				"near approximation) lookahead. In genera"

+				"l, the compressed lookahead is much deep"

+				"er than the full lookahead."

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Max tree nodes:",

+				{22, 312, 37, 437},

+				{46, 315, 62, 445},

+				"",

+				keepCase,

+				"-rl",

+				"This entry specifies the maximum number "

+				"of tokens of tree nodes used by the gram"

+				"mar analysis."

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{76, 25, 91, 350},

+				"Maintenance Release style hoisting",

+				"-mrhoist",

+				"Turn on/off k=1 Maintenance Release styl"

+				"e hoisting."

+			},

+			/* [5] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{96, 25, 111, 431},

+				"EXPERIMENTAL Maintenance Release style h"

+				"oisting",

+				"-mrhoistk",

+				"Turn on/off k>1 EXPERIMENTAL Maintenance"

+				" Release style hoisting."

+			},

+			/* [6] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{116, 25, 131, 363},

+				"Compute context for hoisted predicates",

+				"-prc on",

+				"Turn on/off computation of context for h"

+				"oisted predicates."

+			},

+			/* [7] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Ambiguity aid:",

+				{140, 27, 155, 125},

+				{141, 135, 155, 209},

+				"",

+				keepCase,

+				"-aa",

+				"Ambiguity aid for a rule (rule name or l"

+				"ine number)."

+			},

+			/* [8] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Limits exp growth:",

+				{140, 236, 155, 361},

+				{139, 372, 155, 452},

+				"",

+				keepCase,

+				"-aad",

+				"Limits exp growth of -aa listing - defau"

+				"lt=1 (max=ck value)."

+			},

+			/* [9] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{164, 26, 179, 366},

+				"Lookahead token may appear multiple time"

+				"s",

+				"-aam",

+				"Lookahead token may appear multiple time"

+				"s in -aa listing."

+			}

+		}

+	}

+};

+

diff --git a/Source/Pccts/antlr/antlr1.txt b/Source/Pccts/antlr/antlr1.txt
new file mode 100644
index 0000000..4a7d22e
--- /dev/null
+++ b/Source/Pccts/antlr/antlr1.txt
@@ -0,0 +1,264 @@
+

+

+

+ANTLR(1)               PCCTS Manual Pages                ANTLR(1)

+

+

+

+NAME

+     antlr - ANother Tool for Language Recognition

+

+SYNTAX

+     antlr [_o_p_t_i_o_n_s] _g_r_a_m_m_a_r__f_i_l_e_s

+

+DESCRIPTION

+     _A_n_t_l_r converts an extended form of context-free grammar into

+     a set of C functions which directly implement an efficient

+     form of deterministic recursive-descent LL(k) parser.

+     Context-free grammars may be augmented with predicates to

+     allow semantics to influence parsing; this allows a form of

+     context-sensitive parsing.  Selective backtracking is also

+     available to handle non-LL(k) and even non-LALR(k) con-

+     structs.  _A_n_t_l_r also produces a definition of a lexer which

+     can be automatically converted into C code for a DFA-based

+     lexer by _d_l_g.  Hence, _a_n_t_l_r serves a function much like that

+     of _y_a_c_c, however, it is notably more flexible and is more

+     integrated with a lexer generator (_a_n_t_l_r directly generates

+     _d_l_g code, whereas _y_a_c_c and _l_e_x are given independent

+     descriptions).  Unlike _y_a_c_c which accepts LALR(1) grammars,

+     _a_n_t_l_r accepts LL(k) grammars in an extended BNF notation -

+     which eliminates the need for precedence rules.

+

+     Like _y_a_c_c grammars, _a_n_t_l_r grammars can use automatically-

+     maintained symbol attribute values referenced as dollar

+     variables.  Further, because _a_n_t_l_r generates top-down

+     parsers, arbitrary values may be inherited from parent rules

+     (passed like function parameters).  _A_n_t_l_r also has a mechan-

+     ism for creating and manipulating abstract-syntax-trees.

+

+     There are various other niceties in _a_n_t_l_r, including the

+     ability to spread one grammar over multiple files or even

+     multiple grammars in a single file, the ability to generate

+     a version of the grammar with actions stripped out (for

+     documentation purposes), and lots more.

+

+OPTIONS

+     -ck _n

+          Use up to _n symbols of lookahead when using compressed

+          (linear approximation) lookahead.  This type of looka-

+          head is very cheap to compute and is attempted before

+          full LL(k) lookahead, which is of exponential complex-

+          ity in the worst case.  In general, the compressed loo-

+          kahead can be much deeper (e.g, -ck 10) _t_h_a_n _t_h_e _f_u_l_l

+          _l_o_o_k_a_h_e_a_d (_w_h_i_c_h _u_s_u_a_l_l_y _m_u_s_t _b_e _l_e_s_s _t_h_a_n _4).

+

+     -CC  Generate C++ output from both ANTLR and DLG.

+

+     -cr  Generate a cross-reference for all rules.  For each

+          rule, print a list of all other rules that reference

+          it.

+

+     -e1  Ambiguities/errors shown in low detail (default).

+

+     -e2  Ambiguities/errors shown in more detail.

+

+     -e3  Ambiguities/errors shown in excruciating detail.

+

+     -fe file

+          Rename err.c to file.

+

+     -fh file

+          Rename stdpccts.h header (turns on -gh) to file.

+

+     -fl file

+          Rename lexical output, parser.dlg, to file.

+

+     -fm file

+          Rename file with lexical mode definitions, mode.h, to

+          file.

+

+     -fr file

+          Rename file which remaps globally visible symbols,

+          remap.h, to file.

+

+     -ft file

+          Rename tokens.h to file.

+

+     -ga  Generate ANSI-compatible code (default case).  This has

+          not been rigorously tested to be ANSI XJ11 C compliant,

+          but it is close.  The normal output of _a_n_t_l_r is

+          currently compilable under both K&R, ANSI C, and C++-

+          this option does nothing because _a_n_t_l_r generates a

+          bunch of #ifdef's to do the right thing depending on

+          the language.

+

+     -gc  Indicates that _a_n_t_l_r should generate no C code, i.e.,

+          only perform analysis on the grammar.

+

+     -gd  C code is inserted in each of the _a_n_t_l_r generated pars-

+          ing functions to provide for user-defined handling of a

+          detailed parse trace.  The inserted code consists of

+          calls to the user-supplied macros or functions called

+          zzTRACEIN and zzTRACEOUT.  The only argument is a _c_h_a_r

+          * pointing to a C-style string which is the grammar

+          rule recognized by the current parsing function.  If no

+          definition is given for the trace functions, upon rule

+          entry and exit, a message will be printed indicating

+          that a particular rule as been entered or exited.

+

+     -ge  Generate an error class for each non-terminal.

+

+     -gh  Generate stdpccts.h for non-ANTLR-generated files to

+          include.  This file contains all defines needed to

+          describe the type of parser generated by _a_n_t_l_r (e.g.

+          how much lookahead is used and whether or not trees are

+          constructed) and contains the header action specified

+          by the user.

+

+     -gk  Generate parsers that delay lookahead fetches until

+          needed.  Without this option, _a_n_t_l_r generates parsers

+          which always have _k tokens of lookahead available.

+

+     -gl  Generate line info about grammar actions in C parser of

+          the form # _l_i_n_e "_f_i_l_e" which makes error messages from

+          the C/C++ compiler make more sense as they will point

+          into the grammar file not the resulting C file.

+          Debugging is easier as well, because you will step

+          through the grammar not C file.

+

+     -gs  Do not generate sets for token expression lists;

+          instead generate a ||-separated sequence of

+          LA(1)==_t_o_k_e_n__n_u_m_b_e_r.  The default is to generate sets.

+

+     -gt  Generate code for Abstract-Syntax Trees.

+

+     -gx  Do not create the lexical analyzer files (dlg-related).

+          This option should be given when the user wishes to

+          provide a customized lexical analyzer.  It may also be

+          used in _m_a_k_e scripts to cause only the parser to be

+          rebuilt when a change not affecting the lexical struc-

+          ture is made to the input grammars.

+

+     -k _n Set k of LL(k) to _n; i.e. set tokens of look-ahead

+          (default==1).

+

+     -o dir

+          Directory where output files should go (default=".").

+          This is very nice for keeping the source directory

+          clear of ANTLR and DLG spawn.

+

+     -p   The complete grammar, collected from all input grammar

+          files and stripped of all comments and embedded

+          actions, is listed to stdout.  This is intended to aid

+          in viewing the entire grammar as a whole and to elim-

+          inate the need to keep actions concisely stated so that

+          the grammar is easier to read.  Hence, it is preferable

+          to embed even complex actions directly in the grammar,

+          rather than to call them as subroutines, since the sub-

+          routine call overhead will be saved.

+

+     -pa  This option is the same as -p except that the output is

+          annotated with the first sets determined from grammar

+          analysis.

+

+     -prc on

+          Turn on the computation and hoisting of predicate con-

+          text.

+

+     -prc off

+          Turn off the computation and hoisting of predicate con-

+          text.  This option makes 1.10 behave like the 1.06

+          release with option -pr on.  Context computation is off

+          by default.

+

+     -rl _n

+          Limit the maximum number of tree nodes used by grammar

+          analysis to _n.  Occasionally, _a_n_t_l_r is unable to

+          analyze a grammar submitted by the user.  This rare

+          situation can only occur when the grammar is large and

+          the amount of lookahead is greater than one.  A non-

+          linear analysis algorithm is used by PCCTS to handle

+          the general case of LL(k) parsing.  The average com-

+          plexity of analysis, however, is near linear due to

+          some fancy footwork in the implementation which reduces

+          the number of calls to the full LL(k) algorithm.  An

+          error message will be displayed, if this limit is

+          reached, which indicates the grammar construct being

+          analyzed when _a_n_t_l_r hit a non-linearity.  Use this

+          option if _a_n_t_l_r seems to go out to lunch and your disk

+          start thrashing; try _n=10000 to start.  Once the

+          offending construct has been identified, try to remove

+          the ambiguity that _a_n_t_l_r was trying to overcome with

+          large lookahead analysis.  The introduction of (...)?

+          backtracking blocks eliminates some of these problems -

+          _a_n_t_l_r does not analyze alternatives that begin with

+          (...)? (it simply backtracks, if necessary, at run

+          time).

+

+     -w1  Set low warning level.  Do not warn if semantic

+          predicates and/or (...)? blocks are assumed to cover

+          ambiguous alternatives.

+

+     -w2  Ambiguous parsing decisions yield warnings even if

+          semantic predicates or (...)? blocks are used.  Warn if

+          predicate context computed and semantic predicates

+          incompletely disambiguate alternative productions.

+

+     -    Read grammar from standard input and generate stdin.c

+          as the parser file.

+

+SPECIAL CONSIDERATIONS

+     _A_n_t_l_r works...  we think.  There is no implicit guarantee of

+     anything.  We reserve no legal rights to the software known

+     as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS

+     is in the public domain.  An individual or company may do

+     whatever they wish with source code distributed with PCCTS

+     or the code generated by PCCTS, including the incorporation

+     of PCCTS, or its output, into commercial software.  We

+     encourage users to develop software with PCCTS.  However, we

+     do ask that credit is given to us for developing PCCTS.  By

+     "credit", we mean that if you incorporate our source code

+     into one of your programs (commercial product, research pro-

+     ject, or otherwise) that you acknowledge this fact somewhere

+     in the documentation, research report, etc...  If you like

+     PCCTS and have developed a nice tool with the output, please

+     mention that you developed it using PCCTS.  As long as these

+     guidelines are followed, we expect to continue enhancing

+     this system and expect to make other tools available as they

+     are completed.

+

+FILES

+     *.c  output C parser.

+

+     *.cpp

+          output C++ parser when C++ mode is used.

+

+     parser.dlg

+          output _d_l_g lexical analyzer.

+

+     err.c

+          token string array, error sets and error support rou-

+          tines.  Not used in C++ mode.

+

+     remap.h

+          file that redefines all globally visible parser sym-

+          bols.  The use of the #parser directive creates this

+          file.  Not used in C++ mode.

+

+     stdpccts.h

+          list of definitions needed by C files, not generated by

+          PCCTS, that reference PCCTS objects.  This is not gen-

+          erated by default.  Not used in C++ mode.

+

+     tokens.h

+          output #_d_e_f_i_n_e_s for tokens used and function prototypes

+          for functions generated for rules.

+

+

+SEE ALSO

+     dlg(1), pccts(1)

+

+

+

+

+

diff --git a/Source/Pccts/antlr/bits.c b/Source/Pccts/antlr/bits.c
new file mode 100644
index 0000000..ddd9bd6
--- /dev/null
+++ b/Source/Pccts/antlr/bits.c
@@ -0,0 +1,1025 @@
+/* bits.c -- manage creation and output of bit sets used by the parser.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <ctype.h>

+#include <assert.h>

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+

+/* char is only thing that is pretty much always known == 8 bits

+ * This allows output of antlr (set stuff, anyway) to be androgynous (portable)

+ */

+typedef unsigned char SetWordType;

+#define BitsPerByte		8

+#define BitsPerWord		BitsPerByte*sizeof(SetWordType)

+

+static SetWordType *setwd = NULL;

+int setnum = -1;

+int wordnum = 0;

+

+int esetnum = 0;

+

+/* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets,

+   to bytes that are most portable size-wise.

+   */

+void

+#ifdef __USE_PROTOS

+DumpIntAsChars( FILE *f, char *format, unsigned wd )

+#else

+DumpIntAsChars( f, format, wd )

+FILE *f;

+char *format;

+unsigned wd;

+#endif

+{

+	int i;

+	/* uses max of 32 bit unsigned integer for the moment */

+	static unsigned long byte_mask[sizeof(unsigned long)] =

+				{ 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL };  /* MR20 G. Hobbelt */

+/*				  0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/

+

+	/* for each byte in the word */

+	assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */

+	for (i=0; i<sizeof(unsigned); i++)

+	{

+		/* mask out the ith byte and shift down to the first 8 bits */

+		fprintf(f, format, (wd&byte_mask[i])>>(i*BitsPerByte));

+		if ( i<sizeof(unsigned)-1) fprintf(f, ",");

+	}

+}

+

+/* Create a new setwd (ignoring [Ep] token on end) */

+void

+#ifdef __USE_PROTOS

+NewSetWd( void )

+#else

+NewSetWd( )

+#endif

+{

+	SetWordType *p;

+

+	if ( setwd == NULL )

+	{

+		setwd = (SetWordType *) calloc(TokenNum, sizeof(SetWordType));

+		require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");

+	}

+	for (p = setwd; p<&(setwd[TokenNum]); p++)  {*p=0;}

+	wordnum++;

+}

+

+void

+#ifdef __USE_PROTOS

+DumpSetWd( void )

+#else

+DumpSetWd( )

+#endif

+{

+	if ( GenCC ) DumpSetWdForCC();

+	else DumpSetWdForC();

+}

+

+/* Dump the current setwd to ErrFile. 0..MaxTokenVal */

+void

+#ifdef __USE_PROTOS

+DumpSetWdForC( void )

+#else

+DumpSetWdForC( )

+#endif

+{

+	int i,c=1;

+

+	if ( setwd==NULL ) return;

+	fprintf(DefFile, "extern SetWordType setwd%d[];\n", wordnum);

+	fprintf(ErrFile,

+			"SetWordType setwd%d[%d] = {", wordnum, TokenNum-1);

+	for (i=0; i<TokenNum-1; i++)

+	{

+		DAWDLE;

+		if ( i!=0 ) fprintf(ErrFile, ",");

+		if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;

+		fprintf(ErrFile, "0x%x", setwd[i]);

+	}

+	fprintf(ErrFile, "};\n");

+}

+

+/* Dump the current setwd to Parser.C file. 0..MaxTokenVal;

+ * Only used if -CC on.

+ */

+void

+#ifdef __USE_PROTOS

+DumpSetWdForCC( void )

+#else

+DumpSetWdForCC( )

+#endif

+{

+	int i,c=1;

+

+	if ( setwd==NULL ) return;

+	fprintf(Parser_h, "\tstatic SetWordType setwd%d[%d];\n", wordnum, TokenNum-1);

+	fprintf(Parser_c,

+			"SetWordType %s::setwd%d[%d] = {", CurrentClassName, wordnum,

+			TokenNum-1);

+	for (i=0; i<TokenNum-1; i++)

+	{

+		DAWDLE;

+		if ( i!=0 ) fprintf(Parser_c, ",");

+		if ( c == 8 ) {fprintf(Parser_c, "\n\t"); c=1;} else c++;

+		fprintf(Parser_c, "0x%x", setwd[i]);

+	}

+	fprintf(Parser_c, "};\n");

+}

+

+/* Make a new set.  Dump old setwd and create new setwd if current setwd is full */

+void

+#ifdef __USE_PROTOS

+NewSet( void )

+#else

+NewSet( )

+#endif

+{

+	setnum++;

+	if ( setnum==BitsPerWord )		/* is current setwd full? */

+	{

+		DumpSetWd(); NewSetWd(); setnum = 0;

+	}

+}

+

+/* s is a set of tokens.  Turn on bit at each token position in set 'setnum' */

+void

+#ifdef __USE_PROTOS

+FillSet( set s )

+#else

+FillSet( s )

+set s;

+#endif

+{

+	SetWordType mask=(((unsigned)1)<<setnum);

+	unsigned int e;

+

+	while ( !set_nil(s) )

+	{

+		e = set_int(s);

+		set_rm(e, s);

+		setwd[e] |= mask;

+	}

+}

+

+					/* E r r o r  C l a s s  S t u f f */

+

+/* compute the FIRST of a rule for the error class stuff */

+static set

+#ifdef __USE_PROTOS

+Efirst( char *rule, ECnode *eclass )

+#else

+Efirst( rule, eclass )

+char *rule;

+ECnode *eclass;

+#endif

+{

+	set rk, a;

+	Junction *r;

+	RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);

+

+	if ( q == NULL )

+	{

+		warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",

+						rule, TokenString(eclass->tok)));

+		return empty;

+	}

+	r = RulePtr[q->rulenum];

+	r->end->halt = TRUE;		/* don't let reach fall off end of rule here */

+	rk = empty;

+	REACH(r, 1, &rk, a);

+	r->end->halt = FALSE;

+	return a;

+}

+

+/*

+ * scan the list of tokens/eclasses/nonterminals filling the new eclass

+ * with the set described by the list.  Note that an eclass can be

+ * quoted to allow spaces etc... However, an eclass must not conflict

+ * with a reg expr found elsewhere.  The reg expr will be taken over

+ * the eclass name.

+ */

+static void

+#ifdef __USE_PROTOS

+doEclass( char *eclass )

+#else

+doEclass( eclass )

+char *eclass;

+#endif

+{

+	TermEntry *q;

+	ECnode *p;

+	TCnode *tcnode;

+	ListNode *e;

+	unsigned int t;

+	unsigned deg=0;

+	set a;

+	require(eclass!=NULL, "doEclass: NULL eset");

+	

+	p = (ECnode *) eclass;

+	lexmode(p->lexclass);	/* switch to lexclass where errclass is defined */

+	p->eset = empty;

+	for (e = (p->elist)->next; e!=NULL; e=e->next)

+	{

+		q = NULL;								/* MR23 */

+

+		if ( islower( *((char *)e->elem) ) )	/* is it a rule ref? (alias FIRST request) */

+		{

+			a = Efirst((char *)e->elem, p);

+			set_orin(&p->eset, a);

+			deg += set_deg(a);

+			set_free( a );

+			continue;

+		}

+		else if ( *((char *)e->elem)=='"' )

+		{

+			t = 0;

+			q = (TermEntry *) hash_get(Texpr, (char *) e->elem);

+			if ( q == NULL )

+			{

+				/* if quoted and not an expr look for eclass name */

+				q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem));

+				if ( q != NULL ) t = q->token;

+			}

+			else t = q->token;

+		}

+		else	/* labelled token/eclass/tokclass */

+		{

+			q = (TermEntry *) hash_get(Tname, (char *)e->elem);

+			if ( q != NULL )

+			{

+				if ( strcmp((char *)e->elem, TokenString(p->tok))==0 )

+				{

+					warnNoFL(eMsg1("self-referential error class '%s'; ignored",

+								   (char *)e->elem));

+					continue;

+				}

+				else

+					t = q->token;

+			}

+			else t=0;

+		}

+		if ( t!=0 )

+		{

+			if (isTermEntryTokClass(q))  {			/* MR23 */

+			    tcnode = q->tclass;					/* MR23 */

+				set_orin(&p->eset, tcnode->tset);	/* MR23 */

+				deg = set_deg(p->eset);				/* MR23 */

+			}										/* MR23 */

+			else {

+				set_orel(t, &p->eset);

+				deg++;

+			}

+		}

+		else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",

+							(char *)e->elem, TokenString(p->tok)));

+	}

+	p->setdeg = deg;

+}

+

+void

+#ifdef __USE_PROTOS

+ComputeErrorSets( void )

+#else

+ComputeErrorSets( )

+#endif

+{

+#ifdef __cplusplus

+    list_apply(eclasses, (void (*)(void *)) doEclass);

+#else

+#ifdef __USE_PROTOS

+    list_apply(eclasses, (void (*)(void *)) doEclass);

+#else

+    list_apply(eclasses, doEclass);

+#endif

+#endif

+}

+

+void

+#ifdef __USE_PROTOS

+ComputeTokSets( void )

+#else

+ComputeTokSets( )

+#endif

+{

+	ListNode *t, *e = NULL, *e1, *e2;

+	int something_changed;

+    int i;

+	TCnode *p;

+	TermEntry *q, *q1, *q2;

+

+	if ( tclasses == NULL ) return;

+

+	/* turn lists of token/tokclass references into sets */

+	for (t = tclasses->next; t!=NULL; t=t->next)

+	{

+		p = (TCnode *) t->elem;

+

+		/* if wild card, then won't have entries in tclass, assume all_tokens */

+		if ( p->tok == WildCardToken )

+		{

+			p->tset = set_dup(all_tokens);

+			continue;

+		}

+

+		lexmode(p->lexclass);	/* switch to lexclass where tokclass is defined */

+		p->tset = empty;

+

+		/* instantiate all tokens/token_classes into the tset */

+		for (e = (p->tlist)->next; e!=NULL; e=e->next)

+		{

+			char *tokstr;

+			tokstr = (char *)e->elem;

+			if ( *tokstr == '"' ) {

+                q = (TermEntry *) hash_get(Texpr, tokstr);

+    			require(q!=NULL, "ComputeTokSets: no token def");

+    			set_orel(q->token, &p->tset);

+			} else if (tokstr[0] == '.') {

+                e1=e->next;

+                e2=e1->next;

+                e=e2;

+                q1= (TermEntry *) hash_get(Tname, (char *)e1->elem);

+    			require(q1!=NULL, "ComputeTokSets: no token def");

+                q2= (TermEntry *) hash_get(Tname, (char *)e2->elem);

+    			require(q2!=NULL, "ComputeTokSets: no token def");

+

+                if (set_el(q1->token,imag_tokens)) {

+errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",

+                        TokenString(p->tok),(char *)e1->elem) );

+                }

+                if (set_el(q2->token,imag_tokens)) {

+errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",

+                        TokenString(p->tok),(char *)e2->elem) );

+                }

+                if (q1->token > q2->token) {

+errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number",

+                        TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) );

+                  for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); }

+                } else {

+                  for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); }

+                }

+            } else {

+                q = (TermEntry *) hash_get(Tname, tokstr);

+    			require(q!=NULL, "ComputeTokSets: no token def");

+    			set_orel(q->token, &p->tset);

+            }

+		}

+	}

+

+	/* Go thru list of tokclasses again looking for tokclasses in sets */

+again:

+	something_changed = 0;

+	for (t = tclasses->next; t!=NULL; t=t->next)

+	{

+		set tcl;

+		p = (TCnode *) t->elem;

+		tcl = set_and(p->tset, tokclasses);

+		if ( !set_nil(tcl) )

+		{

+			int tk;

+			/* replace refs to tokclasses with the associated set of tokens */

+			something_changed = 1;

+			while ( !set_nil(tcl) )

+			{

+				tk = set_int(tcl);		/* grab one of the tok class refs */

+				set_rm(tk, tcl);

+				if ( p->tok != tk )		/* tokclass ref to yourself? */

+				{

+					q = (TermEntry *) hash_get(Tname, TokenString(tk));

+					require(q!=NULL, "#tokclass not in hash table");

+					set_orin(&p->tset, q->tclass->tset);

+				}

+				set_rm(tk, p->tset);	/* remove ref that we replaced */

+			}

+		}

+		set_free(tcl);

+	}

+	if ( something_changed ) goto again;

+}

+

+void

+#ifdef __USE_PROTOS

+DumpRemainingTokSets(void)

+#else

+DumpRemainingTokSets()

+#endif

+{

+	TCnode *p;

+	ListNode *t;

+

+	/* Go thru tclasses (for the last time) and dump the sets not dumped

+	 * during code gen; yes, this is a bogus way to do this, but ComputeTokSets()

+	 * can't dump the defs as the error file and tok file has not been created

+	 * yet etc...

+	 */

+	if ( tclasses==NULL ) return;

+	for (t = tclasses->next; t!=NULL; t=t->next)

+	{

+		unsigned e;

+		p = (TCnode *) t->elem;

+		if ( p->dumped ) continue;

+		e = DefErrSet(&(p->tset), 0, TokenString(p->tok));

+		p->dumped = 1;

+		p->setnum = e;

+	}

+}

+

+

+/* replace a subset of an error set with an error class name if a subset is found

+ * repeat process until no replacements made

+ */

+void

+#ifdef __USE_PROTOS

+SubstErrorClass( set *f )

+#else

+SubstErrorClass( f )

+set *f;

+#endif

+{

+	int max, done = 0;

+	ListNode *p;

+	ECnode *ec, *maxclass = NULL;

+	set a;

+	require(f!=NULL, "SubstErrorClass: NULL eset");

+

+	if ( eclasses == NULL ) return;

+	while ( !done )

+	{

+		max = 0;

+		maxclass = NULL;

+		for (p=eclasses->next; p!=NULL; p=p->next)	/* chk all error classes */

+		{

+			ec = (ECnode *) p->elem;

+			if ( ec->setdeg > max )

+			{

+				if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )

+					{maxclass = ec; max=ec->setdeg;}

+			}

+		}

+		if ( maxclass != NULL )	/* if subset found, replace with token */

+		{

+			a = set_dif(*f, maxclass->eset);

+			set_orel((unsigned)maxclass->tok, &a);

+			set_free(*f);

+			*f = a;

+		}

+		else done = 1;

+	}

+}

+

+int

+#ifdef __USE_PROTOS

+DefErrSet1(int nilOK, set *f, int subst, char *name )

+#else

+DefErrSet1(nilOK, f, subst, name )

+int nilOK;

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+#endif

+{

+	if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set");

+	else return DefErrSetForC1(nilOK, f, subst, name, "_set");

+}

+

+int

+#ifdef __USE_PROTOS

+DefErrSet( set *f, int subst, char *name )

+#else

+DefErrSet( f, subst, name )

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+#endif

+{

+    return DefErrSet1(0,f,subst,name);

+}

+

+int

+#ifdef __USE_PROTOS

+DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix)

+#else

+DefErrSetWithSuffix(nilOK, f, subst, name, suffix )

+int nilOK;

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+char *suffix;

+#endif

+{

+	if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix );

+	else return DefErrSetForC1(nilOK, f, subst, name, suffix);

+}

+

+/* Define a new error set.  WARNING...set-implementation dependent.

+ */

+int

+#ifdef __USE_PROTOS

+DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix)

+#else

+DefErrSetForC1(nilOK, f, subst, name, suffix)

+int nilOK;          /* MR13 */

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+const char *suffix;

+#endif

+{

+	unsigned *p, *endp;

+	int e=1;

+

+    if (!nilOK)	require(!set_nil(*f), "DefErrSetForC1: nil set to dump?");

+

+	if ( subst ) SubstErrorClass(f);

+	p = f->setword;

+	endp = &(f->setword[f->n]);

+	esetnum++;

+	if ( name!=NULL )

+		fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix);

+	else

+		fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum);

+	if ( name!=NULL ) {

+		fprintf(ErrFile, "SetWordType %s%s[%d] = {",

+				name,

+                suffix,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+	}

+	else {

+		fprintf(ErrFile, "SetWordType zzerr%d[%d] = {",

+				esetnum,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+	}

+	while ( p < endp )

+	{

+		if ( e > 1 ) fprintf(ErrFile, ", ");

+		DumpIntAsChars(ErrFile, "0x%x", *p++);

+		if ( e == 3 )

+		{

+			DAWDLE;

+			if ( p < endp ) fprintf(ErrFile, ",");

+			fprintf(ErrFile, "\n\t");

+			e=1;

+		}

+		else e++;

+	}

+	fprintf(ErrFile, "};\n");

+

+	return esetnum;

+}

+

+int

+#ifdef __USE_PROTOS

+DefErrSetForC( set *f, int subst, char *name )

+#else

+DefErrSetForC( f, subst, name )

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+#endif

+{

+  return DefErrSetForC1(0,f,subst,name, "_set");

+}

+

+/* Define a new error set.  WARNING...set-implementation dependent;

+ * Only used when -CC on.

+ */

+

+int

+#ifdef __USE_PROTOS

+DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix )

+#else

+DefErrSetForCC1(nilOK, f, subst, name, suffix )

+int nilOK;          /* MR13 */

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+const char *suffix;

+#endif

+{

+	unsigned *p, *endp;

+	int e=1;

+

+    if (!nilOK)	require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?");

+

+	if ( subst ) SubstErrorClass(f);

+	p = f->setword;

+	endp = &(f->setword[f->n]);

+	esetnum++;

+

+	if ( name!=NULL ) {

+		fprintf(Parser_h, "\tstatic SetWordType %s%s[%d];\n", name, suffix,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+		fprintf(Parser_c, "SetWordType %s::%s%s[%d] = {",

+				CurrentClassName,

+				name,

+				suffix,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+	}

+	else {

+		fprintf(Parser_c, "SetWordType %s::err%d[%d] = {",

+				CurrentClassName,

+				esetnum,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+		fprintf(Parser_h, "\tstatic SetWordType err%d[%d];\n", esetnum,

+				NumWords(TokenNum-1)*sizeof(unsigned));

+	}

+

+	while ( p < endp )

+	{

+		if ( e > 1 ) fprintf(Parser_c, ", ");

+		DumpIntAsChars(Parser_c, "0x%x", *p++);

+		if ( e == 3 )

+		{

+			if ( p < endp ) fprintf(Parser_c, ",");

+			fprintf(Parser_c, "\n\t");

+			e=1;

+		}

+		else e++;

+	}

+	fprintf(Parser_c, "};\n");

+

+	return esetnum;

+}

+

+int

+#ifdef __USE_PROTOS

+DefErrSetForCC( set *f, int subst, char *name )

+#else

+DefErrSetForCC( f, subst, name )

+set *f;

+int subst;			/* should be substitute error classes? */

+char *name;

+#endif

+{

+  return DefErrSetForCC1(0,f,subst,name, "_set");

+}

+

+void

+#ifdef __USE_PROTOS

+GenParser_c_Hdr(void)

+#else

+GenParser_c_Hdr()

+#endif

+{

+	int i,j;

+    TermEntry   *te;

+    char * hasAkaName = NULL;									/* MR23 */

+

+	hasAkaName = (char *) malloc(TokenNum+1);					/* MR23 */

+	require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n");		/* MR23 */

+	for (i = 0; i < TokenNum; i++) hasAkaName[i]='0';			/* MR23 */

+	hasAkaName[TokenNum] = 0;                                   /* MR23 */

+

+	fprintf(Parser_c, "/*\n");

+	fprintf(Parser_c, " * %s: P a r s e r  S u p p o r t\n", CurrentClassName);

+	fprintf(Parser_c, " *\n");

+	fprintf(Parser_c, " * Generated from:");

+	for (i=0; i<NumFiles; i++) fprintf(Parser_c, " %s", FileStr[i]);

+	fprintf(Parser_c, "\n");

+	fprintf(Parser_c, " *\n");

+	fprintf(Parser_c, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(Parser_c, " * Parr Research Corporation\n");

+	fprintf(Parser_c, " * with Purdue University Electrical Engineering\n");

+	fprintf(Parser_c, " * with AHPCRC, University of Minnesota\n");

+	fprintf(Parser_c, " * ANTLR Version %s\n", Version);

+	fprintf(Parser_c, " */\n\n");

+	

+  if ( FirstAction != NULL ) dumpAction(FirstAction,Parser_c, 0, -1, 0, 1);    /* MR11 MR15b */

+

+	fprintf(Parser_c, "#define ANTLR_VERSION	%s\n", VersionDef);

+

+	fprintf(Parser_c, "#include \"pcctscfg.h\"\n");

+	fprintf(Parser_c, "#include \"pccts_stdio.h\"\n");

+	fprintf(Parser_c, "#define ANTLR_SUPPORT_CODE\n");

+	if ( UserTokenDefsFile != NULL )

+	   fprintf(Parser_c, "#include %s\n", UserTokenDefsFile);

+	else

+	   fprintf(Parser_c, "#include \"%s\"\n", DefFileName);

+

+	fprintf(Parser_c, "#include \"%s.h\"\n\n", CurrentClassName);

+

+	fprintf(Parser_c, "const ANTLRChar *%s::tokenName(int tok) ",   /* MR1 */

+					CurrentClassName);                  	        /* MR1 */

+	fprintf(Parser_c, "  { return _token_tbl[tok]; }\n");	        /* MR1 */ /* MR10 */

+	/* Dump a Parser::tokens for each automaton */

+	fprintf(Parser_c, "\nconst ANTLRChar *%s::_token_tbl[]={\n",

+                                                 CurrentClassName); /* MR20 */

+	fprintf(Parser_c, "\t/* 00 */\t\"Invalid\"");

+

+	for (i=1; i<TokenNum-1; i++)

+	{

+		DAWDLE;

+		if ( i == EpToken ) continue;

+		/* remapped to invalid token? */

+		if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )

+		{

+			fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i);

+			continue;

+		}

+		if ( TokenString(i) != NULL ) {

+           te=(TermEntry *) hash_get(Tname,TokenString(i));                     /* MR11 */

+            if (te == NULL || te->akaString == NULL) {                          /* MR11 */

+  	   	      fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));

+            } else {

+			  hasAkaName[i] = '1';											    /* MR23 */

+  	   	      fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString);   /* MR11 */

+            }

+        }

+		else

+		{

+			/* look in all lexclasses for the reg expr */

+			for (j=0; j<NumLexClasses; j++)

+			{

+				lexmode(j);

+				if ( ExprString(i) != NULL )

+				{

+					fprintf(Parser_c, ",\n\t/* %02d */\t", i);

+					dumpExpr(Parser_c, ExprString(i));

+					break;

+				}

+			}

+			if ( j>=NumLexClasses )

+			{

+				if ( UserDefdTokens )

+				{

+					fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i);

+				}

+				else

+					fatal_internal(eMsgd("No label or expr for token %d",i));

+			}

+		}

+	}

+	fprintf(Parser_c, "\n};\n");

+

+	/* Build constructors */

+	fprintf(Parser_c, "\n%s::", CurrentClassName);

+	fprintf(Parser_c,	"%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%d)\n",

+						CurrentClassName,

+						(BaseClassName == NULL ? "ANTLRParser" : BaseClassName),

+						OutputLL_k,

+						FoundGuessBlk,

+						DemandLookahead,

+						NumWords(TokenNum-1)*sizeof(unsigned));

+	fprintf(Parser_c, "{\n");

+	fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n");

+    if (TraceGen) {

+      fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n");

+    } else {

+      fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n");

+    };

+	fprintf(Parser_c, "}\n\n");

+	free ( (void *) hasAkaName);

+}

+

+void

+#ifdef __USE_PROTOS

+GenParser_h_Hdr(void)

+#else

+GenParser_h_Hdr()

+#endif

+{

+	int i;

+

+	fprintf(Parser_h, "/*\n");

+	fprintf(Parser_h, " * %s: P a r s e r  H e a d e r \n", CurrentClassName);

+	fprintf(Parser_h, " *\n");

+	fprintf(Parser_h, " * Generated from:");

+	for (i=0; i<NumFiles; i++) fprintf(Parser_h, " %s", FileStr[i]);

+	fprintf(Parser_h, "\n");

+	fprintf(Parser_h, " *\n");

+	fprintf(Parser_h, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(Parser_h, " * Parr Research Corporation\n");

+	fprintf(Parser_h, " * with Purdue University Electrical Engineering\n");

+	fprintf(Parser_h, " * with AHPCRC, University of Minnesota\n");

+	fprintf(Parser_h, " * ANTLR Version %s\n", Version);

+	fprintf(Parser_h, " */\n\n");

+

+  if ( FirstAction != NULL ) dumpAction( FirstAction, Parser_h, 0, -1, 0, 1);         /* MR11 MR15b */

+

+	fprintf(Parser_h, "#ifndef %s_h\n", CurrentClassName);

+	fprintf(Parser_h, "#define %s_h\n\n", CurrentClassName);

+

+    fprintf(Parser_h, "#ifndef ANTLR_VERSION\n");

+    fprintf(Parser_h, "#define ANTLR_VERSION %s\n",VersionDef);

+    fprintf(Parser_h, "#endif\n\n");

+

+	if ( GenAST ) fprintf(Parser_h, "class ASTBase;\n");

+    if (TraceGen) {

+      fprintf(Parser_h,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+      fprintf(Parser_h,"#define zzTRACE_RULES\n");  /* MR20 */

+      fprintf(Parser_h,"#endif\n");                 /* MR22 */

+    };

+	fprintf(Parser_h, "#include \"%s\"\n\n", APARSER_H);

+

+	if ( HdrAction != NULL ) dumpAction( HdrAction, Parser_h, 0, -1, 0, 1);

+	

+/* MR10 */    if (ClassDeclStuff == NULL) {

+/* MR10 */  	fprintf(Parser_h, "class %s : public ANTLRParser {\n", CurrentClassName);

+/* MR10 */    } else {

+/* MR10 */      fprintf(Parser_h, "class %s %s {\n",CurrentClassName,ClassDeclStuff);

+/* MR10 */    };

+

+	fprintf(Parser_h, "public:\n");					          /* MR1 */

+	fprintf(Parser_h, "\tstatic  const ANTLRChar *tokenName(int tk);\n");/* MR1 */

+    fprintf(Parser_h, "\tenum { SET_SIZE = %i };\n",TokenNum-1);         /* MR21 */

+	fprintf(Parser_h, "protected:\n");

+	fprintf(Parser_h, "\tstatic const ANTLRChar *_token_tbl[];\n");     /* MR20 */

+	fprintf(Parser_h, "private:\n");

+}

+

+/* Currently, this is only used in !GenCC mode */

+void

+#ifdef __USE_PROTOS

+GenErrHdr( void )

+#else

+GenErrHdr( )

+#endif

+{

+	int i, j;

+    TermEntry   *te;

+

+	fprintf(ErrFile, "/*\n");

+	fprintf(ErrFile, " * A n t l r  S e t s / E r r o r  F i l e  H e a d e r\n");

+	fprintf(ErrFile, " *\n");

+	fprintf(ErrFile, " * Generated from:");

+	for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);

+	fprintf(ErrFile, "\n");

+	fprintf(ErrFile, " *\n");

+	fprintf(ErrFile, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(ErrFile, " * Parr Research Corporation\n");

+	fprintf(ErrFile, " * with Purdue University Electrical Engineering\n");

+	fprintf(ErrFile, " * With AHPCRC, University of Minnesota\n");

+	fprintf(ErrFile, " * ANTLR Version %s\n", Version);

+	fprintf(ErrFile, " */\n\n");

+

+  if ( FirstAction != NULL ) dumpAction( FirstAction, ErrFile, 0, -1, 0, 1);         /* MR11 MR15b */

+	

+  fprintf(ErrFile, "#define ANTLR_VERSION	%s\n", VersionDef);

+

+  fprintf(ErrFile, "#include \"pcctscfg.h\"\n");

+	fprintf(ErrFile, "#include \"pccts_stdio.h\"\n");

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		fprintf(ErrFile, "#define %s %s\n", DefaultParserName, ParserName);

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		fprintf(ErrFile, "#include \"%s\"\n", RemapFileName);

+	if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );

+	if ( FoundGuessBlk )

+	{

+		fprintf(ErrFile, "#define ZZCAN_GUESS\n");

+		fprintf(ErrFile, "#include \"pccts_setjmp.h\"\n");

+	}

+    if (TraceGen) {

+      fprintf(ErrFile,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+      fprintf(ErrFile,"#define zzTRACE_RULES\n");  /* MR20 */

+      fprintf(ErrFile,"#endif\n");                 /* MR22 */

+    };

+

+	if ( OutputLL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);

+#ifdef DUM

+	if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));

+#endif

+	fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));

+	if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");

+	fprintf(ErrFile, "#include \"antlr.h\"\n");

+	if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n");

+			

+    if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile);

+	/* still need this one as it has the func prototypes */

+	fprintf(ErrFile, "#include \"%s\"\n", DefFileName);

+	fprintf(ErrFile, "#include \"dlgdef.h\"\n");

+	fprintf(ErrFile, "#include \"err.h\"\n\n");

+

+	/* Dump a zztokens for each automaton */

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+	{

+		fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1);

+	}

+	else

+	{

+		fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1);

+	}

+	fprintf(ErrFile, "\t/* 00 */\t\"Invalid\"");

+	for (i=1; i<TokenNum-1; i++)

+	{

+		DAWDLE;

+		if ( i == EpToken ) continue;

+		/* remapped to invalid token? */

+		if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )

+		{

+			fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i);

+			continue;

+		}

+		if ( TokenString(i) != NULL ) {

+            te=(TermEntry *) hash_get(Tname,TokenString(i));                     /* MR11 */

+            if (te == NULL || te->akaString == NULL) {                          /* MR11 */

+  			  fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));

+            } else {

+  			  fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString);    /* MR11 */

+            }

+        }

+		else

+		{

+			/* look in all lexclasses for the reg expr */

+			for (j=0; j<NumLexClasses; j++)

+			{

+				lexmode(j);

+				if ( ExprString(i) != NULL )

+				{

+					fprintf(ErrFile, ",\n\t/* %02d */\t", i);

+					dumpExpr(ErrFile, ExprString(i));

+					break;

+				}

+			}

+			if ( j>=NumLexClasses )

+			{

+				if ( UserDefdTokens )

+				{

+					fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i);

+				}

+				else

+					fatal_internal(eMsgd("No label or expr for token %d",i));

+			}

+		}

+	}

+	fprintf(ErrFile, "\n};\n");

+}

+

+void

+#ifdef __USE_PROTOS

+dumpExpr( FILE *f, char *e )

+#else

+dumpExpr( f, e )

+FILE *f;

+char *e;

+#endif

+{

+	while ( *e!='\0' )

+	{

+		if ( *e=='\\' && *(e+1)=='\\' )

+			{putc('\\', f); putc('\\', f); e+=2;}

+		else if ( *e=='\\' && *(e+1)=='"' )

+			{putc('\\', f); putc('"', f); e+=2;}

+		else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;}

+		else {putc(*e, f); e++;}

+	}

+}

+

+int

+#ifdef __USE_PROTOS

+isTermEntryTokClass(TermEntry *te)

+#else

+isTermEntryTokClass(te)

+TermEntry *te;

+#endif

+{

+	ListNode *t;

+	TCnode *p;

+	TermEntry *q;

+	char *tokstr;

+

+	if (tclasses == NULL) return 0;

+

+	for (t = tclasses->next; t!=NULL; t=t->next)

+	{

+		p = (TCnode *) t->elem;

+		tokstr = TokenString(p->tok);

+		lexmode(p->lexclass);	/* switch to lexclass where tokclass is defined */

+        q = (TermEntry *) hash_get(Tname, tokstr);

+		if (q == te) return 1;

+	}

+	return 0;

+}

diff --git a/Source/Pccts/antlr/build.c b/Source/Pccts/antlr/build.c
new file mode 100644
index 0000000..4eb3b02
--- /dev/null
+++ b/Source/Pccts/antlr/build.c
@@ -0,0 +1,813 @@
+/*

+ * build.c -- functions associated with building syntax diagrams.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <ctype.h>

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+

+#define SetBlk(g, t, approx, first_set_symbol) {         		        \

+			((Junction *)g.left)->jtype = t;					        \

+			((Junction *)g.left)->approx = approx;				        \

+			((Junction *)g.left)->pFirstSetSymbol = first_set_symbol;   \

+			((Junction *)g.left)->end = (Junction *) g.right;	        \

+			((Junction *)g.right)->jtype = EndBlk;}

+

+/* Add the parameter string 'parm' to the parms field of a block-type junction

+ * g.left points to the sentinel node on a block.  i.e. g.left->p1 points to

+ * the actual junction with its jtype == some block-type.

+ */

+void

+#ifdef __USE_PROTOS

+addParm( Node *p, char *parm )

+#else

+addParm( p, parm )

+Node *p;

+char *parm;

+#endif

+{

+	char *q = (char *) malloc( strlen(parm) + 1 );

+	require(p!=NULL, "addParm: NULL object\n");

+	require(q!=NULL, "addParm: unable to alloc parameter\n");

+

+	strcpy(q, parm);

+	if ( p->ntype == nRuleRef )

+	{

+		((RuleRefNode *)p)->parms = q;

+	}

+	else if ( p->ntype == nJunction )

+	{

+		((Junction *)p)->parm = q;	/* only one parameter allowed on subrules */

+	}

+	else fatal_internal("addParm: invalid node for adding parm");

+}

+

+/*

+ * Build an action node for the syntax diagram

+ *

+ * buildAction(ACTION) ::= --o-->ACTION-->o--

+ *

+ * Where o is a junction node.

+ */

+Graph

+#ifdef __USE_PROTOS

+buildAction( char *action, int file, int line, int is_predicate )

+#else

+buildAction( action, file, line, is_predicate )

+char *action;

+int file;

+int line;

+int is_predicate;

+#endif

+{

+	Junction *j1, *j2;

+	Graph g;

+	ActionNode *a;

+	require(action!=NULL, "buildAction: invalid action");

+	

+	j1 = newJunction();

+	j2 = newJunction();

+	a = newActionNode();

+	a->action = (char *) malloc( strlen(action)+1 );

+	require(a->action!=NULL, "buildAction: cannot alloc space for action\n");

+	strcpy(a->action, action);

+	j1->p1 = (Node *) a;

+	a->next = (Node *) j2;

+	a->is_predicate = is_predicate;

+

+    if (is_predicate) {

+        PredEntry   *predEntry;

+        char        *t;

+        char        *key;

+        char        *u;

+        int         inverted=0;

+

+        t=key=(char *)calloc(1,strlen(a->action)+1);

+

+        for (u=a->action; *u != '\0' ; u++) {

+          if (*u != ' ') {

+            if (t==key && *u=='!') {

+              inverted=!inverted;

+            } else {

+              *t++=*u;

+            };

+          };

+        };

+

+        *t='\0';

+

+

+        predEntry=(PredEntry *)hash_get(Pname,key);

+        a->predEntry=predEntry;

+        if (predEntry != NULL) a->inverted=inverted;

+    } else {

+/* MR12c */      char  *strStart=a->action;

+/* MR12c */      char  *strEnd;

+/* MR12c */      strEnd=strStart+strlen(strStart)-1;

+/* MR12c */      for ( ; strEnd >= strStart &&  isspace(*strEnd); strEnd--) *strEnd=0;

+/* MR12c */      while (*strStart != '\0' && isspace(*strStart)) strStart++;

+/* MR12c */      if (ci_strequ(strStart,"nohoist")) {

+/* MR12c */        a->noHoist=1;

+/* MR12c */      }

+	}

+

+	g.left = (Node *) j1; g.right = (Node *) j2;

+	a->file = file;

+	a->line = line;

+	a->rname = CurRule;     /* MR10 */

+	return g;

+}

+

+/*

+ * Build a token node for the syntax diagram

+ *

+ * buildToken(TOKEN) ::= --o-->TOKEN-->o--

+ *

+ * Where o is a junction node.

+ */

+Graph

+#ifdef __USE_PROTOS

+buildToken( char *text )

+#else

+buildToken( text )

+char *text;

+#endif

+{

+	Junction *j1, *j2;

+	Graph g;

+	TokNode *t;

+	require(text!=NULL, "buildToken: invalid token name");

+	

+	j1 = newJunction();

+	j2 = newJunction();

+	t = newTokNode();

+	t->altstart = CurAltStart;

+	if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );}

+	else {t->label=TRUE; t->token = addTname( text );}

+	j1->p1 = (Node *) t;

+	t->next = (Node *) j2;

+	g.left = (Node *) j1; g.right = (Node *) j2;

+	return g;

+}

+

+/*

+ * Build a wild-card node for the syntax diagram

+ *

+ * buildToken(TOKEN) ::= --o-->'.'-->o--

+ *

+ * Where o is a junction node.

+ */

+Graph

+#ifdef __USE_PROTOS

+buildWildCard( char *text )

+#else

+buildWildCard( text )

+char *text;

+#endif

+{

+	Junction *j1, *j2;

+	Graph g;

+	TokNode *t;

+	TCnode *w;

+	TermEntry *p;

+	require(text!=NULL, "buildWildCard: invalid token name");

+	

+	j1 = newJunction();

+	j2 = newJunction();

+	t = newTokNode();

+

+	/* If the ref a wild card, make a token class for it */

+	if ( Tnum(WildCardString) == 0 )

+	{

+		w = newTCnode;

+	  	w->tok = addTname( WildCardString );

+		set_orel(w->tok, &imag_tokens);

+		set_orel(w->tok, &tokclasses);

+		WildCardToken = w->tok;

+		require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL,

+				"hash table mechanism is broken");

+		p->classname = 1;	/* entry is class name, not token */

+		p->tclass = w;		/* save ptr to this tclass def */

+		list_add(&tclasses, (char *)w);

+	}

+	else {

+		p=(TermEntry *)hash_get(Tname, WildCardString);

+		require( p!= NULL, "hash table mechanism is broken");

+		w = p->tclass;

+	}

+

+	t->token = w->tok;

+	t->wild_card = 1;

+	t->tclass = w;

+

+	t->altstart = CurAltStart;

+	j1->p1 = (Node *) t;

+	t->next = (Node *) j2;

+	g.left = (Node *) j1; g.right = (Node *) j2;

+	return g;

+}

+

+void

+#ifdef __USE_PROTOS

+setUpperRange(TokNode *t, char *text)

+#else

+setUpperRange(t, text)

+TokNode *t;

+char *text;

+#endif

+{

+	require(t!=NULL, "setUpperRange: NULL token node");

+	require(text!=NULL, "setUpperRange: NULL token string");

+

+	if ( *text == '"' ) {t->upper_range = addTexpr( text );}

+	else {t->upper_range = addTname( text );}

+}

+

+/*

+ * Build a rule reference node of the syntax diagram

+ *

+ * buildRuleRef(RULE) ::= --o-->RULE-->o--

+ *

+ * Where o is a junction node.

+ *

+ * If rule 'text' has been defined already, don't alloc new space to store string.

+ * Set r->text to point to old copy in string table.

+ */

+Graph

+#ifdef __USE_PROTOS

+buildRuleRef( char *text )

+#else

+buildRuleRef( text )

+char *text;

+#endif

+{

+	Junction *j1, *j2;

+	Graph g;

+	RuleRefNode *r;

+	RuleEntry *p;

+	require(text!=NULL, "buildRuleRef: invalid rule name");

+	

+	j1 = newJunction();

+	j2 = newJunction();

+	r = newRNode();

+	r->altstart = CurAltStart;

+	r->assign = NULL;

+	if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str;

+	else r->text = mystrdup( text );

+	j1->p1  = (Node *) r;

+	r->next = (Node *) j2;

+	g.left = (Node *) j1; g.right = (Node *) j2;

+	return g;

+}

+

+/*

+ * Or two subgraphs into one graph via:

+ *

+ * Or(G1, G2) ::= --o-G1-o--

+ *                  |    ^

+ *					v    |

+ *                  o-G2-o

+ *

+ * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.

+ * If, however, the G1 altnum is 0, make it 1 and then

+ * make G2 altnum = G1 altnum + 1.

+ */

+Graph

+#ifdef __USE_PROTOS

+Or( Graph g1, Graph g2 )

+#else

+Or( g1, g2 )

+Graph g1;

+Graph g2;

+#endif

+{

+	Graph g;

+	require(g1.left != NULL, "Or: invalid graph");

+	require(g2.left != NULL && g2.right != NULL, "Or: invalid graph");

+

+	((Junction *)g1.left)->p2 = g2.left;

+	((Junction *)g2.right)->p1 = g1.right;

+	/* set altnums */

+	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;

+	((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1;

+	g.left = g2.left;

+	g.right = g1.right;

+	return g;

+}

+

+/*

+ * Catenate two subgraphs

+ *

+ * Cat(G1, G2) ::= --o-G1-o-->o-G2-o--

+ * Cat(NULL,G2)::= --o-G2-o--

+ * Cat(G1,NULL)::= --o-G1-o--

+ */

+Graph

+#ifdef __USE_PROTOS

+Cat( Graph g1, Graph g2 )

+#else

+Cat( g1, g2 )

+Graph g1;

+Graph g2;

+#endif

+{

+	Graph g;

+	

+	if ( g1.left == NULL && g1.right == NULL ) return g2;

+	if ( g2.left == NULL && g2.right == NULL ) return g1;

+	((Junction *)g1.right)->p1 = g2.left;

+	g.left = g1.left;

+	g.right = g2.right;

+	return g;

+}

+

+/*

+ * Make a subgraph an optional block

+ *

+ * makeOpt(G) ::= --o-->o-G-o-->o--

+ *                      | 	    ^

+ *						v  	    |

+ *					    o-------o

+ *

+ * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.

+ *

+ * The node on the far right is added so that every block owns its own

+ * EndBlk node.

+ */

+Graph

+#ifdef __USE_PROTOS

+makeOpt( Graph g1, int approx, char * pFirstSetSymbol )

+#else

+makeOpt( g1, approx, pFirstSetSymbol )

+Graph g1;

+int approx;

+char * pFirstSetSymbol;

+#endif

+{

+	Junction *j1,*j2,*p;

+	Graph g;

+	require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph");

+

+	j1 = newJunction();

+	j2 = newJunction();

+	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */

+

+    /*  MR21

+     *

+     *  There is code in genBlk which recognizes the node created

+     *  by emptyAlt() as a special case and bypasses it.  We don't

+     *  want this to happen for the optBlk.

+     */

+

+	g = emptyAlt3(); /* MR21 */

+	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;

+	((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1;

+	for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2)

+		{;}										/* find last alt */

+	p->p2 = g.left;								/* add optional alternative */

+	((Junction *)g.right)->p1 = (Node *)j2;		/* opt alt points to EndBlk */

+	g1.right = (Node *)j2;

+	SetBlk(g1, aOptBlk, approx, pFirstSetSymbol);

+	j1->p1 = g1.left;							/* add generic node in front */

+	g.left = (Node *) j1;

+	g.right = g1.right;

+	return g;

+}

+

+/*

+ * Make a graph into subblock

+ *

+ * makeBlk(G) ::= --o-->o-G-o-->o--

+ *

+ * The node on the far right is added so that every block owns its own

+ * EndBlk node.

+ */

+Graph

+#ifdef __USE_PROTOS

+makeBlk( Graph g1, int approx, char * pFirstSetSymbol )

+#else

+makeBlk( g1, approx, pFirstSetSymbol )

+Graph g1;

+int approx;

+char * pFirstSetSymbol;

+#endif

+{

+	Junction *j,*j2;

+	Graph g;

+	require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");

+

+	j = newJunction();

+	j2 = newJunction();

+	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */

+	g1.right = (Node *)j2;

+	SetBlk(g1, aSubBlk, approx, pFirstSetSymbol);

+	j->p1 = g1.left;							/* add node in front */

+	g.left = (Node *) j;

+	g.right = g1.right;

+

+	return g;

+}

+

+/*

+ * Make a subgraph into a loop (closure) block -- (...)*

+ *

+ * makeLoop(G) ::=       |---|

+ *					     v   |

+ *			   --o-->o-->o-G-o-->o--

+ *                   |           ^

+ *                   v           |

+ *					 o-----------o

+ *

+ * After making loop, always place generic node out front.  It becomes

+ * the start of enclosing block.  The aLoopBlk is the target of the loop.

+ *

+ * Loop blks have TWO EndBlk nodes--the far right and the node that loops back

+ * to the aLoopBlk node.  Node with which we can branch past loop == aLoopBegin and

+ * one which is loop target == aLoopBlk.

+ * The branch-past (initial) aLoopBegin node has end

+ * pointing to the last EndBlk node.  The loop-target node has end==NULL.

+ *

+ * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.

+ */

+Graph

+#ifdef __USE_PROTOS

+makeLoop( Graph g1, int approx, char * pFirstSetSymbol )

+#else

+makeLoop( g1, approx, pFirstSetSymbol)

+Graph g1;

+int approx;

+char * pFirstSetSymbol;

+#endif

+{

+	Junction *back, *front, *begin;

+	Graph g;

+	require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");

+

+	back = newJunction();

+	front = newJunction();

+	begin = newJunction();

+	g = emptyAlt3();

+	((Junction *)g1.right)->p2 = g1.left;		/* add loop branch to G */

+	((Junction *)g1.right)->p1 = (Node *) back;	/* add node to G at end */

+	((Junction *)g1.right)->jtype = EndBlk;		/* mark 1st EndBlk node */

+	((Junction *)g1.left)->jtype = aLoopBlk;	/* mark 2nd aLoopBlk node */

+	((Junction *)g1.left)->end = (Junction *) g1.right;

+	((Junction *)g1.left)->lock = makelocks();

+	((Junction *)g1.left)->pred_lock = makelocks();

+	g1.right = (Node *) back;

+	begin->p1 = (Node *) g1.left;

+	g1.left = (Node *) begin;

+	begin->p2 = (Node *) g.left;				/* make bypass arc */

+	((Junction *)g.right)->p1 = (Node *) back;

+	SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol);

+	front->p1 = g1.left;						/* add node to front */

+	g1.left = (Node *) front;

+

+	return g1;

+}

+

+/*

+ * Make a subgraph into a plus block -- (...)+ -- 1 or more times

+ *

+ * makePlus(G) ::=	 |---|

+ *					 v   |

+ *			   --o-->o-G-o-->o--

+ *

+ * After making loop, always place generic node out front.  It becomes

+ * the start of enclosing block.  The aPlusBlk is the target of the loop.

+ *

+ * Plus blks have TWO EndBlk nodes--the far right and the node that loops back

+ * to the aPlusBlk node.

+ *

+ * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.

+ */

+Graph

+#ifdef __USE_PROTOS

+makePlus( Graph g1, int approx, char * pFirstSetSymbol)

+#else

+makePlus( g1, approx, pFirstSetSymbol)

+Graph g1;

+int approx;

+char * pFirstSetSymbol;

+#endif

+{

+	int has_empty_alt_already = 0;

+	Graph g;

+	Junction *j2, *j3, *first_alt;

+	Junction *last_alt=NULL, *p;

+	require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");

+

+	first_alt = (Junction *)g1.left;

+	j2 = newJunction();

+	j3 = newJunction();

+	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;

+	((Junction *)g1.right)->p2 = g1.left;		/* add loop branch to G */

+	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */

+	((Junction *)g1.right)->jtype = EndBlk;		/* mark 1st EndBlk node */

+	g1.right = (Node *) j2;

+	SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol);

+	((Junction *)g1.left)->lock = makelocks();

+	((Junction *)g1.left)->pred_lock = makelocks();

+	j3->p1 = g1.left;							/* add node to front */

+	g1.left = (Node *) j3;

+

+	/* add an optional branch which is the "exit" branch of loop */

+	/* FIRST, check to ensure that there does not already exist

+	 * an optional path.

+	 */

+	/* find last alt */

+	for(p=first_alt; p!=NULL; p=(Junction *)p->p2)

+	{

+		if ( p->p1->ntype == nJunction &&

+			 p->p1!=NULL &&

+			 ((Junction *)p->p1)->jtype==Generic &&

+			 ((Junction *)p->p1)->p1!=NULL &&

+			 ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )

+		{

+			has_empty_alt_already = 1;

+		}

+		last_alt = p;

+	}

+	if ( !has_empty_alt_already )

+	{

+		require(last_alt!=NULL, "last_alt==NULL; bad (..)+");

+		g = emptyAlt();

+		last_alt->p2 = g.left;

+		((Junction *)g.right)->p1 = (Node *) j2;

+

+		/* make sure lookahead computation ignores this alt for

+		* FIRST("(..)+"); but it's still used for computing the FIRST

+		* of each alternative.

+		*/

+		((Junction *)g.left)->ignore = 1;

+	}

+

+	return g1;

+}

+

+/*

+ * Return an optional path:  --o-->o--

+ */

+

+Graph

+#ifdef __USE_PROTOS

+emptyAlt( void )

+#else

+emptyAlt( )

+#endif

+{

+	Junction *j1, *j2;

+	Graph g;

+

+	j1 = newJunction();

+	j2 = newJunction();

+	j1->p1 = (Node *) j2;

+	g.left = (Node *) j1;

+	g.right = (Node *) j2;

+	

+	return g;

+}

+

+/*  MR21

+ *

+ *  There is code in genBlk which recognizes the node created

+ *  by emptyAlt() as a special case and bypasses it.  We don't

+ *  want this to happen for the optBlk.

+ */

+

+Graph

+#ifdef __USE_PROTOS

+emptyAlt3( void )

+#else

+emptyAlt3( )

+#endif

+{

+	Junction *j1, *j2, *j3;

+	Graph g;

+

+	j1 = newJunction();

+	j2 = newJunction();

+    j3 = newJunction();

+	j1->p1 = (Node *) j2;

+	j2->p1 = (Node *) j3;

+	g.left = (Node *) j1;

+	g.right = (Node *) j3;

+	

+	return g;

+}

+

+/* N o d e  A l l o c a t i o n */

+

+TokNode *

+#ifdef __USE_PROTOS

+newTokNode( void )

+#else

+newTokNode( )

+#endif

+{

+	static TokNode *FreeList = NULL;

+	TokNode *p, *newblk;

+

+	if ( FreeList == NULL )

+	{

+		newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));

+		if ( newblk == NULL )

+			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));

+		for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)

+		{

+			p->next = (Node *)FreeList;	/* add all new token nodes to FreeList */

+			FreeList = p;

+		}

+	}

+	p = FreeList;

+	FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */

+	p->next = NULL;						/* NULL the ptr we used */

+    memset( (char *) p, 0, sizeof(TokNode));        /* MR10 */

+	p->ntype = nToken;

+	p->rname = CurRule;

+	p->file = CurFile;

+	p->line = zzline;

+	p->altstart = NULL;

+

+	return p;

+}

+

+RuleRefNode *

+#ifdef __USE_PROTOS

+newRNode( void )

+#else

+newRNode( )

+#endif

+{

+	static RuleRefNode *FreeList = NULL;

+	RuleRefNode *p, *newblk;

+

+	if ( FreeList == NULL )

+	{

+		newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));

+		if ( newblk == NULL )

+			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));

+		for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)

+		{

+			p->next = (Node *)FreeList;	/* add all new rref nodes to FreeList */

+			FreeList = p;

+		}

+	}

+	p = FreeList;

+	FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */

+	p->next = NULL;						/* NULL the ptr we used */

+    memset( (char *) p, 0, sizeof(RuleRefNode));        /* MR10 */

+	p->ntype = nRuleRef;

+	p->rname = CurRule;

+	p->file = CurFile;

+	p->line = zzline;

+	p->astnode = ASTinclude;

+	p->altstart = NULL;

+	

+	return p;

+}

+

+static int junctionSeqNumber=0;         /* MR10 */

+

+Junction *

+#ifdef __USE_PROTOS

+newJunction( void )

+#else

+newJunction( )

+#endif

+{

+	static Junction *FreeList = NULL;

+	Junction *p, *newblk;

+

+	if ( FreeList == NULL )

+	{

+		newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));

+		if ( newblk == NULL )

+			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));

+		for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)

+		{

+			p->p1 = (Node *)FreeList;	/* add all new Junction nodes to FreeList */

+			FreeList = p;

+		}

+	}

+	p = FreeList;

+	FreeList = (Junction *)FreeList->p1;/* remove a Junction node */

+	p->p1 = NULL;						/* NULL the ptr we used */

+    memset( (char *) p, 0, sizeof(Junction));       /* MR10 */

+	p->ntype = nJunction;

+	p->visited = 0;

+	p->jtype = Generic;

+	p->rname = CurRule;

+	p->file = CurFile;

+	p->line = zzline;

+	p->exception_label = NULL;

+	p->fset = (set *) calloc(CLL_k+1, sizeof(set));

+	require(p->fset!=NULL, "cannot allocate fset in newJunction");

+    p->seq=++junctionSeqNumber;     /* MR10 */

+

+	return p;

+}

+

+ActionNode *

+#ifdef __USE_PROTOS

+newActionNode( void )

+#else

+newActionNode( )

+#endif

+{

+	static ActionNode *FreeList = NULL;

+	ActionNode *p, *newblk;

+

+	if ( FreeList == NULL )

+	{

+		newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));

+		if ( newblk == NULL )

+			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));

+		for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)

+		{

+			p->next = (Node *)FreeList;	/* add all new Action nodes to FreeList */

+			FreeList = p;

+		}

+	}

+	p = FreeList;

+	FreeList = (ActionNode *)FreeList->next;/* remove an Action node */

+    memset( (char *) p, 0, sizeof(ActionNode));     /* MR10 */

+	p->ntype = nAction;

+	p->next = NULL;						/* NULL the ptr we used */

+	p->done = 0;

+	p->pred_fail = NULL;

+	p->guardpred = NULL;

+    p->ampersandPred = NULL;

+	return p;

+}

+

+/*

+ * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.

+ * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.

+ * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.

+ *

+ * if ( lock[k]==TRUE ) then we have been here before looking for k tokens

+ * of lookahead.

+ */

+char *

+#ifdef __USE_PROTOS

+makelocks( void )

+#else

+makelocks( )

+#endif

+{

+	char *p = (char *) calloc(CLL_k+1, sizeof(char));

+	require(p!=NULL, "cannot allocate lock array");

+	

+	return p;

+}

+

+#if 0

+** #ifdef __USE_PROTOS

+** void my_memset(char *p,char value,int count)

+** #else

+** void my_memset(p,value,count)

+**   char      *p;

+**   char      value;

+**   int       count;

+** #endif

+** {

+**    int      i;

+**

+**    for (i=0; i<count; i++) {

+**     p[i]=value;

+**   };

+** }

+#endif

diff --git a/Source/Pccts/antlr/build.xml b/Source/Pccts/antlr/build.xml
new file mode 100644
index 0000000..7ea7458
--- /dev/null
+++ b/Source/Pccts/antlr/build.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK antlr Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="antlr"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <target name="init">

+		<condition property="CheckDepends">

+		  <uptodate targetfile="${WORKSPACE}/Tools/bin/antlr.exe">

+			  <srcfiles dir="." includes="*.c *.h *.g"/>

+			</uptodate>

+		</condition>

+		<if>

+		  <equals arg1="${CheckDepends}" arg2="true"/>

+			<then>

+				<echo message="Executable, antlr.exe, is up to date."/>

+			</then>

+      <else>

+        <echo message="Building the EDK Pccts Tool: ${ToolName}"/>

+      </else>

+		</if>

+  </target>

+

+  <target name="GenTool" depends="init" unless="CheckDepends">

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="TRUE">

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="-f AntlrMS.mak"/>

+    		</exec>

+		  </then>

+	  	<elseif>

+        <istrue value="${cygwin}"/>

+		    <then>

+    	    <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">

+	      	  <arg line="-f makefile.cygwin"/>

+    	  	</exec>

+		    </then>

+      </elseif>

+      <elseif>

+        <istrue value="${gcc}"/>

+        <then>

+    	    <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">

+	      	  <arg line="-s"/>

+	      	  <arg line="-f makefile BIN_DIR=${BIN_DIR}"/>

+    	  	</exec>

+        </then>

+		  </elseif>

+		</if>

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+	</target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="TRUE">

+	    	  <arg line="/C"/>

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="-f AntlrMS.mak clean"/>

+    		</exec>

+		  </then>

+    <elseif>

+      <istrue value="${cygwin}"/>

+      <then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">

+	    	  <arg line="-f makefile.cygwin clean"/>

+    		</exec>

+      </then>

+		</elseif>

+		<elseif>

+      <istrue value="${gcc}"/>

+      <then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">

+	      	  <arg line="-s"/>

+	    	  <arg line="-f makefile clean"/>

+    		</exec>

+      </then>

+		</elseif>

+		</if>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="FALSE">

+	    	  <arg line="/C"/>

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="/f AntlrMS.mak clean"/>

+    		</exec>

+		  </then>

+		<elseif>

+      <istrue value="${cygwin}"/>

+			<then>

+        <echo message="Building antlr with cygwin gcc"/>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="FALSE">

+	      	<arg line="-s"/>

+	    	  <arg line="-f makefile.cygwin clean"/>

+    		</exec>

+		  </then>

+		</elseif>

+		<elseif>

+      <istrue value="${gcc}"/>

+      <then>

+        <echo message="Building antlr with gcc"/>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="FALSE">

+	      	<arg line="-s"/>

+	    	  <arg line="-f makefile clean"/>

+    		</exec>

+      </then>

+		</elseif>

+		</if>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/Pccts/antlr/dumpcycles.c b/Source/Pccts/antlr/dumpcycles.c
new file mode 100644
index 0000000..8156159
--- /dev/null
+++ b/Source/Pccts/antlr/dumpcycles.c
@@ -0,0 +1,67 @@
+#include <stdio.h>

+#include <ctype.h>

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+

+void 

+#ifdef __USE_PROTOS

+dumpcycles(void)

+#else

+dumpcycles()

+#endif

+{

+  Cycle         *c;

+  CacheEntry    *f;

+  ListNode      *p;

+  int           i=0;

+  int           k;

+  int           degree;

+

+  for (k=1; k <= CLL_k; k++) {

+    if (Cycles[k] == NULL) continue;

+

+    for (p = Cycles[k]->next; p!=NULL; p=p->next) {

+  	  c = (Cycle *) p->elem;

+      degree=set_deg(c->cyclicDep);

+	  fprintf(stderr,"Cycle %d: (degree %d) %s -->\n", i++, degree, RulePtr[c->croot]->rname);

+      fprintf(stderr,"    *self*\n");

+      MR_dumpRuleSet(c->cyclicDep);

+      fprintf(stderr,"\n");

+	  f = (CacheEntry *)

+			hash_get(Fcache,Fkey(RulePtr[c->croot]->rname,'o',k));

+      if (f == NULL) {

+        fprintf(stderr,"    *** FOLLOW(%s) must be in cache but isn't ***\n",

+                                         RulePtr[c->croot]->rname);

+      };

+    };

+  };

+}

+

+void 

+#ifdef __USE_PROTOS

+dumpfostack(int k) 

+#else

+dumpfostack(k) 

+int k;

+#endif

+{

+  int   i=0;

+  int   *pi;

+

+  fprintf(stderr,"\n");

+  if (FoStack[k] == NULL) {

+    fprintf(stderr,"FoStack[%d] is null\n",k);

+  };

+  if (FoTOS[k] == NULL) {

+    fprintf(stderr,"FoTOS[%d] is null\n",k);

+  }

+  if (FoTOS[k] != NULL && FoStack[k] != NULL) {

+    for (pi=FoStack[k]; pi <= FoTOS[k]; pi++) {

+      i++;

+      fprintf(stderr,"#%d  rule %d  %s\n",i,*pi,RulePtr[*pi]->rname);

+    }

+  }

+}

diff --git a/Source/Pccts/antlr/dumpnode.c b/Source/Pccts/antlr/dumpnode.c
new file mode 100644
index 0000000..2a34c6f
--- /dev/null
+++ b/Source/Pccts/antlr/dumpnode.c
@@ -0,0 +1,423 @@
+#include <stdio.h>

+#include <ctype.h>

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+

+#ifdef __USE_PROTOS

+void dumpset1(set s)

+#else

+void dumpset1(s)

+  set   s;

+#endif

+{

+  if (set_nil(s)) {

+    fprintf(stderr,"{}");

+  } else {

+    s_fprT(stderr,s);

+  };

+}

+

+#ifdef __USE_PROTOS

+void dumpset(set s)

+#else

+void dumpset(s)

+  set   s;

+#endif

+{

+  dumpset1(s);

+  fprintf(stderr,"\n");

+}

+

+#ifdef __USE_PROTOS

+int isEndRule(Node * p)

+#else

+int isEndRule(p)

+  Node *    p;

+#endif

+{

+  int       result=0;

+  if ( p->ntype == nJunction &&

+       ( (Junction *) p)->jtype == EndRule) {

+    result=1;

+  };

+  return result;

+}

+

+#ifdef __USE_PROTOS

+void dumppred1(int depth,Predicate *p)

+#else

+void dumppred1(depth,p)

+  int           depth;

+  Predicate     *p;

+#endif

+{

+  int       i;

+  int       k;

+

+  for (i=0; i<depth ; i++) {

+    fprintf(stderr,"  ");

+  };

+  if (p->expr == PRED_AND_LIST ||

+      p->expr == PRED_OR_LIST) {

+    fprintf(stderr," %s", (p->expr == NULL ? "null expr" : p->expr));

+    if (p->inverted) fprintf(stderr," predicate inverted !");

+    if (p->redundant) {

+      fprintf(stderr," Redundant!");

+    };

+    if (p->isConst) fprintf(stderr," const %d !",p->constValue);

+    fprintf(stderr,"\n");

+  } else {

+    fprintf(stderr,"predicate k=%d",p->k);

+    k=set_int(p->completionSet);

+    if (k >= 0) {

+      fprintf(stderr," Incomplete Set=%d !",k);

+    };

+    k=set_int(p->completionTree);

+    if (k >= 0) {

+      fprintf(stderr," Incomplete Tree=%d !",k);

+    };

+    if (p->redundant) {

+      fprintf(stderr," Redundant!");

+    };

+    fprintf(stderr," \"%s\" (%x)", (p->expr == NULL ? "null expr" : p->expr) ,p);

+    if (p->source != NULL) {

+       fprintf(stderr,"line %d",p->source->line);

+    };

+    if (p->inverted) fprintf(stderr," predicate inverted !");

+    fprintf(stderr,"\n");

+    for (i=0; i<depth ; i++) {

+      fprintf(stderr,"  ");

+    };

+    fprintf(stderr,"scontext: ");

+    dumpset(p->scontext[1]);

+    for (i=0; i<depth ; i++) {

+      fprintf(stderr,"  ");

+    };

+    fprintf(stderr,"tcontext: ");

+    preorder(p->tcontext);

+    fprintf(stderr,"\n");

+  };

+  fprintf(stderr,"\n");

+  if (p->down != NULL) {

+    dumppred1(depth+1,p->down);

+  };

+  if (p->right != NULL) {

+    dumppred1(depth,p->right);

+  };

+}

+

+#ifdef __USE_PROTOS

+void dumppred(Predicate *p)

+#else

+void dumppred(p)

+  Predicate     *p;

+#endif

+{

+  fprintf(stderr,"---------------------------------\n");

+  dumppred1(0,p);

+  fprintf(stderr,"\n");

+}

+

+#ifdef __USE_PROTOS

+void dumppredtree(Predicate *p)

+#else

+void dumppredtree(p)

+  Predicate     *p;

+#endif

+{

+  fprintf(stderr,"predicate k=%d \"%s\" line %d\n",p->k,p->expr,p->source->line);

+  dumpset(p->scontext[1]);

+}

+

+#ifdef __USE_PROTOS

+void dumppredexpr(Predicate *p)

+#else

+void dumppredexpr(p)

+  Predicate     *p;

+#endif

+{

+  fprintf(stderr,"    pred expr \"%s\"\n",p->expr);

+}

+

+#ifdef __USE_PROTOS

+void dt(Tree *t)

+#else

+void dt(t)

+  Tree  *t;

+#endif

+{

+  MR_dumpTreeF(stderr,0,t,5);

+}

+

+#ifdef __USE_PROTOS

+void d(Node * p)

+#else

+void d(p)

+  Node *    p;

+#endif

+{

+

+  Junction      *j;

+  RuleRefNode   *r;

+  TokNode       *t;

+  ActionNode    *a;

+

+  if (p==NULL) {

+    fprintf(stderr,"dumpNode: Node is NULL");

+    return;

+  };

+

+  switch (p->ntype) {

+    case nJunction :

+      j = (Junction *) p;

+      fprintf(stderr, "Junction (#%d in rule %s line %d) ",j->seq,j->rname,j->line);

+      if (j->guess) fprintf(stderr,"guess block ");

+      switch (j->jtype ) {

+        case aSubBlk :

+          fprintf(stderr,"aSubBlk");

+          break;

+        case aOptBlk :

+          fprintf(stderr,"aOptBlk");

+          break;

+        case aLoopBegin :

+          fprintf(stderr,"aLoopBeginBlk");

+          break;

+        case aLoopBlk :

+          fprintf(stderr,"aLoopBlk");

+          break;

+        case aPlusBlk :

+          fprintf(stderr,"aPlusBlk");

+          break;

+        case EndBlk :

+          fprintf(stderr,"EndBlk");

+          break;

+        case RuleBlk :

+          fprintf(stderr,"RuleBlk");

+          break;

+        case Generic :

+          fprintf(stderr,"Generic");

+          break;

+        case EndRule :

+          fprintf(stderr,"EndRule");

+          break;

+      };

+      if (j->halt) fprintf(stderr,"  halt!");

+      if (j->p1) fprintf(stderr," p1 valid");

+      if (j->p2) {

+        if (j->p2->ntype == nJunction) {

+           fprintf(stderr," (p2=#%d)",( (Junction *) j->p2)->seq);

+        } else {

+           fprintf(stderr," (p2 valid)");

+        };

+      };

+	  if (j->ignore) fprintf(stderr, " ignore/plus-block-bypass");

+      if (j->fset != NULL && set_deg(*j->fset) != 0) {

+         fprintf(stderr,"\nfset:\n");

+         dumpset(*j->fset);

+      };

+      if (j->ftree != NULL) {

+         fprintf(stderr,"\nftree:\n");

+         preorder(j->ftree);

+      };

+      fprintf(stderr,"\n");

+      break;

+    case nRuleRef :

+       r = (RuleRefNode *) p;

+       fprintf(stderr, "RuleRefNode (in rule %s line %d) to rule %s\n", r->rname,r->line,r->text);

+       break;

+    case nToken :

+       t = (TokNode *) p;

+       fprintf(stderr, "TokNode (in rule %s line %d) token %s\n",t->rname,t->line,TerminalString(t->token));

+       break;

+    case nAction :

+       a =(ActionNode *) p;

+       if (a->is_predicate) {

+         fprintf(stderr, "Predicate (in rule %s line %d) %s",a->rname,a->line,a->action);

+         if (a->inverted) fprintf(stderr," action inverted !");

+         if (a->guardpred != NULL) {

+           fprintf(stderr," guarded");

+           dumppredexpr(a->guardpred);

+           if (a->ampersandPred) {

+             fprintf(stderr," \"&&\" style");

+           } else {

+             fprintf(stderr," \"=>\" style");

+           };

+         };

+         if (a->predEntry != NULL) fprintf(stderr," predEntry \"%s\" ",a->predEntry->str);

+         fprintf(stderr,"\n");

+       } else if (a->init_action) {

+         fprintf(stderr, "Init-Action (in rule %s line %d) %s\n",a->rname,a->line,a->action);

+       } else {

+         fprintf(stderr, "Action (in rule %s line %d) %s\n",a->rname,a->line,a->action);

+       };

+       break;

+   };

+}

+

+#ifdef __USE_PROTOS

+Node * dp1(Node * p)

+#else

+Node * dp1(p)

+  Node *    p;

+#endif

+{

+  Node  *result=NULL;

+

+  if (p->ntype == nJunction) {

+    result=( (Junction *) p )->p1;

+    d(result);

+  } else {

+    fprintf(stderr,"dp1: Not a Junction node");

+  };

+  return result;

+}

+

+#ifdef __USE_PROTOS

+Node * dp2(Node * p)

+#else

+Node * dp2(p)

+  Node *    p;

+#endif

+{

+  Node  *result=NULL;

+

+  if (p->ntype == nJunction) {

+    result=( (Junction *) p )->p2;

+    d(result);

+  } else {

+    fprintf(stderr,"dp2: Not a Junction node");

+  };

+  return result;

+}

+

+#ifdef __USE_PROTOS

+Node * dn(Node * p)

+#else

+Node * dn(p)

+  Node *    p;

+#endif

+

+{

+  Node  *result=NULL;

+

+  if (p->ntype == nRuleRef) {

+    result=( (RuleRefNode *)p )->next;

+  } else if (p->ntype == nAction) {

+    result=( (ActionNode *)p )->next;

+  } else if (p->ntype == nToken) {

+    result=( (TokNode *)p )->next;

+  } else {

+    fprintf(stderr,"No next field: Neither a RuleRefNode, ActionNode, nor TokNode");

+  };

+  if (result != NULL) d(result);

+  return result;

+}

+

+#ifdef __USE_PROTOS

+void df(Node * p)

+#else

+void df(p)

+  Node *    p;

+#endif

+{

+  int       count=0;

+  Node      *next;

+

+  fprintf(stderr,"\n#%d ",++count);

+  d(p);

+

+  for (next=p; next != NULL && !isEndRule(next) ; ) {

+    fprintf(stderr,"#%d ",++count);

+    if (next->ntype == nJunction) {

+      next=dp1(next);

+    } else {

+      next=dn(next);

+    };

+  };

+}

+

+#ifdef __USE_PROTOS

+Node * dfn(Node * p,int target)

+#else

+Node * dfn(p,target)

+  Node *    p;

+  int       target;

+#endif

+{

+  Node      *result=NULL;

+  int       count=0;

+  Node      *next;

+

+  fprintf(stderr,"#%d ",++count);

+  d(p);

+

+  for (next=p; next != NULL && !isEndRule(next) ; ) {

+    fprintf(stderr,"#%d ",++count);

+    if (next->ntype == nJunction) {

+      next=dp1(next);

+    } else {

+      next=dn(next);

+    };

+    if (count == target) {

+      result=next;

+      break;

+    };

+  };

+  return result;

+}

+

+

+static int findnodeMatch;

+

+#ifdef __USE_PROTOS

+Junction *findnode1(Node *n)

+#else

+Junction *findnode1(n)

+  Node  *n;

+#endif

+{

+   Node         *next;

+   Junction     *j;

+   Junction     *match;

+

+   if (n == NULL) return NULL;

+   if (n->ntype == nJunction) {

+     j=(Junction *) n;

+     if (j->seq == findnodeMatch) return j;

+     if (j->jtype == EndRule) return NULL;

+     if (j->jtype != RuleBlk && j->jtype != EndBlk) {

+       if (j->p2 != NULL && !j->ignore) {

+          match=findnode1(j->p2);

+          if (match != NULL) return match;

+       };

+     };

+   };

+   next=MR_advance(n);

+   return findnode1(next);

+}

+

+#ifdef __USE_PROTOS

+Junction *findnode(int match)

+#else

+Junction *findnode(match)

+  int   match;

+#endif

+{

+  Junction  *j;

+  Junction  *result=NULL;

+

+  findnodeMatch=match;

+

+  for (j=SynDiag; j != NULL; j=(Junction *)j->p2) {

+    require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block");

+    result=findnode1( (Node *) j);

+    if (result != NULL) break;

+  };

+  if (result != NULL) {

+    d( (Node *) result);

+  };

+  return result;

+}

diff --git a/Source/Pccts/antlr/egman.c b/Source/Pccts/antlr/egman.c
new file mode 100644
index 0000000..c8a633f
--- /dev/null
+++ b/Source/Pccts/antlr/egman.c
@@ -0,0 +1,328 @@
+/*

+ * egman.c

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33MR10

+ * 2001

+ *

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "proto.h"

+

+static ExceptionGroup **egArray=NULL;   /* ExceptionGroup by BlkLevel */

+static LabelEntry     **leArray=NULL;   /* LabelEntry by BlkLevel     */

+static Junction       **altArray=NULL;  /* start of alternates        */

+static int              arraySize=0;

+static int              highWater=0;

+static ExceptionGroup *lastEG=NULL;     /* used in altFixup()         */

+static int             lastBlkLevel=0;  /* used in altFixup()         */

+

+#ifdef __USE_PROTOS

+static void arrayCheck(void);

+#else

+static void arrayCheck();

+#endif

+

+/* Called to add an exception group for an alternative EG */

+

+#ifdef __USE_PROTOS

+void egAdd(ExceptionGroup * eg)

+#else

+void egAdd(eg)

+ExceptionGroup *eg;

+#endif

+{

+  int               i;

+

+  ExceptionGroup    *nextEG;

+  ExceptionGroup    *innerEG;

+

+  LabelEntry        *nextLE;

+  LabelEntry        *innerLE;

+

+  Junction          *nextAlt;

+  Junction          *innerAlt;

+

+  lastEG=eg;

+  lastBlkLevel=BlkLevel;

+

+  arrayCheck();

+  eg->pendingLink=egArray[BlkLevel];

+  egArray[BlkLevel]=eg;

+

+  /* EG for alternates already have their altID filled in      */

+

+  for (i=BlkLevel+1; i<=highWater ; i++) {

+    for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {

+      nextEG=innerEG->pendingLink;

+      innerEG->pendingLink=NULL;

+      innerEG->outerEG=eg;

+    };

+    egArray[i]=NULL;

+  };

+

+  /*

+   *  for patching up the LabelEntry you might use an EG for the

+   *  current alternative - unlike patching up an alternative EG

+   *    i.e. start the loop at BlkLevel rather than (BlkLevel+1)

+   *  fill it in only if the EG and the LE are for the very

+   *    same alternative if they're at the same BlkLevel

+   *  it's easier to leave the LE on this list (filled in) rather than

+   *    trying to selectively remove it.  It will eventually be

+   *    removed anyway when the BlkLevel gets small enough.

+   */

+

+  for (i=BlkLevel; i<=highWater ; i++) {

+    for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {

+      nextLE=innerLE->pendingLink;

+      if (BlkLevel != i ||

+        innerLE->curAltNum == CurAltNum_array[BlkLevel]) {

+        if (innerLE->outerEG == NULL) {

+          innerLE->outerEG=eg;

+        };

+      };

+    };

+    if (BlkLevel != i) leArray[i]=NULL;

+  };

+

+/*

+ * For the start of alternatives it is necessary to make a

+ * distinction between the exception group for the current

+ * alternative and the "fallback" EG for the block which

+ * contains the alternative

+ *

+ * The fallback outerEG is used to handle the case where

+ * no alternative of a block matches.  In that case the

+ * signal is "NoViableAlt" (or "NoSemViableAlt" and the

+ * generator needs the EG of the block CONTAINING the

+ * current one.

+ *

+ *      rule: ( ( ( a

+ *                | b

+ *                )

+ *              | c

+ *              )

+ *            | d

+ *            );

+ */

+

+  for (i=BlkLevel; i <= highWater ; i++) {

+    for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {

+      nextAlt=innerAlt->pendingLink;

+

+      /*  first fill in the EG for the current alternative         */

+      /*  but leave it on the list in order to get the fallback EG */

+      /*  if the EG is at the same LEVEL as the alternative then   */

+      /*    fill it in only if in the very same alternative        */

+      /*                                                           */

+      /*        rule: ( a                                          */

+      /*              | b                                          */

+      /*              | c  exception ...                           */

+      /*              )                                            */

+      /*                                                           */

+      /*  if the EG is outside the alternative (e.g. BlkLevel < i) */

+      /*    then it doesn't matter about the alternative           */

+      /*                                                           */

+      /*        rule: ( a                                          */

+      /*              | b                                          */

+      /*              | c                                          */

+      /*              )   exception ...                            */

+      /*                                                           */

+

+#if 0

+      printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n",

+        BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID);

+#endif

+      if (BlkLevel != i ||

+          innerAlt->curAltNum == CurAltNum_array[BlkLevel]) {

+        if (innerAlt->exception_label == NULL) {

+          innerAlt->exception_label=eg->altID;

+        };

+      };

+

+      /*  ocurs at a later pass then for the exception_label       */

+      /*  if an outerEG has been found then fill in the outer EG   */

+      /*  remove if from the list when the BlkLevel gets smaller   */

+

+      if (BlkLevel != i) {

+        if (innerAlt->outerEG == NULL) {

+          innerAlt->outerEG=eg;

+        };

+      };

+    };

+    if (BlkLevel != i) altArray[i]=NULL;

+  };

+}

+

+#ifdef __USE_PROTOS

+void leAdd(LabelEntry * le)

+#else

+void leAdd(le)

+LabelEntry *le;

+#endif

+

+{

+  arrayCheck();

+  le->pendingLink=leArray[BlkLevel];

+  le->curAltNum=CurAltNum_array[BlkLevel];

+  leArray[BlkLevel]=le;

+}

+

+#ifdef __USE_PROTOS

+void altAdd(Junction *alt)

+#else

+void altAdd(alt)

+Junction *alt;

+#endif

+

+{

+  arrayCheck();

+#if 0

+  printf("BlkLevel=%d CurAltNum=%d\n",

+            BlkLevel,CurAltNum_array[BlkLevel]);

+#endif

+  alt->curAltNum=CurAltNum_array[BlkLevel];

+  alt->pendingLink=altArray[BlkLevel];

+  altArray[BlkLevel]=alt;

+}

+

+static void 

+#ifdef __USE_PROTOS

+arrayCheck(void)

+#else

+arrayCheck()

+#endif

+{

+  ExceptionGroup    **egArrayNew;

+  LabelEntry        **leArrayNew;

+  Junction          **altArrayNew;

+  int               arraySizeNew;

+  int               i;

+

+  if (BlkLevel > highWater) highWater=BlkLevel;

+

+  if (BlkLevel >= arraySize) {

+    arraySizeNew=BlkLevel+5;	/* MR20 */

+    egArrayNew=(ExceptionGroup **)

+        calloc(arraySizeNew,sizeof(ExceptionGroup *));

+    leArrayNew=(LabelEntry **)

+        calloc(arraySizeNew,sizeof(LabelEntry *));

+    altArrayNew=(Junction **)

+        calloc(arraySizeNew,sizeof(Junction *));

+    for (i=0; i<arraySize ; i++) {

+      egArrayNew[i]=egArray[i];

+      leArrayNew[i]=leArray[i];

+      altArrayNew[i]=altArray[i];

+    };

+    arraySize=arraySizeNew;

+    if (egArray != NULL) free( (char *) egArray);

+    if (leArray != NULL) free( (char *) leArray);

+    if (altArray != NULL) free( (char *) altArray);

+    egArray=egArrayNew;

+    leArray=leArrayNew;

+    altArray=altArrayNew;

+  };

+}

+

+/* always call leFixup() BEFORE egFixup() */

+

+void 

+#ifdef __USE_PROTOS

+egFixup(void) 

+#else

+egFixup()

+#endif

+{

+  int               i;

+  ExceptionGroup    *nextEG;

+  ExceptionGroup    *innerEG;

+

+  for (i=1; i<=highWater ; i++) {

+    for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {

+      nextEG=innerEG->pendingLink;

+      innerEG->pendingLink=NULL;

+    };

+    egArray[i]=NULL;

+  };

+  lastEG=NULL;

+  lastBlkLevel=0;

+}

+

+/* always call leFixup() BEFORE egFixup() */

+

+#ifdef __USE_PROTOS

+void leFixup(void) 

+#else

+void leFixup() 

+#endif

+{

+

+  int               i;

+  LabelEntry        *nextLE;

+  LabelEntry        *innerLE;

+

+  for (i=BlkLevel; i<=highWater ; i++) {

+    for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {

+      nextLE=innerLE->pendingLink;

+      innerLE->pendingLink=NULL;

+    };

+    leArray[i]=NULL;

+  };

+}

+

+/* always call altFixup() BEFORE egFixup() */

+

+#ifdef __USE_PROTOS

+void altFixup(void)

+#else

+void altFixup() 

+#endif

+{

+

+  int               i;

+  Junction          *nextAlt;

+  Junction          *innerAlt;

+

+  for (i=BlkLevel; i<=highWater ; i++) {

+    for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {

+

+      /*  if an outerEG has been found then fill in the outer EG   */

+

+      if (lastBlkLevel <= i) {

+        if (innerAlt->outerEG == NULL) {

+          innerAlt->outerEG=lastEG;

+        };

+      };

+      nextAlt=innerAlt->pendingLink;

+      innerAlt->pendingLink=NULL;

+    };

+    altArray[i]=NULL;

+  };

+}

+

diff --git a/Source/Pccts/antlr/err.c b/Source/Pccts/antlr/err.c
new file mode 100644
index 0000000..ca23939
--- /dev/null
+++ b/Source/Pccts/antlr/err.c
@@ -0,0 +1,538 @@
+/*

+ * A n t l r  S e t s / E r r o r  F i l e  H e a d e r

+ *

+ * Generated from: antlr.g

+ *

+ * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001

+ * Parr Research Corporation

+ * with Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include "pcctscfg.h"

+#include "set.h"

+#include <ctype.h>

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#define zzcr_attr(attr,tok,t)

+#define zzSET_SIZE 20

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "err.h"

+

+ANTLRChar *zztokens[157]={

+	/* 00 */	"Invalid",

+	/* 01 */	"Eof",

+	/* 02 */	"QuotedTerm",

+	/* 03 */	"\\n|\\r|\\r\\n",

+	/* 04 */	"\\(\\n|\\r|\\r\\n)",

+	/* 05 */	"\\~[]",

+	/* 06 */	"~[\\n\\r\"\\]+",

+	/* 07 */	"\"",

+	/* 08 */	"\\n|\\r|\\r\\n",

+	/* 09 */	"\\(\\n|\\r|\\r\\n)",

+	/* 10 */	"\\~[]",

+	/* 11 */	"~[\\n\\r\"\\]+",

+	/* 12 */	"'",

+	/* 13 */	"\\n|\\r|\\r\\n",

+	/* 14 */	"\\~[]",

+	/* 15 */	"~[\\n\\r'\\]+",

+	/* 16 */	"\\*/",

+	/* 17 */	"\\*",

+	/* 18 */	"\\n|\\r|\\r\\n",

+	/* 19 */	"~[\\n\\r\\*]+",

+	/* 20 */	"\\*/",

+	/* 21 */	"\\*",

+	/* 22 */	"\\n|\\r|\\r\\n",

+	/* 23 */	"~[\\n\\r\\*]+",

+	/* 24 */	"\\n|\\r|\\r\\n",

+	/* 25 */	"~[\\n\\r]+",

+	/* 26 */	"\\n|\\r|\\r\\n",

+	/* 27 */	"~[\\n\\r]+",

+	/* 28 */	"\\n|\\r|\\r\\n",

+	/* 29 */	"~[\\n\\r]+",

+	/* 30 */	"\\*/",

+	/* 31 */	"\\*",

+	/* 32 */	"\\n|\\r|\\r\\n",

+	/* 33 */	"~[\\n\\r\\*]+",

+	/* 34 */	"Action",

+	/* 35 */	"Pred",

+	/* 36 */	"PassAction",

+	/* 37 */	"consumeUntil\\( [\\ \\t]* \\{~[\\}]+\\} [\\ \\t]* \\)",

+	/* 38 */	"consumeUntil\\( ~[\\)]+ \\)",

+	/* 39 */	"\\n|\\r|\\r\\n",

+	/* 40 */	"\\>",

+	/* 41 */	"$",

+	/* 42 */	"$$",

+	/* 43 */	"$\\[\\]",

+	/* 44 */	"$\\[",

+	/* 45 */	"$[0-9]+",

+	/* 46 */	"$[0-9]+.",

+	/* 47 */	"$[0-9]+.[0-9]+",

+	/* 48 */	"$[_a-zA-Z][_a-zA-Z0-9]*",

+	/* 49 */	"#0",

+	/* 50 */	"#\\[\\]",

+	/* 51 */	"#\\(\\)",

+	/* 52 */	"#[0-9]+",

+	/* 53 */	"#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)",

+	/* 54 */	"#line ~[\\n\\r]* (\\n|\\r|\\r\\n)",

+	/* 55 */	"#[_a-zA-Z][_a-zA-Z0-9]*",

+	/* 56 */	"#\\[",

+	/* 57 */	"#\\(",

+	/* 58 */	"#",

+	/* 59 */	"\\)",

+	/* 60 */	"\\[",

+	/* 61 */	"\\(",

+	/* 62 */	"\\\\]",

+	/* 63 */	"\\\\)",

+	/* 64 */	"\\>",

+	/* 65 */	"'",

+	/* 66 */	"\"",

+	/* 67 */	"\\$",

+	/* 68 */	"\\#",

+	/* 69 */	"\\(\\n|\\r|\\r\\n)",

+	/* 70 */	"\\~[\\]\\)>$#]",

+	/* 71 */	"/",

+	/* 72 */	"/\\*",

+	/* 73 */	"\\*/",

+	/* 74 */	"//",

+	/* 75 */	"~[\\n\\r\\)\\(\\$#\\>\\]\\[\"'/]+",

+	/* 76 */	"[\\t\\ ]+",

+	/* 77 */	"\\n|\\r|\\r\\n",

+	/* 78 */	"\\[",

+	/* 79 */	"\\<\\<",

+	/* 80 */	"\"",

+	/* 81 */	"/\\*",

+	/* 82 */	"\\*/",

+	/* 83 */	"//",

+	/* 84 */	"#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)",

+	/* 85 */	"#line ~[\\n\\r]* (\\n|\\r|\\r\\n)",

+	/* 86 */	"\\>\\>",

+	/* 87 */	"WildCard",

+	/* 88 */	"\\@",

+	/* 89 */	"LABEL",

+	/* 90 */	"grammar-element",

+	/* 91 */	"meta-symbol",

+	/* 92 */	"Pragma",

+	/* 93 */	"FirstSetSymbol",

+	/* 94 */	"{\\}#header",

+	/* 95 */	"{\\}#first",

+	/* 96 */	"{\\}#parser",

+	/* 97 */	"{\\}#tokdefs",

+	/* 98 */	"\\}",

+	/* 99 */	"class",

+	/* 100 */	"NonTerminal",

+	/* 101 */	"TokenTerm",

+	/* 102 */	"\\{",

+	/* 103 */	"!",

+	/* 104 */	"\\<",

+	/* 105 */	"\\>",

+	/* 106 */	":",

+	/* 107 */	";",

+	/* 108 */	"{\\}#lexaction",

+	/* 109 */	"{\\}#lexmember",

+	/* 110 */	"{\\}#lexprefix",

+	/* 111 */	"{\\}#pred",

+	/* 112 */	"\\|\\|",

+	/* 113 */	"&&",

+	/* 114 */	"\\(",

+	/* 115 */	"\\)",

+	/* 116 */	"{\\}#lexclass",

+	/* 117 */	"{\\}#errclass",

+	/* 118 */	"{\\}#tokclass",

+	/* 119 */	"..",

+	/* 120 */	"{\\}#token",

+	/* 121 */	"=",

+	/* 122 */	"[0-9]+",

+	/* 123 */	"\\|",

+	/* 124 */	"\\~",

+	/* 125 */	"^",

+	/* 126 */	"approx",

+	/* 127 */	"LL\\(1\\)",

+	/* 128 */	"LL\\(2\\)",

+	/* 129 */	"\\*",

+	/* 130 */	"\\+",

+	/* 131 */	"?",

+	/* 132 */	"=>",

+	/* 133 */	"exception",

+	/* 134 */	"default",

+	/* 135 */	"catch",

+	/* 136 */	"{\\}#[A-Za-z0-9_]*",

+	/* 137 */	"[\\t\\ ]+",

+	/* 138 */	"\\n|\\r|\\r\\n",

+	/* 139 */	"//",

+	/* 140 */	"/\\*",

+	/* 141 */	"#ifdef",

+	/* 142 */	"#if",

+	/* 143 */	"#ifndef",

+	/* 144 */	"#else",

+	/* 145 */	"#endif",

+	/* 146 */	"#undef",

+	/* 147 */	"#import",

+	/* 148 */	"ID",

+	/* 149 */	"#define",

+	/* 150 */	"INT",

+	/* 151 */	"enum",

+	/* 152 */	"\\{",

+	/* 153 */	"=",

+	/* 154 */	",",

+	/* 155 */	"\\}",

+	/* 156 */	";"

+};

+SetWordType zzerr1[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr2[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xf3,

+	0xbf,0xff,0xff,0xff, 0xff,0xff,0xff,0x1f};

+SetWordType zzerr3[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfb,

+	0x3b,0xf7,0xf7,0xc7, 0xff,0xff,0xff,0x1f};

+SetWordType zzerr4[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x80,0x7,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType setwd1[157] = {0x0,0x50,0xa0,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x6a,0x20,0xa0,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x0,0x0,0x20,0x20,0x21,

+	0x21,0x21,0x21,0x6e,0x6e,0x64,0x20,0x0,

+	0x20,0xa0,0xa0,0xa0,0x20,0x6a,0x6a,0x6a,

+	0x6e,0x20,0x20,0x20,0x20,0x66,0x6e,0x6e,

+	0x20,0x66,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

+	0x20,0x20,0x20,0x20,0x20,0x20};

+SetWordType zzerr5[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr6[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x7,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr7[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x6,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr8[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x4,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr9[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf0,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType setwd2[157] = {0x0,0xf8,0x6,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xf8,0x0,0x1,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xf8,0xf8,0xf8,0x0,0x0,

+	0x0,0x1,0x2,0x6,0x0,0xf8,0xf8,0xf8,

+	0xf8,0x0,0x0,0x0,0x0,0xf8,0xf8,0xf8,

+	0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0xe8,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr10[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0xbc,0xf8,0x74,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr11[20] = {0x0,0x0,0x0,0x0, 0x8,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr12[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr13[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType setwd3[157] = {0x0,0xfa,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xfa,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xfa,0xfa,0xfa,0x5,0x0,

+	0x5,0x0,0x0,0x0,0xe2,0xfa,0xfa,0xfa,

+	0xfa,0xc0,0x80,0x5,0xe0,0xfa,0xfa,0xfa,

+	0x0,0xfa,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0xfa,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr14[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr15[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr16[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr17[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr18[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x24,0x0,0x80,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr19[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr20[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x74,0x3, 0x20,0x0,0x0,0x0};

+SetWordType zzerr21[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x70,0x3, 0x20,0x0,0x0,0x0};

+SetWordType setwd4[157] = {0x0,0xe5,0xda,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xe5,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xed,0xe5,0xe7,0x1a,0x0,

+	0x0,0x0,0x0,0x0,0xc0,0xe5,0xe5,0xe5,

+	0xe5,0x0,0x0,0x0,0x0,0xe5,0xe5,0xe5,

+	0x0,0xe5,0x40,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0xe5,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr22[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x3c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr23[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr24[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr25[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};

+SetWordType zzerr26[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType setwd5[157] = {0x0,0x1f,0xc1,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xdf,0xc0,0xc0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0xc0,0x0,0xc0,0x0,0x0,0xc0,0xc0,0x0,

+	0x0,0x0,0x0,0x7f,0x1f,0xdf,0xc0,0xc0,

+	0x0,0x0,0xc0,0x0,0x67,0x1f,0x1f,0x1f,

+	0x1f,0x0,0x0,0xc0,0x60,0x1f,0x1f,0x1f,

+	0x0,0x1f,0x0,0x0,0x40,0xc0,0x0,0x0,

+	0x0,0x0,0xc0,0xc0,0x0,0x0,0x5f,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr27[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x0,0x0,0x0,0x10, 0x0,0x0,0x0,0x0};

+SetWordType zzerr28[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x2,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr29[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr30[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,

+	0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0};

+SetWordType zzerr31[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,

+	0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};

+SetWordType zzerr32[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr33[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType setwd6[157] = {0x0,0x0,0xfd,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0xfd,0x60,0xe9,0x0,0x0,0xe1,0xe1,0x0,

+	0x0,0x0,0x0,0xe2,0x0,0xfd,0xfd,0xe1,

+	0x20,0x0,0xe1,0x0,0xe2,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xe1,0xe2,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0xe2,0xe0,0x20,0x0,

+	0x0,0x0,0xe1,0xe1,0x0,0x0,0xe2,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr34[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,

+	0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0};

+SetWordType zzerr35[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,

+	0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};

+SetWordType zzerr36[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr37[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xc,

+	0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};

+SetWordType zzerr38[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x84,0x9,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr39[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr40[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x9,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr41[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr42[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType setwd7[157] = {0x0,0x0,0xdf,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xdf,0xdf,0xff,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0xdf,0x3,0xdf,0x0,0x0,0xdf,0xdf,0x0,

+	0x0,0x0,0x0,0xdf,0x0,0xdf,0xdf,0xdf,

+	0x1,0x30,0xdf,0x0,0xdf,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xdf,0xdf,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0xdf,0xdf,0x1,0x0,

+	0x0,0x0,0xdf,0xdf,0x0,0x0,0xdf,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr43[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr44[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xc0, 0x1,0x0,0x0,0x0};

+SetWordType zzerr45[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x30,

+	0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr46[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr47[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x20,

+	0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr48[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x2,0x0, 0x10,0x0,0x0,0x0};

+SetWordType zzerr49[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};

+SetWordType zzerr50[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x8,0xa,0x18, 0x30,0x0,0x0,0x0};

+SetWordType zzerr51[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x4,0x8,0x8,0x18, 0x28,0x0,0x0,0x0};

+SetWordType zzerr52[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr53[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType setwd8[157] = {0x0,0x0,0xe1,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0xe1,0x0,0xe1,0x0,0x0,0xe3,0xe7,0x0,

+	0x0,0x0,0x0,0xe1,0x0,0xe1,0xe1,0xef,

+	0x0,0x0,0xe1,0x0,0xe1,0x0,0x0,0x0,

+	0x0,0x0,0x10,0xef,0xe1,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0xe1,0xe1,0x0,0x0,

+	0x0,0x0,0xe1,0xe1,0x0,0x10,0xe1,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr54[20] = {0x2,0x0,0x0,0x0, 0x14,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0};

+SetWordType zzerr55[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x78,0x9, 0x60,0x0,0x0,0x0};

+SetWordType zzerr56[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr57[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0};

+SetWordType setwd9[157] = {0x0,0x7c,0x1,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x7f,0x1,0x1,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x1,0x0,0x1,0x0,0x0,0x1,0x1,0x0,

+	0x0,0x0,0x0,0x7f,0x7e,0x7f,0x1,0x1,

+	0x0,0x0,0x1,0x0,0x7d,0x7e,0x7e,0x7e,

+	0x7e,0x0,0x0,0x1,0x7d,0x7e,0x7e,0x7e,

+	0x0,0x7e,0x0,0x0,0x7d,0x1,0x0,0x0,

+	0x0,0x0,0x1,0x1,0x0,0x0,0x7f,0x64,

+	0x64,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x80,0x0,0x0,0x0,0x0,0x0,0x80,0x0,

+	0x80,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr58[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0};

+SetWordType zzerr59[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0};

+SetWordType zzerr60[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0};

+SetWordType zzerr61[20] = {0x2,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0};

+SetWordType zzerr62[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};

+SetWordType zzerr63[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};

+SetWordType zzerr64[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};

+SetWordType zzerr65[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0, 0x0,0x0,0x10,0xc};

+SetWordType setwd10[157] = {0x0,0xc,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,

+	0x3,0x0,0x0,0xf0,0xf0,0x0};

+SetWordType setwd11[157] = {0x0,0x1,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,

+	0x1,0x0,0x0,0x0,0x0,0x0};

diff --git a/Source/Pccts/antlr/fcache.c b/Source/Pccts/antlr/fcache.c
new file mode 100644
index 0000000..ff7dcdf
--- /dev/null
+++ b/Source/Pccts/antlr/fcache.c
@@ -0,0 +1,123 @@
+/*

+ * fcache.c

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33MR10

+ *

+ */

+

+#include <stdio.h>

+#include <ctype.h>

+

+#include "pcctscfg.h"

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+

+#ifdef __USE_PROTOS

+CacheEntry *dumpFcache1(char *prev)

+#else

+CacheEntry *dumpFcache1(prev)

+  char  *prev;

+#endif

+{

+    Entry   **table=Fcache;

+

+    int     low=0;

+    int     hi=0;

+

+    CacheEntry  *least=NULL;

+

+	Entry   **p;

+

+	for (p=table; p<&(table[HashTableSize]); p++) {

+

+		CacheEntry *q =(CacheEntry *) *p;

+		

+		if ( q != NULL && low==0 ) low = p-table;

+		while ( q != NULL ) {

+            if (strcmp(q->str,prev) > 0) {

+              if (least == NULL) {

+                least=q;

+              } else {

+                if (strcmp(q->str,least->str) < 0) {

+                  least=q;

+                };

+              };

+            };

+			q = q->next;

+		};

+

+		if ( *p != NULL ) hi = p-table;

+	}

+    return least;

+}

+

+#ifdef __USE_PROTOS

+void reportFcache(CacheEntry *q)

+#else

+void reportFcache(q)

+  CacheEntry    *q;

+#endif

+{

+    char        *qstr;

+

+    fprintf(stdout,"\nrule ");

+    for (qstr=q->str; *qstr != '*' ; qstr++) {

+      fprintf(stdout,"%c",*qstr);

+    };

+

+    qstr++;

+    if (*qstr == 'i') fprintf(stdout," First[");

+    if (*qstr == 'o') fprintf(stdout," Follow[");

+    qstr++;

+    fprintf(stdout,"%s]",qstr);

+    if (q->incomplete) fprintf(stdout," *** incomplete ***");

+    fprintf(stdout,"\n");

+    MR_dumpTokenSet(stdout,1,q->fset);

+}

+

+void 

+#ifdef __USE_PROTOS

+DumpFcache(void) 

+#else

+DumpFcache() 

+#endif

+{

+

+    char        *prev="";

+    int          n=0;

+    CacheEntry  *next;

+

+    fprintf(stdout,"\n\nDump of First/Follow Cache\n");

+

+    for(;;) {

+      next=dumpFcache1(prev);

+      if (next == NULL) break;

+      reportFcache(next);

+      ++n;

+      prev=next->str;

+    };

+    fprintf(stdout,"\nEnd dump of First/Follow Cache\n");

+}

diff --git a/Source/Pccts/antlr/fset.c b/Source/Pccts/antlr/fset.c
new file mode 100644
index 0000000..e1a76ec
--- /dev/null
+++ b/Source/Pccts/antlr/fset.c
@@ -0,0 +1,1555 @@
+/*

+ * fset.c

+ *

+ * Compute FIRST and FOLLOW sets.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+

+#include "pcctscfg.h"

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+#include "limits.h"

+

+#ifdef __USE_PROTOS

+static void ensure_predicates_cover_ambiguous_lookahead_sequences

+                                    (Junction *, Junction *, char *, Tree *);

+#else

+static void ensure_predicates_cover_ambiguous_lookahead_sequences();

+#endif

+

+/*

+ * What tokens are k tokens away from junction q?

+ *

+ * Follow both p1 and p2 paths (unless RuleBlk) to collect the tokens k away from this

+ * node.

+ * We lock the junction according to k--the lookahead.  If we have been at this

+ * junction before looking for the same, k, number of lookahead tokens, we will

+ * do it again and again...until we blow up the stack.  Locks are only used on aLoopBlk,

+ * RuleBlk, aPlusBlk and EndRule junctions to remove/detect infinite recursion from

+ * FIRST and FOLLOW calcs.

+ *

+ * If p->jtype == EndRule we are going to attempt a FOLLOW.  (FOLLOWs are really defined

+ * in terms of FIRST's, however).  To proceed with the FOLLOW, p->halt cannot be

+ * set.  p->halt is set to indicate that a reference to the current rule is in progress

+ * and the FOLLOW is not desirable.

+ *

+ * If we attempt a FOLLOW and find that there is no FOLLOW or REACHing beyond the EndRule

+ * junction yields an empty set, replace the empty set with EOF.  No FOLLOW means that

+ * only EOF can follow the current rule.  This normally occurs only on the start symbol

+ * since all other rules are referenced by another rule somewhere.

+ *

+ * Normally, both p1 and p2 are followed.  However, checking p2 on a RuleBlk node is

+ * the same as checking the next rule which is clearly incorrect.

+ *

+ * Cycles in the FOLLOW sense are possible.  e.g. Fo(c) requires Fo(b) which requires

+ * Fo(c).  Both Fo(b) and Fo(c) are defined to be Fo(b) union Fo(c).  Let's say

+ * Fo(c) is attempted first.  It finds all of the FOLLOW symbols and then attempts

+ * to do Fo(b) which finds of its FOLLOW symbols.  So, we have:

+ *

+ *                  Fo(c)

+ *                 /     \

+ *              a set    Fo(b)

+ *                      /     \

+ *                   a set    Fo(c) .....Hmmmm..... Infinite recursion!

+ *

+ * The 2nd Fo(c) is not attempted and Fo(b) is left deficient, but Fo(c) is now

+ * correctly Fo(c) union Fo(b).  We wish to pick up where we left off, so the fact

+ * that Fo(b) terminated early means that we lack Fo(c) in the Fo(b) set already

+ * laying around.  SOOOOoooo, we track FOLLOW cycles.  All FOLLOW computations are

+ * cached in a hash table.  After the sequence of FOLLOWs finish, we reconcile all

+ * cycles --> correct all Fo(rule) sets in the cache.

+ *

+ * Confused? Good! Read my MS thesis [Purdue Technical Report TR90-30].

+ * TJP 8/93 -- can now read PhD thesis from Purdue.

+ *

+ * Also, FIRST sets are cached in the hash table.  Keys are (rulename,Fi/Fo,k).

+ * Only FIRST sets, for which the FOLLOW is not included, are stored.

+ *

+ * SPECIAL CASE of (...)+ blocks:

+ * I added an optional alt so that the alts could see what

+ * was behind the (...)+ block--thus using enough lookahead

+ * to branch out rather than just enough to distinguish

+ * between alts in the (...)+.  However, when the FIRST("(...)+") is

+ * is needed, must not use this last "optional" alt.  This routine

+ * turns off this path by setting a new 'ignore' flag for

+ * the alt and then resetting it afterwards.

+ */

+

+set

+#ifdef __USE_PROTOS

+rJunc( Junction *p, int k, set *rk )

+#else

+rJunc( p, k, rk )

+Junction *p;

+int k;

+set *rk;

+#endif

+{

+	set     a, b;

+

+	require(p!=NULL,				"rJunc: NULL node");

+	require(p->ntype==nJunction,	"rJunc: not junction");

+

+#ifdef DBG_LL1

+	if ( p->jtype == RuleBlk ) fprintf(stderr, "FIRST(%s,%d) \n",((Junction *)p)->rname,k);

+	else fprintf(stderr, "rJunc: %s in rule %s\n",

+			decodeJType[p->jtype], ((Junction *)p)->rname);

+#endif

+	/* if this is one of the added optional alts for (...)+ then return */

+

+    /* no need to pop backtrace - hasn't been pushed */

+

+	if ( p->ignore ) return empty;

+

+    if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);

+

+/* MR14 */    if (AlphaBetaTrace && p->alpha_beta_guess_end) {

+/* MR14 */         warnFL(

+/* MR14 */           "not possible to compute follow set for alpha in an \"(alpha)? beta\" block.  ",

+/* MR14 */                 FileStr[p->file],p->line);

+/* MR14 */         MR_alphaBetaTraceReport();

+/* MR14 */    };

+

+/* MR14 */    if (p->alpha_beta_guess_end) {

+/* MR14 */      if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+/* MR14 */      return empty;

+/* MR14 */    }

+

+	/* locks are valid for aLoopBlk,aPlusBlk,RuleBlk,EndRule junctions only */

+	if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||

+		 p->jtype==aPlusBlk || p->jtype==EndRule )

+	{

+		require(p->lock!=NULL, "rJunc: lock array is NULL");

+		if ( p->lock[k] )

+		{

+			if ( p->jtype == EndRule )	/* FOLLOW cycle? */

+			{

+#ifdef DBG_LL1

+				fprintf(stderr, "FOLLOW cycle to %s: panic!\n", p->rname);

+#endif

+                if (! MR_AmbSourceSearch) RegisterCycle(p->rname, k);

+			}

+            if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+			return empty;

+		}

+		if ( p->jtype == RuleBlk &&

+                 p->end->halt  &&

+                     ! MR_AmbSourceSearch)	/* check for FIRST cache */

+		{

+			CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'i',k));

+			if ( q != NULL )

+			{

+				set_orin(rk, q->rk);

+                if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+   				return set_dup( q->fset );

+			}

+		}

+		if ( p->jtype == EndRule &&

+                !p->halt &&                     /* MR11 was using cache even when halt set */

+                     ! MR_AmbSourceSearch)		/* FOLLOW set cached already? */

+		{

+			CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k));

+			if ( q != NULL )

+			{

+#ifdef DBG_LL1

+				fprintf(stderr, "cache for FOLLOW(%s,%d):", p->rname,k);

+				s_fprT(stderr, q->fset);

+				if ( q->incomplete ) fprintf(stderr, " (incomplete)");

+				fprintf(stderr, "\n");

+#endif

+				if ( !q->incomplete )

+				{

+                    if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+					return set_dup( q->fset );

+				}

+			}

+		}

+		p->lock[k] = TRUE;	/* This rule is busy */

+	}

+

+	a = b = empty;

+

+	if ( p->jtype == EndRule )

+	{

+		if (p->halt )			/* don't want FOLLOW here? */ /* unless MR10 hoisting */

+		{

+ 	  	      p->lock[k] = FALSE;

+			  set_orel(k, rk);						/* indicate this k value needed */

+              if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+			  return empty;

+		}

+		if (! MR_AmbSourceSearch) FoPush(p->rname, k);		/* Attempting FOLLOW */

+		if ( p->p1 == NULL ) set_orel((TokenInd!=NULL?TokenInd[EofToken]:EofToken), &a);/* if no FOLLOW assume EOF */

+#ifdef DBG_LL1

+		fprintf(stderr, "-->FOLLOW(%s,%d)\n", p->rname,k);

+#endif

+	}

+

+	if ( p->p1 != NULL ) {

+/* MR14 */      if (p->guess) {

+/* MR14 */        if (p->guess_analysis_point == NULL) {

+/* MR14 */           Node * guess_point;

+/* MR14 */           guess_point=(Node *)analysis_point(p);

+/* MR14 */           if (guess_point == (Node *)p) {

+/* MR14 */             guess_point=p->p1;

+/* MR14 */           }

+/* MR14 */           p->guess_analysis_point=guess_point;

+/* MR14 */        }

+/* MR14 */        REACH(p->guess_analysis_point, k, rk, a);

+                } else {

+                  REACH(p->p1, k, rk, a);

+                }

+    }	

+

+	/* C a c h e  R e s u l t s */

+

+	if ( p->jtype == RuleBlk && p->end->halt && ! MR_AmbSourceSearch)		/* can save FIRST set? */

+	{

+		CacheEntry *q = newCacheEntry( Fkey(p->rname,'i',k) );

+		/*fprintf(stderr, "Caching %s FIRST %d\n", p->rname, k);*/

+		hash_add(Fcache, Fkey(p->rname,'i',k), (Entry *)q);

+		q->fset = set_dup( a );

+		q->rk = set_dup( *rk );

+	}

+

+	if ( p->jtype == EndRule &&

+            !p->halt &&                         /* MR11 was using cache even with halt set */

+                 ! MR_AmbSourceSearch)			/* just completed FOLLOW? */

+	{

+		/* Cache Follow set */

+		CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k));

+		if ( q==NULL )

+		{

+			q = newCacheEntry( Fkey(p->rname,'o',k) );

+			hash_add(Fcache, Fkey(p->rname,'o',k), (Entry *)q);

+		}

+		/*fprintf(stderr, "Caching %s FOLLOW %d\n", p->rname, k);*/

+		if ( set_nil(a) && !q->incomplete )

+		{

+			/* Don't ever save a nil set as complete.

+			 * Turn it into an eof set.

+			 */

+			set_orel(EofToken, &a);

+		}

+		set_orin(&(q->fset), a);

+		FoPop( k );

+		if ( FoTOS[k] == NULL && Cycles[k] != NULL ) ResolveFoCycles(k);

+#ifdef DBG_LL1

+		fprintf(stderr, "saving FOLLOW(%s,%d):", p->rname, k);

+		s_fprT(stderr, q->fset);

+		if ( q->incomplete ) fprintf(stderr, " (incomplete)");

+		fprintf(stderr, "\n");

+#endif

+	}

+	

+    if (p->jtype != RuleBlk && p->p2 != NULL && /* MR14 */ ! p->guess) {

+       REACH(p->p2, k, rk, b);

+    }	

+

+	if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||

+		 p->jtype==aPlusBlk || p->jtype==EndRule )

+		p->lock[k] = FALSE;							/* unlock node */

+

+	set_orin(&a, b);

+	set_free(b);

+    if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+	return a;

+}

+

+set

+#ifdef __USE_PROTOS

+rRuleRef( RuleRefNode *p, int k, set *rk_out )

+#else

+rRuleRef( p, k, rk_out )

+RuleRefNode *p;

+int k;

+set *rk_out;

+#endif

+{

+	set rk;

+	Junction *r;

+	int k2;

+	set a, rk2, b;

+	int save_halt;

+	RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);

+	require(p!=NULL,			"rRuleRef: NULL node");

+	require(p->ntype==nRuleRef,	"rRuleRef: not rule ref");

+

+#ifdef DBG_LL1

+	fprintf(stderr, "rRuleRef: %s\n", p->text);

+#endif

+

+    if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);

+

+	if ( q == NULL )

+	{

+		warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );

+		REACH(p->next, k, rk_out, a);

+        if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+		return a;

+	}

+	rk2 = empty;

+

+/* MR9 Problems with rule references in guarded predicates */

+/* MR9    Perhaps can use hash table to find rule ?        */

+

+/* MR9 */    if (RulePtr == NULL) {

+/* MR9 */        fatalFL(eMsg2("Rule %s uses rule %s via RulePtr before it has been initialized",

+/* MR9 */                                p->rname,q->str),FileStr[p->file],p->line);

+/* MR9 */    };

+

+	r = RulePtr[q->rulenum];

+	if ( r->lock[k] )

+	{

+		errNoFL( eMsg2("infinite left-recursion to rule %s from rule %s",

+						r->rname, p->rname) );

+

+        if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+

+		return empty;

+	}

+

+	save_halt = r->end->halt;

+	r->end->halt = TRUE;		/* don't let reach fall off end of rule here */

+	rk = empty;

+	REACH(r, k, &rk, a);

+	r->end->halt = save_halt;

+	while ( !set_nil(rk) ) {

+		k2 = set_int(rk);               /* MR11 this messes up the ambiguity search routine */

+		set_rm(k2, rk);

+		REACH(p->next, k2, &rk2, b);    /* MR11 by changing the value of k                  */

+		set_orin(&a, b);

+		set_free(b);

+	}

+	set_free(rk);				/* this has no members, but free it's memory */

+	set_orin(rk_out, rk2);		/* remember what we couldn't do */

+	set_free(rk2);

+    if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+	return a;

+}

+

+/*

+ * Return FIRST sub k ( token_node )

+ *

+ * TJP 10/11/93 modified this so that token nodes that are actually

+ * ranges (T1..T2) work.

+ */

+set

+#ifdef __USE_PROTOS

+rToken( TokNode *p, int k, set *rk )

+#else

+rToken( p, k, rk )

+TokNode *p;

+int k;

+set *rk;

+#endif

+{

+	set a;

+

+	require(p!=NULL,			"rToken: NULL node");

+	require(p->ntype==nToken,	"rToken: not token node");

+

+#ifdef DBG_LL1

+	fprintf(stderr, "rToken: %s\n", (TokenString(p->token)!=NULL)?TokenString(p->token):

+									ExprString(p->token));

+#endif

+

+

+    if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);

+

+    if (MR_AmbSourceSearch && (k-1) == 0) {

+

+      set       localConstrain;

+      set       intersection;

+

+      localConstrain=fset[maxk-k+1];

+

+      if (! set_nil(p->tset)) {

+        intersection=set_and(localConstrain,p->tset);

+        if (! set_nil(intersection)) {

+          MR_backTraceReport();

+        };

+        set_free(intersection);

+      } else {

+        if (set_el( (unsigned) p->token,localConstrain)) {

+          MR_backTraceReport();

+        }

+      };

+    };

+

+	if ( k-1 == 0 )	{

+

+        if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+

+		if ( !set_nil(p->tset) ) {

+            return set_dup(p->tset);

+        } else {

+    		return set_of(p->token);

+        };

+	}

+

+	REACH(p->next, k-1, rk, a);

+	

+    if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+

+	return a;

+}

+

+set

+#ifdef __USE_PROTOS

+rAction( ActionNode *p, int k, set *rk )

+#else

+rAction( p, k, rk )

+ActionNode *p;

+int k;

+set *rk;

+#endif

+{

+	set a;

+

+	require(p!=NULL,			"rJunc: NULL node");

+	require(p->ntype==nAction,	"rJunc: not action");

+	

+/* MR11 */    if (p->is_predicate && p->ampersandPred != NULL) {

+/* MR11 */      Predicate   *pred=p->ampersandPred;

+/* MR11 */      if (k <= pred->k) {

+/* MR11 */        REACH(p->guardNodes,k,rk,a);

+/* MR11 */        return a;

+/* MR11 */      };

+/* MR11 */    };

+

+    /* it might be a good idea when doing an MR_AmbSourceSearch

+       to *not* look behind predicates under some circumstances

+       we'll look into that later

+    */

+

+	REACH(p->next, k, rk, a);	/* ignore actions */

+	return a;

+}

+

+				/* A m b i g u i t y  R e s o l u t i o n */

+

+

+void

+#ifdef __USE_PROTOS

+dumpAmbigMsg( set *fset, FILE *f, int want_nls )

+#else

+dumpAmbigMsg( fset, f, want_nls )

+set *fset;

+FILE *f;

+int want_nls;

+#endif

+{

+	int i;

+

+    set     copy;               /* MR11 */

+

+	if ( want_nls ) fprintf(f, "\n\t");

+	else fprintf(f, " ");

+

+	for (i=1; i<=CLL_k; i++)

+	{

+        copy=set_dup(fset[i]);  /* MR11 */

+

+		if ( i>1 )

+		{

+			if ( !want_nls ) fprintf(f, ", ");

+		}

+		if ( set_deg(copy) > 3 && elevel == 1 )

+		{

+			int e,m;

+			fprintf(f, "{");

+			for (m=1; m<=3; m++)

+			{

+				e=set_int(copy);

+				fprintf(f, " %s", TerminalString(e));

+				set_rm(e, copy);

+			}

+			fprintf(f, " ... }");

+		}

+		else s_fprT(f, copy);

+		if ( want_nls ) fprintf(f, "\n\t");

+        set_free(copy);

+	}

+	fprintf(f, "\n");

+

+}

+

+static void

+#ifdef __USE_PROTOS

+verify_context(Predicate *predicate)

+#else

+verify_context(predicate)

+Predicate *predicate;

+#endif

+{

+	if ( predicate == NULL ) return;

+

+	if ( predicate->expr == PRED_OR_LIST ||

+		 predicate->expr == PRED_AND_LIST )

+	{

+		verify_context(predicate->down);

+		verify_context(predicate->right);       /* MR10 */

+		return;

+	}

+

+	if ( !predicate->source->ctxwarned && predicate->source->guardpred==NULL &&

+		 ((predicate->k > 1 &&

+		 !is_single_tuple(predicate->tcontext)) ||

+		 ( predicate->k == 1 &&

+			  set_deg(predicate->scontext[1])>1 )) )

+	{

+

+/* MR9 Suppress annoying messages caused by our own clever(?) fix */

+

+  		fprintf(stderr, ErrHdr, FileStr[predicate->source->file],

+				predicate->source->line);

+		fprintf(stderr, " warning: predicate applied for >1 lookahead %d-sequences\n", predicate->k);

+		fprintf(stderr, ErrHdr, FileStr[predicate->source->file],

+				predicate->source->line);

+		fprintf(stderr, "     predicate text: \"%s\"\n",

+                        (predicate->expr == NULL ? "(null)" : predicate->expr) );

+		fprintf(stderr, ErrHdr, FileStr[predicate->source->file],

+				predicate->source->line);

+		fprintf(stderr, "     You may only want one lookahead %d-sequence to apply\n", predicate->k);

+		fprintf(stderr, ErrHdr, FileStr[predicate->source->file],

+				predicate->source->line);

+		fprintf(stderr, "     Try using a context guard '(...)? =>'\n");

+		predicate->source->ctxwarned = 1;

+	}

+    verify_context(predicate->right);       /* MR10 */

+}

+

+/*

+ * If delta is the set of ambiguous lookahead sequences, then make sure that

+ * the predicate(s) for productions alt1,alt2 cover the sequences in delta.

+ *

+ * For example,

+ *	a : <<PRED1>>? (A B|A C)

+ *	  | b

+ *    ;

+ *	b : <<PRED2>>? A B

+ *	  | A C

+ *	  ;

+ *

+ * This should give a warning that (A C) predicts both productions and alt2

+ * does not have a predicate in the production that generates (A C).

+ *

+ * The warning detection is simple.  Let delta = LOOK(alt1) intersection LOOK(alt2).

+ * Now, if ( delta set-difference context(predicates-for-alt1) != empty then

+ * alt1 does not "cover" all ambiguous sequences.

+ *

+ * If ambig is nonempty, then ambig in LL(k) sense -> use tree info; else use fset

+ * info.  Actually, sets are used only if k=1 for this grammar.

+ */

+static void

+#ifdef __USE_PROTOS

+ensure_predicates_cover_ambiguous_lookahead_sequences

+                        ( Junction *alt1, Junction *alt2, char *sub, Tree *ambig )

+#else

+ensure_predicates_cover_ambiguous_lookahead_sequences( alt1, alt2, sub, ambig )

+Junction *alt1;

+Junction *alt2;

+char *sub;

+Tree *ambig;

+#endif

+{

+	if ( !ParseWithPredicates ) return;

+

+	if ( ambig!=NULL )

+	{

+		Tree *non_covered = NULL;

+		if ( alt1->predicate!=NULL )

+			non_covered = tdif(ambig, alt1->predicate, alt1->fset, alt2->fset);

+		if ( (non_covered!=NULL || alt1->predicate==NULL) && WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+			fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",

+							alt1->altnum, sub);

+			if ( alt1->predicate!=NULL && non_covered!=NULL )

+			{

+				fprintf(stderr, " upon");

+				preorder(non_covered);

+			}

+			else if ( alt1->predicate==NULL )

+			{

+				fprintf(stderr, " upon");

+				preorder(ambig->down);

+			}

+			fprintf(stderr, "\n");

+		}

+		Tfree(non_covered);

+		non_covered = NULL;

+		if ( alt2->predicate!=NULL )

+			non_covered = tdif(ambig, alt2->predicate, alt1->fset, alt2->fset);

+		if ( (non_covered!=NULL || alt2->predicate==NULL) && WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line);

+			fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",

+							alt2->altnum, sub);

+			if ( alt2->predicate!=NULL && non_covered!=NULL )

+			{

+				fprintf(stderr, " upon");

+				preorder(non_covered);

+			}

+			else if ( alt2->predicate==NULL )

+			{

+				fprintf(stderr, " upon");

+				preorder(ambig->down);

+			}

+			fprintf(stderr, "\n");

+		}

+		Tfree(non_covered);

+	}

+	else if ( !set_nil(alt1->fset[1]) )

+	{

+		set delta, non_covered;

+		delta = set_and(alt1->fset[1], alt2->fset[1]);

+		non_covered = set_dif(delta, covered_set(alt1->predicate));

+		if ( set_deg(non_covered)>0 && WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+			fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",

+							alt1->altnum, sub);

+			if ( alt1->predicate!=NULL )

+			{

+				fprintf(stderr, " upon ");

+				s_fprT(stderr, non_covered);

+			}

+			fprintf(stderr, "\n");

+		}

+		set_free( non_covered );

+		non_covered = set_dif(delta, covered_set(alt2->predicate));

+		if ( set_deg(non_covered)>0 && WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line);

+			fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",

+							alt2->altnum, sub);

+			if ( alt2->predicate!=NULL )

+			{

+				fprintf(stderr, " upon ");

+				s_fprT(stderr, non_covered);

+			}

+			fprintf(stderr, "\n");

+		}

+		set_free( non_covered );

+		set_free( delta );

+	}

+	else fatal_internal("productions have no lookahead in predicate checking routine");

+}

+

+#ifdef __USE_PROTOS

+void MR_doPredicatesHelp(int inGuessBlock,Junction *alt1,Junction *alt2,int jtype,char *sub)

+#else

+void MR_doPredicatesHelp(inGuessBlock,alt1,alt2,jtype,sub)

+  int       inGuessBlock;

+  Junction  *alt1;

+  Junction  *alt2;

+  int       jtype;

+  char      *sub;

+#endif

+{

+    Predicate   *p1;

+    Predicate   *p2;

+

+    Junction    *parentRule=MR_nameToRuleBlk(alt1->rname);

+

+    if (inGuessBlock && WarningLevel <= 1) return;

+

+    /* let antlr give the usual error message */

+

+    if (alt1->predicate == NULL && alt2->predicate == NULL) return;

+

+    if ( (jtype == RuleBlk || jtype == aSubBlk)

+             && (alt1->predicate == NULL && alt2->predicate != NULL)) {

+        fprintf(stderr, ErrHdr, FileStr[parentRule->file],parentRule->line);

+        fprintf(stderr," warning: alt %d line %d and alt %d line %d of %s\n%s%s%s",

+          alt1->altnum,

+          alt1->line,

+          alt2->altnum,

+          alt2->line,

+          sub,

+          "     These alts have ambig lookahead sequences resolved by a predicate for\n",

+          "     the second choice. The second choice may not be reachable.\n",

+          "     You may want to use a complementary predicate or rearrange the alts\n"

+        );

+        return;

+    };

+

+    /* first do the easy comparison.  then do the hard one */

+

+    if (MR_comparePredicates(alt1->predicate,alt2->predicate)) {

+

+      if (jtype == aLoopBegin || jtype == aPlusBlk ) {

+

+        /* I'm not sure this code is reachable.

+           Predicates following a (...)+ or (...)* block are probably

+             considered validation predicates and therefore not

+             participate in the predication expression

+        */

+

+      	fprintf(stderr, ErrHdr,FileStr[parentRule->file],parentRule->line);

+        fprintf(stderr," warning: %s of %s in rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s",

+          "the predicates used to disambiguate optional/exit paths of ",

+          sub,

+          CurRule,

+          FileStr[alt1->file],

+          alt1->altnum,

+          alt1->line,

+          alt2->altnum,

+          alt2->line,

+          "     are identical and have no resolving power\n");

+      } else {

+    	fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);

+        fprintf(stderr," warning: %s rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s",

+          "the predicates used to disambiguate",

+          CurRule,

+          FileStr[alt1->file],

+          alt1->altnum,

+          alt1->line,

+          alt2->altnum,

+          alt2->line,

+          "     are identical and have no resolving power\n");

+      };

+    } else {

+      p1=predicate_dup_without_context(alt1->predicate);

+      p1=MR_unfold(p1);

+      MR_clearPredEntry(p1);

+      MR_simplifyInverted(p1,0);

+      p1=MR_predSimplifyALL(p1);

+      p2=predicate_dup_without_context(alt2->predicate);

+      p2=MR_unfold(p2);

+      MR_clearPredEntry(p2);

+      MR_simplifyInverted(p2,0);

+      p2=MR_predSimplifyALL(p2);

+      if (MR_comparePredicates(p1,p2)) {

+        if (jtype == aLoopBegin || jtype == aPlusBlk ) {

+          fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);

+          fprintf(stderr," warning: %s of %s in rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s%s",

+            "the predicates used to disambiguate optional/exit paths of ",

+            sub,

+            CurRule,

+            FileStr[alt1->file],

+            alt1->altnum,

+            alt1->line,

+            alt2->altnum,

+            alt2->line,

+            "     are identical when compared without context and may have no\n",

+            "     resolving power for some lookahead sequences.\n");

+        } else {

+          fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);

+          fprintf(stderr," warning: %s rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s%s",

+            "the predicates used to disambiguate",

+            CurRule,

+            FileStr[alt1->file],

+            alt1->altnum,

+            alt1->line,

+            alt2->altnum,

+            alt2->line,

+            "     are identical when compared without context and may have no\n",

+            "     resolving power for some lookahead sequences.\n");

+        };

+        if (InfoP) {

+          fprintf(output,"\n#if 0\n\n");

+          fprintf(output,"The following predicates are identical when compared without\n");

+          fprintf(output,"  lookahead context information.  For some ambiguous lookahead\n");

+          fprintf(output,"  sequences they may not have any power to resolve the ambiguity.\n");

+          fprintf(output,"\n");

+

+          fprintf(output,"Choice 1: %s  alt %d  line %d  file %s\n\n",

+                  MR_ruleNamePlusOffset( (Node *) alt1),

+                  alt1->altnum,

+                  alt1->line,

+                  FileStr[alt1->file]);

+          fprintf(output,"  The original predicate for choice 1 with available context information:\n\n");

+          MR_dumpPred1(2,alt1->predicate,1);

+          fprintf(output,"  The predicate for choice 1 after expansion (but without context information):\n\n");

+          MR_dumpPred1(2,p1,0);

+          if (p1 == NULL) {

+            Predicate   *phelp;

+            fprintf(output,"  The predicate for choice 1 after expansion (but before simplification)\n\n");

+            phelp=predicate_dup_without_context(alt1->predicate);

+            phelp=MR_unfold(phelp);

+            MR_clearPredEntry(phelp);

+            MR_simplifyInverted(phelp,0);

+            phelp=MR_predSimplifyALLX(phelp,1);

+            MR_dumpPred1(2,phelp,0);

+            predicate_free(phelp);

+          };

+          fprintf(output,"\n");

+

+          fprintf(output,"Choice 2: %s  alt %d  line %d  file %s\n\n",

+                  MR_ruleNamePlusOffset( (Node *) alt2),

+                  alt2->altnum,

+                  alt2->line,

+                  FileStr[alt2->file]);

+          fprintf(output,"  The original predicate for choice 2 with available context information:\n\n");

+          MR_dumpPred1(1,alt2->predicate,1);

+          fprintf(output,"  The predicate for choice 2 after expansion (but without context information):\n\n");

+          MR_dumpPred1(1,p2,0);

+          if (p2 == NULL) {

+            Predicate   *phelp;

+            fprintf(output,"  The predicate for choice 2 after expansion (but before simplification)\n\n");

+            phelp=predicate_dup_without_context(alt2->predicate);

+            phelp=MR_unfold(phelp);

+            MR_clearPredEntry(phelp);

+            MR_simplifyInverted(phelp,0);

+            phelp=MR_predSimplifyALLX(phelp,1);

+            MR_dumpPred1(2,phelp,0);

+            predicate_free(phelp);

+          };

+          fprintf(output,"\n#endif\n");

+        };

+      } else if (MR_secondPredicateUnreachable(p1,p2)) {

+        if (jtype == aLoopBegin || jtype == aPlusBlk ) {

+          fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);

+          fprintf(stderr," warning: %s of %s in rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s%s",

+            "the predicate used to disambiguate the first choice of the optional/exit paths of ",

+            sub,

+            CurRule,

+            FileStr[alt1->file],

+            alt1->altnum,

+            alt1->line,

+            alt2->altnum,

+            alt2->line,

+            "     appears to \"cover\" the second predicate when compared without context.\n",

+            "     The second predicate may have no resolving power for some lookahead sequences.\n");

+        } else {

+          fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);

+          fprintf(stderr," warning: %s rule %s\n     (file %s alt %d line %d and alt %d line %d)\n%s%s",

+            "the predicate used to disambiguate the first choice of",

+            CurRule,

+            FileStr[alt1->file],

+            alt1->altnum,

+            alt1->line,

+            alt2->altnum,

+            alt2->line,

+            "     appears to \"cover\" the second predicate when compared without context.\n",

+            "     The second predicate may have no resolving power for some lookahead sequences.\n");

+        };

+        if (InfoP) {

+          fprintf(output,"\n#if 0\n\n");

+          fprintf(output,"The first predicate appears to \"cover\" the second predicate when they\n");

+          fprintf(output,"  are compared without lookahead context information.  For some ambiguous\n");

+          fprintf(output,"  lookahead sequences the second predicate may not have any power to\n");

+          fprintf(output,"  resolve the ambiguity.\n");

+          fprintf(output,"\n");

+          fprintf(output,"Choice 1: %s  alt %d  line %d  file %s\n\n",

+                  MR_ruleNamePlusOffset( (Node *) alt1),

+                  alt1->altnum,

+                  alt1->line,

+                  FileStr[alt1->file]);

+          fprintf(output,"  The original predicate for choice 1 with available context information:\n\n");

+          MR_dumpPred1(2,alt1->predicate,1);

+          fprintf(output,"  The predicate for choice 1 after expansion (but without context information):\n\n");

+          MR_dumpPred1(2,p1,0);

+          if (p1 == NULL) {

+            Predicate   *phelp;

+            fprintf(output,"  The predicate for choice 1 after expansion (but before simplification)\n\n");

+            phelp=predicate_dup_without_context(alt1->predicate);

+            phelp=MR_unfold(phelp);

+            MR_clearPredEntry(phelp);

+            MR_simplifyInverted(phelp,0);

+            phelp=MR_predSimplifyALLX(phelp,1);

+            MR_dumpPred1(2,phelp,0);

+            predicate_free(phelp);

+          };

+          fprintf(output,"\n");

+

+          fprintf(output,"Choice 2: %s  alt %d  line %d  file %s\n\n",

+                  MR_ruleNamePlusOffset( (Node *) alt2),

+                  alt2->altnum,

+                  alt2->line,

+                  FileStr[alt2->file]);

+          fprintf(output,"  The original predicate for choice 2 with available context information:\n\n");

+          MR_dumpPred1(1,alt2->predicate,1);

+          fprintf(output,"  The predicate for choice 2 after expansion (but without context information):\n\n");

+          MR_dumpPred1(1,p2,0);

+          if (p2 == NULL) {

+            Predicate   *phelp;

+            fprintf(output,"  The predicate for choice 2 after expansion (but before simplification)\n\n");

+            phelp=predicate_dup_without_context(alt2->predicate);

+            phelp=MR_unfold(phelp);

+            MR_clearPredEntry(phelp);

+            MR_simplifyInverted(phelp,0);

+            phelp=MR_predSimplifyALLX(phelp,1);

+            MR_dumpPred1(2,phelp,0);

+            predicate_free(phelp);

+          };

+          fprintf(output,"\n#endif\n");

+        };

+      };

+      predicate_free(p1);

+      predicate_free(p2);

+    };

+}

+

+static  int     totalOverflow=0;                /* MR9 */

+

+void

+#ifdef __USE_PROTOS

+HandleAmbiguity( Junction *block, Junction *alt1, Junction *alt2, int jtype )

+#else

+HandleAmbiguity( block, alt1, alt2, jtype )

+Junction *block;

+Junction *alt1;

+Junction *alt2;

+int jtype;

+#endif

+{

+	unsigned **ftbl;

+	set *fset, b;

+	int i, numAmbig,n2;

+	Tree *ambig=NULL, *t, *u;

+	char *sub = "";

+    long    n;

+    int     thisOverflow=0;             /* MR9 */

+    long    set_deg_value;              /* MR10 */

+    long    threshhold;                 /* MR10 */

+

+	require(block!=NULL, "NULL block");

+	require(block->ntype==nJunction, "invalid block");

+

+	/* These sets are used to constrain LL_k set, but are made CLL_k long anyway */

+	fset = (set *) calloc(CLL_k+1, sizeof(set));

+	require(fset!=NULL, "cannot allocate fset");

+	ftbl = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *));

+	require(ftbl!=NULL, "cannot allocate ftbl");

+

+	/* create constraint table and count number of possible ambiguities (use<=LL_k) */

+	for (n=1,i=1; i<=CLL_k; i++)

+	{

+         		b = set_and(alt1->fset[i], alt2->fset[i]);

+/* MR9 */       set_deg_value = set_deg(b);

+/* MR10 */      if (n > 0) {

+/* MR10 */        threshhold = LONG_MAX / n;

+/* MR10 */        if (set_deg_value <= threshhold) {

+/* MR10 */       	n *= set_deg_value;

+/* MR10 */        } else {

+/* MR10 */          n=LONG_MAX;

+/* MR9 */           if (totalOverflow == 0) {

+#if 0

+                      /* MR10 comment this out because it just makes users worry */

+

+/* MR9 */             warnNoFL("Overflow in computing number of possible ambiguities in HandleAmbiguity\n");

+#endif

+/* MR9 */           };

+/* MR9 */           thisOverflow++;

+/* MR9 */           totalOverflow++;

+/* MR9 */         };

+/* MR10 */      } else {

+/* MR10 */        n *= set_deg_value;

+/* MR9 */       };

+		fset[i] = set_dup(b);

+		ftbl[i] = set_pdq(b);

+		set_free(b);

+	}

+

+	switch ( jtype )

+	{

+		case aSubBlk: sub = "of (..) "; break;

+		case aOptBlk: sub = "of {..} "; break;

+		case aLoopBegin: sub = "of (..)* "; break;

+		case aLoopBlk: sub = "of (..)* "; break;

+		case aPlusBlk: sub = "of (..)+ "; break;

+		case RuleBlk: sub = "of the rule itself "; break;

+		default : sub = ""; break;

+	}

+

+	/* If the block is marked as a compressed lookahead only block, then

+	 * simply return; ambiguity warning is given only at warning level 2.

+	 */

+	if ( block->approx>0 )

+	{

+		if ( ParseWithPredicates )

+		{

+            if (alt1->predicate != NULL) predicate_free(alt1->predicate);  /* MR12 */

+            if (alt2->predicate != NULL) predicate_free(alt2->predicate);  /* MR12 */

+

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+          	alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+            require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");

+            alt1->predicate=MR_predSimplifyALL(alt1->predicate);

+

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+    		alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+            require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");

+            alt2->predicate=MR_predSimplifyALL(alt2->predicate);

+

+            MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);

+

+			if ( HoistPredicateContext

+                    && (alt1->predicate!=NULL||alt2->predicate!=NULL) )

+			{

+				verify_context(alt1->predicate);

+				verify_context(alt2->predicate);

+			}

+

+			if ( HoistPredicateContext

+                     && (alt1->predicate!=NULL||alt2->predicate!=NULL)

+                     && WarningLevel>1 )

+			ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);

+		}

+

+		if ( WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+			if ( jtype == aLoopBegin || jtype == aPlusBlk )

+				fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);

+			else

+				fprintf(stderr, " warning(approx): alts %d and %d %sambiguous upon",

+						alt1->altnum, alt2->altnum, sub);

+			dumpAmbigMsg(fset, stderr, 0);

+            MR_traceAmbSource(fset,alt1,alt2);

+		}

+		for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+		free((char *)fset);

+		for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+		free((char *)ftbl);

+		return;

+    }

+

+	/* if all sets have degree 1 for k<LL_k, then must be ambig upon >=1 permutation;

+	 * don't bother doing full LL(k) analysis.

+	 * (This "if" block handles the LL(1) case)

+	 */

+

+	n2 = 0;

+	for (i=1; i<LL_k; i++) n2 += set_deg(alt1->fset[i])+set_deg(alt2->fset[i]);

+

+    /* here STARTS the special case in which the lookahead sets for alt1 and alt2

+       all have degree 1 for k<LL_k (including LL_k=1)

+    */

+

+	if ( n2==2*(LL_k-1) )

+	{

+

+        /* TJP: added to fix the case where LL(1) and syntactic predicates didn't

+         * work.  It now recognizes syntactic predicates, but does not like combo:

+         * LL(1)/syn/sem predicates. (10/24/93)

+         */

+

+		if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL )

+		{

+			if ( WarningLevel==1 )

+			{

+				for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+				free((char *)fset);

+				for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+				free((char *)ftbl);

+				return;

+			}

+

+			fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+			if ( jtype == aLoopBegin || jtype == aPlusBlk )

+			   fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);

+			else

+			   fprintf(stderr, " warning: alts %d and %d %sambiguous upon",

+					   alt1->altnum, alt2->altnum, sub);

+			dumpAmbigMsg(fset, stderr, 0);

+            MR_traceAmbSource(fset,alt1,alt2);

+		}

+

+		ambig = NULL;

+		if ( LL_k>1 ) ambig = make_tree_from_sets(alt1->fset, alt2->fset);

+		if ( ParseWithPredicates )

+		{

+           if (alt1->predicate != NULL) predicate_free(alt1->predicate);  /* MR12 */

+           if (alt2->predicate != NULL) predicate_free(alt2->predicate);  /* MR12 */

+

+           require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+           alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);

+           require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+           require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");

+           alt1->predicate=MR_predSimplifyALL(alt1->predicate);

+

+           require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+    	   alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);

+           require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+           require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");

+           alt2->predicate=MR_predSimplifyALL(alt2->predicate);

+

+           MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);

+

+		   if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )

+		   {

+				verify_context(alt1->predicate);

+				verify_context(alt2->predicate);

+		   }

+		   if (HoistPredicateContext&&(alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1)

+			  ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);

+		   if ( WarningLevel == 1 &&

+			   (alt1->predicate!=NULL||alt2->predicate!=NULL))

+		   {

+			  for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+			  free((char *)fset);

+			  for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+			  free((char *)ftbl);

+			  Tfree(ambig);

+			  return;

+		   }

+		}

+/* end TJP (10/24/93) */

+

+		fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+		if ( jtype == aLoopBegin || jtype == aPlusBlk )

+			fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);

+		else

+		   fprintf(stderr, " warning: alts %d and %d %sambiguous upon",

+				   alt1->altnum, alt2->altnum, sub);

+		if ( elevel == 3 && LL_k>1 )

+		{

+		   preorder(ambig);

+		   fprintf(stderr, "\n");

+  	       for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+    	   free((char *)fset);

+		   for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+		   free((char *)ftbl);

+		   Tfree(ambig);

+		   return;

+        };

+

+		Tfree(ambig);

+		dumpAmbigMsg(fset, stderr, 0);

+

+        /* because this is a special case in which both alt1 and alt2 have

+           lookahead sets of degree 1 for k<LL_k (including k=1) the linear

+           lookahead style search is adequate

+        */

+

+        MR_traceAmbSource(fset,alt1,alt2);

+

+		for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+		free((char *)fset);

+		for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+		free((char *)ftbl);

+		return;

+	}

+

+    /* here ENDS the special case in which the lookahead sets for alt1 and alt2

+       all have degree 1 for k<LL_k (including LL_k=1)

+    */

+

+	/* in case tree construction runs out of memory, set info to make good err msg */

+

+	CurAmbigAlt1 = alt1->altnum;

+	CurAmbigAlt2 = alt2->altnum;

+	CurAmbigbtype = sub;

+	CurAmbigfile = alt1->file;

+	CurAmbigline = alt1->line;

+	

+	/* Don't do full LL(n) analysis if (...)? block because the block,

+	   by definition, defies LL(n) analysis.

+	   If guess (...)? block and ambiguous then don't remove anything from

+	   2nd alt to resolve ambig.

+	   Want to predict with LL sup 1 ( n ) decision not LL(n) if guess block

+	   since it is much cheaper than LL(n).  LL sup 1 ( n ) "covers" the LL(n)

+	   lookahead information.

+

+	   Note: LL(n) context cannot be computed for semantic predicates when

+	   followed by (..)?.

+

+	   If (..)? then we scream "AAAHHHH!  No LL(n) analysis will help"

+

+       Is 'ambig' always defined if we enter this if?  I hope so

+	   because the 'ensure...()' func references it. TJP Nov 1993.

+	   */

+

+	/* THM MR30:  Instead of using first_item_is_guss_block we use

+	   first_item_is_guess_block_extra which will look inside a

+	   loop block for a guess block.  In other words ( (...)? )*.

+	   It there is an ambiguity in this circumstance then we suppress

+	   the normal methods of resolving ambiguities.

+	*/

+

+	if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL )

+	{

+		if ( ParseWithPredicates )

+		{

+            if (alt1->predicate != NULL) predicate_free(alt1->predicate);  /* MR12 */

+            if (alt2->predicate != NULL) predicate_free(alt2->predicate);  /* MR12 */

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+        	alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+            require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");

+            alt1->predicate=MR_predSimplifyALL(alt1->predicate);

+

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+    		alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+            require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");

+            alt2->predicate=MR_predSimplifyALL(alt2->predicate);

+

+            MR_doPredicatesHelp(1,alt1,alt2,jtype,sub);

+

+			if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )

+			{

+				verify_context(alt1->predicate);

+				verify_context(alt2->predicate);

+			}

+			if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 )

+				ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);

+			if ( WarningLevel==1 &&

+				(alt1->predicate!=NULL||alt2->predicate!=NULL))

+			{

+				for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+				free((char *)fset);

+				for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+				free((char *)ftbl);

+				return;

+			}

+		}

+

+		if ( WarningLevel>1 )

+		{

+			fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+			if ( jtype == aLoopBegin || jtype == aPlusBlk )

+				fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);

+			else

+				fprintf(stderr, " warning: alts %d and %d %sambiguous upon",

+						alt1->altnum, alt2->altnum, sub);

+			dumpAmbigMsg(fset, stderr, 0);

+            MR_traceAmbSource(fset,alt1,alt2);

+		}

+

+		for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+		free((char *)fset);

+		for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+		free((char *)ftbl);

+		return;

+	}

+	

+	/* Not resolved with (..)? block.  Do full LL(n) analysis */

+	

+	/* ambig is the set of k-tuples truly in common between alt 1 and alt 2 */

+    /* MR11 VerifyAmbig once used fset destructively */

+

+	ambig = VerifyAmbig(alt1, alt2, ftbl, fset, &t, &u, &numAmbig);

+

+	/* are all things in intersection really ambigs? */

+

+	if (thisOverflow ||  numAmbig < n )                     /* MR9 */

+	{

+		Tree *v;

+

+		/* remove ambig permutation from 2nd alternative to resolve ambig;

+		 * We want to compute the set of artificial tuples, arising from

+		 * LL sup 1 (n) compression, that collide with real tuples from the

+		 * 2nd alternative.  This is the set of "special case" tuples that

+		 * the LL sup 1 (n) decision template maps incorrectly.

+		 */

+

+        /* when generating code in genExpr() it does

+         *

+         *      if ( genExprSets(j->fset) && !genExprTree(j->ftree)) {...

+         *

+         * Sooooo the j->ftree is the tree of alt2

+         *               after removal of conflicts, not alt1 !

+         */

+

+		if ( ambig!=NULL )

+		{

+            /* at the top of ambig is an ALT node */

+

+			for (v=ambig->down; v!=NULL; v=v->right)

+			{

+				u = trm_perm(u, v);     /* remove v FROM u */

+			}

+/*			fprintf(stderr, "after rm alt2:"); preorder(u); fprintf(stderr, "\n");*/

+		}

+		Tfree( t );

+		alt1->ftree = tappend(alt1->ftree, u);

+		alt1->ftree = tleft_factor(alt1->ftree);

+	}

+

+	if ( ambig==NULL )

+	{

+		for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+		free((char *)fset);

+		for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+		free((char *)ftbl);

+		return;

+	}

+

+	ambig = tleft_factor(ambig);

+

+/* TJP:

+ * At this point, we surely have an LL(k) ambiguity.  Check for predicates

+ */

+	if ( ParseWithPredicates )

+	{

+        if (alt1->predicate != NULL) predicate_free(alt1->predicate);  /* MR12 */

+        if (alt2->predicate != NULL) predicate_free(alt2->predicate);  /* MR12 */

+        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+    	alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);

+        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+        require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");

+        alt1->predicate=MR_predSimplifyALL(alt1->predicate);

+

+        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+		alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);

+        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+        require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");

+        alt2->predicate=MR_predSimplifyALL(alt2->predicate);

+

+        MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);

+

+		if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )

+		{

+			verify_context(alt1->predicate);

+			verify_context(alt2->predicate);

+		}

+		if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 )

+		   ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);

+		if ( WarningLevel==1 &&

+ 			(alt1->predicate!=NULL||alt2->predicate!=NULL))

+		{

+

+			/* We found at least one pred for at least one of the alts;

+			 * If warnings are low, just return.

+			 */

+

+			Tfree(ambig);

+            for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+    	    free((char *)fset);

+    		for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+    		free((char *)ftbl);

+			return;

+		}

+		/* else we're gonna give a warning */

+	}

+/* end TJP addition */

+

+	fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);

+	if ( jtype == aLoopBegin || jtype == aPlusBlk )

+		fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);

+	else

+		fprintf(stderr, " warning: alts %d and %d %sambiguous upon",

+					alt1->altnum, alt2->altnum, sub);

+	if ( elevel == 3 )

+	{

+		preorder(ambig->down);      /* <===== k>1 ambiguity message data */

+		fprintf(stderr, "\n");

+	} else {

+        MR_skipped_e3_report=1;

+    	dumpAmbigMsg(fset, stderr, 0);

+    };

+

+    MR_traceAmbSourceK(ambig,alt1,alt2);     /* <====== k>1 ambiguity aid */

+

+	Tfree(ambig);

+

+    for (i=1; i<=CLL_k; i++) set_free( fset[i] );

+	free((char *)fset);

+	for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );

+	free((char *)ftbl);

+}

+

+/* Don't analyze alpha block of (alpha)?beta; if (alpha)? then analyze

+ * Return the 1st node of the beta block if present else return j.

+ */

+Junction *

+#ifdef __USE_PROTOS

+analysis_point( Junction *j )

+#else

+analysis_point( j )

+Junction *j;

+#endif

+{

+	Junction *gblock;

+

+    /* MR13b  When there was an action/predicate preceding a guess block

+              the guess block became invisible at the analysis_point.

+

+              first_item_is_guess_block accepts any kind of node,

+              despite the fact that the formal is a junction.  But

+              I don't want to have to change it all over the place

+              until I know it works.

+    */

+

+	if ( j->ntype != nJunction && j->ntype != nAction) return j;

+

+	gblock = first_item_is_guess_block((Junction *)j);

+

+	if ( gblock!=NULL )

+	{

+		Junction *past = gblock->end;

+		Junction *p;

+		require(past!=NULL, "analysis_point: no end block on (...)? block");

+

+		for (p=(Junction *)past->p1; p!=NULL; )

+		{

+			if ( p->ntype==nAction )

+			{

+				p=(Junction *)((ActionNode *)p)->next;

+				continue;

+			}

+			if ( p->ntype!=nJunction )

+			{

+                past->alpha_beta_guess_end=1;           /* MR14 */

+				return (Junction *)past->p1;

+			}

+			if ( p->jtype==EndBlk || p->jtype==EndRule )

+			{

+				return j;

+			}

+/* MR6                                									      */

+/* MR6	A guess block is of the form "(alpha)? beta" or "(alpha)?".           */

+/* MR6  When beta is omitted (second form) this means "(alpha)? alpha".       */

+/* MR6  The program does not store another copy of alpha in this case.        */

+/* MR6  During analysis when the program needs to know what follows the       */

+/* MR6    guess clause.  It calls this routine.                               */

+/* MR6                                                                        */

+/* MR6      If it is of the form "(alpha)? beta" it returns a pointer to beta.*/

+/* MR6                                                                        */

+/* MR6      If it is of the form "(alpha)?" it returns a pointer to the guess */

+/* MR6        block itself thereby reusing the junction tree.                 */

+/* MR6                                                                        */

+/* MR6  It works by searching the "next in sequence" chain (skipping actions) */

+/* MR6    searching for a RuleRef or Token node.  (Those are the only 4 kinds */

+/* MR6    of nodes: Junctions, RuleRef, Token, and Action.)                   */

+/* MR6                                                                        */

+/* MR6  This won't work for the special case "(alpha)? ()" because it has no  */

+/* MR6    rule references or token nodes.  It eventually encounters a         */

+/* MR6	  junction of type EndBlk or EndRule and says to its caller: nothing  */

+/* MR6    more here to analyze - must be of the form "(alpha)?".              */

+/* MR6                                                                        */

+/* MR6  In the case of "(alpha)? ()" it should return a pointer to "()"       */

+/* MR6                                                                        */

+/* MR6  I think.                                                              */

+/* MR6                                                                        */

+			if ( p->jtype!=Generic) {		                           /* MR6 */

+                past->alpha_beta_guess_end=1;                          /* MR14 */

+				return (Junction *)past->p1;                           /* MR6 */

+			};					                                       /* MR6 */

+   			p=(Junction *)p->p1;

+		}

+	}

+	return j;

+}

+

+set

+#ifdef __USE_PROTOS

+First( Junction *j, int k, int jtype, int *max_k )

+#else

+First( j, k, jtype, max_k )

+Junction *j;

+int k;

+int jtype;

+int *max_k;

+#endif

+{

+	Junction *alt1, *alt2;

+	set a, rk, fCurBlk;

+	int savek;

+	int p1, p2;

+

+    int     save_maintainBackTrace;

+

+	require(j->ntype==nJunction, "First: non junction passed");

+

+	/* C o m p u t e  F I R S T  s e t  w i t h  k  l o o k a h e a d */

+	fCurBlk = rk = empty;

+	for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2 )

+	{

+		Junction * p = NULL;

+		Junction * p1junction = NULL;

+		p = analysis_point((Junction *)alt1->p1);

+		p1junction = (Junction *) (alt1->p1);

+#if 0

+		if (p != p1junction) {

+			fprintf(stdout,"Analysis point for #%d is #%d", p1junction->seq, p->seq); /* debug */

+		}

+#endif

+		REACH(p, k, &rk, alt1->fset[k]);

+		require(set_nil(rk), "rk != nil");

+		set_free(rk);

+		set_orin(&fCurBlk, alt1->fset[k]);

+	}

+

+	/* D e t e c t  A m b i g u i t i e s */

+	*max_k = 1;

+	for (p1=1,alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2, p1++)

+	{

+		for (p2=1,alt2=(Junction *)alt1->p2; alt2!=NULL; alt2 = (Junction *)alt2->p2, p2++)

+		{

+			savek = k;

+			a = set_and(alt1->fset[k], alt2->fset[k]);

+			while ( !set_nil(a) )

+			{

+				/* if we have hit the max k requested, just give warning */

+				if ( j->approx==k ) {

+				}

+

+				if ( k==CLL_k )

+				{

+#ifdef NOT_USED

+***					int save_LL_k = LL_k;

+***					int save_CLL_k = CLL_k;

+***					/* Get new LL_k from interactive feature if enabled */

+***					if ( AImode )

+***						AmbiguityDialog(j, jtype, alt1, alt2, &CLL_k, &LL_k);

+#endif

+					*max_k = CLL_k;

+                    save_maintainBackTrace=MR_MaintainBackTrace;

+                    if (AlphaBetaTrace) MR_MaintainBackTrace=0;

+					HandleAmbiguity(j, alt1, alt2, jtype);

+                    MR_MaintainBackTrace=save_maintainBackTrace;

+					break;

+				}

+				else

+				{

+					Junction *p = analysis_point((Junction *)alt1->p1);

+					Junction *q = analysis_point((Junction *)alt2->p1);

+					k++;	/* attempt ambig alts again with more lookahead */

+

+					REACH(p, k, &rk, alt1->fset[k]);

+					require(set_nil(rk), "rk != nil");

+					REACH(q, k, &rk, alt2->fset[k]);

+					require(set_nil(rk), "rk != nil");

+					set_free(a);

+					a = set_and(alt1->fset[k], alt2->fset[k]);

+					if ( k > *max_k ) *max_k = k;

+				}

+			}

+			set_free(a);

+			k = savek;

+		}

+	}

+

+	return fCurBlk;

+}

diff --git a/Source/Pccts/antlr/fset2.c b/Source/Pccts/antlr/fset2.c
new file mode 100644
index 0000000..7f686a5
--- /dev/null
+++ b/Source/Pccts/antlr/fset2.c
@@ -0,0 +1,2250 @@
+/*

+ * fset2.c

+ *

+ * Compute FIRST sets for full LL(k)

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#include <stdlib.h>

+

+#ifdef PCCTS_USE_STDARG

+#include <stdarg.h>

+#else

+#include <varargs.h>

+#endif

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+

+/* ick! globals.  Used by permute() to track which elements of a set have been used */

+

+static int *findex;

+set *fset;              /* MR11 make global */

+static unsigned **ftbl;

+static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */

+int ConstrainSearch;

+int maxk;               /* set to initial k upon tree construction request */

+                        /* MR11 make global */

+static Tree *FreeList = NULL;

+

+#ifdef __USE_PROTOS

+static int tmember_of_context(Tree *, Predicate *);

+#else

+static int tmember_of_context();

+#endif

+

+#if TREE_DEBUG

+set     set_of_tnodes_in_use;

+int     stop_on_tnode_seq_number=(-1);     /* (-1) to disable */

+#endif

+

+/* Do root

+ * Then each sibling

+ */

+

+void

+#ifdef __USE_PROTOS

+preorder( Tree *tree )

+#else

+preorder( tree )

+Tree *tree;

+#endif

+{

+	if ( tree == NULL ) return;

+	if ( tree->down != NULL ) fprintf(stderr, " (");

+	if ( tree->token == ALT ) fprintf(stderr, " ALT");

+	else fprintf(stderr, " %s", TerminalString(tree->token));

+	if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk);

+	preorder(tree->down);

+	if ( tree->down != NULL ) fprintf(stderr, " )");

+	preorder(tree->right);

+}

+

+#ifdef __USE_PROTOS

+int MR_tree_matches_constraints(int k,set * constrain,Tree *t)

+#else

+int MR_tree_matches_constraints(k,constrain,t)

+  int       k;

+  set *     constrain;

+  Tree *    t;

+#endif

+{

+  int       i;

+  Tree      *u;

+

+  if (k == 0) return 1;

+

+  /* for testing guard predicates: if the guard tree is shorter

+     than the constraint then it is a match.  The reason is that

+     a guard of (A B) should be equivalent to a guard of (A B . . .)

+     where "." matches every token.  Thus a match which runs out

+     of tree before constraint is a match.

+  */

+

+  if (t == NULL) return 1;

+  require (set_deg(constrain[0]) == 1,

+            "MR_tree_matches_constraints: set_deg != 1");

+  i=set_int(constrain[0]);

+  if (t->token != i) return 0;

+  if (k-1 == 0) return 1;

+  for (u=t->down; u != NULL; u=u->right) {

+    if (MR_tree_matches_constraints(k-1,&constrain[1],u)) {

+       return 1;

+    };

+  };

+  return 0;

+}

+

+/* check the depth of each primary sibling to see that it is exactly

+ * k deep. e.g.;

+ *

+ *	ALT

+ *   |

+ *   A ------- B

+ *   |         |

+ *   C -- D    E

+ *

+ * Remove all branches <= k deep.

+ *

+ * Added by TJP 9-23-92 to make the LL(k) constraint mechanism to work.

+ */

+

+static int pruneCount=0;

+static int prunePeak=200;

+

+Tree *

+#ifdef __USE_PROTOS

+prune( Tree *t, int k )

+#else

+prune( t, k )

+Tree *t;

+int k;

+#endif

+{

+    pruneCount++;

+    if (pruneCount > prunePeak+100) {

+      prunePeak=pruneCount;

+#if 0

+***   fprintf(stderr,"pruneCount=%d\n",pruneCount);

+/***  preorder(t);   ***/

+***   fprintf(stderr,"\n",pruneCount);

+#endif

+    };

+    if ( t == NULL ) {

+        pruneCount--;

+        return NULL;

+    };

+    if ( t->token == ALT ) fatal_internal("prune: ALT node in FIRST tree");

+    if ( t->right!=NULL ) t->right = prune(t->right, k);

+    if ( k>1 )

+	{

+		if ( t->down!=NULL ) t->down = prune(t->down, k-1);

+		if ( t->down == NULL )

+		{

+			Tree *r = t->right;

+			t->right = NULL;

+			Tfree(t);

+            pruneCount--;

+			return r;

+		}

+	}

+    pruneCount--;

+    return t;

+}

+

+/* build a tree (root child1 child2 ... NULL) */

+#ifdef PCCTS_USE_STDARG

+Tree *tmake(Tree *root, ...)

+#else

+Tree *tmake(va_alist)

+va_dcl

+#endif

+{

+	Tree *w;

+	va_list ap;

+	Tree *child, *sibling=NULL, *tail=NULL;

+#ifndef PCCTS_USE_STDARG

+	Tree *root;

+#endif

+

+#ifdef PCCTS_USE_STDARG

+	va_start(ap, root);

+#else

+	va_start(ap);

+	root = va_arg(ap, Tree *);

+#endif

+	child = va_arg(ap, Tree *);

+	while ( child != NULL )

+	{

+#ifdef DUM

+		/* added "find end of child" thing TJP March 1994 */

+		for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */

+#else

+		w = child;

+#endif

+

+		if ( sibling == NULL ) {sibling = child; tail = w;}

+		else {tail->right = child; tail = w;}

+		child = va_arg(ap, Tree *);

+	}

+

+	/* was "root->down = sibling;" */

+	if ( root==NULL ) root = sibling;

+	else root->down = sibling;

+

+	va_end(ap);

+	return root;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tnode( int tok )

+#else

+tnode( tok )

+int tok;

+#endif

+{

+	Tree *p, *newblk;

+	static int n=0;

+	

+	if ( FreeList == NULL )

+	{

+		/*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/

+		if ( TreeResourceLimit > 0 )

+		{

+			if ( (n+TreeBlockAllocSize) >= TreeResourceLimit )

+			{

+				fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);

+				fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n",

+								CurAmbigAlt1,

+								CurAmbigAlt2,

+								CurAmbigbtype);

+				exit(PCCTS_EXIT_FAILURE);

+			}

+		}

+		newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree));

+		if ( newblk == NULL )

+		{

+			fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);

+			fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n",

+							CurAmbigAlt1,

+							CurAmbigAlt2,

+							CurAmbigbtype);

+			exit(PCCTS_EXIT_FAILURE);

+		}

+		n += TreeBlockAllocSize;

+		for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++)

+		{

+			p->right = FreeList;	/* add all new Tree nodes to Free List */

+			FreeList = p;

+		}

+	}

+	p = FreeList;

+	FreeList = FreeList->right;		/* remove a tree node */

+	p->right = NULL;				/* zero out ptrs */

+	p->down = NULL;

+	p->token = tok;

+

+    TnodesAllocated++;                                      /* MR10 */

+    TnodesInUse++;                                          /* MR10 */

+    if (TnodesInUse > TnodesPeak) TnodesPeak=TnodesInUse;   /* MR10 */

+

+#ifdef TREE_DEBUG

+	require(!p->in_use, "tnode: node in use!");

+	p->in_use = 1;

+    p->seq=TnodesAllocated;

+    set_orel( (unsigned) TnodesAllocated,&set_of_tnodes_in_use);

+    if (stop_on_tnode_seq_number == p->seq) {

+      fprintf(stderr,"\n*** just allocated tnode #%d ***\n",

+            stop_on_tnode_seq_number);

+    };

+#endif

+	return p;

+}

+

+static Tree *

+#ifdef __USE_PROTOS

+eofnode( int k )

+#else

+eofnode( k )

+int k;

+#endif

+{

+	Tree *t=NULL;

+	int i;

+

+	for (i=1; i<=k; i++)

+	{

+		t = tmake(tnode((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), t, NULL);

+	}

+	return t;

+}

+

+

+

+void

+#ifdef __USE_PROTOS

+_Tfree( Tree *t )

+#else

+_Tfree( t )

+Tree *t;

+#endif

+{

+	if ( t!=NULL )

+	{

+#ifdef TREE_DEBUG

+        if (t->seq == stop_on_tnode_seq_number) {

+           fprintf(stderr,"\n*** just freed tnode #%d ***\n",t->seq);

+        };

+		require(t->in_use, "_Tfree: node not in use!");

+		t->in_use = 0;

+        set_rm( (unsigned) t->seq,set_of_tnodes_in_use);

+#endif

+		t->right = FreeList;

+		FreeList = t;

+        TnodesInUse--;                   /* MR10 */

+	}

+}

+

+/* tree duplicate */

+Tree *

+#ifdef __USE_PROTOS

+tdup( Tree *t )

+#else

+tdup( t )

+Tree *t;

+#endif

+{

+	Tree *u;

+	

+	if ( t == NULL ) return NULL;

+	u = tnode(t->token);

+	u->v.rk = t->v.rk;

+	u->right = tdup(t->right);

+	u->down = tdup(t->down);

+	return u;

+}

+

+/* tree duplicate (assume tree is a chain downwards) */

+Tree *

+#ifdef __USE_PROTOS

+tdup_chain( Tree *t )

+#else

+tdup_chain( t )

+Tree *t;

+#endif

+{

+	Tree *u;

+	

+	if ( t == NULL ) return NULL;

+	u = tnode(t->token);

+	u->v.rk = t->v.rk;

+	u->down = tdup(t->down);

+	return u;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tappend( Tree *t, Tree *u )

+#else

+tappend( t, u )

+Tree *t;

+Tree *u;

+#endif

+{

+	Tree *w;

+

+/*** fprintf(stderr, "tappend(");

+ *** preorder(t); fprintf(stderr, ",");

+ *** preorder(u); fprintf(stderr, " )\n");

+*/

+	if ( t == NULL ) return u;

+	if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u);

+	for (w=t; w->right!=NULL; w=w->right) {;}

+	w->right = u;

+	return t;

+}

+

+/* dealloc all nodes in a tree */

+void

+#ifdef __USE_PROTOS

+Tfree( Tree *t )

+#else

+Tfree( t )

+Tree *t;

+#endif

+{

+	if ( t == NULL ) return;

+	Tfree( t->down );

+	Tfree( t->right );

+	_Tfree( t );

+}

+

+/* find all children (alts) of t that require remaining_k nodes to be LL_k

+ * tokens long.

+ *

+ * t-->o

+ *     |

+ *     a1--a2--...--an		<-- LL(1) tokens

+ *     |   |        |

+ *     b1  b2  ...  bn		<-- LL(2) tokens

+ *     |   |        |

+ *     .   .        .

+ *     .   .        .

+ *     z1  z2  ...  zn		<-- LL(LL_k) tokens

+ *

+ * We look for all [Ep] needing remaining_k nodes and replace with u.

+ * u is not destroyed or actually used by the tree (a copy is made).

+ */

+Tree *

+#ifdef __USE_PROTOS

+tlink( Tree *t, Tree *u, int remaining_k )

+#else

+tlink( t, u, remaining_k )

+Tree *t;

+Tree *u;

+int remaining_k;

+#endif

+{

+	Tree *p;

+	require(remaining_k!=0, "tlink: bad tree");

+

+	if ( t==NULL ) return NULL;

+	/*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/

+	if ( t->token == EpToken && t->v.rk == remaining_k )

+	{

+		require(t->down==NULL, "tlink: invalid tree");

+		if ( u == NULL ) {

+/* MR10 */  Tree  *tt=t->right;

+/* MR10 */  _Tfree(t);

+/* MR10 */  return tt;

+        };

+		p = tdup( u );

+		p->right = t->right;

+		_Tfree( t );

+		return p;

+	}

+	t->down = tlink(t->down, u, remaining_k);

+	t->right = tlink(t->right, u, remaining_k);

+	return t;

+}

+

+/* remove as many ALT nodes as possible while still maintaining semantics */

+Tree *

+#ifdef __USE_PROTOS

+tshrink( Tree *t )

+#else

+tshrink( t )

+Tree *t;

+#endif

+{

+	if ( t == NULL ) return NULL;

+	t->down = tshrink( t->down );

+	t->right = tshrink( t->right );

+	if ( t->down == NULL )

+	{

+		if ( t->token == ALT )

+		{

+			Tree *u = t->right;

+			_Tfree(t);

+			return u;			/* remove useless alts */

+		}

+		return t;

+	}

+

+	/* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */

+	if ( t->token == ALT && t->down->right == NULL)

+	{

+		Tree *u = t->down;

+		u->right = t->right;

+		_Tfree( t );

+		return u;

+	}

+	/* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */

+	if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL )

+	{

+		Tree *u = t->down->down;

+		_Tfree( t->down );

+		t->down = u;

+		return t;

+	}

+	return t;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tflatten( Tree *t )

+#else

+tflatten( t )

+Tree *t;

+#endif

+{

+	if ( t == NULL ) return NULL;

+	t->down = tflatten( t->down );

+	t->right = tflatten( t->right );

+	if ( t->down == NULL ) return t;

+	

+	if ( t->token == ALT )

+	{

+		Tree *u;

+		/* find tail of children */

+		for (u=t->down; u->right!=NULL; u=u->right) {;}

+		u->right = t->right;

+		u = t->down;

+		_Tfree( t );

+		return u;

+	}

+	return t;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tJunc( Junction *p, int k, set *rk )

+#else

+tJunc( p, k, rk )

+Junction *p;

+int k;

+set *rk;

+#endif

+{

+	Tree *t=NULL, *u=NULL;

+	Junction *alt;

+	Tree *tail=NULL, *r;

+

+#ifdef DBG_TRAV

+	fprintf(stderr, "tJunc(%d): %s in rule %s\n", k,

+			decodeJType[p->jtype], ((Junction *)p)->rname);

+#endif

+

+/* MR14 */    if (AlphaBetaTrace && p->alpha_beta_guess_end) {

+/* MR14 */         warnFL(

+/* MR14 */           "not possible to compute follow set for alpha in an \"(alpha)? beta\" block.  ",

+/* MR14 */                 FileStr[p->file],p->line);

+/* MR14 */         MR_alphaBetaTraceReport();

+/* MR14 */    };

+

+/* MR14 */    if (p->alpha_beta_guess_end) {

+/* MR14 */      return NULL;

+/* MR14 */    }

+

+	if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||

+		 p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk )

+	{

+		if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) {

+			require(p->lock!=NULL, "rJunc: lock array is NULL");

+			if ( p->lock[k] ) return NULL;

+			p->lock[k] = TRUE;

+		}

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+		TRAV(p->p1, k, rk, tail);

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+

+		if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;}

+		r = tmake(tnode(ALT), tail, NULL);

+		for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2)

+		{

+			/* if this is one of the added optional alts for (...)+ then break */

+			if ( alt->ignore ) break;

+

+			if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;}

+			else

+			{

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+				TRAV(alt->p1, k, rk, tail->right);

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+				if ( tail->right != NULL ) tail = tail->right;

+			}

+		}

+		if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE;

+#ifdef DBG_TREES

+		fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n");

+#endif

+		if ( r->down == NULL ) {_Tfree(r); return NULL;}

+		return r;

+	}

+

+	if ( p->jtype==EndRule )

+	{

+		if ( p->halt )						/* don't want FOLLOW here? */

+		{

+/****		if ( ContextGuardTRAV ) return NULL; ****/

+			set_orel( (unsigned) k, rk);	/* indicate this k value needed */ /* MR10 cast */

+			t = tnode(EpToken);

+			t->v.rk = k;

+			return t;

+		}

+		require(p->lock!=NULL, "rJunc: lock array is NULL");

+		if ( p->lock[k] ) return NULL;

+		/* if no FOLLOW assume k EOF's */

+		if ( p->p1 == NULL ) return eofnode(k);

+		p->lock[k] = TRUE;

+	}

+

+/* MR14 */	if (p->p1 != NULL && p->guess &&  p->guess_analysis_point == NULL) {

+/* MR14 */    Node * guess_point;

+/* MR14 */    guess_point=(Node *)analysis_point(p);

+/* MR14 */    if (guess_point == (Node *)p) {

+/* MR14 */      guess_point=p->p1;

+/* MR14 */    }

+/* MR14 */    p->guess_analysis_point=guess_point;

+/* MR14 */  }	

+

+	if ( p->p2 == NULL )

+	{

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+/* M14 */        if (p->guess_analysis_point != NULL) {

+/* M14 */ 		   TRAV(p->guess_analysis_point, k, rk,t);

+/* M14 */        } else {

+        		   TRAV(p->p1, k, rk,t);

+/* M14 */        }

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+

+		if ( p->jtype==EndRule ) p->lock[k]=FALSE;

+		return t;

+	}

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+/* M14 */        if (p->guess_analysis_point != NULL) {

+/* M14 */ 		   TRAV(p->guess_analysis_point, k, rk,t);

+/* M14 */        } else {

+        		   TRAV(p->p1, k, rk,t);

+/* M14 */        }

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+

+	if ( p->jtype!=RuleBlk && /* MR14 */ !p->guess) TRAV(p->p2, k, rk, u);

+

+	if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */

+

+	if ( t==NULL ) return tmake(tnode(ALT), u, NULL);

+	return tmake(tnode(ALT), t, u, NULL);

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tRuleRef( RuleRefNode *p, int k, set *rk_out )

+#else

+tRuleRef( p, k, rk_out )

+RuleRefNode *p;

+int k;

+set *rk_out;

+#endif

+{

+	int k2;

+	Tree *t=NULL, *u=NULL;

+	Junction *r;

+	set rk, rk2;

+	int save_halt;

+	RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);

+	

+#ifdef DBG_TRAV

+	fprintf(stderr, "tRuleRef: %s\n", p->text);

+#endif

+	if ( q == NULL )

+	{

+		TRAV(p->next, k, rk_out, t);/* ignore undefined rules */

+		return t;

+	}

+	rk = rk2 = empty;

+    if (RulePtr == NULL) fatal("RulePtr==NULL");

+	r = RulePtr[q->rulenum];

+	if ( r->lock[k] ) return NULL;

+	save_halt = r->end->halt;

+	r->end->halt = TRUE;		/* don't let reach fall off end of rule here */

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+	TRAV(r, k, &rk, t);

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+

+	r->end->halt = save_halt;

+#ifdef DBG_TREES

+	fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n");

+#endif

+	t = tshrink( t );

+	while ( !set_nil(rk) ) {	/* any k left to do? if so, link onto tree */

+		k2 = set_int(rk);

+		set_rm(k2, rk);

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR10 */    };

+

+		TRAV(p->next, k2, &rk2, u);

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      MR_pointerStackPop(&MR_BackTraceStack);

+/* MR10 */    };

+

+		t = tlink(t, u, k2);	/* any alts missing k2 toks, add u onto end */

+        Tfree(u);               /* MR10 */

+	}

+	set_free(rk);				/* rk is empty, but free it's memory */

+	set_orin(rk_out, rk2);		/* remember what we couldn't do */

+	set_free(rk2);

+	return t;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tToken( TokNode *p, int k, set *rk )

+#else

+tToken( p, k, rk )

+TokNode *p;

+int k;

+set *rk;

+#endif

+{

+	Tree *t=NULL, *tset=NULL, *u;

+

+	if (ConstrainSearch) {

+      if (MR_AmbSourceSearch) {

+		require(constrain>=fset&&constrain<=&(fset[CLL_k]),"tToken: constrain is not a valid set");

+      } else {

+		require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set");

+      };

+      constrain = &fset[maxk-k+1];

+	}

+

+#ifdef DBG_TRAV

+        	fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token));

+        	if ( ConstrainSearch ) {

+        		fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n");

+        	}

+#endif

+

+	/* is it a meta token (set of tokens)? */

+

+	if ( !set_nil(p->tset) )

+	{

+		unsigned e=0;

+		set a;

+		Tree *n, *tail = NULL;

+

+		if ( ConstrainSearch ) {

+          a = set_and(p->tset, *constrain);

+          if (set_nil(a)) {         /* MR10 */

+            set_free(a);            /* MR11 */

+            return NULL;            /* MR10 */

+          };                        /* MR10 */

+		} else {

+          a = set_dup(p->tset);

+        };

+

+		for (; !set_nil(a); set_rm(e, a))

+		{

+			e = set_int(a);

+			n = tnode(e);

+			if ( tset==NULL ) { tset = n; tail = n; }

+			else { tail->right = n; tail = n; }

+		}

+		set_free( a );

+	}

+	else if ( ConstrainSearch && !set_el(p->token, *constrain) )

+    {

+/*      fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token),

+                k);*/

+        return NULL;

+    }

+	else {

+        tset = tnode( p->token );

+    };

+

+/* MR10 */    if (MR_MaintainBackTrace) {

+/* MR10 */      if (k == 1) {

+/* MR10 */        MR_pointerStackPush(&MR_BackTraceStack,p);

+/* MR13 */        if (MR_SuppressSearch) {

+/* MR13 */          MR_suppressSearchReport();

+/* MR13 */        } else {

+/* MR10 */          MR_backTraceReport();

+/* MR13 */        };

+/* MR10 */        MR_pointerStackPop(&MR_BackTraceStack);

+/* MR11 */        Tfree(tset);

+/* MR11 */        return NULL;

+/* MR10 */      };

+/* MR10 */    };

+

+	if ( k == 1 ) return tset;

+

+    if (MR_MaintainBackTrace) {

+      MR_pointerStackPush(&MR_BackTraceStack,p);

+    };

+

+	TRAV(p->next, k-1, rk, t);

+

+    if (MR_MaintainBackTrace) {

+      Tfree(t);

+      Tfree(tset);

+      MR_pointerStackPop(&MR_BackTraceStack);

+      return NULL;

+    };

+

+	/* here, we are positive that, at least, this tree will not contribute

+	 * to the LL(2) tree since it will be too shallow, IF t==NULL.

+	 * If doing a context guard walk, then don't prune.

+	 */

+	if ( t == NULL && !ContextGuardTRAV )	/* tree will be too shallow */

+	{

+		if ( tset!=NULL ) Tfree( tset );

+		return NULL;

+	}

+#ifdef DBG_TREES

+	fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n");

+#endif

+

+	/* if single token root, then just make new tree and return */

+    /* MR10 - set_nil(p->tset) isn't a good test because of ConstraintSearch */

+

+	if (tset->right == NULL) return tmake(tset, t, NULL);    /* MR10 */

+

+	/* here we must make a copy of t as a child of each element of the tset;

+	 * e.g., "T1..T3 A" would yield ( nil ( T1 A ) ( T2 A ) ( T3 A ) )

+	 */

+	for (u=tset; u!=NULL; u=u->right)

+	{

+		/* make a copy of t and hook it onto bottom of u */

+		u->down = tdup(t);

+	}

+	Tfree( t );

+#ifdef DBG_TREES

+	fprintf(stderr, "range is:"); preorder(tset); fprintf(stderr, "\n");

+#endif

+	return tset;

+}

+

+Tree *

+#ifdef __USE_PROTOS

+tAction( ActionNode *p, int k, set *rk )

+#else

+tAction( p, k, rk )

+ActionNode *p;

+int k;

+set *rk;

+#endif

+{

+	Tree        *t=NULL;

+    set         *save_fset=NULL;

+    int         i;

+

+	/* fprintf(stderr, "tAction\n"); */

+

+/*  An MR_SuppressSearch is looking for things that can be

+      reached even when the predicate is false.

+

+    There are three kinds of predicates:

+        plain:              r1: <<p>>? r2

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

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

+

+    Of the three kinds of predicates, only a guard predicate

+      has things which are reachable even when the predicate

+      is false.  To be reachable the constraint must *not*

+      match the guard.

+

+*/

+

+    if (p->is_predicate && MR_SuppressSearch) {

+

+      Predicate     *pred=p->guardpred;

+

+      if (pred == NULL) {

+        t=NULL;

+        goto EXIT;

+      };

+      constrain = &fset[maxk-k+1];

+      if (pred->k == 1) {

+        set     dif;

+        dif=set_dif(*constrain,pred->scontext[1]);

+        if (set_nil(dif)) {

+          set_free(dif);

+          t=NULL;

+          goto EXIT;

+        };

+        set_free(dif);

+      } else {

+        if (MR_tree_matches_constraints(k,constrain,pred->tcontext)) {

+          t=NULL;

+          goto EXIT;

+        };

+      }

+    };

+

+    /* The ampersand predicate differs from the

+         other predicates because its first set

+         is a subset of the first set behind the predicate

+

+            r1: (A)? && <<p>>? r2 ;

+            r2: A | B;

+

+       In this case first[1] of r1 is A, even

+         though first[1] of r2 is {A B}.

+    */

+

+    if (p->is_predicate && p->ampersandPred != NULL) {

+

+      Predicate     *pred=p->ampersandPred;

+      Tree          *tAND;

+      Tree          *tset;

+

+      if (k <= pred->k) {

+        if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);

+        TRAV(p->guardNodes,k,rk,t);

+        if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);

+        return t;

+      } else {

+        require (k>1,"tAction for ampersandpred: k <= 1");

+        if (ConstrainSearch) {

+          if (MR_AmbSourceSearch) {

+    		require(constrain>=fset&&constrain<=&(fset[CLL_k]),

+                                "tToken: constrain is not a valid set");

+          } else {

+    		require(constrain>=fset&&constrain<=&(fset[LL_k]),

+                                "tToken: constrain is not a valid set");

+          };

+          save_fset=(set *) calloc (CLL_k+1,sizeof(set));

+          require (save_fset != NULL,"tAction save_fset alloc");

+          for (i=1; i <= CLL_k ; i++) {

+            save_fset[i]=set_dup(fset[i]);

+          };

+          if (pred->k == 1) {

+            constrain = &fset[maxk-k+1];

+            set_andin(constrain,pred->scontext[1]);

+            if (set_nil(*constrain)) {

+              t=NULL;

+              goto EXIT;

+            };

+          } else {

+            constrain = &fset[maxk-k+1];

+            if (! MR_tree_matches_constraints(pred->k,constrain,pred->tcontext)) {

+               t=NULL;

+               goto EXIT;

+            };  /* end loop on i          */

+          }; /* end loop on pred scontext/tcontext */

+        }; /* end if on k > pred->k     */

+      }; /* end if on constrain search  */

+

+      TRAV(p->next,k,rk,t);

+

+      if (t != NULL) {

+        t=tshrink(t);

+        t=tflatten(t);

+        t=tleft_factor(t);

+        if (pred->tcontext != NULL) {

+          tAND=MR_computeTreeAND(t,pred->tcontext);

+        } else {

+          tset=MR_make_tree_from_set(pred->scontext[1]);

+          tAND=MR_computeTreeAND(t,tset);

+          Tfree(tset);

+        };

+        Tfree(t);

+        t=tAND;

+      };

+      goto EXIT;

+

+    }; /* end if on ampersand predicate */

+

+    TRAV(p->next,k,rk,t);

+

+EXIT:

+    if (save_fset != NULL) {

+      for (i=1 ; i <= CLL_k ; i++) {

+        set_free(fset[i]);

+        fset[i]=save_fset[i];

+      };

+      free ( (char *) save_fset);

+    };

+	return t;

+}

+

+/* see if e exists in s as a possible input permutation (e is always a chain) */

+

+int

+#ifdef __USE_PROTOS

+tmember( Tree *e, Tree *s )

+#else

+tmember( e, s )

+Tree *e;

+Tree *s;

+#endif

+{

+	if ( e==NULL||s==NULL ) return 0;

+/** fprintf(stderr, "tmember(");

+***	preorder(e); fprintf(stderr, ",");

+***	preorder(s); fprintf(stderr, " )\n");

+*/

+	if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down);

+	if ( e->token!=s->token )

+	{

+		if ( s->right==NULL ) return 0;

+		return tmember(e, s->right);

+	}

+	if ( e->down==NULL && s->down == NULL ) return 1;

+	if ( tmember(e->down, s->down) ) return 1;

+	if ( s->right==NULL ) return 0;

+	return tmember(e, s->right);

+}

+

+/* see if e exists in s as a possible input permutation (e is always a chain);

+ * Only check s to the depth of e.  In other words, 'e' can be a shorter

+ * sequence than s.

+ */

+int

+#ifdef __USE_PROTOS

+tmember_constrained( Tree *e, Tree *s)

+#else

+tmember_constrained( e, s )

+Tree *e;

+Tree *s;

+#endif

+{

+	if ( e==NULL||s==NULL ) return 0;

+/**	fprintf(stderr, "tmember_constrained(");

+***	preorder(e); fprintf(stderr, ",");

+***	preorder(s); fprintf(stderr, " )\n");

+**/

+	if ( s->token == ALT && s->right == NULL )

+		return tmember_constrained(e, s->down);

+	if ( e->token!=s->token )

+	{

+		if ( s->right==NULL ) return 0;

+		return tmember_constrained(e, s->right);

+	}

+	if ( e->down == NULL ) return 1; /* if s is matched to depth of e return */

+	if ( tmember_constrained(e->down, s->down) ) return 1;

+	if ( s->right==NULL ) return 0;

+	return tmember_constrained(e, s->right);

+}

+

+/* combine (? (A t) ... (A u) ...) into (? (A t u)) */

+Tree *

+#ifdef __USE_PROTOS

+tleft_factor( Tree *t )

+#else

+tleft_factor( t )

+Tree *t;

+#endif

+{

+	Tree *u, *v, *trail, *w;

+

+	/* left-factor what is at this level */

+	if ( t == NULL ) return NULL;

+	for (u=t; u!=NULL; u=u->right)

+	{

+		trail = u;

+		v=u->right;

+		while ( v!=NULL )

+		{

+			if ( u->token == v->token )

+			{

+				if ( u->down!=NULL )

+				{

+					for (w=u->down; w->right!=NULL; w=w->right) {;}

+					w->right = v->down;	/* link children together */

+				}

+				else u->down = v->down;

+				trail->right = v->right;		/* unlink factored node */

+				_Tfree( v );

+				v = trail->right;

+			}

+			else {trail = v; v=v->right;}

+		}

+	}

+	/* left-factor what is below */

+	for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down );

+	return t;

+}

+

+/* remove the permutation p from t if present */

+Tree *

+#ifdef __USE_PROTOS

+trm_perm( Tree *t, Tree *p )

+#else

+trm_perm( t, p )

+Tree *t;

+Tree *p;

+#endif

+{

+	/*

+	fprintf(stderr, "trm_perm(");

+	preorder(t); fprintf(stderr, ",");

+	preorder(p); fprintf(stderr, " )\n");

+	*/

+	if ( t == NULL || p == NULL ) return NULL;

+	if ( t->token == ALT )

+	{

+		t->down = trm_perm(t->down, p);

+		if ( t->down == NULL ) 				/* nothing left below, rm cur node */

+		{

+			Tree *u = t->right;

+			_Tfree( t );

+			return trm_perm(u, p);

+		}

+		t->right = trm_perm(t->right, p);	/* look for more instances of p */

+		return t;

+	}

+	if ( p->token != t->token )				/* not found, try a sibling */

+	{

+		t->right = trm_perm(t->right, p);

+		return t;

+	}

+	t->down = trm_perm(t->down, p->down);

+	if ( t->down == NULL ) 					/* nothing left below, rm cur node */

+	{

+		Tree *u = t->right;

+		_Tfree( t );

+		return trm_perm(u, p);

+	}

+	t->right = trm_perm(t->right, p);		/* look for more instances of p */

+	return t;

+}

+

+/* add the permutation 'perm' to the LL_k sets in 'fset' */

+void

+#ifdef __USE_PROTOS

+tcvt( set *fset, Tree *perm )

+#else

+tcvt( fset, perm )

+set *fset;

+Tree *perm;

+#endif

+{

+	if ( perm==NULL ) return;

+	set_orel(perm->token, fset);

+	tcvt(fset+1, perm->down);

+}

+

+/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1])

+ * as a child.

+ */

+Tree *

+#ifdef __USE_PROTOS

+permute( int k, int max_k )

+#else

+permute( k, max_k )

+int k, max_k;

+#endif

+{

+	Tree *t, *u;

+	

+	if ( k>max_k ) return NULL;

+	if ( ftbl[k][findex[k]] == nil ) return NULL;

+	t = permute(k+1, max_k);

+	if ( t==NULL&&k<max_k )		/* no permutation left below for k+1 tokens? */

+	{

+		findex[k+1] = 0;

+		(findex[k])++;			/* try next token at this k */

+		return permute(k, max_k);

+	}

+	

+	u = tmake(tnode(ftbl[k][findex[k]]), t, NULL);

+	if ( k == max_k ) (findex[k])++;

+	return u;

+}

+

+/* Compute LL(k) trees for alts alt1 and alt2 of p.

+ * function result is tree of ambiguous input permutations

+ *

+ * ALGORITHM may change to look for something other than LL_k size

+ * trees ==> maxk will have to change.

+ */

+Tree *

+#ifdef __USE_PROTOS

+VerifyAmbig( Junction *alt1, Junction *alt2, unsigned **ft, set *fs, Tree **t, Tree **u, int *numAmbig )

+#else

+VerifyAmbig( alt1, alt2, ft, fs, t, u, numAmbig )

+Junction *alt1;

+Junction *alt2;

+unsigned **ft;

+set *fs;

+Tree **t;

+Tree **u;

+int *numAmbig;

+#endif

+{

+	set rk;

+	Tree *perm, *ambig=NULL;

+	Junction *p;

+	int k;

+    int    tnodes_at_start=TnodesAllocated;

+    int    tnodes_at_end;

+    int    tnodes_used;

+    set    *save_fs;

+    int    j;

+

+    save_fs=(set *) calloc(CLL_k+1,sizeof(set));

+    require(save_fs != NULL,"save_fs calloc");

+

+    for (j=0; j <= CLL_k ; j++) save_fs[j]=set_dup(fs[j]);

+

+	maxk = LL_k;				/* NOTE: for now, we look for LL_k */

+	ftbl = ft;

+	fset = fs;

+	constrain = &(fset[1]);

+	findex = (int *) calloc(LL_k+1, sizeof(int));

+	if ( findex == NULL )

+	{

+		fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);

+		fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n",

+						CurAmbigAlt1,

+						CurAmbigAlt2,

+						CurAmbigbtype);

+		exit(PCCTS_EXIT_FAILURE);

+	}

+	for (k=1; k<=LL_k; k++) findex[k] = 0;

+

+	rk = empty;

+	ConstrainSearch = 1;	/* consider only tokens in ambig sets */

+

+	p = analysis_point((Junction *)alt1->p1);

+	TRAV(p, LL_k, &rk, *t);

+	*t = tshrink( *t );

+	*t = tflatten( *t );

+	*t = tleft_factor( *t );    /* MR10 */

+	*t = prune(*t, LL_k);

+	*t = tleft_factor( *t );

+

+/***	fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/

+	if ( *t == NULL )

+	{

+/***	fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/

+		Tfree( *t );	/* kill if impossible to have ambig */

+		*t = NULL;

+	}

+

+	p = analysis_point((Junction *)alt2->p1);

+

+	TRAV(p, LL_k, &rk, *u);

+	*u = tshrink( *u );

+	*u = tflatten( *u );

+	*t = tleft_factor( *t );    /* MR10 */

+	*u = prune(*u, LL_k);

+	*u = tleft_factor( *u );

+/*	fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/

+	if ( *u == NULL )

+	{

+/*		fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/

+		Tfree( *u );

+		*u = NULL;

+	}

+

+	for (k=1; k<=LL_k; k++) set_clr( fs[k] );

+

+	ambig = tnode(ALT);

+	k = 0;

+	if ( *t!=NULL && *u!=NULL )

+	{

+		while ( (perm=permute(1,LL_k))!=NULL )

+		{

+/*			fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/

+			if ( tmember(perm, *t) && tmember(perm, *u) )

+			{

+/*				fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/

+

+				k++;

+				perm->right = ambig->down;

+				ambig->down = perm;

+				tcvt(&(fs[1]), perm);

+			}

+			else Tfree( perm );

+		}

+	}

+

+    for (j=0; j <= CLL_k ; j++) fs[j]=save_fs[j];

+    free( (char *) save_fs);

+

+    tnodes_at_end=TnodesAllocated;

+    tnodes_used=tnodes_at_end - tnodes_at_start;

+

+    if (TnodesReportThreshold > 0 && tnodes_used > TnodesReportThreshold) {

+      fprintf(stdout,"There were %d tuples whose ambiguity could not be resolved by full lookahead\n",k);

+      fprintf(stdout,"There were %d tnodes created to resolve ambiguity between:\n\n",tnodes_used);

+      fprintf(stdout,"  Choice 1: %s  line %d  file %s\n",

+                                 MR_ruleNamePlusOffset( (Node *) alt1),alt1->line,FileStr[alt1->file]);

+      fprintf(stdout,"  Choice 2: %s  line %d  file %s\n",

+                                 MR_ruleNamePlusOffset( (Node *) alt2),alt2->line,FileStr[alt2->file]);

+      for (j=1; j <= CLL_k ; j++) {

+        fprintf(stdout,"\n    Intersection of lookahead[%d] sets:\n",j);

+        MR_dumpTokenSet(stdout,2,fs[j]);

+      };

+      fprintf(stdout,"\n");

+    };

+

+	*numAmbig = k;

+	if ( ambig->down == NULL ) {_Tfree(ambig); ambig = NULL;}

+	free( (char *)findex );

+/*	fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/

+	return ambig;

+}

+

+static Tree *

+#ifdef __USE_PROTOS

+bottom_of_chain( Tree *t )

+#else

+bottom_of_chain( t )

+Tree *t;

+#endif

+{

+    if ( t==NULL ) return NULL;

+    for (; t->down != NULL; t=t->down) {;}

+    return t;

+}

+

+/*

+ * Make a tree from k sets where the degree of the first k-1 sets is 1.

+ */

+Tree *

+#ifdef __USE_PROTOS

+make_tree_from_sets( set *fset1, set *fset2 )

+#else

+make_tree_from_sets( fset1, fset2 )

+set *fset1;

+set *fset2;

+#endif

+{

+	set inter;

+	int i;

+	Tree *t=NULL, *n, *u;

+	unsigned *p,*q;

+	require(LL_k>1, "make_tree_from_sets: LL_k must be > 1");

+

+	/* do the degree 1 sets first */

+	for (i=1; i<=LL_k-1; i++)

+	{

+		inter = set_and(fset1[i], fset2[i]);

+		require(set_deg(inter)==1, "invalid set to tree conversion");

+		n = tnode(set_int(inter));

+		if (t==NULL) t=n; else tmake(t, n, NULL);

+		set_free(inter);

+	}

+

+	/* now add the chain of tokens at depth k */

+	u = bottom_of_chain(t);

+	inter = set_and(fset1[LL_k], fset2[LL_k]);

+	if ( (q=p=set_pdq(inter)) == NULL ) fatal_internal("Can't alloc space for set_pdq");

+	/* first one is linked to bottom, then others are sibling linked */

+	n = tnode(*p++);

+	u->down = n;

+	u = u->down;

+	while ( *p != nil )

+	{

+		n = tnode(*p);

+		u->right = n;

+		u = u->right;

+		p++;

+	}

+	free((char *)q);

+

+	return t;

+}

+

+/* create and return the tree of lookahead k-sequences that are in t, but not

+ * in the context of predicates in predicate list p.

+ */

+Tree *

+#ifdef __USE_PROTOS

+tdif( Tree *ambig_tuples, Predicate *p, set *fset1, set *fset2 )

+#else

+tdif( ambig_tuples, p, fset1, fset2 )

+Tree *ambig_tuples;

+Predicate *p;

+set *fset1;

+set *fset2;

+#endif

+{

+	unsigned **ft;

+	Tree *dif=NULL;

+	Tree *perm;

+	set b;

+	int i,k;

+

+	if ( p == NULL ) return tdup(ambig_tuples);

+

+	ft = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *));

+	require(ft!=NULL, "cannot allocate ft");

+	for (i=1; i<=CLL_k; i++)

+	{

+		b = set_and(fset1[i], fset2[i]);

+		ft[i] = set_pdq(b);

+		set_free(b);

+	}

+	findex = (int *) calloc(LL_k+1, sizeof(int));

+	if ( findex == NULL )

+	{

+		fatal_internal("out of memory in tdif while checking predicates");

+	}

+	for (k=1; k<=LL_k; k++) findex[k] = 0;

+

+#ifdef DBG_TRAV

+	fprintf(stderr, "tdif_%d[", p->k);

+	preorder(ambig_tuples);

+	fprintf(stderr, ",");

+	preorder(p->tcontext);

+	fprintf(stderr, "] =");

+#endif

+

+	ftbl = ft;

+	while ( (perm=permute(1,p->k))!=NULL )

+	{

+#ifdef DBG_TRAV

+		fprintf(stderr, "test perm:"); preorder(perm); fprintf(stderr, "\n");

+#endif

+		if ( tmember_constrained(perm, ambig_tuples) &&

+			 !tmember_of_context(perm, p) )

+		{

+#ifdef DBG_TRAV

+			fprintf(stderr, "satisfied upon"); preorder(perm); fprintf(stderr, "\n");

+#endif

+			k++;

+			if ( dif==NULL ) dif = perm;

+			else

+			{

+				perm->right = dif;

+				dif = perm;

+			}

+		}

+		else Tfree( perm );

+	}

+

+#ifdef DBG_TRAV

+	preorder(dif);

+	fprintf(stderr, "\n");

+#endif

+

+	for (i=1; i<=CLL_k; i++) free( (char *)ft[i] );

+	free((char *)ft);

+	free((char *)findex);

+

+	return dif;

+}

+

+/* is lookahead sequence t a member of any context tree for any

+ * predicate in p?

+ */

+static int

+#ifdef __USE_PROTOS

+tmember_of_context( Tree *t, Predicate *p )

+#else

+tmember_of_context( t, p )

+Tree *t;

+Predicate *p;

+#endif

+{

+	for (; p!=NULL; p=p->right)

+	{

+		if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST )

+			return tmember_of_context(t, p->down);

+		if ( tmember_constrained(t, p->tcontext) ) return 1;

+		if ( tmember_of_context(t, p->down) ) return 1;

+	}

+	return 0;

+}

+

+int

+#ifdef __USE_PROTOS

+is_single_tuple( Tree *t )

+#else

+is_single_tuple( t )

+Tree *t;

+#endif

+{

+	if ( t == NULL ) return 0;

+	if ( t->right != NULL ) return 0;

+	if ( t->down == NULL ) return 1;

+	return is_single_tuple(t->down);

+}

+

+

+/* MR10 Check that a context guard contains only allowed things */

+/* MR10   (mainly token references).                            */

+

+#ifdef __USE_PROTOS

+int contextGuardOK(Node *p,int h,int *hmax)

+#else

+int contextGuardOK(p,h,hmax)

+  Node  *p;

+  int   h;

+  int   *hmax;

+#endif

+{

+    Junction     *j;

+    TokNode      *tn;

+

+    if (p == NULL) return 1;

+    if (p->ntype == nToken) {

+      h++;

+      if (h > *hmax) *hmax=h;

+      tn=(TokNode *)p;

+      if (tn->el_label != NULL) {

+        warnFL(eMsg1("a label (\"%s\") for a context guard element is meaningless",tn->el_label),

+                             FileStr[p->file],p->line);

+      };

+      return contextGuardOK( ( (TokNode *) p)->next,h,hmax);

+    } else if (p->ntype == nAction) {

+      goto Fail;

+    } else if (p->ntype == nRuleRef) {

+      goto Fail;

+    } else {

+      require (p->ntype == nJunction,"Unexpected ntype");

+      j=(Junction *) p;

+      if (j->jtype != Generic &&

+          j->jtype != aSubBlk &&        /* pretty sure this one is allowed */

+/****     j->jtype != aOptBlk && ****/  /* pretty sure this one is allowed */ /* MR11 not any more ! */

+          j->jtype != EndBlk) {

+        errFL("A context guard may not contain an option block: {...} or looping block: (...)* or (...)+",

+                  FileStr[p->file],p->line);

+        contextGuardOK(j->p1,h,hmax);

+        return 0;

+      };

+      /* do both p1 and p2 so use | rather than ||  */

+      return contextGuardOK(j->p2,h,hmax) | contextGuardOK(j->p1,h,hmax);

+    };

+Fail:

+    errFL("A context guard may contain only Token references - guard will be ignored",

+                             FileStr[p->file],p->line);

+    contextGuardOK( ( (ActionNode *) p)->next,h,hmax);

+    return 0;

+}

+

+/*

+ * Look at a (...)? generalized-predicate context-guard and compute

+ * either a lookahead set (k==1) or a lookahead tree for k>1.  The

+ * k level is determined by the guard itself rather than the LL_k

+ * variable.  For example, ( A B )? is an LL(2) guard and ( ID )?

+ * is an LL(1) guard.  For the moment, you can only have a single

+ * tuple in the guard.  Physically, the block must look like this

+ *   --o-->TOKEN-->o-->o-->TOKEN-->o-- ... -->o-->TOKEN-->o--

+ * An error is printed for any other type.

+ */

+Predicate *

+#ifdef __USE_PROTOS

+computePredFromContextGuard(Graph blk,int *msgDone)    /* MR10 */

+#else

+computePredFromContextGuard(blk,msgDone)               /* MR10 */

+  Graph     blk;

+  int       *msgDone;                                       /* MR10 */

+#endif

+{

+    Junction *junc = (Junction *)blk.left, *p;

+    Tree        *t=NULL;

+	Predicate   *pred = NULL;

+	set         scontext, rk;

+    int         ok;

+    int         hmax=0;

+

+    require(junc!=NULL && junc->ntype == nJunction, "bad context guard");

+

+/* MR10 Check for anything other than Tokens and generic junctions */

+

+    *msgDone=0;                                             /* MR10 */

+    ok=contextGuardOK( (Node *)junc,0,&hmax);               /* MR10 */

+    if (! ok) {                                             /* MR10 */

+      *msgDone=1;                                           /* MR10 */

+      return NULL;                                          /* MR10 */

+    };                                                      /* MR10 */

+    if (hmax == 0) {

+errFL("guard is 0 tokens long",FileStr[junc->file],junc->line);          /* MR11 */

+      *msgDone=1;

+      return NULL;

+    };

+    if (hmax > CLL_k) {                                     /* MR10 */

+errFL(eMsgd2("guard is %d tokens long - lookahead is limited to max(k,ck)==%d", /* MR10 */

+        hmax,CLL_k),                                        /* MR10 */

+        FileStr[junc->file],junc->line);                    /* MR10 */

+      *msgDone=1;                                           /* MR10 */

+      return NULL;                                          /* MR10 */

+    };                                                      /* MR10 */

+

+	rk = empty;

+	p = junc;

+	pred = new_pred();

+	pred->k = hmax;     /* MR10 should be CLL_k, not LLK ? */

+	if (hmax > 1 )      /* MR10 was LL_k                   */

+	{

+		ConstrainSearch = 0;

+		ContextGuardTRAV = 1;

+		TRAV(p, hmax, &rk, t);  /* MR10 was LL_k */

+		ContextGuardTRAV = 0;

+		set_free(rk);

+		t = tshrink( t );

+		t = tflatten( t );

+		t = tleft_factor( t );

+/*

+		fprintf(stderr, "ctx guard:");

+		preorder(t);

+		fprintf(stderr, "\n");

+*/

+		pred->tcontext = t;

+	}

+	else

+	{

+		REACH(p, 1, &rk, scontext);

+		require(set_nil(rk), "rk != nil");

+		set_free(rk);

+/*

+		fprintf(stderr, "LL(1) ctx guard is:");

+		s_fprT(stderr, scontext);

+		fprintf(stderr, "\n");

+*/

+		pred->scontext[1] = scontext;

+	}

+

+    list_add(&ContextGuardPredicateList,pred);     /* MR13 */

+

+	return pred;

+}

+

+/* MR13

+   When the context guard is originally computed the

+   meta-tokens are not known.

+*/

+

+#ifdef __USE_PROTOS

+void recomputeContextGuard(Predicate *pred)

+#else

+void recomputeContextGuard(pred)

+    Predicate   *pred;

+#endif

+{

+    Tree *          t=NULL;

+	set             scontext;

+    set             rk;

+    ActionNode *    actionNode;

+    Junction *      p;

+

+    actionNode=pred->source;

+    require (actionNode != NULL,"context predicate's source == NULL");

+

+    p=actionNode->guardNodes;

+    require (p != NULL,"context predicate's guardNodes == NULL");

+

+	rk = empty;

+	if (pred->k > 1 )

+	{

+		ConstrainSearch = 0;

+		ContextGuardTRAV = 1;

+		TRAV(p, pred->k, &rk, t);

+		ContextGuardTRAV = 0;

+		set_free(rk);

+		t = tshrink( t );

+		t = tflatten( t );

+		t = tleft_factor( t );

+        Tfree(pred->tcontext);

+		pred->tcontext = t;

+	}

+	else

+	{

+		REACH(p, 1, &rk, scontext);

+		require(set_nil(rk), "rk != nil");

+		set_free(rk);

+        set_free(pred->scontext[1]);

+		pred->scontext[1] = scontext;

+	}

+}

+

+/* MR11 - had enough of flags yet ? */

+

+int     MR_AmbSourceSearch=0;

+int     MR_AmbSourceSearchGroup=0;

+int     MR_AmbSourceSearchChoice=0;

+int     MR_AmbSourceSearchLimit=0;

+int     MR_matched_AmbAidRule=0;

+

+static    set         *matchSets[2]={NULL,NULL};

+static    int         *tokensInChain=NULL;

+static    Junction    *MR_AmbSourceSearchJ[2];

+

+void MR_traceAmbSourceKclient()

+{

+  int       i;

+  set       *save_fset;

+  int       save_ConstrainSearch;

+  set       incomplete;

+  Tree      *t;

+

+  if (matchSets[0] == NULL) {

+    matchSets[0]=(set *) calloc (CLL_k+1,sizeof(set));

+    require (matchSets[0] != NULL,"matchSets[0] alloc");

+    matchSets[1]=(set *) calloc (CLL_k+1,sizeof(set));

+    require (matchSets[1] != NULL,"matchSets[1] alloc");

+  };

+

+  for (i=1 ; i <= MR_AmbSourceSearchLimit ; i++) {

+    set_clr(matchSets[0][i]);

+    set_orel( (unsigned) tokensInChain[i],

+                              &matchSets[0][i]);

+    set_clr(matchSets[1][i]);

+    set_orel( (unsigned) tokensInChain[i],

+                              &matchSets[1][i]);

+  };

+

+  save_fset=fset;

+  save_ConstrainSearch=ConstrainSearch;

+

+

+

+  for (i=0 ; i < 2 ; i++) {

+

+#if 0

+**    fprintf(stdout,"  Choice:%d  Depth:%d  ",i+1,MR_AmbSourceSearchLimit);

+**    fprintf(stdout,"(");

+**    for (j=1 ; j <= MR_AmbSourceSearchLimit ; j++) {

+**      if (j != 1) fprintf(stdout," ");

+**      fprintf(stdout,"%s",TerminalString(tokensInChain[j]));

+**    };

+**    fprintf(stdout,")\n\n");

+#endif

+

+    fset=matchSets[i];

+

+    MR_AmbSourceSearch=1;

+    MR_MaintainBackTrace=1;

+    MR_AmbSourceSearchChoice=i;

+    ConstrainSearch=1;

+

+    maxk = MR_AmbSourceSearchLimit;

+

+    incomplete=empty;

+    t=NULL;

+

+    constrain = &(fset[1]);

+    MR_pointerStackReset(&MR_BackTraceStack);

+

+    TRAV(MR_AmbSourceSearchJ[i],maxk,&incomplete,t);

+

+    Tfree(t);

+

+    require (set_nil(incomplete),"MR_traceAmbSourceK TRAV incomplete");

+    require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");

+

+    set_free(incomplete);

+  };

+

+  ConstrainSearch=save_ConstrainSearch;

+  fset=save_fset;

+  MR_AmbSourceSearch=0;

+  MR_MaintainBackTrace=0;

+  MR_AmbSourceSearchChoice=0;

+}

+

+#ifdef __USE_PROTOS

+Tree *tTrunc(Tree *t,int depth)

+#else

+Tree *tTrunc(t,depth)

+  Tree  *t;

+#endif

+{

+    Tree    *u;

+

+    require ( ! (t == NULL && depth > 0),"tree too short");

+

+    if (depth == 0) return NULL;

+

+    if (t->token == ALT) {

+      u=tTrunc(t->down,depth);

+    } else {

+      u=tnode(t->token);

+      u->down=tTrunc(t->down,depth-1);

+    };

+    if (t->right != NULL) u->right=tTrunc(t->right,depth);

+    return u;

+}

+

+#ifdef __USE_PROTOS

+void MR_iterateOverTree(Tree *t,int chain[])

+#else

+void MR_iterateOverTree(t,chain)

+  Tree          *t;

+  int           chain[];

+#endif

+{

+  if (t == NULL) return;

+  chain[0]=t->token;

+  if (t->down != NULL) {

+    MR_iterateOverTree(t->down,&chain[1]);

+  } else {

+    MR_traceAmbSourceKclient();

+  };

+  MR_iterateOverTree(t->right,&chain[0]);

+  chain[0]=0;

+}

+

+#ifdef __USE_PROTOS

+void MR_traceAmbSourceK(Tree *t,Junction *alt1,Junction *alt2)

+#else

+void MR_traceAmbSourceK(t,alt1,alt2)

+  Tree      *t;

+  Junction  *alt1;

+  Junction  *alt2;

+#endif

+{

+    int         i;

+    int         depth;

+    int         maxDepth;

+    Tree        *truncatedTree;

+

+    if (MR_AmbAidRule == NULL) return;

+

+    if ( ! (

+            strcmp(MR_AmbAidRule,alt1->rname) == 0 ||

+            strcmp(MR_AmbAidRule,alt2->rname) == 0 ||

+            MR_AmbAidLine==alt1->line ||

+            MR_AmbAidLine==alt2->line

+           )

+       ) return;

+

+    MR_matched_AmbAidRule++;

+

+    /* there are no token sets in trees, only in TokNodes */

+

+    MR_AmbSourceSearchJ[0]=analysis_point( (Junction *) alt1->p1);

+    MR_AmbSourceSearchJ[1]=analysis_point( (Junction *) alt2->p1);

+

+    if (tokensInChain == NULL) {

+      tokensInChain=(int *) calloc (CLL_k+1,sizeof(int));

+      require (tokensInChain != NULL,"tokensInChain alloc");

+    };

+

+    MR_AmbSourceSearchGroup=0;

+

+    fprintf(stdout,"\n");

+    fprintf(stdout,"  Ambiguity Aid                 ");

+    fprintf(stdout,

+                (MR_AmbAidDepth <= LL_k ?

+                    "(-k %d  -aa %s  %s  -aad %d)\n\n" :

+                        "(-k %d  -aa %s  %s  [-k value limits -aad %d])\n\n"),

+                LL_k,

+                MR_AmbAidRule,

+                (MR_AmbAidMultiple ? "-aam" : ""),

+                MR_AmbAidDepth);

+

+    for (i=0 ; i < 2 ; i++) {

+      fprintf(stdout,"    Choice %d: %-25s  line %d  file %s\n",

+                  (i+1),

+                  MR_ruleNamePlusOffset( (Node *) MR_AmbSourceSearchJ[i]),

+                  MR_AmbSourceSearchJ[i]->line,

+                  FileStr[MR_AmbSourceSearchJ[i]->file]);

+    };

+

+    fprintf(stdout,"\n");

+

+    if (MR_AmbAidDepth < LL_k) {

+      maxDepth=MR_AmbAidDepth;

+    } else {

+      maxDepth=LL_k;

+    };

+

+    for (depth=1 ; depth <= maxDepth; depth++) {

+      MR_AmbSourceSearchLimit=depth;

+      if (depth < LL_k) {

+        truncatedTree=tTrunc(t,depth);

+        truncatedTree=tleft_factor(truncatedTree);

+        MR_iterateOverTree(truncatedTree,&tokensInChain[1]);    /* <===== */

+        Tfree(truncatedTree);

+      } else {

+        MR_iterateOverTree(t,tokensInChain);                /* <===== */

+      };

+      fflush(stdout);

+      fflush(stderr);

+    };

+

+    fprintf(stdout,"\n");

+    MR_AmbSourceSearch=0;

+    MR_MaintainBackTrace=0;

+    MR_AmbSourceSearchGroup=0;

+    MR_AmbSourceSearchChoice=0;

+    MR_AmbSourceSearchLimit=0;

+

+}

+

+

+/* this if for k=1 grammars only

+

+   this is approximate only because of the limitations of linear

+   approximation lookahead.  Don't want to do a k=3 search when

+   the user only specified a ck=3 grammar

+*/

+

+#ifdef __USE_PROTOS

+void MR_traceAmbSource(set *matchSets,Junction *alt1, Junction *alt2)

+#else

+void MR_traceAmbSource(matchSets,alt1,alt2)

+  set       *matchSets;

+  Junction  *alt1;

+  Junction  *alt2;

+#endif

+{

+    set         *save_fset;

+    Junction    *p[2];

+    int         i;

+    int         j;

+    set         *dup_matchSets;

+    set         intersection;

+    set         incomplete;

+    set         tokensUsed;

+    int         depth;

+

+    if (MR_AmbAidRule == NULL) return;

+    if ( ! (

+            strcmp(MR_AmbAidRule,alt1->rname) == 0 ||

+            strcmp(MR_AmbAidRule,alt2->rname) == 0 ||

+            MR_AmbAidLine==alt1->line ||

+            MR_AmbAidLine==alt2->line

+           )

+       ) return;

+

+    MR_matched_AmbAidRule++;

+

+    save_fset=fset;

+

+    dup_matchSets=(set *) calloc(CLL_k+1,sizeof(set));

+    require (dup_matchSets != NULL,"Can't allocate dup_matchSets");

+

+    p[0]=analysis_point( (Junction *) alt1->p1);

+    p[1]=analysis_point( (Junction *) alt2->p1);

+

+    fprintf(stdout,"\n");

+

+    fprintf(stdout,"  Ambiguity Aid                 ");

+    fprintf(stdout,

+                (MR_AmbAidDepth <= CLL_k ?

+                    "(-ck %d  -aa %s  %s  -aad %d)\n\n" :

+                        "(-ck %d  -aa %s  %s  [-ck value limits -aad %d])\n\n"),

+                CLL_k,

+                MR_AmbAidRule,

+                (MR_AmbAidMultiple ? "-aam" : ""),

+                MR_AmbAidDepth);

+

+    for (i=0 ; i < 2 ; i++) {

+      fprintf(stdout,"    Choice %d: %-25s  line %d  file %s\n",

+                            (i+1),

+                            MR_ruleNamePlusOffset( (Node *) p[i]),

+                            p[i]->line,FileStr[p[i]->file]);

+    };

+

+    for (j=1; j <= CLL_k ; j++) {

+      fprintf(stdout,"\n    Intersection of lookahead[%d] sets:\n",j);

+      intersection=set_and(alt1->fset[j],alt2->fset[j]);

+      MR_dumpTokenSet(stdout,2,intersection);

+      set_free(intersection);

+    };

+

+    fprintf(stdout,"\n");

+

+    require (1 <= MR_AmbAidDepth && MR_AmbAidDepth <= CLL_k,

+                "illegal MR_AmbAidDepth");

+

+    MR_AmbSourceSearchGroup=0;

+    for (depth=1; depth <= MR_AmbAidDepth; depth++) {

+        MR_AmbSourceSearchLimit=depth;

+        for (i=0 ; i < 2 ; i++) {

+

+/***        fprintf(stdout,"  Choice:%d  Depth:%d\n\n",i+1,depth);  ***/

+

+            for (j=0 ; j <= CLL_k ; j++) { dup_matchSets[j]=set_dup(matchSets[j]); };

+            fset=dup_matchSets;

+

+            fflush(output);

+            fflush(stdout);

+

+            MR_AmbSourceSearch=1;

+            MR_MaintainBackTrace=1;

+            MR_AmbSourceSearchChoice=i;

+

+            maxk = depth;

+            tokensUsed=empty;

+            incomplete=empty;

+

+            constrain = &(fset[1]);

+            MR_pointerStackReset(&MR_BackTraceStack);

+

+            REACH(p[i],depth,&incomplete,tokensUsed);

+

+            fflush(output);

+            fflush(stdout);

+

+            require (set_nil(incomplete),"MR_traceAmbSource REACH incomplete");

+            require (MR_BackTraceStack.count == 0,"1: MR_BackTraceStack.count != 0");

+

+            set_free(incomplete);

+            set_free(tokensUsed);

+

+            for (j=0 ; j <= CLL_k ; j++) { set_free(dup_matchSets[j]); };

+        };

+    };

+

+    fprintf(stdout,"\n");

+

+    MR_AmbSourceSearch=0;

+    MR_MaintainBackTrace=0;

+    MR_AmbSourceSearchGroup=0;

+    MR_AmbSourceSearchChoice=0;

+    MR_AmbSourceSearchLimit=0;

+

+    fset=save_fset;

+    free ( (char *) dup_matchSets);

+}

+

+static int itemCount;

+

+void MR_backTraceDumpItemReset() {

+  itemCount=0;

+}

+

+#ifdef __USE_PROTOS

+void MR_backTraceDumpItem(FILE *f,int skip,Node *n)

+#else

+void MR_backTraceDumpItem(f,skip,n)

+  FILE      *f;

+  int       skip;

+  Node      *n;

+#endif

+{

+  TokNode       *tn;

+  RuleRefNode   *rrn;

+  Junction      *j;

+  ActionNode    *a;

+

+  switch (n->ntype) {

+    case nToken:

+        itemCount++; if (skip) goto EXIT;

+        tn=(TokNode *)n;

+        if (set_nil(tn->tset)) {

+          fprintf(f,"  %2d #token %-23s",itemCount,TerminalString(tn->token));

+        } else {

+          fprintf(f,"  %2d #tokclass %-20s",itemCount,TerminalString(tn->token));

+        };

+        break;

+    case nRuleRef:

+        itemCount++; if (skip) goto EXIT;

+        rrn=(RuleRefNode *)n;

+        fprintf(f,"  %2d to %-27s",itemCount,rrn->text);

+        break;

+    case nAction:

+        a=(ActionNode *)n;

+        goto EXIT;

+    case nJunction:

+

+      j=(Junction *)n;

+

+      switch (j->jtype) {

+        case aSubBlk:

+            if (j->guess) {

+              itemCount++; if (skip) goto EXIT;

+              fprintf(f,"  %2d %-30s",itemCount,"in (...)? block at");

+              break;

+            };

+/******     fprintf(f,"  %2d %-32s",itemCount,"in (...) block at");  *******/

+/******     break;                                                          *******/

+            goto EXIT;

+        case aOptBlk:

+            itemCount++; if (skip) goto EXIT;

+            fprintf(f,"  %2d %-30s",itemCount,"in {...} block");

+            break;

+        case aLoopBlk:

+            itemCount++; if (skip) goto EXIT;

+            fprintf(f,"  %2d %-30s",itemCount,"in (...)* block");

+            break;

+        case EndBlk:

+            if (j->alpha_beta_guess_end) {

+              itemCount++; if (skip) goto EXIT;

+              fprintf(f,"  %2d %-30s",itemCount,"end (...)? block at");

+              break;

+            };

+            goto EXIT;

+/******     fprintf(f,"  %2d %-32s",itemCount,"end of a block at");     *****/

+/******     break;                                                             *****/

+        case RuleBlk:

+            itemCount++; if (skip) goto EXIT;

+            fprintf(f,"  %2d %-30s",itemCount,j->rname);

+            break;

+        case Generic:

+            goto EXIT;

+        case EndRule:

+            itemCount++; if (skip) goto EXIT;

+            fprintf (f,"  %2d end %-26s",itemCount,j->rname);

+            break;

+        case aPlusBlk:

+            itemCount++; if (skip) goto EXIT;

+            fprintf(f,"  %2d %-30s",itemCount,"in (...)+ block");

+            break;

+        case aLoopBegin:

+            goto EXIT;

+      };

+      break;

+  };

+  fprintf(f," %-23s line %-4d  %s\n",MR_ruleNamePlusOffset(n),n->line,FileStr[n->file]);

+EXIT:

+  return;

+}

+

+

+static PointerStack     previousBackTrace={0,0,NULL};

+

+#ifdef __USE_PROTOS

+void MR_backTraceReport(void)

+#else

+void MR_backTraceReport()

+#endif

+{

+  int       i;

+  int       match = 0;

+  int       limitMatch;

+

+  Node      *p;

+  TokNode   *tn;

+  set       remainder;

+  int       depth;

+

+  /* Even when doing a k=2 search this routine can get

+       called when there is only 1 token on the stack.

+     This is because something like rRuleRef can change

+       the search value of k from 2 to 1 temporarily.

+     It does this because the it wants to know the k=1

+       first set before it does a k=2 search

+  */

+

+  depth=0;

+  for (i=0; i < MR_BackTraceStack.count ; i++) {

+    p=(Node *) MR_BackTraceStack.data[i];

+    if (p->ntype == nToken) depth++;

+  };

+

+/* MR14 */  if (MR_AmbSourceSearch) {

+/* MR14 */     require (depth <= MR_AmbSourceSearchLimit,"depth > MR_AmbSourceSearchLimit");

+/* MR14 */  }

+

+  /* MR23 THM - Traceback report was being called at the wrong time for -alpha reports */

+  /*            Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu)                  */

+

+  if (MR_AmbSourceSearchLimit == 0 || depth < MR_AmbSourceSearchLimit) {

+    return;

+  };

+

+  MR_backTraceDumpItemReset();

+

+  limitMatch=MR_BackTraceStack.count;

+  if (limitMatch > previousBackTrace.count) {

+    limitMatch=previousBackTrace.count;

+  };

+

+  for (match=0; match < limitMatch; match++) {

+    if (MR_BackTraceStack.data[match] !=

+        previousBackTrace.data[match]) {

+      break;

+    };

+  };

+

+  /* not sure at the moment why there would be duplicates */

+

+  if (match != MR_BackTraceStack.count) {

+

+    fprintf(stdout,"     Choice:%d  Depth:%d  Group:%d",

+        (MR_AmbSourceSearchChoice+1),

+        MR_AmbSourceSearchLimit,

+        ++MR_AmbSourceSearchGroup);

+

+    depth=0;

+    fprintf(stdout,"  (");

+    for (i=0; i < MR_BackTraceStack.count ; i++) {

+      p=(Node *) MR_BackTraceStack.data[i];

+      if (p->ntype != nToken) continue;

+      tn=(TokNode *)p;

+      if (depth != 0) fprintf(stdout," ");

+      fprintf(stdout,TerminalString(tn->token));

+      depth++;

+      if (! MR_AmbAidMultiple) {

+        if (set_nil(tn->tset)) {

+          set_rm( (unsigned) tn->token,fset[depth]);

+        } else {

+          remainder=set_dif(fset[depth],tn->tset);

+          set_free(fset[depth]);

+          fset[depth]=remainder;

+        };

+      };

+    };

+    fprintf(stdout,")\n");

+

+    for (i=0; i < MR_BackTraceStack.count ; i++) {

+      MR_backTraceDumpItem(stdout, (i<match) ,(Node *) MR_BackTraceStack.data[i]);

+    };

+    fprintf(stdout,"\n");

+    fflush(stdout);

+

+    MR_pointerStackReset(&previousBackTrace);

+

+    for (i=0; i < MR_BackTraceStack.count ; i++) {

+      MR_pointerStackPush(&previousBackTrace,MR_BackTraceStack.data[i]);

+    };

+

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_setConstrainPointer(set * newConstrainValue)

+#else

+void MR_setConstrainPointer(newConstrainValue)

+  set * newConstrainValue;

+#endif

+{

+	constrain=newConstrainValue;

+}

diff --git a/Source/Pccts/antlr/gen.c b/Source/Pccts/antlr/gen.c
new file mode 100644
index 0000000..368a96b
--- /dev/null
+++ b/Source/Pccts/antlr/gen.c
@@ -0,0 +1,4797 @@
+/*

+ * gen.c

+ *

+ * Generate C code (ANSI, K&R, C++)

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <ctype.h>

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+

+#define NumExprPerLine	4

+static int on1line=0;

+static set tokensRefdInBlock;

+

+					/* T r a n s l a t i o n  T a b l e s */

+

+/* C_Trans[node type] == pointer to function that knows how to translate that node. */

+#ifdef __cplusplus

+void (*C_Trans[NumNodeTypes+1])(...) = {

+	NULL,

+	NULL,					/* See next table.

+Junctions have many types */

+	(void (*)(...)) genRuleRef,

+	(void (*)(...)) genToken,

+	(void (*)(...)) genAction

+ };

+#else

+void (*C_Trans[NumNodeTypes+1])() = {

+	NULL,

+	NULL,					/* See next table.

+Junctions have many types */

+	genRuleRef,

+	genToken,

+	genAction

+ };

+#endif

+

+/* C_JTrans[Junction type] == pointer to function that knows how to translate that

+ * kind of junction node.

+ */

+#ifdef __cplusplus

+void (*C_JTrans[NumJuncTypes+1])(...) = {

+	NULL,

+	(void (*)(...)) genSubBlk,

+	(void (*)(...)) genOptBlk,

+	(void (*)(...)) genLoopBlk,

+	(void (*)(...)) genEndBlk,

+	(void (*)(...)) genRule,

+	(void (*)(...)) genJunction,

+	(void (*)(...)) genEndRule,

+	(void (*)(...)) genPlusBlk,

+	(void (*)(...)) genLoopBegin

+ };

+#else

+void (*C_JTrans[NumJuncTypes+1])() = {

+	NULL,

+	genSubBlk,

+	genOptBlk,

+	genLoopBlk,

+	genEndBlk,

+	genRule,

+	genJunction,

+	genEndRule,

+	genPlusBlk,

+	genLoopBegin

+ };

+#endif

+

+#define PastWhiteSpace(s)	while (*(s) == ' ' || *(s) == '\t') {s++;}

+

+static int tabs = 0;

+

+/* MR6	Got tired of text running off page when using standard tab stops */

+

+#define TAB { int i; 					                		\

+	      if (TabWidth==0) { 					                \

+	         for (i=0; i<tabs; i++) fputc('\t', output);		                \

+	      } else {           							\

+		 for (i=0; i<tabs*TabWidth; i++) fputc(' ',output);     	        \

+	      };	                						\

+	    }

+

+static void

+#ifdef __USE_PROTOS

+tab( void )

+#else

+tab( )

+#endif

+TAB

+

+#ifdef __USE_PROTOS

+static char *tokenFollowSet(TokNode *);

+static ActionNode *findImmedAction( Node * );

+static void dumpRetValAssign(char *, char *, RuleRefNode *);		/* MR30 */

+static void dumpAfterActions(FILE *output);

+static set ComputeErrorSet(Junction *, int, int);

+static void makeErrorClause(Junction *, set, int, int);

+static void DumpFuncHeader( Junction *, RuleEntry * );

+static int has_guess_block_as_first_item(Junction *);

+static int genExprSets(set *, int);

+static void genExprTree( Tree *t, int k );

+static void genExprTreeOriginal( Tree *t, int k );                  /* MR10 */

+static char * findOuterHandlerLabel(ExceptionGroup *eg);            /* MR7 */

+static void OutLineInfo(FILE *file,int line,char *fileName);        /* MR14 */

+#else

+static char *tokenFollowSet();

+static ActionNode *findImmedAction();

+static void dumpRetValAssign();

+static void dumpAfterActions();

+static set ComputeErrorSet();

+static void makeErrorClause();

+static void DumpFuncHeader();

+static int has_guess_block_as_first_item();

+static int genExprSets();

+static void genExprTree();

+static void genExprTreeOriginal();                                  /* MR10 */

+static char * findOuterHandlerLabel();                              /* MR7 */

+static void OutLineInfo();                                          /* MR14 */

+#endif

+

+#define gen(s)			{tab(); fprintf(output, s);}

+#define gen1(s,a)		{tab(); fprintf(output, s,a);}

+#define gen2(s,a,b)		{tab(); fprintf(output, s,a,b);}

+#define gen3(s,a,b,c)	{tab(); fprintf(output, s,a,b,c);}

+#define gen4(s,a,b,c,d)	{tab(); fprintf(output, s,a,b,c,d);}

+#define gen5(s,a,b,c,d,e)	{tab(); fprintf(output, s,a,b,c,d,e);}

+#define gen6(s,a,b,c,d,e,f)	{tab(); fprintf(output, s,a,b,c,d,e,f);}

+#define gen7(s,a,b,c,d,e,f,g)	{tab(); fprintf(output, s,a,b,c,d,e,f,g);}

+

+#define _gen(s)			{fprintf(output, s);}

+#define _gen1(s,a)		{fprintf(output, s,a);}

+#define _gen2(s,a,b)	{fprintf(output, s,a,b);}

+#define _gen3(s,a,b,c)	{fprintf(output, s,a,b,c);}

+#define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}

+#define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}

+#define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}

+#define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}

+

+

+/* MR11 a convenient place to set a break point */

+

+#ifdef __USE_PROTOS

+void MR_break(void) 

+#else

+void MR_break() 

+#endif

+{

+  return;

+}

+

+/* MR10 genTraceOut(Junction *)      */

+

+#ifdef __USE_PROTOS

+static void genTraceOut(Junction *q)

+#else

+static void genTraceOut(q)

+  Junction  *q;

+#endif

+{

+  if ( TraceGen ) {

+		if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);}

+    		else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);

+  }

+}

+

+static void

+#ifdef __USE_PROTOS

+warn_about_using_gk_option(void)

+#else

+warn_about_using_gk_option()

+#endif

+{

+	static int warned_already=0;

+

+	if ( !DemandLookahead || warned_already ) return;

+	warned_already = 1;

+	warnNoFL("-gk option could cause trouble for <<...>>? predicates");

+}

+

+void

+#ifdef __USE_PROTOS

+freeBlkFsets( Junction *q )

+#else

+freeBlkFsets( q )

+Junction *q;

+#endif

+{

+	int i;

+	Junction *alt;

+	require(q!=NULL, "freeBlkFsets: invalid node");

+

+	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )

+	{

+		for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);

+	}

+}

+

+/*

+ * Generate a local variable allocation for each token references

+ * in this block.

+ */

+static void

+#ifdef __USE_PROTOS

+genTokenPointers( Junction *q )

+#else

+genTokenPointers( q )

+Junction *q;

+#endif

+{

+	/* Rule refs are counted and can be referenced, but their

+	 * value is not set to anything useful ever.

+	 *

+     * The ptrs are to be named _tij where i is the current level

+	 * and j is the element number within an alternative.

+	 */

+	int first=1, t=0;

+	set a;

+	tokensRefdInBlock = q->tokrefs;

+

+	if ( set_deg(q->tokrefs) == 0 ) return;

+	a = set_dup(q->tokrefs);

+	gen("ANTLRTokenPtr ");

+	for (; !set_nil(a); set_rm(t, a))

+	{

+		t = set_int(a);

+		if ( first ) first = 0;

+		else _gen(",");

+		if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);

+		_gen2("_t%d%d", BlkLevel, t);

+		if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}

+		else _gen("=NULL");

+	}

+	_gen(";\n");

+	set_free(a);

+}

+

+static int

+#ifdef __USE_PROTOS

+hasDefaultException(ExceptionGroup *eg)

+#else

+hasDefaultException(eg)

+ExceptionGroup *eg;

+#endif

+{

+    ListNode *q;

+

+    for (q = eg->handlers->next; q!=NULL; q=q->next)

+    {

+        ExceptionHandler *eh = (ExceptionHandler *)q->elem;

+        if ( strcmp("default", eh->signalname)==0 ) {

+            return 1;

+        }

+    }

+    return 0;

+}

+static void

+#ifdef __USE_PROTOS

+dumpException(ExceptionGroup *eg, int no_default_case)

+#else

+dumpException(eg, no_default_case)

+ExceptionGroup *eg;

+int no_default_case;

+#endif

+{

+    char    *outerLabel;                                             /* MR7 */

+    int     altHandler=0;                                            /* MR7 */

+    int     namedHandler=0;                                          /* MR7 */

+

+    outerLabel=findOuterHandlerLabel(eg);                            /* MR7 */

+

+    if (eg->label != NULL) {                                         /* MR7 */

+      namedHandler=1;                                                /* MR7 */

+    } else if (eg->forRule) {                                        /* MR7 */

+      /* nothing */                                                  /* MR20 */

+    } else {                                                         /* MR7 */

+      altHandler=1;                                                  /* MR7 */

+    };                                                               /* MR7 */

+

+#if 0

+**     if (! eg->used) {                                             /* MR7 */

+**     	warnFL("exception group never used",                         /* MR7 */

+**             FileStr[eg->altstart->file],eg->altstart->line);      /* MR7 */

+**     };                                                            /* MR7 */

+#endif

+

+    if (namedHandler) {                                              /* MR7 */

+	  gen1("switch ( _signal ) {  /* [%s] */\n",eg->label);          /* MR7 */

+    } else {                                                         /* MR7 */

+	  gen("switch ( _signal ) {\n");                                 /* MR7 */

+      gen("case NoSignal: break;  /* MR7 */\n");                     /* MR7 */

+    };                                                               /* MR7 */

+	{

+		ListNode *q;

+		for (q = eg->handlers->next; q!=NULL; q=q->next)

+		{

+			ExceptionHandler *eh = (ExceptionHandler *)q->elem;

+			if ( strcmp("default", eh->signalname)==0 ) {

+				gen("default :\n");

+				tabs++;

+				dumpAction(eh->action, output, tabs, -1, 1, 1);

+                gen("_signal=NoSignal;  /* MR7 */\n");                  /* MR7 */

+                gen("break;  /* MR7 */\n");                             /* MR7 */

+				tabs--;

+				gen("}\n");

+

+                /* copied from later code in dumpException */        /* MR7 */

+

+                if (namedHandler) {                                  /* MR7 */

+                  gen("if (_signal != NoSignal)");                   /* MR7 */

+                  _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);/* MR7 */

+                } else if (altHandler) {                             /* MR7 */

+                  gen1("goto %s_handler;  /* MR7 */\n",outerLabel);  /* MR7 */

+                };

+				return;

+			}

+			gen1("case %s :\n", eh->signalname);

+			tabs++;

+			if ( eh->action != NULL )

+			{

+				dumpAction(eh->action, output, tabs, -1, 1, 1);

+                gen("break;  /* MR7 */\n");                          /* MR7 */

+			}

+			tabs--;

+		}

+	}

+	if ( no_default_case ) return;

+

+	gen("default :\n");

+    tabs++;                                                         /* MR7 */

+    gen("break;  /* MR7 */\n");                                     /* MR7 */

+    tabs--;                                                         /* MR7 */

+

+	tabs++;

+/*****	gen("*_retsignal = _signal;\n"); *****/

+

+	tabs--;

+	gen("}\n");

+

+    if (namedHandler) {                                             /* MR7 */

+      gen("if (_signal != NoSignal)");                              /* MR7 */

+      _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);           /* MR7 */

+    } else if (altHandler) {                                        /* MR7 */

+      gen1("goto %s_handler;  /* MR7 */\n",outerLabel);             /* MR7 */

+    };

+

+}

+

+static void

+#ifdef __USE_PROTOS

+dumpExceptions(ListNode *list)

+#else

+dumpExceptions(list)

+ListNode *list;

+#endif

+{

+	ListNode *p;

+

+	for (p = list->next; p!=NULL; p=p->next)

+	{

+		ExceptionGroup *eg = (ExceptionGroup *) p->elem;

+		_gen2("%s%s_handler:\n",

+			  eg->label==NULL?"":eg->label,

+			  eg->altID==NULL?"":eg->altID);

+		if ( eg->altID!=NULL ) dumpException(eg, 0);

+		else {

+			/* This must be the rule exception handler */

+			dumpException(eg, 1);

+			if ( !hasDefaultException(eg) )

+            {

+                gen("default :\n");

+                tabs++;

+                gen("zzdflthandlers(_signal,_retsignal);\n");

+                tabs--;

+                gen("}\n");

+            }

+		}

+	}

+}

+

+/* For each element label that is found in a rule, generate a unique

+ * Attribute (and AST pointer if GenAST) variable.

+ */

+void

+#ifdef __USE_PROTOS

+genElementLabels(ListNode *list)

+#else

+genElementLabels(list)

+ListNode *list;

+#endif

+{

+	int first=1;

+	ListNode *p;

+

+	if ( GenCC ) {gen("ANTLRTokenPtr");}

+	else {gen("Attrib");}

+	for (p = list->next; p!=NULL; p=p->next)

+	{

+		char *ep = (char *)p->elem;

+		if ( first ) first = 0;

+		else _gen(",");

+		if ( GenCC ) {_gen1(" %s=NULL",ep);}

+		else {_gen1(" %s",ep);}

+	}

+	_gen(";\n");

+

+	if ( !GenAST ) return;

+

+	first = 1;

+	gen("AST");

+	for (p = list->next; p!=NULL; p=p->next)

+	{

+		char *ep = (char *)p->elem;

+		if ( first ) first = 0;

+		else _gen(",");

+		_gen1(" *%s_ast=NULL",ep);

+	}

+	_gen(";\n");

+}

+

+/*

+ * Generate a local variable allocation for each token or rule reference

+ * in this block.

+ */

+static void

+#ifdef __USE_PROTOS

+genASTPointers( Junction *q )

+#else

+genASTPointers( q )

+Junction *q;

+#endif

+{

+	int first=1, t;

+	set a;

+

+	a = set_or(q->tokrefs, q->rulerefs);

+	if ( set_deg(a) > 0 )

+	{

+		gen("AST ");

+		for (; !set_nil(a); set_rm(t, a))

+		{

+			t = set_int(a);

+			if ( first ) first = 0;

+			else _gen(",");

+			_gen2("*_ast%d%d=NULL", BlkLevel, t);

+		}

+		set_free(a);

+	}

+	_gen(";\n");

+}

+

+static void

+#ifdef __USE_PROTOS

+BLOCK_Head( void )

+#else

+BLOCK_Head( )

+#endif

+{

+	gen("{\n");

+	tabs++;

+	if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);

+}

+

+static void

+#ifdef __USE_PROTOS

+BLOCK_Tail( void )

+#else

+BLOCK_Tail( )

+#endif

+{

+	if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);

+	if ( !GenCC ) gen("}\n");

+	tabs--;

+	gen("}\n");

+}

+

+static void

+#ifdef __USE_PROTOS

+BLOCK_Preamble( Junction *q )

+#else

+BLOCK_Preamble( q )

+Junction *q;

+#endif

+{

+	ActionNode *a;

+	Junction *begin;

+

+	BLOCK_Head();

+	if ( GenCC ) genTokenPointers(q);

+	if ( GenCC&&GenAST ) genASTPointers(q);

+	if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");

+	if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)

+	else if ( !GenCC ) gen("zzMake0;\n");

+	if ( !GenCC ) gen("{\n");

+	if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);

+	else begin = q;

+	if ( has_guess_block_as_first_item(begin) )

+	{

+		gen("zzGUESS_BLOCK\n");

+	}

+	if ( q->jtype == aLoopBegin )

+		a = findImmedAction( ((Junction *)q->p1)->p1 );	/* look at aLoopBlk */

+	else

+		a = findImmedAction( q->p1 );

+	if ( a!=NULL && !a->is_predicate) {

+/* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);

+		   a->done = 1;	/* remove action. We have already handled it */

+	}

+}

+

+void

+#ifdef __USE_PROTOS

+genCombinedPredTreeContextOrig( Predicate *p )

+#else

+genCombinedPredTreeContextOrig( p )

+Predicate *p;

+#endif

+{

+	static set *ctx=NULL;		/* genExprSets() is destructive, make copy*/

+	require(p!=NULL, "can't make context tree for NULL pred tree");

+

+#ifdef DBG_PRED

+	fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p);

+	s_fprT(stderr, p->scontext[1]);

+	fprintf(stderr, "\n");

+#endif

+	if ( p->down == NULL )

+	{

+/***	if ( p->k>1 && p->tcontext!=NULL ) ***/

+		if ( p->tcontext!=NULL )

+		{

+			_gen("(");

+			genExprTree(p->tcontext, 1);

+			_gen(")");

+		}

+/***	else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/

+		else if ( set_deg(p->scontext[1])>0 )

+		{

+			if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));

+			require(ctx!=NULL, "ctx cannot allocate");

+			ctx[0]=empty;

+			ctx[1]=set_dup(p->scontext[1]);

+			_gen("(");

+			genExprSets(&(ctx[0]), p->k);

+			_gen(")");

+			set_free(ctx[1]);

+		}

+		else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {

+			fatal_internal("pred tree is orphan OR or AND list");

+		}

+		else {

+            if (! HoistPredicateContext) {

+              _gen(" 1 /* no context: prc is off */ ");

+            } else {

+              fatal_internal("pred tree context is empty");

+            };

+		}

+		return;

+	}

+

+/* MR10 - make AND just like OR */

+

+	if ( p->expr == PRED_AND_LIST )

+	{

+        Predicate *list = p->down;

+        for (; list!=NULL; list=list->right)

+        {

+     	     genCombinedPredTreeContextOrig(list);

+       		 if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ ");

+        };

+		return;

+	}

+

+	if ( p->expr == PRED_OR_LIST )

+	{

+        Predicate *list = p->down;

+        for (; list!=NULL; list=list->right)

+        {

+           genCombinedPredTreeContextOrig(list);

+           if ( list->right!=NULL ) _gen("||");

+        };

+        return;

+     };

+

+	fatal("pred tree is really wacked");

+}

+

+/* [genCombinedPredTreeContext] */

+

+void

+#ifdef __USE_PROTOS

+genCombinedPredTreeContext( Predicate *p )

+#else

+genCombinedPredTreeContext( p )

+Predicate *p;

+#endif

+{

+  Tree  *t;

+  int   predDepth=0;

+

+  if (0 && ! MR_usingPredNames && ! MRhoisting) {

+    genCombinedPredTreeContextOrig(p);

+  } else {

+/* MR13 */    MR_pred_depth(p,&predDepth);

+/* MR13 */    if (predDepth == 1) {

+/* MR13 */

+/* MR13 */      set   scontext[2];

+/* MR13 */      scontext[0]=empty;

+/* MR13 */      scontext[1]=MR_compute_pred_set(p);

+/* MR13 */      if (set_nil(scontext[1])) {

+/* MR13 */        _gen(" 1 /* MR12 no context (-prc off) */ ");

+/* MR13 */      } else {

+/* MR13 */        _gen("(");

+/* MR13 */        genExprSets(&scontext[0], 1);

+/* MR13 */        set_free(scontext[1]);

+/* MR13 */        _gen(")");

+/* MR13 */      };

+

+    } else {

+      t=MR_compute_pred_tree_context(p);

+      if (t == NULL) {

+        _gen(" 1 /* MR12 no context (-prc off) */ ");

+      } else {

+        _gen("(");

+        genExprTree(t, 1);

+        Tfree(t);   /* MR10 */

+        _gen(")");

+      };

+    };

+  };

+}

+

+/* [genPredTreeGate] */

+

+void

+#ifdef __USE_PROTOS

+genPredTreeGate( Predicate *p, int in_and_expr )

+#else

+genPredTreeGate( p, in_and_expr )

+Predicate *p;

+int in_and_expr;

+#endif

+{

+	if ( in_and_expr )

+	{

+		_gen("!(");

+		genCombinedPredTreeContext(p);

+		_gen(")||");

+		if ( p->down!=NULL ) _gen("\n");

+	}

+	else

+	{

+		_gen("(");

+		genCombinedPredTreeContext(p);

+		_gen(")&&");

+		if ( p->down!=NULL ) _gen("\n");

+	}

+}

+

+#ifdef __USE_PROTOS

+void genPredEntry(Predicate *p,int outer)

+#else

+void genPredEntry(p,outer)

+  Predicate     *p;

+  int           outer;

+#endif

+{

+    int         inverted=0;

+    Predicate   *q;

+    int         localOuter=outer;

+    int         needRP=0;

+

+    if (p == NULL) return;

+

+    if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) {

+      if (p->inverted != p->predEntry->pred->inverted) {

+        _gen("! /* inverted pred */ (");

+        needRP=1;

+      } else {

+        if (!localOuter) _gen("(");

+        needRP=1;

+      };

+      dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0);

+      if (needRP) _gen(")");

+      return;

+    };

+

+    inverted=p->inverted;

+

+    if (inverted) {

+      _gen(" ! /* inverted pred */ (");

+      localOuter=1;

+    };

+

+    if (p->expr == PRED_OR_LIST) {

+      if (!localOuter) _gen("(");

+      for (q=p->down; q != NULL ; q=q->right) {

+        genPredEntry(q,0);

+        if (q->right != NULL) _gen(" || ");

+      };

+      if (!localOuter) _gen(")");

+    } else if (p->expr == PRED_AND_LIST) {

+      if (!localOuter) _gen("(");

+      for (q=p->down; q != NULL ; q=q->right) {

+        genPredEntry(q,0);

+        if (q->right != NULL) _gen(" && ");

+      };

+      if (!localOuter) _gen(")");

+    } else {

+      if (!localOuter) _gen("(");

+      require (p->source != NULL,"predEntry->source == NULL");

+      require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0");

+      dumpAction(p->source->action,output,0,p->source->file,p->source->line,0);

+      if (!localOuter) _gen(")");

+    };

+

+    if (inverted) {

+        _gen(")");

+    }

+}

+

+void

+#ifdef __USE_PROTOS

+dumpPredAction(ActionNode *anode,

+                    char *s,FILE *output,int tabs,int file,int line,int final_newline)

+#else

+dumpPredAction(anode,

+                    s,output,tabs,file,line,final_newline)

+

+    ActionNode  *anode;

+    char        *s;

+    FILE        *output;

+    int         tabs;

+    int         file;

+    int         line;

+    int         final_newline;

+#endif

+{

+    PredEntry   *predEntry=anode->predEntry;

+    int         inverted=anode->inverted;

+    Predicate   *workPred;

+

+    if (predEntry == NULL) {

+

+      /* inline predicate literal */

+

+      require(inverted == 0,"dumpPredAction action->inverted");

+  	  dumpAction(s,output,tabs,file,line,final_newline);

+

+    } else {

+

+      /* a reference to a predicate - possibly with an inverted source */

+

+      if (predEntry->predLiteral != NULL) {

+        if (inverted) _gen("! /* inverted pred */ (");

+        dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0);

+        if (inverted) _gen(")");

+      } else {

+        workPred=predicate_dup(predEntry->pred);

+        if (inverted) workPred->inverted=!workPred->inverted;

+        genPredEntry(workPred,1);

+        predicate_free(workPred);

+      };

+    };

+}

+

+/* [genPred] */

+

+void

+#ifdef __USE_PROTOS

+genPred(Predicate *p, Node *j,int suppress_sva)

+#else

+genPred(p,j,suppress_sva)

+    Predicate   *p;

+    Node        *j;

+    int         suppress_sva;

+#endif

+{

+	if ( FoundException && !suppress_sva) {_gen("(_sva=(");}    /* MR11 suppress_sva */

+	else {_gen("(");}

+	if ( GenLineInfo && j->file != -1 ) _gen("\n");

+    if (p->source != NULL && p->source->ampersandPred != NULL) {

+      if (p->source->ampersandPred->k == 1) {

+

+            set     ctx[2];

+

+			ctx[0]=empty;

+			ctx[1]=set_dup(p->source->ampersandPred->scontext[1]);

+

+			_gen("(");

+			genExprSets(&(ctx[0]), p->k);

+			_gen(") && ");

+			set_free(ctx[1]);

+      } else {

+        _gen("( ");

+        genExprTree(p->source->ampersandPred->tcontext,1);

+		_gen(" ) && ");

+      };

+    };

+

+    dumpPredAction((ActionNode *)p->source,

+                p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);

+

+	if ( FoundException && !suppress_sva)   /* MR11 suppress_sva */

+         {_gen("),_sva)");}    /* MR10 - get red of "meant ==" messages */

+	else {_gen(")");}

+}

+

+void

+#ifdef __USE_PROTOS

+MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr)

+#else

+MR_distinctORcontextOpt(p,j,in_and_expr)

+    Predicate   *p;

+    Node        *j;

+    int         in_and_expr;

+#endif

+{

+    Predicate   *q;

+

+    _gen(" /* MR10 Distinct OR context optimization */ \n");

+

+    if (in_and_expr) {

+      gen("zzpf=0,\n");

+      for (q=p->down; q != NULL; q=q->right) {

+        gen("(  ");

+        genCombinedPredTreeContext(q);

+        _gen(" && (zzpf=1, ");

+        genPred(q,j,0);

+        _gen("  )) ||\n");

+      };

+      gen("!zzpf)");

+    } else {

+      require (0,

+            "MR_distinctORcontextOpt: can't get here when using MR_predSimplify");

+#if 0

+**      for (q=p->down; q != NULL; q=q->right) {

+**        gen("(  ");

+**        genCombinedPredTreeContext(q);

+**        _gen(" && ");

+**        genPred(q,j);

+**        if (q->right != NULL) {

+**          _gen("  ) ||\n");

+**        };

+**      };

+**      gen(")");

+#endif

+   };

+}

+

+void

+#ifdef __USE_PROTOS

+genPredTreeOrig( Predicate *p, Node *j, int in_and_expr )

+#else

+genPredTreeOrig( p, j, in_and_expr )

+Predicate *p;

+Node *j;

+int in_and_expr;

+#endif

+{

+

+/* MR10 */  int     allHaveContext=1;

+/* MR10 */  int     noneHaveContext=1;

+

+/* MR10 */  MR_predContextPresent(p,&allHaveContext,&noneHaveContext);

+

+	if ( ! noneHaveContext )                  /* MR10 context guards ignored when -prc off */

+	{

+		_gen("(");

+		genPredTreeGate(p, in_and_expr);

+	}

+

+	/* if leaf node, just gen predicate */

+

+	if ( p->down==NULL )

+	{

+		genPred(p,j,0);

+		if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */

+		return;

+	}

+

+	/* if AND list, do both preds (only two possible) */

+	if ( p->expr == PRED_AND_LIST )

+	{

+#if 0

+**		_gen("(");

+**		genPredTreeOrig(p->down, j, 1);

+**		_gen("&&");

+**		genPredTreeOrig(p->down->right, j, 1);

+**		_gen(")");

+**		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */

+**		return;

+#endif

+        /* MR11 - make it work with AND with more than two children - like OR */

+

+		Predicate *list;

+		_gen("(");

+		list = p->down;

+		for (; list!=NULL; list=list->right)

+		{

+			genPredTreeOrig(list, j, 1);

+			if ( list->right!=NULL ) _gen("&&");

+		}

+		_gen(")");

+		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */

+		return;

+    };

+

+	if ( p->expr == PRED_OR_LIST )

+	{

+		Predicate *list;

+		_gen("(");

+		list = p->down;

+		for (; list!=NULL; list=list->right)

+		{

+			genPredTreeOrig(list, j, 0);

+			if ( list->right!=NULL ) _gen("||");

+		}

+		_gen(")");

+		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */

+		return;

+	}

+

+	fatal_internal("genPredTreeOrig: predicate tree is wacked");

+}

+

+#if 0

+**   Predicate member dummyPredDepth is no longer used in MR10

+**     but we might need it again in the future

+**

+**   if (MRhoisting) {

+**     if ( !noneHaveContext &&

+**          ! in_and_expr &&

+**          p->source != NULL &&

+**          p->source->dummyPredicateDepth > 0 &&

+**          p->down == NULL) {

+** 		_gen("(");

+** 		genCombinedPredTreeContext(p);

+** 		_gen("  )\n");

+** 		return;

+**     };

+**   };

+#endif

+

+/* [genPredTree] */

+

+/* in_and_expr

+

+   what to do if the context is wrong

+   what to do if the context is correct but the predicate is false

+

+   remember: if the context is wrong it's the same as if the

+             predicate is true as far as enabling an alternative

+

+        Consider (AND p q r)

+

+        if in an ... && ... expression then you don't want

+        the entire predicate chain to fail just because the

+        context for one component is wrong: so return true

+

+        Consider (OR p q r)

+

+        if in an ... || ... expression then you don't want

+        the entire predicate chain to succeed just because

+        the context for one component is correct when the

+        corresponding test is false: so return false when

+        the context is correct but the test is false.

+*/

+

+void

+#ifdef __USE_PROTOS

+genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva )

+#else

+genPredTree( p, j, in_and_expr, suppress_sva)

+  Predicate     *p;

+  Node          *j;

+  int           in_and_expr;

+  int           suppress_sva;

+#endif

+{

+

+    int         allHaveContext=1;

+    int         noneHaveContext=1;

+    Tree        *groupTree;

+    Tree        *oneTree;

+    Predicate   *q;

+    int         identicalORcontextOptimization=0;

+    int         identicalANDcontextOptimization=0;

+

+    if (0 && !MR_usingPredNames && !MRhoisting) {

+      genPredTreeOrig(p,j,in_and_expr);

+      return;

+    };

+

+    MR_predContextPresent(p,&allHaveContext,&noneHaveContext);

+

+	if ( ! noneHaveContext ) {                 /* MR10 context guards ignored when -prc off */

+

+      _gen("(");

+

+            /* MR10 optimize OR predicates which are all leaves */

+

+      if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) {

+        groupTree=MR_compute_pred_tree_context(p);

+        for (q=p->down ; q != NULL ; q=q->right) {

+          oneTree=MR_compute_pred_tree_context(q);

+          if (! MR_tree_equ(groupTree,oneTree)) {

+            Tfree(oneTree);

+            break;

+          };

+          Tfree(oneTree);

+        };

+        Tfree(groupTree);

+        if (q == NULL) {

+          _gen("/* MR10 individual OR gates suppressed when all predicates are leaves");

+          _gen(" with identical context */\n");

+          genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */

+          identicalORcontextOptimization=1;

+        } else {

+          MR_distinctORcontextOpt(p,j,in_and_expr);

+          return;

+        };

+      } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) {

+

+            /* MR12 optimize AND predicates which are all leaves */

+

+        groupTree=MR_compute_pred_tree_context(p);

+        for (q=p->down ; q != NULL ; q=q->right) {

+          oneTree=MR_compute_pred_tree_context(q);

+          if (! MR_tree_equ(groupTree,oneTree)) {

+            Tfree(oneTree);

+            break;

+          };

+          Tfree(oneTree);

+        };

+        Tfree(groupTree);

+        if (q == NULL) {

+          _gen("/* MR12 individual AND gates suppressed when all predicates are leaves");

+          _gen(" with identical context */\n");

+          genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */

+          identicalANDcontextOptimization=1;

+        } else {

+          genPredTreeGate(p, in_and_expr);

+        };

+      } else {

+  	    genPredTreeGate(p, in_and_expr);

+      };

+	}

+

+	/* if leaf node, just gen predicate */

+

+	if ( p->down==NULL )

+	{

+		genPred(p,j,suppress_sva);

+		if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */

+		return;

+	}

+

+	/* if AND list, do both preds (only two possible) */

+    /* MR10    not any more ! */

+

+	if ( p->expr == PRED_AND_LIST )

+	{

+		Predicate *list;

+		_gen("(");

+		list = p->down;

+        for (; list != NULL; list=list->right) {

+          if (identicalANDcontextOptimization) {

+            genPred(list, j,suppress_sva);

+          } else {

+	   	    genPredTree(list, j, 1, suppress_sva);  /* in and context */

+          };

+          if ( list->right!=NULL ) _gen("&&");

+        };

+		_gen(")");

+		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */

+		return;

+	}

+

+	if ( p->expr == PRED_OR_LIST )

+	{

+		Predicate *list;

+		_gen("(");

+		list = p->down;

+		for (; list!=NULL; list=list->right)

+		{

+            if (identicalORcontextOptimization) {

+	          genPred(list, j,suppress_sva);

+            } else {

+	   	      genPredTree(list, j, 0, suppress_sva);

+            };

+			if ( list->right!=NULL ) _gen("||");

+		}

+		_gen(")");

+		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */

+		return;

+	}

+

+	fatal_internal("predicate tree is wacked");

+}

+

+/* [genPredTreeMainXX] */

+

+Predicate *     /* MR10 */

+#ifdef __USE_PROTOS

+genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr)

+#else

+genPredTreeMainXX( p, j ,in_and_expr)

+    Predicate   *p;

+    Node        *j;

+    int         in_and_expr;

+#endif

+{

+

+    int     allHaveContext=1;

+    int     noneHaveContext=1;

+

+#if 0

+    fprintf(stderr,"Pred before\n");

+    dumppred(p);

+    fprintf(stderr,"\n");

+    fprintf(stderr,"Pred after\n");

+    dumppred(p);

+    fprintf(stderr,"\n");

+#endif

+

+    p=MR_predSimplifyALL(p);    /* MR10 */

+

+    require (MR_predicate_context_completed(p),"predicate context is not complete");

+

+    MR_cleanup_pred_trees(p);   /* MR10 */

+

+    MR_predContextPresent(p,&allHaveContext,&noneHaveContext);

+    if (!noneHaveContext & !allHaveContext) {

+      warnFL("predicate contains elements both with and without context",

+                FileStr[j->file],j->line);

+    };

+

+    if (InfoP) {

+       _gen("\n#if 0\n\n");

+       MR_dumpPred(p,1);

+       _gen("#endif\n");

+    };

+	genPredTree(p,j,in_and_expr,0);

+    return p;

+}

+

+Predicate *     /* MR10 */

+#ifdef __USE_PROTOS

+genPredTreeMain( Predicate *p, Node *j)

+#else

+genPredTreeMain( p, j)

+    Predicate   *p;

+    Node        *j;

+#endif

+{

+  return genPredTreeMainXX(p,j,1);

+}

+

+static void

+#ifdef __USE_PROTOS

+genExprTreeOriginal( Tree *t, int k )

+#else

+genExprTreeOriginal( t, k )

+Tree *t;

+int k;

+#endif

+{

+	require(t!=NULL, "genExprTreeOriginal: NULL tree");

+	

+	if ( t->token == ALT )

+	{

+		_gen("("); genExprTreeOriginal(t->down, k); _gen(")");

+		if ( t->right!=NULL )

+		{

+			_gen("||");

+			on1line++;

+			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+			_gen("("); genExprTreeOriginal(t->right, k); _gen(")");

+		}

+		return;

+	}

+	if ( t->down!=NULL ) _gen("(");

+	_gen1("LA(%d)==",k);

+	if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)

+	else _gen1("%s", TokenString(t->token));

+	if ( t->down!=NULL )

+	{

+		_gen("&&");

+		on1line++;

+		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+		_gen("("); genExprTreeOriginal(t->down, k+1); _gen(")");

+	}

+	if ( t->down!=NULL ) _gen(")");

+	if ( t->right!=NULL )

+	{

+		_gen("||");

+		on1line++;

+		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+		_gen("("); genExprTreeOriginal(t->right, k); _gen(")");

+	}

+}

+

+#ifdef __USE_PROTOS

+static void MR_LAtokenString(int k,int token)

+#else

+static void MR_LAtokenString(k,token)

+  int   k;

+  int   token;

+#endif

+{

+    char    *ts;

+

+    ts=TokenString(token);

+    if (ts == NULL) {

+      _gen2(" LA(%d)==%d",k,token);

+    } else {

+      _gen2(" LA(%d)==%s",k,ts);

+    };

+}

+

+

+#ifdef __USE_PROTOS

+static int MR_countLeaves(Tree *t)

+#else

+static int MR_countLeaves(t)

+  Tree  *t;

+#endif

+{

+  if (t == NULL) return 0;

+  if (t->token == ALT) {

+    return MR_countLeaves(t->down)+MR_countLeaves(t->right);

+  } else {

+    return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right);

+  };

+}

+

+#ifdef __USE_PROTOS

+static void MR_genOneLine(Tree *tree,int k)

+#else

+static void MR_genOneLine(tree,k)

+  Tree      *tree;

+  int       k;

+#endif

+{

+    if (tree == NULL) return;

+    if (tree->token == ALT) {

+       MR_genOneLine(tree->down,k);

+    } else {

+       MR_LAtokenString(k,tree->token);

+       if (tree->down != NULL &&

+           tree->down->right == NULL) {

+          _gen(" &&");

+          MR_genOneLine(tree->down,k+1);

+       } else if (tree->down != NULL) {

+         _gen(" && (");

+         MR_genOneLine(tree->down,k+1);

+         _gen(")");

+       };

+    };

+    if (tree->right != NULL) {

+      _gen(" ||");

+      MR_genOneLine(tree->right,k);

+    };

+}

+

+static int across;

+static int depth;

+static int lastkonline;

+

+#ifdef __USE_PROTOS

+static void MR_genMultiLine(Tree *tree,int k)

+#else

+static void MR_genMultiLine(tree,k)

+  Tree  *tree;

+  int   k;

+#endif

+{

+    int     i;

+

+    if (tree == NULL) return;

+    if (tree->token == ALT) {

+      MR_genMultiLine(tree,k);

+    } else {

+      MR_LAtokenString(k,tree->token);

+      lastkonline=k;

+      across++;

+      if (tree->down != NULL && tree->down->right == NULL) {

+        if (across > 3) {

+          _gen("\n");

+          across=0;

+          lastkonline=0;

+          for (i=0 ; i < depth+k ; i++) _gen("   ");

+          _gen("&&");

+        } else {

+          _gen(" &&");

+        };

+        MR_genMultiLine(tree->down,k+1);

+      } else if (tree->down != NULL) {

+        _gen("\n");

+        lastkonline=0;

+        across=0;

+        for (i=0 ; i < depth+k ; i++) _gen("   ");

+        _gen("&& (");

+        MR_genMultiLine(tree->down,k+1);

+        _gen(")");

+      };

+    };

+    if (tree->right != NULL) {

+      if (k < lastkonline) {

+        _gen("\n");

+        across=0;

+        lastkonline=0;

+        for (i=0; i < depth+k-1 ; i++) _gen("   ");

+        _gen("||");

+      } else if (across > 3 ) {

+        _gen("\n");

+        across=0;

+        lastkonline=0;

+        for (i=0; i < depth+k ; i++) _gen("   ");

+        _gen("||");

+      } else {

+        _gen(" ||");

+      };

+      MR_genMultiLine(tree->right,k);

+    };

+}

+

+#ifdef __USE_PROTOS

+static void genExprTree(Tree *tree,int k)

+#else

+static void genExprTree(tree,k)

+  Tree  *tree;

+  int   k;

+#endif

+{

+    int     count;

+

+#if 0

+    /* MR20 THM This was probably an error.

+            The routine should probably reference that static 

+            "across" and this declaration hides it.

+    */

+

+    int     across;

+#endif

+  

+    require (tree != NULL,"genExprTree: tree is NULL");

+    require (k > 0,"genExprTree: k <= 0");

+

+    if (0 && !MRhoisting) {   /* MR11 make new version standard */

+      genExprTreeOriginal(tree,k);

+    } else {

+      count=MR_countLeaves(tree);

+      if (count < 5) {

+        MR_genOneLine(tree,k);

+      } else {

+        _gen("\n");

+        across=0;

+        depth=0;

+        lastkonline=0;

+        MR_genMultiLine(tree,k);

+        _gen("\n");

+      };

+    };

+}

+

+

+/*

+ * Generate LL(k) type expressions of the form:

+ *

+ *		 (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&

+ *		 (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&

+ *			.....

+ *		 (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)

+ *

+ * If GenExprSetsOpt generate:

+ *

+ *		(setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...

+ *

+ * where n is set_deg(expr) and Ti is some random token and k is the last nonempty

+ * set in fset <=CLL_k.

+ * k=1..CLL_k where CLL_k >= 1.

+ *

+ * This routine is visible only to this file and cannot answer a TRANS message.

+ *

+ */

+

+/*  [genExpr] */

+

+static int

+#ifdef __USE_PROTOS

+genExpr( Junction *j )

+#else

+genExpr( j )

+Junction *j;

+#endif

+{

+	int max_k;

+

+	/* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead

+	 * from CLL_k..LL_k

+	 */

+	{

+		int limit;

+		if ( j->ftree!=NULL ) limit = LL_k;

+		else limit = CLL_k;

+		max_k = genExprSets(j->fset, limit);

+	}

+

+	/* Do tests for real tuples from other productions that conflict with

+	 * artificial tuples generated by compression (using sets of tokens

+	 * rather than k-trees).

+	 */

+	if ( j->ftree != NULL )

+	{

+		_gen(" && !("); genExprTree(j->ftree, 1); _gen(")");

+	}

+

+	if ( ParseWithPredicates && j->predicate!=NULL )

+	{

+		Predicate *p = j->predicate;

+		warn_about_using_gk_option();

+		_gen("&&");

+		j->predicate=genPredTreeMain(p, (Node *)j);     /* MR10 */

+	}

+

+	return max_k;

+}

+

+static int

+#ifdef __USE_PROTOS

+genExprSets( set *fset, int limit )

+#else

+genExprSets( fset, limit )

+set *fset;

+int limit;

+#endif

+{

+	int k = 1;

+	int max_k = 0;

+	unsigned *e, *g, firstTime=1;

+

+    if (set_nil(fset[1])) {

+      _gen(" 0 /* MR13 empty set expression  - undefined rule ? infinite left recursion ? */ ");

+      MR_BadExprSets++;

+    };

+

+	if ( GenExprSetsOpt )

+	{

+		while ( k <= limit && !set_nil(fset[k]) )   /* MR11 */

+		{

+			if ( set_deg(fset[k])==1 )	/* too simple for a set? */

+			{

+				int e;

+				_gen1("(LA(%d)==",k);

+				e = set_int(fset[k]);

+				if ( TokenString(e) == NULL ) _gen1("%d)", e)

+				else _gen1("%s)", TokenString(e));

+			}

+			else

+			{

+				NewSet();

+				FillSet( fset[k] );

+				_gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);

+			}

+			if ( k>max_k ) max_k = k;

+			if ( k == CLL_k ) break;

+			k++;

+			if ( k<=limit && !set_nil(fset[k]) ) _gen(" && ");  /* MR11 */

+			on1line++;

+			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+		}

+		return max_k;

+	}

+

+	while ( k<= limit &&  !set_nil(fset[k]) )       /* MR11 */

+	{

+		if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");

+		for (; *e!=nil; e++)

+		{

+			if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }

+			on1line++;

+			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+			_gen1("LA(%d)==",k);

+			if ( TokenString(*e) == NULL ) _gen1("%d", *e)

+			else _gen1("%s", TokenString(*e));

+		}

+		free( (char *)g );

+		_gen(")");

+		if ( k>max_k ) max_k = k;

+		if ( k == CLL_k ) break;

+		k++;

+		if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); }   /* MR11 */

+		on1line++;

+		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }

+	}

+	return max_k;

+}

+

+/*

+ * Generate code for any type of block.  If the last alternative in the block is

+ * empty (not even an action) don't bother doing it.  This permits us to handle

+ * optional and loop blocks as well.

+ *

+ * Only do this block, return after completing the block.

+ * This routine is visible only to this file and cannot answer a TRANS message.

+ */

+static set

+#ifdef __USE_PROTOS

+genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */)

+#else

+genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */)

+Junction *q;

+int jtype;

+int *max_k;

+int *need_right_curly;

+int *lastAltEmpty; /* MR23 */

+#endif

+{

+	set f;

+	Junction *alt;

+	int a_guess_in_block = 0;

+	require(q!=NULL,				"genBlk: invalid node");

+	require(q->ntype == nJunction,	"genBlk: not junction");

+	*need_right_curly=0;

+	*lastAltEmpty = 0;		/* MR23 */

+	if ( q->p2 == NULL )	/* only one alternative?  Then don't need if */

+	{	

+		if (first_item_is_guess_block((Junction *)q->p1)!=NULL )

+		{

+            if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) {

+  			  warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);

+            };

+   	   	    gen("zzGUESS\n");	/* guess anyway to make output code consistent */

+/* MR10 disable */  /**** gen("if ( !zzrv )\n"); ****/

+/* MR10 */          gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++;

+        };

+		TRANS(q->p1);

+		return empty;		/* no decision to be made-->no error set */

+	}

+

+	f = First(q, 1, jtype, max_k);

+	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )

+	{

+		if ( alt->p2 == NULL )					/* chk for empty alt */

+		{	

+			Node *p = alt->p1;

+			if ( p->ntype == nJunction )

+			{

+				/* we have empty alt */

+/* MR23

+   There is a conflict between giving good error information for non-exceptions

+   and making life easy for those using parser exception handling.  Consider:

+

+         r: { A } b;

+		 b: B;

+		 

+		   with input "C"

+

+   Before MR21 the error message would be "expecting B - found C".  After MR21

+   the error message would be "expcect A, B - found C".  This was good, but it

+   caused problems for those using parser exceptions because the reference to

+   B was generated inside the {...} where B really wasn't part of the block.

+

+   In MR23 this has been changed for the case where exceptions are in use to

+   not generate the extra check in the tail of the {A} block.

+*/

+

+

+/* MR23 */	if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) {

+/* MR23 */      *lastAltEmpty = 1;

+/* MR23 */		if (FoundException) {

+/* MR23 */			/* code to restore state if a prev alt didn't follow guess */

+/* MR23 */			if ( a_guess_in_block && jtype != aPlusBlk) {

+/* MR23 */				gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n");

+/* MR23 */			}

+/* MR23 */			break;

+/* MR23 */		};

+/* MR28 */      if (jtype == aPlusBlk) {

+/* MR28 */          break;

+/* MR28 */      }

+/* MR23 */	}

+		}

+	} /* end of for loop on alt */

+

+/* MR10 */        if (alt->p2 == NULL &&

+/* MR10 */               ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {

+/* MR10 */          if (first_item_is_guess_block(alt)) {

+/* MR10 */               warnFL("(...)? as last alternative of block is unnecessary",

+/* MR10 */                                FileStr[alt->file],alt->line);

+/* MR10 */          };

+/* MR10 */        };

+

+		if ( alt != q ) gen("else ")

+		else

+		{

+			if ( DemandLookahead ) {

+				if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}

+				else gen1("look(%d);\n", *max_k);

+			}

+		}

+

+		if ( alt!=q )

+		{

+			_gen("{\n");

+			tabs++;

+			(*need_right_curly)++;

+			/* code to restore state if a prev alt didn't follow guess */

+			if ( a_guess_in_block )

+				gen("if ( !zzrv ) zzGUESS_DONE;\n");

+		}

+		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )

+		{

+			a_guess_in_block = 1;

+			gen("zzGUESS\n");

+		}

+		gen("if ( ");

+		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");

+		genExpr(alt);

+		_gen(" ) ");

+		_gen("{\n");

+		tabs++;

+		TRANS(alt->p1);

+		--tabs;

+		gen("}\n");

+/* MR10 */        if (alt->p2 == NULL) {

+/* MR10 */          if (first_item_is_guess_block(alt)) {

+/* MR10 */            gen("/* MR10 */ else {\n");

+/* MR10 */            tabs++;

+/* MR10 */  		  (*need_right_curly)++;

+/* MR10 */  		  /* code to restore state if a prev alt didn't follow guess */

+/* MR10 */            gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");

+/* MR10 */            gen("/* MR10 */ if (0) {}     /* last alternative of block is guess block */\n");

+/* MR10 */          };

+/* MR10 */        };

+	}

+	return f;

+}

+

+static int

+#ifdef __USE_PROTOS

+has_guess_block_as_first_item( Junction *q )

+#else

+has_guess_block_as_first_item( q )

+Junction *q;

+#endif

+{

+	Junction *alt;

+

+	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )

+	{

+		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;

+	}

+	return 0;

+}

+

+static int

+#ifdef __USE_PROTOS

+has_guess_block_as_last_item( Junction *q )

+#else

+has_guess_block_as_last_item( q )

+Junction *q;

+#endif

+{

+	Junction *alt;

+

+    if (q == NULL) return 0;

+	for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {};

+    return first_item_is_guess_block( (Junction *) alt->p1) != NULL;

+}

+

+/* MR30 See description of first_item_is_guess_block for background */

+

+Junction *

+#ifdef __USE_PROTOS

+first_item_is_guess_block_extra(Junction *q )

+#else

+first_item_is_guess_block_extra(q)

+Junction *q;

+#endif

+{

+	while ( q!=NULL &&

+            (  ( q->ntype==nAction ) ||

+               ( q->ntype==nJunction &&

+                    (q->jtype==Generic || q->jtype == aLoopBlk) 

+               )

+            )

+          )

+	{

+		if ( q->ntype==nJunction ) q = (Junction *)q->p1;

+		else q = (Junction *) ((ActionNode *)q)->next;

+	}

+

+	if ( q==NULL ) return NULL;

+	if ( q->ntype!=nJunction ) return NULL;

+	if ( q->jtype!=aSubBlk ) return NULL;

+	if ( !q->guess ) return NULL;

+

+	return q;

+}

+

+/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node

+ * of (...)?;  This function ignores actions and predicates.

+ */

+

+Junction *

+#ifdef __USE_PROTOS

+first_item_is_guess_block( Junction *q )

+#else

+first_item_is_guess_block( q )

+Junction *q;

+#endif

+{

+	Junction * qOriginal = q;	/* DEBUG */

+

+    /* MR14  Couldn't find aSubBlock which was a guess block when it lay

+             behind aLoopBlk.  The aLoopBlk only appear in conjunction with

+             aLoopBegin, but the routine didn't know that.  I think.

+

+       MR14a Added extra parentheses to clarify precedence

+

+	   MR30  This appears to have been a mistake.  The First set was then

+	         computed incorrectly for:

+

+					r : ( (A)? B

+					    | C

+						)*

+			 

+			 The routine analysis_point was seeing the guess block when

+			 it was still analyzing the loopBegin block.  As a consequence,

+			 when it looked for the analysis_point it was processing the B, but

+			 skipping over the C alternative altogether because it thought

+			 it was looking at a guess block, not realizing there was a loop

+			 block in front of the loopBegin.

+

+             loopBegin  loopBlk  subBlk/guess  A  G  EB  G  B EB EB  EB  ER

+			    |          |          |                     ^   ^

+				|		   |                                |   |

+                |          +-> G  C G ----------------------+   |

+                |                                               |

+				+--- G G G -------------------------------------+

+    

+			 Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu).

+

+		MR30  This is still more complicated.  This fix caused ambiguity messages

+		to be reported for "( (A B)? )* A B" but not for "( (A B)? )+".  Why is

+		there a difference when these are outwardly identical ?  It is because the

+		start of a (...)* block is represented by two nodes: a loopBegin block

+		followed by a loopBlock whereas the start of a (...)+ block is

+		represented as a single node: a plusBlock.  So if first_item_is_guess_block

+		is called when the current node is a loopBegin it starts with the

+		loop block rather than the the sub block which follows the loop block.

+		However, we can't just skip past the loop block because some routines

+		depend on the old implementation.  So, we provide a new implementation

+		which does skip the loopBlock.  However, which should be called when ?

+		I'm not sure, but my guess is that first_item_is_guess_block_extra (the

+		new one) should only be called for the ambiguity routines.

+

+    */

+

+	while ( q!=NULL &&

+            (  ( q->ntype==nAction ) ||

+               ( q->ntype==nJunction &&

+                    (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/

+               )

+            )

+          )

+	{

+		if ( q->ntype==nJunction ) q = (Junction *)q->p1;

+		else q = (Junction *) ((ActionNode *)q)->next;

+	}

+

+	if ( q==NULL ) return NULL;

+	if ( q->ntype!=nJunction ) return NULL;

+	if ( q->jtype!=aSubBlk ) return NULL;

+	if ( !q->guess ) return NULL;

+

+	return q;

+}

+

+/* MR1				                 					    */

+/* MR1  10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs  */

+/* MR1				                                                        */

+

+#define STRINGIZEBUFSIZE 1024

+

+static char stringizeBuf[STRINGIZEBUFSIZE];

+char *

+#ifdef __USE_PROTOS

+stringize(char * s)

+#else

+stringize(s)

+char *s;

+#endif

+

+{

+  char		*p;

+  char		*stop;

+

+  p=stringizeBuf;

+  stop=&stringizeBuf[1015];

+

+  if (s != 0) {

+    while (*s != 0) {

+      if (p >= stop) {

+	goto stringizeStop;

+      } else if (*s == '\n') {

+        *p++='\\';

+        *p++='n';

+        *p++='\\';

+	*p++=*s++;

+      } else if (*s == '\\') {

+	*p++=*s;

+	*p++=*s++;

+      } else if (*s == '\"') {

+        *p++='\\';

+	*p++=*s++;

+        while (*s != 0) {

+          if (p >= stop) {

+	     goto stringizeStop;

+	  } else if (*s == '\n') {

+	    *p++='\\';

+	    *p++=*s++;

+	  } else if (*s == '\\') {

+	    *p++=*s++;

+	    *p++=*s++;

+	  } else if (*s == '\"') {

+	    *p++='\\';

+	    *p++=*s++;

+	    break;

+	  } else {

+	    *p++=*s++;

+          };

+        };

+      } else if (*s == '\'') {

+	*p++=*s++;

+        while (*s != 0) {

+          if (p >= stop) {

+	     goto stringizeStop;

+	  } else if (*s == '\'') {

+	    *p++=*s++;

+	    break;

+	  } else if (*s == '\\') {

+	    *p++=*s++;

+	    *p++=*s++;

+	  } else if (*s == '\"') {

+	    *p++='\\';

+	    *p++=*s++;

+	    break;

+	  } else {

+	    *p++=*s++;

+          };

+        };

+      } else {

+        *p++=*s++;

+      };

+    };

+  };

+  goto stringizeExit;

+stringizeStop:

+  *p++='.';        	

+  *p++='.';        	

+  *p++='.';        	

+stringizeExit:

+  *p=0;

+  return stringizeBuf;

+}

+

+#ifdef __USE_PROTOS

+int isNullAction(char *s)

+#else

+int isNullAction(s)

+  char  *s;

+#endif

+{

+  char  *p;

+  for (p=s; *p != '\0' ; p++) {

+    if (*p != ';' && *p !=' ') return 0;

+  };

+  return 1;

+}

+/* MR1									                                    */

+/* MR1	End of Routine to stringize code for failed predicates msgs         */

+/* MR1				                                                        */

+

+/* Generate an action.  Don't if action is NULL which means that it was already

+ * handled as an init action.

+ */

+void

+#ifdef __USE_PROTOS

+genAction( ActionNode *p )

+#else

+genAction( p )

+ActionNode *p;

+#endif

+{

+	require(p!=NULL,			"genAction: invalid node and/or rule");

+	require(p->ntype==nAction,	"genAction: not action");

+

+	if ( !p->done )  /* MR10 */ /* MR11 */

+	{

+		if ( p->is_predicate)

+		{

+			if ( p->guardpred != NULL )

+			{

+                Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */

+                gen("if (!");

+       			guardDup=genPredTreeMain(guardDup, (Node *)p);

+                predicate_free(guardDup);

+			}

+/* MR10 */  else if (p->ampersandPred != NULL) {

+/* MR10 */      gen("if (!");

+/* MR10 */      p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);

+/* MR10 */  }

+			else

+			{

+				gen("if (!(");

+				/* make sure that '#line n' is on front of line */

+				if ( GenLineInfo && p->file != -1 ) _gen("\n");

+				dumpPredAction(p,p->action, output, 0, p->file, p->line, 0);

+				_gen(")");

+			}

+

+/* MR23 Change failed predicate macro to have three arguments:

+

+        macro arg 1: The stringized predicate itself

+        macro arg 2: 0 => no user-defined error action

+                     1 => user-defined error action

+        macro arg 3: The user-defined error action

+

+   This gives the user more control of the error action.

+*/

+			tabs++;

+			gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n",         /* MR23 */

+					stringize(p->action),	                         /* MR23 */

+                    (p->pred_fail == NULL ?                          /* MR23/MR27 */

+                       	"0 /* report */" : "1 /* user action */"),   /* MR23/MR27 */

+                    (p->pred_fail == NULL ?                          /* MR23 */

+                        "0; /* no user action */" : p->pred_fail));  /* MR23 */

+			tabs--;

+		}

+		else    /* not a predicate */

+		{

+            if (! isNullAction(p->action) && !p->noHoist) {

+  	  		  if ( FoundGuessBlk ) {

+				if ( GenCC ) {

+                  gen("if ( !guessing ) {\n");

+                } else {

+				  gen("zzNON_GUESS_MODE {\n");

+                };

+              };

+			  dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */

+			  if ( FoundGuessBlk ) gen("}\n");

+            };

+		}

+	}

+	TRANS(p->next)

+}

+

+/*

+ *		if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in

+ *		else pass addr of temp root ptr (&_ast) (don't zzlink it in).

+ *

+ *		if ! modifies rule-ref, then never link it in and never pass zzSTR.

+ *		Always pass address of temp root ptr.

+ */

+void

+#ifdef __USE_PROTOS

+genRuleRef( RuleRefNode *p )

+#else

+genRuleRef( p )

+RuleRefNode *p;

+#endif

+{

+	Junction *q;

+	char *handler_id = "";

+	RuleEntry *r, *r2;

+	char *parm = "", *exsig = "";

+

+    int     genRuleRef_emittedGuessGuard=0;     /* MR10 */

+

+	require(p!=NULL,			"genRuleRef: invalid node and/or rule");

+	require(p->ntype==nRuleRef, "genRuleRef: not rule reference");

+	

+	if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )

+		handler_id = p->altstart->exception_label;

+

+	r = (RuleEntry *) hash_get(Rname, p->text);

+	if ( r == NULL )

+	{

+		warnFL( eMsg1("rule %s not defined",

+					  p->text), FileStr[p->file], p->line );

+		return;

+	}

+

+/* MR8 5-Aug-97     Reported by S.Bochnak@microtool.com.pl                  */

+/*                  Don't do assign when no return values declared          */

+/*                  Move definition of q up and use it to guard p->assign   */

+

+	q = RulePtr[r->rulenum];	/* find definition of ref'd rule */  /* MR8 */

+

+	r2 = (RuleEntry *) hash_get(Rname, p->rname);

+	if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}

+

+    OutLineInfo(output,p->line,FileStr[p->file]);

+

+	if ( GenCC && GenAST ) {

+		gen("_ast = NULL;\n");

+	}

+

+	if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) {      /* MR8 */

+		if ( GenCC ) {

+          gen("if ( !guessing ) {\n");

+        } else {

+          gen("zzNON_GUESS_MODE {\n");

+        };

+        tabs++;                                                      /* MR11 */

+        genRuleRef_emittedGuessGuard=1;                              /* MR11 */

+    };

+

+	if ( FoundException ) exsig = "&_signal";

+

+	tab();

+	if ( GenAST )

+	{

+		if ( GenCC ) {

+/****			if ( r2->noAST || p->astnode==ASTexclude )

+****/

+			{

+/****				_gen("_ast = NULL;\n");

+****/

+				parm = "&_ast";

+			}

+/*** we always want to set just a pointer now, then set correct

+pointer after

+

+			else {

+				_gen("_astp =

+(_tail==NULL)?(&_sibling):(&(_tail->_right));\n");

+				parm = "_astp";

+			}

+****/

+		}

+		else {

+			if ( r2->noAST || p->astnode==ASTexclude )

+			{

+				_gen("_ast = NULL; ");

+				parm = "&_ast";

+			}

+			else parm = "zzSTR";

+		}

+		if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */

+		{

+			if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */

+			else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);

+		}

+		if ( FoundException ) {

+			_gen5("%s%s(%s,&_signal%s%s); ",

+				  RulePrefix,

+				  p->text,

+				  parm,

+				  (p->parms!=NULL)?",":"",

+				  (p->parms!=NULL)?p->parms:"");

+			if ( p->ex_group!=NULL ) {

+				_gen("\n");

+				gen("if (_signal) {\n");

+				tabs++;

+				dumpException(p->ex_group, 0);

+				tabs--;

+				gen("}");

+			}

+			else {

+				_gen1("if (_signal) goto %s_handler;", handler_id);

+			}

+		}

+		else {

+			_gen5("%s%s(%s%s%s);",

+				  RulePrefix,

+				  p->text,

+				  parm,

+				  (p->parms!=NULL)?",":"",

+				  (p->parms!=NULL)?p->parms:"");

+		}

+		if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )

+		{

+			/* rule has a ! or element does */

+			/* still need to assign to #i so we can play with it */

+			_gen("\n");

+			gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);

+		}

+		else if ( !r2->noAST && p->astnode == ASTinclude )

+		{

+			/* rule doesn't have a ! and neither does element */

+/* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {

+/* MR10 */    _gen("\n");

+/* MR10 */    if (GenCC) gen ("if (!guessing) {    /* MR10 */")

+/* MR10 */          else gen ("if (!zzguessing) {    /* MR10 */\n");

+/* MR10 */    tabs++;

+/* MR10 */  };

+			if ( GenCC ) {

+				_gen("\n");

+				gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");

+				gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);

+				tab();

+			}

+			else _gen(" ");

+            if ( GenCC ) {

+                _gen("ASTBase::"); }

+                else _gen("zz");

+			_gen("link(_root, &_sibling, &_tail);");

+

+/* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {     /* MR10 */

+/* MR10 */    _gen("\n");

+/* MR10 */    tabs--;

+/* MR10 */    if (GenCC) gen ("};    /* MR10 */")

+/* MR10 */          else gen ("};    /* MR10 */");

+/* MR10 */  };

+		}

+	}

+	else

+	{

+		if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */

+		{

+			if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */

+			else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);

+		}

+		if ( FoundException ) {

+			_gen4("%s%s(&_signal%s%s); ",

+				  RulePrefix,

+				  p->text,

+				  (p->parms!=NULL)?",":"",

+				  (p->parms!=NULL)?p->parms:"");

+			if ( p->ex_group!=NULL ) {

+				_gen("\n");

+				gen("if (_signal) {\n");

+				tabs++;

+				dumpException(p->ex_group, 0);

+				tabs--;

+				gen("}");

+			}

+			else {

+				_gen1("if (_signal) goto %s_handler;", handler_id);

+			}

+		}

+		else {

+			_gen3("%s%s(%s);",

+				  RulePrefix,

+				  p->text,

+				  (p->parms!=NULL)?p->parms:"");

+		}

+		if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n");           /* MR8 */

+	}

+

+	if ( p->assign!=NULL && q->ret!=NULL) {                          /* MR8 */

+		if ( hasMultipleOperands(p->assign) )                        /* MR23 */

+		{

+			_gen("\n");

+			dumpRetValAssign(p->assign, q->ret, p);                  /* MR30 */

+			_gen("}");

+		}

+	}

+	_gen("\n");

+

+	/* Handle element labels now */

+	if ( p->el_label!=NULL )

+	{

+		if ( GenAST )

+		{

+			if ( GenCC ) {

+				gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);

+			}

+			else {gen1("%s_ast = zzastCur;\n", p->el_label);}

+		}

+       	else if (!GenCC ) {

+			gen1("%s = zzaCur;\n", p->el_label);

+        }

+	}

+

+	if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) {       /* MR8 */

+		/* in guessing mode, don't branch to handler upon error */

+        tabs--;                                                     /* MR11 */

+		gen("} else {\n");

+        tabs++;                                                     /* MR11 */

+		if ( FoundException ) {

+			gen6("%s%s(%s%s&_signal%s%s);\n",

+				 RulePrefix,

+				 p->text,

+				 parm,

+                 (*parm!='\0')?",":"",

+                 (p->parms!=NULL)?",":"",

+				 (p->parms!=NULL)?p->parms:"");

+		}

+		else {

+			gen5("%s%s(%s%s%s);\n",

+				 RulePrefix,

+				 p->text,

+				 parm,

+				 (p->parms!=NULL && *parm!='\0')?",":"",

+				 (p->parms!=NULL)?p->parms:"");

+		}

+        tabs--;                                                     /* MR11 */

+		gen("}\n");

+	}

+	TRANS(p->next)

+}

+

+/*

+ * Generate code to match a token.

+ *

+ * Getting the next token is tricky.  We want to ensure that any action

+ * following a token is executed before the next GetToken();

+ */

+void

+#ifdef __USE_PROTOS

+genToken( TokNode *p )

+#else

+genToken( p )

+TokNode *p;

+#endif

+{

+	RuleEntry *r;

+	char *handler_id = "";

+	ActionNode *a;

+	char *set_name;

+	char *set_nameErrSet;

+	int complement;

+	int ast_label_in_action = 0;	/* MR27 */

+	int pushedCmodeAST = 0;			/* MR27 */

+

+	require(p!=NULL,			"genToken: invalid node and/or rule");

+	require(p->ntype==nToken,	"genToken: not token");

+	if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )

+		handler_id = p->altstart->exception_label;

+

+	r = (RuleEntry *) hash_get(Rname, p->rname);

+	if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}

+

+/*

+ * MR27 Has the element label been referenced as an AST (with the # operator) ?

+ *      If so, then we'll want to build the AST even though the user has used

+ *      the ! operator.

+ */

+/* MR27 */	if (GenAST && p->el_label != NULL) {

+/* MR27 */		ast_label_in_action = list_search_cstring(r->ast_labels_in_actions,

+/* MR27 */		                                          p->el_label);

+/* MR27 */	}

+	

+    OutLineInfo(output,p->line,FileStr[p->file]);

+

+	if ( !set_nil(p->tset) )	/* implies '.', ~Tok, or tokenclass */

+	{

+		unsigned e;

+		unsigned eErrSet = 0;

+		set b;

+		set bErrSet;					/* MR23 */

+		b = set_dup(p->tset);

+		bErrSet = set_dup(p->tset);	    /* MR23 */

+		complement = p->complement; /* MR23 */

+		if ( p->tclass!=NULL  && complement == 0 /* MR23 */) { /* token class not complemented*/

+			static char buf[MaxRuleName+20];	    /* MR23 */

+			static char bufErrSet[MaxRuleName+20];	/* MR23 */

+			if ( p->tclass->dumped ) {

+				e = p->tclass->setnum;

+				eErrSet = p->tclass->setnumErrSet;

+			}

+			else {

+				e = DefErrSet(&b, 0, TokenString(p->token));

+				eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset");

+				p->tclass->dumped = 1;	/* indicate set has been created */

+				p->tclass->setnum = e;

+				p->tclass->setnumErrSet = eErrSet;					/* MR23 */

+			}

+			sprintf(buf, "%s_set", TokenString(p->token));

+			sprintf(bufErrSet, "%s_errset", TokenString(p->token));	/* MR23 */

+			set_name = buf;

+			set_nameErrSet = bufErrSet;								/* MR23 */

+		}

+

+		/* MR23 - Forgot about the case of ~TOKCLASS. */

+

+		else if ( p->tclass!=NULL  && complement != 0 /* MR23 */)

+		{

+			static char buf[MaxRuleName+20];	    /* MR23 */

+			static char bufErrSet[MaxRuleName+20];	/* MR23 */

+			if ( p->tclass->dumpedComplement ) {

+				e = p->tclass->setnumComplement;

+				eErrSet = p->tclass->setnumErrSetComplement;

+			}

+			else {

+				e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar");

+				eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar");

+				p->tclass->dumpedComplement = 1;	/* indicate set has been created */

+				p->tclass->setnumComplement = e;

+				p->tclass->setnumErrSetComplement = eErrSet;					/* MR23 */

+			}

+			sprintf(buf, "%s_setbar", TokenString(p->token));

+			sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token));	/* MR23 */

+			set_name = buf;

+			set_nameErrSet = bufErrSet;								/* MR23 */

+		}

+		else {					/* wild card */

+			static char buf[sizeof("zzerr")+10];

+			static char bufErrSet[sizeof("zzerr")+10];

+			int n = DefErrSet( &b, 0, NULL );

+			int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set");

+			if ( GenCC ) sprintf(buf, "err%d", n);

+			else sprintf(buf, "zzerr%d", n);

+			if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet);

+			else sprintf(bufErrSet, "zzerr%d", nErrSet);

+			set_name = buf;

+			set_nameErrSet = bufErrSet;

+		}

+

+		if ( !FoundException ) {

+/* MR23 */		gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet);

+		}

+		else if ( p->ex_group==NULL ) {

+            if ( p->use_def_MT_handler )

+                gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",

+                     set_name,

+                     p->token,

+                     tokenFollowSet(p))

+            else

+                gen2("zzsetmatch_wsig(%s, %s_handler);",

+                     set_name,

+                     handler_id);

+		}

+		else

+		{

+			gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);

+			tabs++;

+/* MR6 */	if (FoundGuessBlk) {

+/* MR6 */	  if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}

+/* MR6 */	  else gen("if ( zzguessing ) goto fail;\n");

+/* MR6 */	};

+			gen("_signal=MismatchedToken;\n");

+			dumpException(p->ex_group, 0);

+			tabs--;

+			gen("}\n");

+		}

+		set_free(b);

+		set_free(bErrSet);

+	}

+	else if ( TokenString(p->token)!=NULL )

+	{

+		if ( FoundException ) {

+			if ( p->use_def_MT_handler )

+				gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))

+			else if ( p->ex_group==NULL )

+			{

+				gen2("zzmatch_wsig(%s, %s_handler);",

+					 TokenString(p->token),

+					 handler_id);

+			}

+			else

+			{

+/* MR6 */		if (GenCC) {

+/* MR6 */		  gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));

+/* MR6 */		} else {

+/* MR6 */		  gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token));

+/* MR6 */		};

+				tabs++;

+/* MR6 */		if (FoundGuessBlk) {

+/* MR6 */	  	  if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}

+/* MR6 */		  else gen("if ( zzguessing ) goto fail;\n");

+/* MR6 */		};

+				gen("_signal=MismatchedToken;\n");

+				dumpException(p->ex_group, 0);

+				tabs--;

+				gen("}\n");

+			}

+		}

+		else gen1("zzmatch(%s);", TokenString(p->token));

+	}

+	else {

+        if ( FoundException ) {

+            if ( p->use_def_MT_handler )

+				gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",

+					 p->token,tokenFollowSet(p))

+            else

+                gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);

+        }

+		else {gen1("zzmatch(%d);", p->token);}

+	}

+

+	a = findImmedAction( p->next );

+	/* generate the token labels */

+	if ( GenCC && p->elnum>0 )

+	{

+		/* If building trees in C++, always gen the LT() assigns */

+		if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )

+		{

+/* MR10 */	if ( FoundGuessBlk ) {

+/* MR10 */    gen("\n");

+/* MR10 */    if (p->label_used_in_semantic_pred) {

+/* MR10 */		gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);  /* MR10 */\n", BlkLevel-1, p->elnum);

+/* MR10 */    } else {

+/* MR10 */		gen("if ( !guessing ) {\n"); tab();

+/* MR10 */		_gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);

+/* MR10 */      gen("}\n");

+/* MR10 */    };

+/* MR10 */  } else {

+/* MR10 */	  _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum);

+/* MR10 */  };

+/* MR10 */

+		}

+

+/*

+ *  MR23 labase is never used in the C++ runtime library.

+ *       and this code is generated only in C++ mode

+ */

+

+/***		if ( LL_k>1 )                                    / * MR23 disabled */

+/***			if ( !DemandLookahead ) _gen(" labase++;");  / * MR23 disabled */

+/***		_gen("\n");                                      / * MR23 disabled */

+/***		tab();                                           / * MR23 disabled */

+	}

+	if ( GenAST )

+	{

+		if ( FoundGuessBlk &&

+				(ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )

+		{

+			if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}

+			else {_gen("zzNON_GUESS_MODE {\n"); tab();}

+		}

+

+/* MR27 addition when labels referenced when operator ! used */

+

+		pushedCmodeAST = 0; /* MR27 */

+		if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) {

+			_gen("\n");

+			if (GenCC) {

+/* MR13 */      if (NewAST) {

+/* MR13 */    	    gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);

+/* MR13 */      } else {

+/* MR13 */    	    gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);

+/* MR13 */      }

+			}

+			else {

+				pushedCmodeAST = 1;

+				gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */");

+			}

+		}

+

+/* end MR27 addition for labels referenced when operator ! used */

+

+		if (!r->noAST )

+		{

+			if (GenCC && !(p->astnode == ASTexclude) ) {

+				_gen("\n");

+/* MR13 */      if (NewAST) {

+/* MR13 */    	    gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);

+/* MR13 */      } else {

+/* MR13 */    	    gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);

+/* MR13 */      }

+				tab();

+			}

+			if ( GenCC && !(p->astnode == ASTexclude) )

+				{_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}

+			else _gen(" ");

+			if ( p->astnode==ASTchild ) {

+				if ( !GenCC ) _gen("zz");

+				_gen("subchild(_root, &_sibling, &_tail);");

+			}

+			else if ( p->astnode==ASTroot ) {

+				if ( !GenCC ) _gen("zz");

+				_gen("subroot(_root, &_sibling, &_tail);");

+			}

+			if ( GenCC && !(p->astnode == ASTexclude) ) {

+				_gen("\n");

+				tab();

+			}

+		}

+		else if ( !GenCC ) {

+			if (! pushedCmodeAST) _gen(" zzastDPush;");

+		}

+		if ( FoundGuessBlk &&

+				(ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )

+			{gen("}\n"); tab();}

+	}

+

+	/* Handle element labels now */

+	if ( p->el_label!=NULL )

+	{

+        int     done_NON_GUESSMODE=0;

+

+		_gen("\n");

+

+/* MR10 */    /* do Attrib / Token ptr for token label used in semantic pred */

+/* MR10 */    /* for these cases do assign even in guess mode                */

+/* MR10 */

+/* MR10 */    if (p->label_used_in_semantic_pred) {

+/* MR10 */      if ( GenCC ) {

+/* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {

+/* MR10 */          gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum);

+/* MR10 */        } else {

+/* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);

+/* MR10 */        };

+/* MR10 */      } else {

+/* MR10 */		  gen1("%s = zzaCur;", p->el_label);

+/* MR10 */      };

+/* MR10 */      if (FoundGuessBlk) _gen("  /* MR10 */");

+/* MR10 */      _gen("\n");

+/* MR10 */    };

+

+		/* Do Attrib / Token ptr */

+

+/* MR10 */  if (! p->label_used_in_semantic_pred) {

+/* MR10 */

+/* MR10 */      if ( FoundGuessBlk ) {

+/* MR10 */        if (! done_NON_GUESSMODE) {

+/* MR10 */          done_NON_GUESSMODE=1;

+/* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}

+/* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}

+/* MR10 */        };

+/* MR10 */      };

+/* MR10 */

+/* MR10 */      if ( GenCC ) {

+/* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {

+/* MR10 */          gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);

+/* MR10 */        } else {

+/* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);

+/* MR10 */        };

+/* MR10 */      } else {

+/* MR10 */        gen1("%s = zzaCur;\n", p->el_label);

+/* MR10 */      };

+/* MR10 */  };

+

+		/* Do AST ptr */

+

+		if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */

+		{

+

+/* MR10 */      if ( FoundGuessBlk ) {

+/* MR10 */        if (! done_NON_GUESSMODE) {

+/* MR10 */          done_NON_GUESSMODE=1;

+/* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}

+/* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}

+/* MR10 */        };

+/* MR10 */      };

+

+			if ( GenCC ) {

+				gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);

+			}

+			else {gen1("%s_ast = zzastCur;\n", p->el_label);}

+		}

+

+/* MR10 */  if (done_NON_GUESSMODE) {

+/* MR10 */    gen("}\n"); tab();

+/* MR10 */  };

+

+	}

+

+	/* Handle any actions immediately following action */

+	if ( a != NULL )  /* MR10 */ /* MR11 */

+    {

+    	/* delay next token fetch until after action */

+		_gen("\n");

+		if ( a->is_predicate)

+		{

+#if 0

+/* Disabled in MR30 ************************************************************

+   And moved into genAction

+   *****************************************************************************

+*/

+ 

+    	    gen("if (!(");

+

+			/* make sure that '#line n' is on front of line */  /* MR14 */

+			if ( GenLineInfo && p->file != -1 ) _gen("\n");     /* MR14 */

+			dumpPredAction(a,a->action, output, 0, a->file, a->line, 0);

+

+/* MR23 Change failed predicate macro to have three arguments:

+

+        macro arg 1: The stringized predicate itself

+        macro arg 2: 0 => no user-defined error action

+                     1 => user-defined error action

+        macro arg 3: The user-defined error action

+

+   This gives the user more control of the error action.

+*/

+			_gen(")) \n");

+			tabs++;

+			gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n",           /* MR23 */

+					stringize(a->action),	                         /* MR23 */

+                    (a->pred_fail == NULL ?                          /* MR23/MR27 */

+                       	"0 /* report */" : "1 /* user action */"),   /* MR23/MR27 */

+                    (a->pred_fail == NULL ?                          /* MR23 */

+                        "0; /* no user action */" : a->pred_fail));  /* MR23 */

+			tabs--;

+/* Disabled in MR30 ************************************************************

+   And moved into genAction

+   *****************************************************************************

+*/

+#endif

+		}

+		else    /* MR9 a regular action - not a predicate action */

+		{

+

+/* MR23: Search an action which is not a predicate for LT(i),

+         LA(i), or LATEXT(i) in order to warn novice users that

+         it refers to the previous matched token, not the next

+         one.  This is different than the case for semantic

+         predicates.

+*/

+                                 

+/* MR23 */    if (GenCC) {

+/* MR23 */	    if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1;

+/* MR23 */    }

+/* MR23 */    else {

+/* MR23 */      if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1;            

+/* MR23 */      if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1;

+/* MR23 */    }

+

+			if ( FoundGuessBlk ) {

+   				if ( GenCC ) {gen("if ( !guessing ) {\n");}

+   				else gen("zzNON_GUESS_MODE {\n");

+			}

+   			dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */

+       		if ( FoundGuessBlk ) gen("}\n");

+			a->done = 1; /* MR30 */

+ 		}

+/***    a->done = 1;  MR30 Moved up into then branch for true actions, but not predicates ***/

+		if ( !DemandLookahead ) {

+			if ( GenCC ) {

+				if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");

+				_gen(" consume();")

+                if ( FoundException && p->use_def_MT_handler )

+                    _gen(" _signal=NoSignal;");

+                _gen("\n");

+			}

+            else

+            {

+                if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");

+					_gen(" zzCONSUME;\n");

+                if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");

+                _gen("\n");

+            }

+		}

+		else gen("\n");

+		if (a->done) {			/* MR30 */

+			TRANS( a->next );   /* MR30 */

+		}						/* MR30 */

+		else {					/* MR30 */

+			TRANS( p->next );	/* MR30 */

+		}						/* MR30 */

+	}

+	else

+	{

+        if ( !DemandLookahead ) {

+			if ( GenCC ) {

+				if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");

+				_gen(" consume();")

+				if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");

+				_gen("\n");

+			}

+			else {

+				if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");

+				_gen(" zzCONSUME;");

+				if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");

+				_gen("\n");

+			}

+		}

+		else _gen("\n");

+		TRANS(p->next);

+	}

+}

+

+/*  MR21

+ *

+ *  There was a bug in the code generation for {...} which causes it

+ *  to omit the optional tokens from the error messages.  The easiest

+ *  way to fix this was to make the opt block look like a sub block:

+ *

+ *          { a | b | c }

+ *

+ *  becomes (internally):

+ *

+ *          ( a | b | c | )

+ *

+ *  The code for genOptBlk is now identical to genSubBlk except for

+ *  cosmetic changes.

+ */

+

+void

+#ifdef __USE_PROTOS

+genOptBlk( Junction *q )

+#else

+genOptBlk( q )

+Junction *q;

+#endif

+{

+	int max_k;

+	set f;

+	int need_right_curly;

+	set savetkref;

+	int lastAltEmpty;			/* MR23 */

+	savetkref = tokensRefdInBlock;

+	require(q->ntype == nJunction,	"genOptBlk: not junction");

+	require(q->jtype == aOptBlk,	"genOptBlk: not opt block");

+

+    OutLineInfo(output,q->line,FileStr[q->file]);

+	BLOCK_Preamble(q);

+	BlkLevel++;

+    BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */

+	f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+/* MR23

+   Bypass error clause generation when exceptions are used in {...} block 

+   See multi-line note in genBlk near call to isEmptyAlt.

+*/

+	if (! FoundException) {

+	    if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}

+	}

+	else {

+		gen("/* MR23 skip error clause for {...} when exceptions in use */\n");

+	}

+	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+	freeBlkFsets(q);

+	--BlkLevel;

+	BLOCK_Tail();

+

+	if ( q->guess )

+	{

+		gen("zzGUESS_DONE\n");

+	}

+

+	/* must duplicate if (alpha)?; one guesses (validates), the

+	 * second pass matches */

+	if ( q->guess && analysis_point(q)==q )

+	{

+        OutLineInfo(output,q->line,FileStr[q->file]);

+		BLOCK_Preamble(q);

+		BlkLevel++;

+		f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}

+		{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+		freeBlkFsets(q);

+		--BlkLevel;

+		BLOCK_Tail();

+	}

+

+	tokensRefdInBlock = savetkref;

+	if (q->end->p1 != NULL) TRANS(q->end->p1);

+}

+

+/*

+ * Generate code for a loop blk of form:

+ *

+ *				 |---|

+ *				 v   |

+ *			   --o-G-o-->o--

+ */

+void

+#ifdef __USE_PROTOS

+genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )

+#else

+genLoopBlk( begin, q, start, max_k )

+Junction *begin;

+Junction *q;

+Junction *start;	/* where to start generating code from */

+int max_k;

+#endif

+{

+	set         f;

+	int         need_right_curly;

+	set         savetkref;

+    Junction    *guessBlock;    /* MR10 */

+    int         singleAlt;      /* MR10 */

+	int			lastAltEmpty;	/* MR23 */

+

+	savetkref = tokensRefdInBlock;

+	require(q->ntype == nJunction,	"genLoopBlk: not junction");

+	require(q->jtype == aLoopBlk,	"genLoopBlk: not loop block");

+

+	if ( q->visited ) return;

+	q->visited = TRUE;

+

+    /* first_item_is_guess_block doesn't care what kind of node it is */

+

+    guessBlock=first_item_is_guess_block( (Junction *) q->p1);  /* MR10 */

+    singleAlt=q->p2==NULL;                                      /* MR10 */

+

+	if (singleAlt && !guessBlock)	    /* MR10 */ /* only one alternative? */

+	{

+		if ( DemandLookahead ) {

+			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}

+			else gen1("look(%d);\n", max_k);

+		}

+		gen("while ( ");

+		if ( begin!=NULL ) genExpr(begin);

+		else genExpr(q);

+		/* if no predicates have been hoisted for this single alt (..)*

+		 * do so now

+		 */

+        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+		if ( ParseWithPredicates && begin->predicate==NULL )

+		{

+			Predicate *a = MR_find_predicates_and_supp((Node *)q->p1);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+

+			if ( a!=NULL )

+			{

+				_gen("&&");

+				a=genPredTreeMain(a, (Node *)q);    /* MR10 */

+			}

+/* MR10 */  if (MRhoisting) {

+/* MR10 */    predicate_free(a);

+/* MR10 */  };

+		}

+		_gen(" ) {\n");

+		tabs++;

+		TRANS(q->p1);

+		if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);

+		if ( DemandLookahead ) {

+			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}

+			else gen1("look(%d);\n", max_k);

+		}

+		--tabs;

+		gen("}\n");

+		freeBlkFsets(q);

+		q->visited = FALSE;

+		tokensRefdInBlock = savetkref;

+		return;

+	}

+	gen("for (;;) {\n");        /* MR20 G. Hobbelt */

+	tabs++;

+/* MR6				                					*/

+/* MR6 	   "begin" can never be null when called from genLoopBegin	*/

+/* MR6     because q==(Junction *)begin->p1 and we know q is valid	*/

+/* MR6								                            	*/

+/* MR6	   from genLoopBegin:						                */

+/* MR6			                						            */

+/* MR6		 if ( LL_k>1 && !set_nil(q->fset[2]) )			        */

+/* MR6	 	   genLoopBlk( q, (Junction *)q->p1, q, max_k );	    */

+/* MR6		else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );	*/

+/* MR6				                				            	*/

+	if ( begin!=NULL )

+	{

+		if ( DemandLookahead )

+		{

+			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}

+			else gen1("look(%d);\n", max_k);

+		}

+		/* The bypass arc of the (...)* predicts what to do when you fail, but

+		 * ONLY after having tested the loop start expression.  To avoid this,

+		 * we simply break out of the (...)* loop when we find something that

+		 * is not in the prediction of the loop (all alts thereof).

+		 */

+		gen("if ( !(");

+

+/***	TJP says: It used to use the prediction expression for the bypass arc

+     	of the (...)*.  HOWEVER, if a non LL^1(k) decision was found, this

+    	thing would miss the ftree stored in the aLoopBegin node and generate

+    	an LL^1(k) decision anyway.

+

+ ***		genExpr((Junction *)begin->p2);

+ ***/

+

+            genExpr((Junction *)begin);

+            _gen(")) break;\n");

+

+	}

+

+	/* generate code for terminating loop (this is optional branch) */

+

+	f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+	set_free(f);

+	freeBlkFsets(q);

+

+	/* generate code for terminating loop (this is optional branch) */

+

+/* MR6 						                    			            */

+/* MR6  30-May-97 Bug reported by Manuel Ornato				            */

+/* MR6            A definite bug involving the exit from a loop block   */

+/* MR6 		  In 1.23 and later versions (including 1.33) Instead       */

+/* MR6              exiting the block and reporting a syntax error the  */

+/* MR6		    code loops forever.     				                */

+/* MR6	          Looking at 1.20 which generates proper code it is not */

+/* MR6		    clear which of two changes should be undone.            */

+/* MR6		  This is my best guess.                                    */

+/* MR6		  From earlier MR6 note we know that begin can never be     */

+/* MR6		    null when genLoopBlk called from genLoopBegin           */

+/* MR6 */

+/* MR6 */ if ( begin==NULL) {

+/* MR6 */   /* code for exiting loop "for sure" */

+/* MR6 */   gen("/* Suppressed by MR6 */ /*** else break; ***/\n");

+/* MR6 */ };

+

+/* MR10 */if (singleAlt && guessBlock) {

+/* MR10 */  tabs--;

+/* MR6 */   gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n");

+/* MR10 */  need_right_curly--;

+/* MR10 */ } else {

+/* MR6 */   gen("else break; /* MR6 code for exiting loop \"for sure\" */\n");

+/* MR10 */ };

+

+	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+	if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);

+	--tabs;

+	gen("}\n");

+	q->visited = FALSE;

+	tokensRefdInBlock = savetkref;

+}

+

+/*

+ * Generate code for a loop blk of form:

+ *

+ * 				         |---|

+ *					     v   |

+ *			   --o-->o-->o-G-o-->o--

+ *                   |           ^

+ *                   v           |

+ *					 o-----------o

+ *

+ * q->end points to the last node (far right) in the blk.

+ *

+ * Note that q->end->jtype must be 'EndBlk'.

+ *

+ * Generate code roughly of the following form:

+ *

+ *	do {

+ *		... code for alternatives ...

+ *  } while ( First Set of aLoopBlk );

+ *

+ *	OR if > 1 alternative

+ *

+ *	do {

+ *		... code for alternatives ...

+ *		else break;

+ *  } while ( 1 );

+ */

+void

+#ifdef __USE_PROTOS

+genLoopBegin( Junction *q )

+#else

+genLoopBegin( q )

+Junction *q;

+#endif

+{

+	set f;

+	int i;

+	int max_k;

+	set savetkref;

+	savetkref = tokensRefdInBlock;

+	require(q!=NULL,				"genLoopBegin: invalid node and/or rule");

+	require(q->ntype == nJunction,	"genLoopBegin: not junction");

+	require(q->jtype == aLoopBegin,	"genLoopBegin: not loop block");

+	require(q->p2!=NULL,			"genLoopBegin: invalid Loop Graph");

+

+    OutLineInfo(output,q->line,FileStr[q->file]);

+

+	BLOCK_Preamble(q);

+	BlkLevel++;

+    BlockPreambleOption(q,q->pFirstSetSymbol);       /* MR21 */

+	f = First(q, 1, aLoopBegin, &max_k);

+	/* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */

+	if ( LL_k>1 && !set_nil(q->fset[2]) )

+		genLoopBlk( q, (Junction *)q->p1, q, max_k );

+	else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );

+

+	for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);

+	for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);

+	--BlkLevel;

+	BLOCK_Tail();

+	set_free(f);

+	tokensRefdInBlock = savetkref;

+/* MR21 */	if (MR_BlkErr) {

+/* MR21 */		set f, fArray[2];

+/* MR21 */		f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );

+/* MR21 */      fArray[0]= empty;

+/* MR21 */		fArray[1]= set_dup(f);

+/* MR21 */      gen("if (");

+/* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */

+/* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");

+/* MR21 */      tabs++;

+/* MR21 */      tab();

+/* MR21 */      _gen("/* nothing */ }\n");

+/* MR21 */      tab();

+/* MR21 */      makeErrorClause(q,f,1,0 /* use plus block bypass ? */ );  /* frees set */

+/* MR21 */      tabs--;

+/* MR21 */	};

+	if (q->end->p1 != NULL) TRANS(q->end->p1);

+}

+

+/*

+ * Generate code for a loop blk of form:

+ *

+ * 					 |---|

+ *					 v   |

+ *			       --o-G-o-->o--

+ *

+ * q->end points to the last node (far right) in the blk.

+ * Note that q->end->jtype must be 'EndBlk'.

+ *

+ * Generate code roughly of the following form:

+ *

+ *	do {

+ *		... code for alternatives ...

+ *  } while ( First Set of aPlusBlk );

+ *

+ *	OR if > 1 alternative

+ *

+ *	do {

+ *		... code for alternatives ...

+ *		else if not 1st time through, break;

+ *  } while ( 1 );

+ */

+void

+#ifdef __USE_PROTOS

+genPlusBlk( Junction *q )

+#else

+genPlusBlk( q )

+Junction *q;

+#endif

+{

+	int         max_k;

+	set         f;

+	int         need_right_curly;

+	int			lastAltEmpty;	/* MR23 */

+	set         savetkref;

+    Junction    *guessBlock;    /* MR10 */

+    int         singleAlt;      /* MR10 */

+

+	savetkref = tokensRefdInBlock;

+	require(q!=NULL,				"genPlusBlk: invalid node and/or rule");

+	require(q->ntype == nJunction,	"genPlusBlk: not junction");

+	require(q->jtype == aPlusBlk,	"genPlusBlk: not Plus block");

+	require(q->p2 != NULL,			"genPlusBlk: not a valid Plus block");

+

+	if ( q->visited ) return;

+	q->visited = TRUE;

+    OutLineInfo(output,q->line,FileStr[q->file]);

+	BLOCK_Preamble(q);

+	BlkLevel++;

+

+    BlockPreambleOption((Junction *)q, q->pFirstSetSymbol);       /* MR21 */

+    

+    /* first_item_is_guess_block  doesn't care what kind of node it is */

+

+    guessBlock=first_item_is_guess_block( (Junction *)q->p1);   /* MR10 */

+

+	/* if the ignore flag is set on the 2nd alt and that alt is empty,

+	 * then it is the implied optional alternative that we added for (...)+

+	 * and, hence, only 1 alt.

+	 */

+

+/* MR10  Reported by Pulkkinen Esa (esap@cs.tut.fi)

+ *       Outer code for guess blocks ignored when there is only one alt

+ *         for a (...)+ block.

+ *       Force use of regular code rather than "optimized" code for that case

+ */

+

+    singleAlt=( ( (Junction *) q->p2)->p2 == NULL) &&

+        	  ( ( (Junction *) q->p2)->ignore );			/* only one alternative? */

+

+    if (singleAlt && !guessBlock)   /* MR10 */

+	{

+

+		Predicate *a=NULL;

+		/* if the only alt has a semantic predicate, hoist it; must test before

+		 * entering loop.

+		 */

+		if ( ParseWithPredicates )

+		{

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+			a = MR_find_predicates_and_supp((Node *)q);

+            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

+

+			if ( a!=NULL ) {

+				gen("if (");

+				a=genPredTreeMain(a, (Node *)q);    /* MR10 */

+				_gen(") {\n");

+			}

+		}

+		gen("do {\n");

+		tabs++;

+		TRANS(q->p1);

+		if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);

+		f = First(q, 1, aPlusBlk, &max_k);

+		if ( DemandLookahead ) {

+			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}

+			else gen1("look(%d);\n", max_k);

+		}

+		--tabs;

+		gen("} while ( ");

+		if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);

+		genExpr(q);

+		if ( ParseWithPredicates && a!=NULL )

+		{

+            if (! MR_comparePredicates(q->predicate,a)) {

+    			_gen("&&");

+    			a=genPredTreeMain(a, (Node *)q);    /* MR10 */

+            };

+		}

+		_gen(" );\n");

+		if ( ParseWithPredicates && a!=NULL ) gen("}\n");

+		--BlkLevel;

+		BLOCK_Tail();

+		q->visited = FALSE;

+		freeBlkFsets(q);

+		set_free(f);

+		tokensRefdInBlock = savetkref;

+/* MR21 */	if (MR_BlkErr) {

+/* MR21 */		set f, fArray[2];

+/* MR21 */		f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );

+/* MR21 */      fArray[0]= empty;

+/* MR21 */		fArray[1]= set_dup(f);

+/* MR21 */      gen("if (");

+/* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */

+/* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");

+/* MR21 */      tabs++;

+/* MR21 */      tab();

+/* MR21 */      _gen("/* nothing */ }\n");

+/* MR21 */      tab();

+/* MR21 */      makeErrorClause(q,f,1,1 /* use plus block bypass ? */ );  /* frees set */

+/* MR21 */      tabs--;

+/* MR21 */	};

+		if (q->end->p1 != NULL) TRANS(q->end->p1);

+/* MR10 */  if (MRhoisting) {

+/* MR10 */    predicate_free(a);

+/* MR10 */  };

+		return;

+	}

+	gen("do {\n");

+	tabs++;

+	f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+/* MR6              									        */

+/* MR6	Sinan Karasu	(sinan@tardis.ds.boeing.com)			*/

+/* MR6    Failed to turn off guess mode when leaving block		*/

+/* MR6				                           					*/

+/* MR6  */ if ( has_guess_block_as_last_item(q) ) {

+/* MR10 */   gen("/* MR10 ()+ */ else {\n");

+/* MR10 */   tabs++;

+/* MR10 */   need_right_curly++;

+/* MR10 */   gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n");

+/* MR6  */   gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n");

+/* MR10 */ } else {

+/* MR10 */   gen("/* MR10 ()+ */ else {\n");

+/* MR10 */   tabs++;

+/* MR10 */   need_right_curly++;

+/* MR10 */   gen("if ( zzcnt > 1 ) break;\n");

+/* MR10 */ };

+

+/* MR21 */	if (MR_BlkErr && 1 >= max_k) {

+/* MR21 */		set f;

+/* MR21 */		f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );

+/* MR21 */      tabs++;

+/* MR21 */      tab();

+/* MR21 */      makeErrorClause(q,f,1,0 /* use plus block bypass ? */ );  /* frees set */

+/* MR21 */      tabs--;

+/* MR21 */	}

+/* MR21 */  else {

+				tab();

+                makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */);

+										    /* MR21 I think this generates the wrong set ? */

+                                            /* MR21 because it includes the plus block bypass ? */

+										    /* MR21 but I'm afraid to change it without additional checking */

+            }

+

+	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+	freeBlkFsets(q);

+	gen("zzcnt++;");

+	if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);

+	_gen("\n");

+	if ( DemandLookahead ) {

+		if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}

+		else gen1("look(%d);\n", max_k);

+	}

+	--tabs;

+	if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}

+	else gen("} while ( 1 );\n");

+	--BlkLevel;

+	BLOCK_Tail();

+	q->visited = FALSE;

+	tokensRefdInBlock = savetkref;

+/* MR21 */	if (MR_BlkErr) {

+/* MR21 */		set f, fArray[2];

+/* MR21 */		f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );

+/* MR21 */      fArray[0]= empty;

+/* MR21 */		fArray[1]= set_dup(f);

+/* MR21 */      gen("if (");

+/* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */

+/* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");

+/* MR21 */      tabs++;

+/* MR21 */      tab();

+/* MR21 */      _gen("/* nothing */ }\n");

+/* MR21 */      tab();

+/* MR21 */      makeErrorClause(q,f,1,1 /* use plus block bypass ? */ );  /* frees set */

+/* MR21 */      tabs--;

+/* MR21 */	};

+	if (q->end->p1 != NULL) TRANS(q->end->p1);

+}

+

+/*

+ * Generate code for a sub blk of alternatives of form:

+ *

+ *			       --o-G1--o--

+ *					 |     ^

+ *					 v    /|

+ *			         o-G2-o|

+ *					 |     ^

+ *					 v     |

+ *				   ..........

+ *					 |     ^

+ *					 v    /

+ *			         o-Gn-o

+ *

+ * q points to the 1st junction of blk (upper-left).

+ * q->end points to the last node (far right) in the blk.

+ * Note that q->end->jtype must be 'EndBlk'.

+ * The last node in every alt points to q->end.

+ *

+ * Generate code of the following form:

+ *	if ( First(G1) ) {

+ *		...code for G1...

+ *	}

+ *	else if ( First(G2) ) {

+ *		...code for G2...

+ *	}

+ *	...

+ *	else {

+ *		...code for Gn...

+ *	}

+ */

+

+void

+#ifdef __USE_PROTOS

+genSubBlk( Junction *q )

+#else

+genSubBlk( q )

+Junction *q;

+#endif

+{

+	int max_k;

+	set f;

+	int need_right_curly;

+	int lastAltEmpty;		/* MR23 */

+	set savetkref;

+	savetkref = tokensRefdInBlock;

+	require(q->ntype == nJunction,	"genSubBlk: not junction");

+	require(q->jtype == aSubBlk,	"genSubBlk: not subblock");

+

+    OutLineInfo(output,q->line,FileStr[q->file]);

+	BLOCK_Preamble(q);

+	BlkLevel++;

+    BlockPreambleOption(q,q->pFirstSetSymbol);       /* MR21 */

+	f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+

+/* MR23

+   Bypass error clause generation when exceptions are used in a sub block

+   in which the last alternative is epsilon.  Example: "(A | B | )". 

+   See multi-line note in genBlk near call to isEmptyAlt.

+*/

+	if (FoundException && lastAltEmpty) {

+		gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n");

+	}

+	else {

+		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}

+	}

+    

+	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+	freeBlkFsets(q);

+	--BlkLevel;

+	BLOCK_Tail();

+

+	if ( q->guess )

+	{

+		gen("zzGUESS_DONE\n");

+	}

+

+	/* must duplicate if (alpha)?; one guesses (validates), the

+	 * second pass matches */

+	if ( q->guess && analysis_point(q)==q )

+	{

+        OutLineInfo(output,q->line,FileStr[q->file]);

+		BLOCK_Preamble(q);

+		BlkLevel++;

+		f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);}

+		{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+		freeBlkFsets(q);

+		--BlkLevel;

+		BLOCK_Tail();

+	}

+

+	tokensRefdInBlock = savetkref;

+	if (q->end->p1 != NULL) TRANS(q->end->p1);

+}

+

+static int TnodesAllocatedPrevRule=0;

+

+/*

+ * Generate code for a rule.

+ *

+ *		rule--> o-->o-Alternatives-o-->o

+ * Or,

+ *		rule--> o-->o-Alternative-o-->o

+ *

+ * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction

+ * (one alternative--no block), the last is EndRule.

+ * The second to last is EndBlk if more than one alternative exists in the rule.

+ *

+ * To get to the init-action for a rule, we must bypass the RuleBlk,

+ * and possible SubBlk.

+ * Mark any init-action as generated so genBlk() does not regenerate it.

+ */

+void

+#ifdef __USE_PROTOS

+genRule( Junction *q )

+#else

+genRule( q )

+Junction *q;

+#endif

+{

+

+	const char * returnValueInitializer;

+

+do {    /* MR10     Change recursion into iteration         */

+

+	int max_k;

+	set follow, rk, f;

+	ActionNode *a;

+	RuleEntry *r;

+	int lastAltEmpty;		/* MR23 */

+	static int file = -1;

+	int need_right_curly;

+	require(q->ntype == nJunction,	"genRule: not junction");

+	require(q->jtype == RuleBlk,	"genRule: not rule");

+

+/* MR14 */    require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0");

+/* MR14 */    MR_pointerStackReset(&MR_BackTraceStack);

+/* MR14 */    if (AlphaBetaTrace) MR_MaintainBackTrace=1;

+

+    CurRule=q->rname;                               /* MR11 */

+

+	r = (RuleEntry *) hash_get(Rname, q->rname);

+	if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");

+	if ( q->file != file )		/* open new output file if need to */

+	{

+/* MR6              									*/

+/* MR6  Simpler to debug when output goes to stdout rather than a file 	*/

+/* MR6				                					*/

+/* MR6 */	if (UseStdout) {

+/* MR6 */	  output = stdout;

+/* MR6 */	} else {

+/* MR6 */  	  if ( output != NULL) fclose( output );

+/* MR6 */	  output = fopen(OutMetaName(outname(FileStr[q->file])), "w");

+/* MR6 */	};

+		require(output != NULL, "genRule: can't open output file");

+

+#ifdef SPECIAL_FOPEN

+       special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */

+#endif

+		if ( file == -1 ) genHdr1(q->file);

+		else genHdr(q->file);

+		file = q->file;

+	}

+

+    if (InfoM) {

+      fprintf(stderr,"    rule %s\n",q->rname);

+      fflush(output);

+    };

+

+#if 0

+    if (strcmp(q->rname,"***debug***") == 0) {

+      fprintf(stderr,"***debug*** %s reached\n",q->rname);

+      MR_break();

+    };

+#endif

+

+	DumpFuncHeader(q,r);

+	tabs++;

+

+	/* MR23 

+	   

+	   If there is a single return value then it can be initialized in 

+	   the declaration using assignment syntax.  If there are multiple

+	   return values then antlr creates a struct and initialization takes

+	   place element by element for each element of the struct.  For

+       multiple elements the initialization is by assignment so we have

+       to wait until all declarations are done before emitting that code -

+       because of restrictions in C which don't exist in C++.

+

+       In the past (before MR23) the only kind of initialization was

+	   the PURIFY macro which was just a memset() of 0.  Now we allow

+	   the user to specify an initial value.  PURIFY is still used in C

+	   mode because C does not have constructors.  However, PURIFY is

+	   not used in C++ mode because it might overwrite information created

+	   by elements which have their own ctor.

+       

+	*/

+

+	if ( q->ret!=NULL )

+	{

+		if ( hasMultipleOperands(q->ret) )                         /* MR23 */

+		{

+

+            /* Emit initialization code later. */

+

+			gen1("struct _rv%d _retv;\n",r->rulenum);

+		}

+		else

+		{

+            /* Emit initialization code now. */

+

+			tab();

+			DumpType(q->ret, output);

+            returnValueInitializer = getInitializer(q->ret);

+            if (returnValueInitializer == NULL) {                  /* MR23 */

+      			gen(" _retv;\n");                     		    /* MR1 MR3 */

+            }                                                      /* MR23 */

+            else {                                                 /* MR23 */

+                gen1(" _retv = %s;\n", returnValueInitializer);    /* MR23 */

+            }                                                      /* MR23 */

+		}

+	}

+

+    OutLineInfo(output,q->line,FileStr[q->file]);

+

+    if (InfoM) {

+      fflush(output);

+    };

+

+	gen("zzRULE;\n");

+	if ( FoundException )

+	{

+		gen("int _sva=1;\n");

+	}

+	if ( GenCC && GenAST )

+		gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");

+	if ( GenCC ) genTokenPointers(q);

+	if ( GenCC&&GenAST ) genASTPointers(q);

+	if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);

+	if ( FoundException ) gen("int _signal=NoSignal;\n");

+

+	if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);

+

+/* MR10 */  /* move zzTRACEIN to before init action */

+

+/* MR10 */	if ( TraceGen ) {

+/* MR10 */		if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);}

+/* MR10 */		else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);

+/* MR10 */	}

+

+/* MR7      Moved PURIFY() to after all local variables have been declared */

+/* MR7      so that the generated code is valid C as well as C++           */

+/* MR7        Jan Mikkelsen 10-June-1997                                   */

+

+

+     /*

+       MR23    Do the PURIFY macro only for C mode.

+               C++ users should use constructors or initialization expressions.

+     */

+

+	if ( q->ret != NULL )                                            /* MR7 */

+	{                                                                /* MR7 */

+		if (hasMultipleOperands(q->ret)) {                           /* MR23 */

+			if (PURIFY == TRUE) {

+                gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */

+            }

+        }                                                            /* MR7 */

+		else {                                                       /* MR7 */

+

+			/* MR23

+			   If there were only one return value operand and

+			   it had an initializer then it would have been

+			   initiailized in the declaration.

+			*/

+

+			returnValueInitializer = getInitializer(q->ret);         /* MR23 */

+			if (returnValueInitializer == NULL) {                    /* MR23 */

+    			if (PURIFY == TRUE) {

+        			gen("PCCTS_PURIFY(_retv,sizeof(");               /* MR23 */

+	    			DumpType(q->ret, output);                        /* MR7 */

+					gen("))\n");                                     /* MR7 */

+				}

+			}                                                        /* MR23 */

+		}                                                            /* MR7 */

+

+        if (hasMultipleOperands(q->ret)) {                           /* MR23 */

+          DumpInitializers(output, r, q->ret);                       /* MR23 */

+        }

+

+	}

+	if ( !GenCC ) gen("zzMake0;\n");

+	if ( FoundException ) gen("*_retsignal = NoSignal;\n");

+

+	if ( !GenCC ) gen("{\n");

+

+	if ( has_guess_block_as_first_item((Junction *)q->p1) )

+	{

+		gen("zzGUESS_BLOCK\n");

+	}

+

+	/* L o o k  F o r  I n i t  A c t i o n */

+	if ( ((Junction *)q->p1)->jtype == aSubBlk )

+		a = findImmedAction( ((Junction *)q->p1)->p1 );

+	else

+		a = findImmedAction( q->p1 );	/* only one alternative in rule */

+	if ( a!=NULL && !a->is_predicate)

+	{

+ /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);

+  		    a->done = 1;	/* ignore action. We have already handled it */

+	}

+

+	BlkLevel++;

+	q->visited = TRUE;				/* mark RULE as visited for FIRST/FOLLOW */

+    BlockPreambleOption((Junction *)q->p1, NULL);   /* MR21 */

+	f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);

+	if ( q->p1 != NULL )

+		if ( ((Junction *)q->p1)->p2 != NULL )

+			{tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);}

+	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }

+	freeBlkFsets((Junction *)q->p1);

+	q->visited = FALSE;

+	--BlkLevel;

+	if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);

+

+    genTraceOut(q);

+

+	if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");

+	/* E r r o r  R e c o v e r y */

+	NewSet();

+	rk = empty;

+

+/* MR14 */    if (r->dontComputeErrorSet) {

+/* MR14 */      follow=empty;

+              } else {

+                MR_pointerStackReset(&MR_BackTraceStack);   /* MR14 */

+                MR_ErrorSetComputationActive=1;

+                REACH(q->end, 1, &rk, follow);

+                MR_ErrorSetComputationActive=0;

+                require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");

+              }

+

+  FillSet( follow );

+	set_free( follow );

+

+  /* MR20 G. Hobbelt 

+     Isn't it so that "fail:" is ONLY referenced when:

+

+      	 !FoundException || FoundGuessBlk ?

+

+     Therefore add the "if" around this piece of code generation...

+

+     Should guessing mode also use _handler label instead of "fail"

+     when exception handling is active? gen can automatically put 

+     "if (guessing)" there so as to skip all kinds of user code.

+

+   */

+

+	if ( !FoundException || FoundGuessBlk )  /* MR20 G. Hobbelt */

+  {                                          /* MR20 G. Hobbelt */

+	_gen("fail:\n");

+	if ( !GenCC ) gen("zzEXIT(zztasp1);\n");

+	if ( FoundGuessBlk ) {

+	   	if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}

+		else gen("if ( guessing ) zzGUESS_FAIL;\n");

+	}

+	if ( q->erraction!=NULL )

+		dumpAction(q->erraction, output, tabs, q->file, q->line, 1);

+	if ( GenCC )

+	{

+		gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",

+			 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);

+	}

+	else

+	{

+		gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",

+			 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);

+	}

+	gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);

+

+	if ( q->ret!=NULL ) {

+      genTraceOut(q);

+      gen("return _retv;\n");

+    } else if ( q->exceptions!=NULL ) {

+      genTraceOut(q);

+      gen("return;\n");

+    } else if (!FoundException) {       /* MR10 */

+      genTraceOut(q);                   /* MR10 */

+    };

+

+  }                                        /* MR20 G. Hobbelt */

+

+	if ( !GenCC ) gen("}\n");

+

+	/* Gen code for exception handlers */

+    /* make sure each path out contains genTraceOut() */

+

+	if ( q->exceptions!=NULL )

+	{

+

+		gen("/* exception handlers */\n");

+

+		dumpExceptions(q->exceptions);

+

+        if ( !r->has_rule_exception )

+        {

+            _gen("_handler:\n");

+            gen("zzdflthandlers(_signal,_retsignal);\n");

+        }

+/*  MR20 G. Gobbelt   The label "adios" is never referenced */

+

+#if 0

+	_gen("_adios:\n");

+#endif

+    if ( q->ret!=NULL ) {

+            genTraceOut(q);

+            gen("return _retv;\n");

+        }

+		else {

+            genTraceOut(q);

+            gen("return;\n");

+        }

+	}

+	else if ( FoundException )

+	{

+      _gen("_handler:\n");

+      gen("zzdflthandlers(_signal,_retsignal);\n");

+

+/* MR1                                                                      */

+/* MR1	 7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com)            */

+/* MR1							                                            */

+

+   	  if ( q->ret != NULL) {			                             /* MR1 */

+            genTraceOut(q);                                          /* MR10 */

+            gen("return _retv;\n");			                         /* MR1 */

+      } else {					                                     /* MR1 */

+            genTraceOut(q);                                          /* MR10 */

+            gen("return;\n")    ;				                     /* MR1 */

+      };						                                     /* MR1 */

+	}

+

+	tabs--;

+	gen("}\n");

+

+/* MR10     Tired of looking at stacks that are as deep as the number of    */

+/* MR10       rules.  Changes recursion to iteration.                       */

+

+    MR_releaseResourcesUsedInRule( (Node *) q );      /* MR10 */

+

+    if (InfoT) {

+      fprintf(output,"\n/* tnodes created for rule %s:  %d */\n",

+                q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) );

+    };

+

+    TnodesAllocatedPrevRule=TnodesAllocated;

+

+    if (q->p2 == NULL) dumpAfterActions( output );

+    q=(Junction *)q->p2;

+    require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk");

+

+} while (q != NULL);

+

+/**** The old code                           ****/

+/****	if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */

+/****	else dumpAfterActions( output );     ****/

+

+}

+

+

+/* This is for the function definition, not the declaration. */

+

+static void

+#ifdef __USE_PROTOS

+DumpFuncHeader( Junction *q, RuleEntry *r )

+#else

+DumpFuncHeader( q, r )

+Junction *q;

+RuleEntry *r;

+#endif

+{

+/*								                                            */

+/*  MR1 10-Apr-97  MR1  Simplify insertion of commas in function header     */

+/*								                                            */

+	int	needComma;					                                 /* MR1 */

+

+

+	/* A N S I */

+	_gen("\n");

+	if ( q->ret!=NULL )

+	{

+		if ( hasMultipleOperands(q->ret) )                            /* MR23 */

+		{

+			if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)

+			else gen1("struct _rv%d\n",r->rulenum);

+		}

+		else

+		{

+			DumpType(q->ret, output);

+			gen("\n");

+		}

+	}

+	else

+	{

+		_gen("void\n");

+	}

+/*  MR1			                                                            */

+/*  MR1	10-Apr-97  133MR1	Replace __STDC__ with __USE_PROTOS              */

+/*  MR1								                                        */

+	if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n");		     /* MR1 */

+	if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)

+	else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname);

+

+    	/* If we generate C++ method names, we must hide default arguments */

+        /* which can appear in the parameter declaration list.             */

+        /* NOTICE: this is done only here, for the method definition, but  */

+        /*         not for the method declaration inside the class         */

+        /*         definition. This is exactly the behaviour defined in    */

+        /*         C++ standard for default paramters.                     */

+

+	DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */);

+	_gen("\n");

+

+	if ( GenCC ) {

+      gen("{\n");

+      return;

+    }

+

+	/* K & R */

+	gen("#else\n");

+	gen2("%s%s(", RulePrefix, q->rname);

+	needComma=0;						                             /* MR1 */

+	if ( GenAST )						                             /* MR1 */

+	{							                                     /* MR1 */

+		_gen("_root");					                             /* MR1 */

+		needComma=1;					                             /* MR1 */

+	}							                                     /* MR1 */

+	if ( FoundException )					                         /* MR1 */

+	{							                                     /* MR1 */

+		if (needComma) {_gen(",");needComma=0;};	                 /* MR1 */

+		_gen("_retsignal");				                             /* MR1 */

+		needComma=1;					                             /* MR1 */

+	}							                                     /* MR1 */

+/* MR5	Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97      MR5 */

+	DumpListOfParmNames( q->pdecl, output, needComma );	             /* MR5 */

+	gen(")\n");

+	if ( GenAST ) gen("AST **_root;\n");

+	if ( FoundException ) gen("int *_retsignal;\n");

+	DumpOldStyleParms( q->pdecl, output );

+	gen("#endif\n");

+    gen("{\n");

+}

+

+void

+#ifdef __USE_PROTOS

+DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer)

+#else

+DumpANSIFunctionArgDef(f,q,bInitializer)

+FILE *f;

+Junction *q;

+int bInitializer;

+#endif

+{

+	if ( GenAST )

+	{

+		if ( GenCC ) {fprintf(f,"ASTBase **_root");}

+		else fprintf(f,"AST**_root");

+		if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");

+	}

+	if ( FoundException )

+	{

+		if ( GenAST ) fprintf(f,",");

+		fprintf(f,"int *_retsignal");

+		if ( q->pdecl!=NULL ) {

+            fprintf(f,",");

+        }

+	}

+	if ( q->pdecl!=NULL ) {

+        DumpFormals(f, q->pdecl, bInitializer);     /* MR23 */

+    }

+	else {

+        if ( !GenAST && !FoundException ) {

+            fprintf(f,"void");

+        }

+    }

+	fprintf(f,")");

+}

+

+void

+#ifdef __USE_PROTOS

+genJunction( Junction *q )

+#else

+genJunction( q )

+Junction *q;

+#endif

+{

+	require(q->ntype == nJunction,	"genJunction: not junction");

+	require(q->jtype == Generic,	"genJunction: not generic junction");

+

+	if ( q->p1 != NULL ) TRANS(q->p1);

+	if ( q->p2 != NULL ) TRANS(q->p2);

+}

+

+void

+#ifdef __USE_PROTOS

+genEndBlk( Junction *q )

+#else

+genEndBlk( q )

+Junction *q;

+#endif

+{

+}

+

+void

+#ifdef __USE_PROTOS

+genEndRule( Junction *q )

+#else

+genEndRule( q )

+Junction *q;

+#endif

+{

+}

+

+void

+#ifdef __USE_PROTOS

+genHdr( int file )

+#else

+genHdr( file )

+int file;

+#endif

+{

+    int     i;

+

+	_gen("/*\n");

+	_gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");

+	_gen(" *\n");

+	_gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");

+	_gen(" * Purdue University Electrical Engineering\n");

+	_gen(" * With AHPCRC, University of Minnesota\n");

+	_gen1(" * ANTLR Version %s\n", Version);

+	_gen(" *\n");

+/* MR10 */    _gen(" *  ");

+/* MR10 */    for (i=0 ; i < Save_argc ; i++) {

+/* MR10 */      _gen(" ");

+/* MR10 */      _gen(Save_argv[i]);

+/* MR10 */    };

+	_gen("\n");

+	_gen(" *\n");

+    _gen(" */\n\n");

+	if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1);    /* MR11 MR15b */

+	_gen1("#define ANTLR_VERSION	%s\n", VersionDef);

+	_gen("#include \"pcctscfg.h\"\n");

+	_gen("#include \"pccts_stdio.h\"\n");

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		_gen2("#define %s %s\n", DefaultParserName, ParserName);

+   	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		{_gen1("#include \"%s\"\n", RemapFileName);}

+    OutLineInfo(output,1,FileStr[file]);

+	if ( GenCC ) {

+		if ( UserTokenDefsFile != NULL )

+			fprintf(output, "#include %s\n", UserTokenDefsFile);

+		else

+			fprintf(output, "#include \"%s\"\n", DefFileName);

+	}

+

+	if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);

+	if ( !GenCC && FoundGuessBlk )

+	{

+		_gen("#define ZZCAN_GUESS\n");

+		_gen("#include \"pccts_setjmp.h\"\n");  /* MR15 K.J. Cummings (cummings@peritus.com) */

+	}

+	if ( FoundException )

+	{

+		_gen("#define EXCEPTION_HANDLING\n");

+		_gen1("#define NUM_SIGNALS %d\n", NumSignals);

+	}

+	if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);

+	if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");

+	if ( GenAST ) {

+		if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}

+		else _gen("#include \"ast.h\"\n\n");

+	}

+	if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");

+#ifdef DUM

+	if ( !GenCC && LexGen ) {

+		_gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));

+	}

+#endif

+	/* ###WARNING: This will have to change when SetWordSize changes */

+	if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));

+    if (TraceGen) {

+      _gen("#ifndef zzTRACE_RULES\n");  /* MR20 */

+      _gen("#define zzTRACE_RULES\n");  /* MR20 */

+      _gen("#endif\n");                 /* MR22 */

+    };

+	if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}

+	else {

+		_gen1("#include \"%s\"\n", APARSER_H);

+		_gen1("#include \"%s.h\"\n", CurrentClassName);

+	}

+	if ( !GenCC ) {

+		if ( UserDefdTokens )

+			{_gen1("#include %s\n", UserTokenDefsFile);}

+		/* still need this one as it has the func prototypes */

+		_gen1("#include \"%s\"\n", DefFileName);

+	}

+	/* still need this one as it defines the DLG interface */

+	if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");

+	if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);

+	if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);

+	if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);

+

+/* MR10  Ofer Ben-Ami (gremlin@cs.huji.ac.il)           */

+/* MR10    Finally, a definition of the Purify macro    */

+

+    if (PURIFY == TRUE) {                                                   /* MR23 */

+        _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */

+        _gen(" -nopurify option */\n\n");                                   /* MR23 */

+    	_gen("#ifndef PCCTS_PURIFY\n");

+        _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n");

+        _gen("#endif\n\n");

+    }                                                                       /* MR23 */

+}

+

+void

+#ifdef __USE_PROTOS

+genHdr1( int file )

+#else

+genHdr1( file )

+int file;

+#endif

+{

+	ListNode *p;

+

+	genHdr(file);

+	if ( GenAST )

+	{

+		if ( !GenCC ) {

+			_gen("#include \"ast.c\"\n");

+			_gen("zzASTgvars\n\n");

+		}

+	}

+	if ( !GenCC ) _gen("ANTLR_INFO\n");

+	if ( BeforeActions != NULL )

+	{

+		for (p = BeforeActions->next; p!=NULL; p=p->next)

+		{

+			UserAction *ua = (UserAction *)p->elem;

+			dumpAction( ua->action, output, 0, ua->file, ua->line, 1);

+		}

+	}

+

+	if ( !FoundException ) return;

+

+	if ( GenCC )

+	{

+		_gen1("\nvoid %s::\n", CurrentClassName);

+		_gen("zzdflthandlers( int _signal, int *_retsignal )\n");

+		_gen("{\n");

+	}

+	else

+	{

+		_gen("\nvoid\n");

+/*  MR1				                                                        */

+/*  MR1	10-Apr-97  133MR1	Replace __STDC__ with __USE_PROTOS              */

+/*  MR1	                                                                    */

+	    _gen("#ifdef __USE_PROTOS\n");                               /* MR1 */

+		_gen("zzdflthandlers( int _signal, int *_retsignal )\n");

+		_gen("#else\n");

+		_gen("zzdflthandlers( _signal, _retsignal )\n");

+		_gen("int _signal;\n");

+		_gen("int *_retsignal;\n");

+		_gen("#endif\n");

+		_gen("{\n");

+	}

+	tabs++;

+	if ( DefaultExGroup!=NULL )

+	{

+		dumpException(DefaultExGroup, 1);

+		if ( !hasDefaultException(DefaultExGroup) )

+		{

+			gen("default :\n");

+			tabs++;

+			gen("*_retsignal = _signal;\n");

+			tabs--;

+			gen("}\n");

+		}

+	}

+	else {

+		gen("*_retsignal = _signal;\n");

+	}

+

+	tabs--;

+	_gen("}\n\n");

+}

+

+void

+#ifdef __USE_PROTOS

+genStdPCCTSIncludeFile( FILE *f,char *gate )    /* MR10 */

+#else

+genStdPCCTSIncludeFile( f , gate)               /* MR10 */

+FILE *f;

+char * gate;                                    /* MR10 */

+#endif

+{

+/* MR10 Ramanathan Santhanam (ps@kumaran.com)           */

+/* MR10 Same preprocessor symbol use to gate stdpccts.h */

+/* MR10   even when two grammars are in use.            */

+/* MR10 Derive gate symbol from -fh filename            */

+

+    if (gate == NULL) {

+      fprintf(f,"#ifndef STDPCCTS_H\n");          /* MR10 */

+      fprintf(f,"#define STDPCCTS_H\n");          /* MR10 */

+    } else {

+      fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate);  /* MR10 */

+      fprintf(f,"#define STDPCCTS_%s_H\n",gate);  /* MR10 */

+    };

+	fprintf(f,"/*\n");

+    if (gate == NULL) {

+	  fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);

+    } else {

+	  fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S  I n c l u d e\n", stdpccts);

+    }

+	fprintf(f," *\n");

+	fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(f," * Purdue University Electrical Engineering\n");

+	fprintf(f," * With AHPCRC, University of Minnesota\n");

+	fprintf(f," * ANTLR Version %s\n", Version);

+	fprintf(f," */\n\n");

+

+    fprintf(f,"#ifndef ANTLR_VERSION\n");

+	fprintf(f,"#define ANTLR_VERSION	%s\n", VersionDef);

+    fprintf(f,"#endif\n\n");

+

+    if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1);  /* MR11 */

+

+	fprintf(f,"#include \"pcctscfg.h\"\n");

+	fprintf(f,"#include \"pccts_stdio.h\"\n");

+	if ( GenCC )

+	{

+		if ( UserDefdTokens )

+			fprintf(f, "#include %s\n", UserTokenDefsFile);

+		else {

+			fprintf(f, "#include \"%s\"\n", DefFileName);

+		}

+

+		fprintf(f, "#include \"%s\"\n", ATOKEN_H);

+

+		if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);

+

+		fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);

+

+		if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);

+		if ( GenAST ) {

+			fprintf(f, "#include \"%s\"\n", ASTBASE_H);

+		}

+

+        if (TraceGen) {

+          fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+          fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */

+          fprintf(f,"#endif\n");                 /* MR22 */

+        };

+

+		fprintf(f,"#include \"%s\"\n", APARSER_H);

+		fprintf(f,"#include \"%s.h\"\n", CurrentClassName);

+		if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);

+		fprintf(f, "#endif\n");

+		return;

+	}

+

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+		fprintf(f, "#include \"%s\"\n", RemapFileName);

+	if ( UserTokenDefsFile != NULL )

+	   fprintf(f, "#include %s\n", UserTokenDefsFile);

+	if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);

+	if ( FoundGuessBlk )

+	{

+		fprintf(f,"#define ZZCAN_GUESS\n");

+		fprintf(f,"#include \"pccts_setjmp.h\"\n");

+	}

+    if (TraceGen) {

+      fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+      fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */

+      fprintf(f,"#endif\n");                 /* MR22 */

+    };

+	if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);

+	if ( GenAST ) fprintf(f,"#define GENAST\n");

+	if ( FoundException )

+	{

+/* MR1	 7-Apr-97  1.33MR1					                           */

+/* MR1	 	   Fix suggested by:				                   */

+/* MR1		   Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu)         */

+

+		fprintf(f,"#define EXCEPTION_HANDLING\n");	            /* MR1 */

+		fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals);          /* MR1 */

+	}

+	if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");

+#ifdef DUM

+	if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));

+#endif

+	/* ###WARNING: This will have to change when SetWordSize changes */

+	fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));

+    if (TraceGen) {

+      fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+      fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */

+      fprintf(f,"#endif\n");                 /* MR22 */

+    };

+	fprintf(f,"#include \"antlr.h\"\n");

+	if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");

+	if ( UserDefdTokens )

+		fprintf(f, "#include %s\n", UserTokenDefsFile);

+	/* still need this one as it has the func prototypes */

+	fprintf(f, "#include \"%s\"\n", DefFileName);

+	/* still need this one as it defines the DLG interface */

+	fprintf(f,"#include \"dlgdef.h\"\n");

+	/* don't need this one unless DLG is used */

+	if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);

+	fprintf(f,"#endif\n");

+}

+

+/* dump action 's' to file 'output' starting at "local" tab 'tabs'

+   Dump line information in front of action if GenLineInfo is set

+   If file == -1 then GenLineInfo is ignored.

+   The user may redefine the LineInfoFormatStr to his/her liking

+   most compilers will like the default, however.

+

+   June '93; changed so that empty lines are left alone so that

+   line information is correct for the compiler/debuggers.

+*/

+void

+#ifdef __USE_PROTOS

+dumpAction( char *s, FILE *output, int tabs, int file, int line,

+int final_newline )

+#else

+dumpAction( s, output, tabs, file, line, final_newline )

+char *s;

+FILE *output;

+int tabs;

+int file;

+int line;

+int final_newline;

+#endif

+{

+    int inDQuote, inSQuote;

+    require(s!=NULL, 		"dumpAction: NULL action");

+    require(output!=NULL,	eMsg1("dumpAction: output FILE is NULL for %s",s));

+

+	if ( GenLineInfo && file != -1 )

+	{

+        OutLineInfo(output,line,FileStr[file]);

+	}

+    PastWhiteSpace( s );

+	/* don't print a tab if first non-white char is a # (preprocessor command) */

+	if ( *s!='#' ) {TAB;}

+    inDQuote = inSQuote = FALSE;

+    while ( *s != '\0' )

+    {

+        if ( *s == '\\' )

+        {

+            fputc( *s++, output ); /* Avoid '"' Case */

+            if ( *s == '\0' ) return;

+            if ( *s == '\'' ) fputc( *s++, output );

+            if ( *s == '\"' ) fputc( *s++, output );

+        }

+        if ( *s == '\'' )

+        {

+            if ( !inDQuote ) inSQuote = !inSQuote;

+        }

+        if ( *s == '"' )

+        {

+            if ( !inSQuote ) inDQuote = !inDQuote;

+        }

+        if ( *s == '\n' )

+        {

+            fputc('\n', output);

+			s++;

+            PastWhiteSpace( s );

+            if ( *s == '}' )

+            {

+                --tabs;

+				TAB;

+                fputc( *s++, output );

+                continue;

+            }

+            if ( *s == '\0' ) return;

+			if ( *s != '#' )	/* #define, #endif etc.. start at col 1 */

+            {

+				TAB;

+			}

+        }

+        if ( *s == '}' && !(inSQuote || inDQuote) )

+        {

+            --tabs;            /* Indent one fewer */

+        }

+        if ( *s == '{' && !(inSQuote || inDQuote) )

+        {

+            tabs++;            /* Indent one more */

+        }

+        fputc( *s, output );

+        s++;

+    }

+    if ( final_newline ) fputc('\n', output);

+}

+

+static void

+#ifdef __USE_PROTOS

+dumpAfterActions( FILE *output )

+#else

+dumpAfterActions( output )

+FILE *output;

+#endif

+{

+	ListNode *p;

+	require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");

+	if ( AfterActions != NULL )

+	{

+		for (p = AfterActions->next; p!=NULL; p=p->next)

+		{

+			UserAction *ua = (UserAction *)p->elem;

+			dumpAction( ua->action, output, 0, ua->file, ua->line, 1);

+		}

+	}

+	fclose( output );

+}

+

+/*

+ * Find the next action in the stream of execution.  Do not pass

+ * junctions with more than one path leaving them.

+ * Only pass generic junctions.

+ *

+ *	Scan forward while (generic junction with p2==NULL)

+ *	If we stop on an action, return ptr to the action

+ *	else return NULL;

+ */

+static ActionNode *

+#ifdef __USE_PROTOS

+findImmedAction( Node *q )

+#else

+findImmedAction( q )

+Node *q;

+#endif

+{

+	Junction *j;

+	require(q!=NULL, "findImmedAction: NULL node");

+	require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");

+	

+	while ( q->ntype == nJunction )

+	{

+		j = (Junction *)q;

+		if ( j->jtype != Generic || j->p2 != NULL ) return NULL;

+		q = j->p1;

+		if ( q == NULL ) return NULL;

+	}

+	if ( q->ntype == nAction ) return (ActionNode *)q;

+	return NULL;

+}

+

+static void

+#ifdef __USE_PROTOS

+dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */)

+#else

+dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */)

+char *retval;

+char *ret_def;

+RuleRefNode *ruleRefNode;

+#endif

+{

+	char *q = ret_def;

+	

+	tab();

+	while ( *retval != '\0' && *q != '\0')

+	{

+		while ( isspace((*retval)) ) retval++;

+		while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);

+		fprintf(output, " = _trv.");

+		

+		DumpNextNameInDef(&q, output);

+		while ( isspace(*q) ) q++;

+		fputc(';', output); fputc(' ', output);

+		if ( *retval == ',' ) retval++;

+	}

+	if (*retval == '\0' && *q != '\0') {

+/* MR30 */    errFL("Fewer output values than output formals for rule reference",

+/* MR30 */                 FileStr[ruleRef->file],ruleRef->line);

+	}

+	if (*retval != '\0' && *q == '\0') {

+/* MR30 */    errFL("More output actuals than output formals for rule reference",

+/* MR30 */                 FileStr[ruleRef->file],ruleRef->line);

+	}

+}

+

+/* This function computes the set of tokens that can possibly be seen k

+ * tokens in the future from point j

+ */

+

+static set

+#ifdef __USE_PROTOS

+ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass)

+#else

+ComputeErrorSet( j, k, usePlusBlockBypass )

+Junction *j;

+int k;

+int usePlusBlockBypass;

+#endif

+{

+	Junction *alt1;

+	set a, rk, f;

+	require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");

+

+	f = rk = empty;

+	for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)

+	{

+        if (alt1->ignore && ! usePlusBlockBypass) continue;     /* MR21 - Ignore aPlusBlk forward p2 */

+		REACH(alt1->p1, k, &rk, a);

+		require(set_nil(rk), "ComputeErrorSet: rk != nil");

+		set_free(rk);

+		set_orin(&f, a);

+		set_free(a);

+	}

+	return f;

+}

+

+static char *

+#ifdef __USE_PROTOS

+tokenFollowSet(TokNode *p)

+#else

+tokenFollowSet(p)

+TokNode *p;

+#endif

+{

+    static char buf[100];

+    set rk, a;

+    int n;

+    rk = empty;

+

+    REACH(p->next, 1, &rk, a);

+    require(set_nil(rk), "rk != nil");

+    set_free(rk);

+    n = DefErrSet( &a, 0, NULL );

+    set_free(a);

+    if ( GenCC )

+        sprintf(buf, "err%d", n);

+    else

+        sprintf(buf, "zzerr%d", n);

+    return buf;

+}

+

+static void

+#ifdef __USE_PROTOS

+makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass )

+#else

+makeErrorClause( q, f, max_k, usePlusBlockBypass )

+Junction *q;

+set f;

+int max_k;

+int usePlusBlockBypass;

+#endif

+{

+    char *  handler_id="";                                           /* MR7 */

+    int     nilf=0;                                                  /* MR13 */

+    RuleEntry *ruleEntry;                                            /* MR14 */

+

+	if ( FoundException )

+	{

+		_gen("else {\n");

+		tabs++;

+		if ( FoundGuessBlk )

+		{

+			if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}

+			else gen("if ( zzguessing ) goto fail;\n");

+		}

+		gen("if (_sva) _signal=NoViableAlt;\n");

+		gen("else _signal=NoSemViableAlt;\n");

+        if (q->outerEG != NULL) {

+          handler_id=q->outerEG->altID;

+#if 0

+        } else {

+          printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label);

+          gen("*** DEBUG *** outerEG==NULL\n");

+#endif

+        };

+		gen1("goto %s_handler;  /* MR7 */\n",handler_id);    /* MR7 */

+		tabs--;

+		gen("}\n");

+		return;

+	}

+

+	if ( max_k == 1 )

+	{

+/* MR13 */  nilf=set_nil(f);

+    	  	if ( GenCC ) {

+              _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL));

+            } else {

+               _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL));

+            };

+    		set_free(f);

+	}

+	else

+	{

+		int i;

+		set_free(f);

+		if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}

+		else _gen1("else {zzFAIL(%d", max_k);

+

+    ruleEntry = (RuleEntry *) hash_get(Rname,q->rname);

+

+		for (i=1; i<=max_k; i++)

+		{

+/* MR14 */  if (ruleEntry->dontComputeErrorSet) {

+/* MR14 */    f=empty;

+            } else {

+      	      f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ );

+            }

+

+      if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}

+			else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));

+			

+			set_free(f);

+		}

+	}

+	_gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");

+/* MR13 */  if (nilf) {

+/* MR13 */    errFL("empty error set for alt - probably because of undefined rule or infinite left recursion",

+/* MR13 */                 FileStr[q->file],q->line);

+/* MR13 */    gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */");

+/* MR13 */  };

+}

+

+static                                                               /* MR7 */

+#ifdef __USE_PROTOS

+char * findOuterHandlerLabel(ExceptionGroup *eg)                     /* MR7 */

+#else

+char * findOuterHandlerLabel(eg)                                     /* MR7 */

+ExceptionGroup *eg;                                                  /* MR7 */

+#endif

+{

+  char              *label=NULL;                                     /* MR7 */

+  ExceptionGroup    *outerEG;                                        /* MR7 */

+

+  if (eg->forRule == 0) {                                            /* MR7 */

+    if (eg->labelEntry != NULL) {                                    /* MR7 */

+      outerEG=eg->labelEntry->outerEG;                               /* MR7 */

+      if (outerEG != NULL) {                                         /* MR7 */

+        label=outerEG->altID;                                        /* MR7 */

+        outerEG->used=1;                                             /* MR7 */

+      };                                                             /* MR7 */

+    } else if (eg->outerEG != NULL) {                                /* MR7 */

+      outerEG=eg->outerEG;                                           /* MR7 */

+      label=outerEG->altID;                                          /* MR7 */

+      outerEG->used=1;                                               /* MR7 */

+    };                                                               /* MR7 */

+  };                                                                 /* MR7 */

+  return (label==NULL ? "" : label);                                 /* MR7 */

+}                                                                    /* MR7 */

+

+/*** debug ***/

+#if 0

+** static                                                               /* MR7 */

+** #ifdef __USE_PROTOS

+** char * findOuterAltHandlerLabel(Junction *startJ)                    /* MR7 */

+** #else

+** char * findOuterAltHandlerLabel(startJ)                              /* MR7 */

+** Junction *startJ;                                                    /* MR7 */

+** #endif

+** {                                                                    /* MR7 */

+**   char      *label=NULL;                                             /* MR7 */

+**   Junction  *alt;                                                    /* MR7 */

+**                                                                      /* MR7 */

+**   for (alt=startJ; alt != NULL; alt=alt->outerAltstart) {            /* MR7 */

+**     label=alt->exception_label;                                      /* MR7 */

+**     if (label != NULL) break;                                        /* MR7 */

+**   };                                                                 /* MR7 */

+**   return (label==NULL ? "" : label);                                 /* MR7 */

+** }                                                                    /* MR7 */

+#endif

+

+#ifdef __USE_PROTOS

+static void OutLineInfo(FILE *file,int line,char *fileName)

+#else

+static void OutLineInfo(file,line,fileName)

+  FILE *    file;

+  int       line;

+  char *    fileName;

+#endif

+{

+    static  char * prevFileName=NULL;

+    static  char * prevFileNameMS=NULL;

+

+    char *  p;

+    char *  q;

+

+    if (! GenLineInfo) return;

+

+    if (!GenLineInfoMS) {

+	    fprintf(file, LineInfoFormatStr,line,fileName);

+    } else {

+      if (fileName == prevFileName) {

+	    fprintf(file, LineInfoFormatStr,line,prevFileNameMS);

+      } else {

+        if (prevFileNameMS != NULL) free (prevFileNameMS);

+        prevFileNameMS=(char *)calloc(1,strlen(fileName)+1);

+        require(prevFileNameMS != NULL,"why not do this in calloc wrapper");

+        q=prevFileNameMS;

+        for (p=fileName; *p != 0; p++) {

+            *q=*p;

+            if (*q == '\\') *q='/';

+            q++;

+        }

+      }

+      prevFileName=fileName;

+    };

+}

+

+#if 0

+

+/* MR21 */

+

+#ifdef __USE_PROTOS

+void OutFirstSetSymbol(Junction *q, char * pSymbol)

+#else

+void OutFirstSetSymbol(q, pSymbol)

+    Junction* q;

+	char * pSymbol

+#endif

+{

+

+	set f;

+    if (pSymbol == NULL) return;

+	gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);

+    f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);

+    DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");

+    set_free(f);

+}

+#endif

+

+/* MR21 */

+

+#ifdef __USE_PROTOS

+void BlockPreambleOption(Junction *q, char * pSymbol)

+#else

+void BlockPreambleOption(q, pSymbol)

+    Junction* q;

+	char * pSymbol;

+#endif

+{

+	set f = empty;

+    if (pSymbol != NULL) {

+        f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);

+    	gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);

+        DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");

+    }

+    set_free(f);

+}

+

+/* MR21 */

+

+void

+#ifdef __USE_PROTOS

+dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line,

+int final_newline )

+#else

+dumpActionPlus(a, s, output, tabs, file, line, final_newline )

+ActionNode *a;

+char *s;

+FILE *output;

+int tabs;

+int file;

+int line;

+int final_newline;

+#endif

+{

+    dumpAction(s,output,tabs,file,line,final_newline);

+}

+

+

+#if 0

+** #ifdef __USE_PROTOS

+** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass)

+** #else

+** void MR_ErrorSets(q, max_k, usePlusBlockBypass)

+** Junction *q;

+** int max_k;

+** int usePlusBlockBypass;

+** #endif

+** {

+**     int k;

+**     set setResult;

+** 	Junction* alt1;

+** 	Junction* p;

+** 	set rk;

+** 

+**     require (max_k <= CLL_k, "k > CLL_k");

+** 

+** 

+**     for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); }

+** 

+**     for (k = 1; k <= max_k; k++) {

+**         for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2)

+**     	{

+**             if (alt1->ignore && ! usePlusBlockBypass) continue;

+**         	p = analysis_point((Junction *)alt1->p1);

+**     		REACH(p, k, &rk, setResult);

+**     		require(set_nil(rk), "rk != nil");

+**             set_orin(&q->fset[k], setResult);

+**     	}

+**     }

+** }

+#endif

+

+

+#ifdef __USE_PROTOS

+void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn)

+#else

+void DumpInitializers(output, r, pReturn)

+FILE* output;

+RuleEntry *r;

+char * pReturn;

+#endif

+{

+	char *p = pReturn;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+	int nest = 0;

+    char *q;

+

+	require(pReturn!=NULL, "DumpInitializer: invalid string"); 

+

+    while (*p != 0) {

+    	p = endFormal(p,

+    			      &pDataType,

+    				  &pSymbol,

+    				  &pEqualSign,

+    				  &pValue,

+    				  &pSeparator,

+    				  &nest);

+        if (nest != 0) return;

+        if (pValue != NULL) {

+			tab();

+            q = strBetween(pSymbol, pEqualSign, pSeparator);

+            fprintf(output, "_retv.%s", q);

+            q = strBetween(pValue, NULL, pSeparator);

+            fprintf(output, " = %s;\n", q);

+        }

+    }

+}

+

+#ifdef __USE_PROTOS

+void DumpFormals(FILE* output, char * pReturn, int bInitializer)

+#else

+void DumpFormals(output, pReturn, bInitializer)

+FILE* output;

+char * pReturn;

+int bInitializer;

+#endif

+{

+	char *p = pReturn;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+	int nest = 0;

+    char *q;

+    int count = 0;

+

+	require(pReturn!=NULL, "DumpFormals: invalid string"); 

+

+    while (*p != 0) {

+    	p = endFormal(p,

+    			      &pDataType,

+    				  &pSymbol,

+    				  &pEqualSign,

+    				  &pValue,

+    				  &pSeparator,

+    				  &nest);

+        if (nest != 0) return;

+        if (count > 0) fprintf(output,",");

+        if (pDataType != NULL && pSymbol != NULL) {

+            q = strBetween(pDataType, pSymbol, pSeparator);

+            fprintf(output, "%s", q);

+            q = strBetween(pSymbol, pEqualSign, pSeparator);

+            fprintf(output," %s",q);

+            if (pValue != NULL) {

+                q = strBetween(pValue, NULL, pSeparator);

+                if (bInitializer != 0) {

+                    fprintf(output, " = %s", q);

+                }

+            }

+        }

+        count++;

+    }

+}

+

+/* MR23 Check for empty alt in a more intelligent way.

+        Previously, an empty alt for genBlk had to point directly

+		to the endBlock.  This did not work once I changed {...}

+		blocks to look like (...|...| epsilon) since there were

+		intervening generics.  This fixes the problem for this

+		particular case.  Things like actions or empty blocks of

+		various kinds will still cause problems, but I wasnt't

+		prepared to handle pathological cases like (A|()*). It

+		does handle (A | ()), which is a recommended idiom for

+		epsilon.

+

+        Actually, this isn't quite correct since it doesn't handle

+		the case of the ignore bit in the plus block bypass, but

+		I'm too tired to figure out the correct fix, and will just

+		work around it.

+*/

+

+#ifdef __USE_PROTOS

+int isEmptyAlt(Node * alt, Node * endBlock)

+#else

+int isEmptyAlt(alt, endBlock)

+Node * alt;

+Node * endBlock;

+#endif

+{

+	Node * n = alt;

+	Junction * j;

+	while (n != endBlock) {

+		switch (n->ntype) {

+

+			case nRuleRef:

+				return 0;

+

+			case nToken:

+				return 0;

+

+			case nAction:

+				return 0;

+

+			case nJunction:

+				goto JUNCTION;

+

+			default:

+				fatal_internal("Invalid node type");

+				return 0;

+		}

+JUNCTION:

+		j = (Junction *) n;

+

+		switch (j->jtype) {

+			case Generic:

+				{

+					n = j->p1;

+					goto NEXT;

+				}

+

+			case aSubBlk:

+				{

+					n = j->p1;	/* MR26 */

+					goto NEXT;	/* MR26 */

+				}

+

+			case EndBlk:

+					return 0;

+

+			case EndRule:

+					return 1;

+

+			default:

+					return 0;

+		}

+NEXT: continue;

+	}

+	return 1;

+}

diff --git a/Source/Pccts/antlr/generic.h b/Source/Pccts/antlr/generic.h
new file mode 100644
index 0000000..8d736d5
--- /dev/null
+++ b/Source/Pccts/antlr/generic.h
@@ -0,0 +1,286 @@
+/*

+ * generic.h -- generic include stuff for new PCCTS ANTLR.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#define StrSame			0

+

+#define DefaultParserName	"zzparser"

+

+/* MR9  JVincent@novell.com     Allow user to override default ZZLEXBUFSIZE  */

+/* MR11 thm                     Raise antlr's own default ZZLEXBUFSIZE to 8k */

+/* MR22 thm                     Raise antlr's own default ZZLEXBUFSIZE to 32k */

+

+#ifndef ZZLEXBUFSIZE

+#define ZZLEXBUFSIZE 32000

+#endif

+

+/* Tree/FIRST/FOLLOW defines -- valid only after all grammar has been read */

+#define ALT			TokenNum+1

+#define SET			TokenNum+2

+#define TREE_REF	TokenNum+3

+

+					/* E r r o r  M a c r o s */

+

+#define fatal(err)	fatalFL(err, __FILE__, __LINE__)

+#define fatal_internal(err)	fatal_intern(err, __FILE__, __LINE__)

+

+

+#define eMsg1(s,a)	eMsg3(s,a,NULL,NULL)

+#define eMsg2(s,a,b)	eMsg3(s,a,b,NULL)

+

+				/* S a n i t y  C h e c k i n g */

+

+#ifndef require

+#define require(expr, err) {if ( !(expr) ) fatal_internal(err);}

+#endif

+

+					/* L i s t  N o d e s */

+

+typedef struct _ListNode {

+			void *elem;			/* pointer to any kind of element */

+			struct _ListNode *next;

+		} ListNode;

+

+/* Define a Cycle node which is used to track lists of cycles for later

+ * reconciliation by ResolveFoCycles().

+ */

+typedef struct _c {

+			int croot;			/* cycle root */

+			set cyclicDep;		/* cyclic dependents */

+			unsigned deg;		/* degree of FOLLOW set of croot */

+		} Cycle;

+

+typedef struct _e {

+			int tok;			/* error class name == TokenStr[tok] */

+			ListNode *elist;	/* linked list of elements in error set */

+			set eset;

+			int setdeg;			/* how big is the set */

+			int lexclass;		/* which lex class is it in? */

+		} ECnode;

+

+typedef struct _TCnode {

+			int tok;			/* token class name */

+			ListNode *tlist;	/* linked list of elements in token set */

+			set tset;

+			int lexclass;		/* which lex class is it in? */

+			unsigned char dumped; /* this def has been been dumped */

+			unsigned char dumpedComplement; /* this def has been been dumped */

+			unsigned setnum;	/* which set number is this guy? (if dumped) */

+			unsigned setnumComplement;		 /* MR23 */

+			unsigned setnumErrSet;			 /* MR23 which set is this #tokclass error set (if dumped) */

+			unsigned setnumErrSetComplement; /* MR23 */

+		} TCnode;

+

+typedef struct _ft {

+			char *token;		/* id of token type to remap */

+			int tnum;			/* move token type to which token position */

+		} ForcedToken;

+

+typedef struct _ContextGuardPredicates {    /* MR13 */

+            Predicate *pred;                /* MR13 */

+        } ContextGuardPredicates;           /* MR13 */

+

+#define newListNode	(ListNode *) calloc(1, sizeof(ListNode));

+#define newCycle	(Cycle *) calloc(1, sizeof(Cycle));

+#define newECnode	(ECnode *) calloc(1, sizeof(ECnode));

+#define newTCnode	(TCnode *) calloc(1, sizeof(TCnode));

+

+

+				/* H a s h  T a b l e  E n t r i e s */

+

+typedef struct _t {				/* Token name or expression */

+			char *str;

+			struct _t *next;

+			int token;			/* token number */

+			unsigned char classname;	/* is it a err/tok class name or token */

+			TCnode *tclass;		/* ptr to token class */

+			char *action;

+            char *akaString;

+		} TermEntry;

+

+typedef struct _r {				/* Rule name and ptr to start of rule */

+			char *str;

+			struct _t *next;

+			int rulenum;		/* RulePtr[rulenum]== ptr to RuleBlk junction */

+			unsigned char noAST;/* gen AST construction code? (def==gen code) */

+			char *egroup;		/* which error group (err reporting stuff) */

+#if 0

+			/* MR27  This appears to never be used.  Delete this code later. */

+

+			ListNode *el_labels;/* list of element labels ref in all of rule */

+#endif

+			ListNode *ast_labels_in_actions; /* MR27 */

+            unsigned char has_rule_exception;

+            char dontComputeErrorSet;    /* MR14 - don't compute error set

+                                          special for rule in alpha part of

+                                          (alpha)? beta block */

+		} RuleEntry;

+

+typedef struct _f {				/* cache Fi/Fo set */

+			char *str;			/* key == (rulename, computation, k) */

+			struct _f *next;

+			set fset;			/* First/Follow of rule */

+			set rk;				/* set of k's remaining to be done after ruleref */

+			int incomplete;		/* only w/FOLLOW sets.  Use only if complete */

+		} CacheEntry;

+

+typedef struct _LabelEntry {	/* element labels */

+			char *str;

+			struct _f *next;

+			Node *elem;			/* which element does it point to? */

+			ExceptionGroup *ex_group;

+								/* Is there an exception attached to label? */

+            ExceptionGroup *outerEG;                                 /* MR7 */

+                                /* next EG if ex_group doesn't catch it MR7 */

+            struct _LabelEntry  *pendingLink;                        /* MR7 */

+                                /* too lazy to use ListNode ?           MR7 */

+            int     curAltNum;                                       /* MR7 */

+		} LabelEntry;

+

+typedef struct _SignalEntry {

+			char *str;

+			struct _f *next;

+			int signum;			/* unique signal number */

+		} SignalEntry;

+

+typedef struct _PredEntry {				/* MR11 predicate name and ptr to string */

+			char              *str;

+            struct _PredEntry *next;

+            int               file;

+            int               line;

+            Predicate         *pred;

+            char              *predLiteral;

+		} PredEntry;

+

+typedef struct _PointerStack {      /* MR10 */

+        int     count;

+        int     size;

+        void    **data;

+        } PointerStack;

+

+#define newTermEntry(s)		(TermEntry *) newEntry(s, sizeof(TermEntry))

+#define newRuleEntry(s)		(RuleEntry *) newEntry(s, sizeof(RuleEntry))

+#define newCacheEntry(s)	(CacheEntry *) newEntry(s, sizeof(CacheEntry))

+#define newLabelEntry(s)	(LabelEntry *) newEntry(s, sizeof(LabelEntry))

+#define newSignalEntry(s)	(SignalEntry *) newEntry(s, sizeof(SignalEntry))

+#define newPredEntry(s)     (PredEntry *) newEntry(s,sizeof(PredEntry))

+

+typedef struct _UserAction {

+			char *action;

+			int file, line;

+		} UserAction;

+

+

+					/* L e x i c a l  C l a s s */

+

+/* to switch lex classes, switch ExprStr and Texpr (hash table) */

+typedef struct _lc {

+			char *classnum, **exprs;

+			Entry **htable;

+		} LClass;

+

+typedef struct _exprOrder {

+			char *expr;

+			int lclass;

+		} Expr;

+

+

+typedef Graph Attrib;

+

+						/* M a x i m u m s */

+

+/* MR20 Note G. Hobbelt These values are superceded by values in hash.h */

+

+#ifndef HashTableSize

+#define HashTableSize	253

+#endif

+#ifndef StrTableSize

+#define StrTableSize	15000	/* all tokens, nonterminals, rexprs stored here */

+#endif

+#define MaxLexClasses	50		/* how many automatons */

+/* TokenStart and EofToken are ignored if #tokdefs meta-op is used */

+#define TokenStart		2		/* MUST be in 1 + EofToken */

+#define EofToken		1		/* Always predefined to be 1 */

+

+#ifndef MaxNumFiles

+#define MaxNumFiles		99

+#endif

+

+/**** MR9 JVincent@novell.com  Move to pcctscfg.h */

+/**** #define MaxFileName		300	****/ /* MR9  Move to pcctscfg.h */ /* largest file name size */

+

+#define MaxRuleName		100		/* largest rule name size */

+#define TSChunk			100		/* how much to expand TokenStr/ExprStr each time */

+#define TIChunk			TSChunk	/* expand TokenInd by same as TokenStr to mirror them */

+#define FoStackSize		100		/* deepest FOLLOW recursion possible */

+

+#define MaxClassDeclStuff   256    /* MR10 */

+

+#define NumPredefinedSignals 3

+

+           /* S t a n d a r d  S i g n a l s */

+

+#define sigNoSignal				0

+#define sigMismatchedToken		1

+#define sigNoViableAlt			2

+#define sigNoSemViableAlt		3

+

+

+

+/* AST token types */

+#define ASTexclude		0

+#define ASTchild		1

+#define ASTroot			2

+#define ASTinclude		3		/* include subtree made by rule ref */

+

+

+#define PredictionVariable				"zzpr_expr"

+#define PredictionLexClassSuffix		"_zzpred"

+

+#define WildCardString					"WildCard"

+

+#if 0

+    /*  Removed in version 1.33MR19

+        Don't understand why this never caused problems before

+    */

+

+    /*********************************************************

+    #ifndef ANTLRm

+	#define ANTLRm(st, f, _m)	zzbufsize = ZZLEXBUFSIZE;\

+					zzmode(_m);					\

+					zzenterANTLR(f);			\

+					st; ++zzasp;				\

+					zzleaveANTLR(f);

+	#endif						

+    *********************************************************/

+#endif

+

+#include "proto.h"

+#include "pcctscfg.h"   /* MR14 */

+#include <string.h>

diff --git a/Source/Pccts/antlr/globals.c b/Source/Pccts/antlr/globals.c
new file mode 100644
index 0000000..59d0032
--- /dev/null
+++ b/Source/Pccts/antlr/globals.c
@@ -0,0 +1,484 @@
+/*

+ * globals.c	--	File containing all variables/tables visible to all files.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+

+#include "pcctscfg.h"

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+

+char Version[] = "1.33MR33" ;	/* PCCTS version number */	                   /* MRXXX */

+char VersionDef[] = "13333";    /* same (except int equiv for preproc symbol) */ /* MRXXX */

+

+char LexStartSymbol[] = "START";/* Name of starting lexical class/automaton */

+char *RemapFileName = "remap.h";

+char *DlgFileName = "parser.dlg";

+char *DefFileName = "tokens.h";

+char *ErrFileName = "err.c";

+char *ModeFileName = "mode.h";

+char *StdMsgName = NULL;

+

+char *ParserName = DefaultParserName;

+

+/* list of PCCTS supplied support symbols; these are renamed when more than

+ * one ANTLR-generated parsers are linked together to avoid name conflicts.

+ * Can't use '##' ANSIC preprocessor concat operator with K&R and:

+ *		#define zzskip	zzparser ## skip

+ * will not work for ANSI/C++ as 'zzparserskip' is created w/o zzparser

+ * being substituted--ack!!!

+ */

+char *StandardSymbols[] = {

+/* ANTLR stuff */

+	"zzStackOvfMsg",

+	"zzasp",

+	"zzaStack",

+	"inf_tokens",

+	"inf_text",

+	"inf_text_buffer",

+	"inf_text_buffer_ptr",

+	"inf_text_buffer_size",

+ 	"inf_labase",

+	"inf_last",

+	"inf_lap",

+	"zztokenLA",

+	"zztextLA",

+	"zzlap",

+	"zzlabase",

+	"zztoktext",

+	"zztoken",

+	"zzdirty",

+	"zzguessing",

+	"zzguess_start",

+	"zzresynch",

+	"zzinf_tokens",

+	"zzinf_text",

+	"zzinf_text_buffer",

+	"zzinf_labase",

+	"zzinf_last",

+	"zzfill_inf_look",

+	"zzFAIL",

+	"zzsave_antlr_state",

+	"zzrestore_antlr_state",

+	"zzsyn",

+	"zzset_el",

+	"zzset_deg",

+	"zzedecode",

+	"_zzsetmatch",

+	"_zzmatch",

+	"_inf_zzgettok",

+    "zzconsumeUntil",

+    "zzconsumeUntilToken",

+    "_zzmatch_wsig",

+    "_zzsetmatch_wsig",

+    "_zzmatch_wdfltsig",

+    "_zzsetmatch_wdfltsig",

+	"zzdflthandlers",

+/* DLG stuff */

+	"zzreal_line",

+	"zzcharfull",

+	"zzerr",

+	"zzlextext",

+	"zzbegexpr",

+	"zzendexpr",

+	"zzbufsize",

+	"zzbegcol",

+	"zzendcol",

+	"zzline",

+	"zzchar",

+	"zzbufovf",

+	"zzrdstream",

+	"zzrdfunc",

+	"zzrdstr",

+	"zzclose_stream",

+	"zzsave_dlg_state",

+	"zzrestore_dlg_state",

+	"zzmode",

+	"zzskip",

+	"zzmore",

+	"zzreplchar",

+	"zzreplstr",

+	"zzgettok",

+	"zzadvance",

+	"zzerrstd",

+	"zzerr_in",

+	"zzconstr_attr",

+	"zzempty_attr",

+	"zzerraction",

+	"zztokens",			/* list of token regular expressions */

+	"dfa",

+	"accepts",

+	"actions",

+    "zzTraceOptionValue",       /* MR10 */

+    "zzTraceGuessOptionValue",  /* MR10 */

+    "zzTraceCurrentRuleName",   /* MR10 */

+    "zzTraceDepth",             /* MR10 */

+    "zzGuessSeq",               /* MR10 */

+    "zzSyntaxErrCount",         /* MR11 */

+    "zzLexErrCount",            /* MR11 */

+    "zzTraceGuessDone",         /* MR13 - BJS */

+    "zzTraceGuessFail",         /* MR13 - BJS */

+    "zzTraceGuessOption",       /* MR13 - BJS */

+    "zzTraceIn",                /* MR13 - BJS */

+    "zzTraceOption",            /* MR13 - BJS */

+    "zzTraceOut",               /* MR13 - BJS */

+    "zzTraceReset",             /* MR13 - BJS */

+	NULL		/* must be present */

+};

+

+/* list of PCCTS supplied support functions; these are renamed when more than

+ * one ANTLR-generated parsers are linked together to avoid name conflicts.

+ */

+char *ASTSymbols[] = {

+	"AST",

+	"zzast_sp",

+	"zzastStack",

+	"zzlink",

+	"zzastnew",

+	"zzsubchild",

+	"zzsubroot",

+	"zzpre_ast",

+	"zzfree_ast",

+	"zztmake",

+	"zzdup_ast",

+	"zztfree",

+	"zzdouble_link",

+	NULL		/* must be present */

+};

+

+/* Current ambiguity examination information */

+int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile;

+char *CurAmbigbtype;

+

+

+						/* M e t h o d  T a b l e s */

+/*

+ * The following tables are used to fill syntax diagram nodes with the correct

+ * function pointers for computing FIRST sets and printing themselves.

+ */

+

+/* fpTraverse[node type] == pointer to function that calculates trees

+ * representing the FIRST sets for that node (maintains spatial info).

+ * We use 'struct _tree' not 'tree' due to a g++ 2.4.3 bug.

+ */

+#ifdef __cplusplus

+struct _tree *(*fpTraverse[NumNodeTypes+1])(... /* Node *, int, set * */) = {

+	NULL,

+	(struct _tree *(*)(...)) tJunc,

+	(struct _tree *(*)(...)) tRuleRef,

+	(struct _tree *(*)(...)) tToken,

+	(struct _tree *(*)(...)) tAction

+};

+#else

+Tree *(*fpTraverse[NumNodeTypes+1])() = {

+	NULL,

+	tJunc,

+	tRuleRef,

+	tToken,

+	tAction

+};

+#endif

+

+/* fpReach[node type] == pointer to function that calculates FIRST set for

+ * that node. (r stands for reach).  We use 'struct _set' not 'set'

+ * due to a g++ 2.4.3 bug.

+ */

+#ifdef __cplusplus

+struct _set (*fpReach[NumNodeTypes+1])(... /* Node *, int, set * */) = {

+	NULL,

+	(struct _set (*)(...)) rJunc,

+	(struct _set (*)(...)) rRuleRef,

+	(struct _set (*)(...)) rToken,

+	(struct _set (*)(...)) rAction

+};

+#else

+set (*fpReach[NumNodeTypes+1])() = {

+	NULL,

+	rJunc,

+	rRuleRef,

+	rToken,

+	rAction

+};

+#endif

+

+/* fpPrint[node type] == pointer to function that knows how to print that node. */

+#ifdef __cplusplus

+void (*fpPrint[NumNodeTypes+1])(... /* Node * */) = {

+	NULL,

+	(void (*)(...)) pJunc,

+	(void (*)(...)) pRuleRef,

+	(void (*)(...)) pToken,

+	(void (*)(...)) pAction

+};

+#else

+void (*fpPrint[NumNodeTypes+1])() = {

+	NULL,

+	pJunc,

+	pRuleRef,

+	pToken,

+	pAction

+};

+#endif

+

+char *decodeJType[] = {

+	"invalid",

+	"aSubBlk",

+	"aOptBlk",

+	"aLoopBlk",

+	"EndBlk",

+	"RuleBlk",

+	"Generic",

+	"EndRule",

+	"aPlusBlk",

+	"aLoopBegin"

+};

+

+

+							/* H a s h  T a b l e s */

+

+Entry	**Tname,			/* Table of all token names (maps name to tok num)*/

+		**Texpr,			/* Table of all token expressions

+							   (maps expr to tok num) */

+		**Rname,			/* Table of all Rules (has ptr to start of rule) */

+		**Fcache,			/* Cache of First/Follow Computations */

+		**Tcache;			/* Tree cache; First/Follow for permute trees */

+Entry	**Elabel;			/* Table of all element label names */

+Entry	**Sname;			/* Signal names */

+Entry   **Pname;            /* symbolic predicate names MR11 */

+

+

+							/* V a r i a b l e s */

+

+int     Save_argc;          /* MR10 */

+char    **Save_argv;        /* MR10 */

+int		EpToken=0;			/* Imaginary Epsilon token number */

+int		WildCardToken=0;

+int		CurFile= -1;		/* Index into FileStr table */

+char    *CurPredName=NULL;  /* MR11 */

+char	*CurRule=NULL;		/* Pointer to current rule name */

+int     CurRuleDebug=0;     /* MR13 debug flag */

+RuleEntry *CurRuleNode=NULL;/* Pointer to current rule node in syntax tree */

+char	*CurRetDef=NULL;	/* Pointer to current return type definition */

+char	*CurParmDef=NULL;	/* Pointer to current parameter definition */

+Junction *CurRuleBlk=NULL;	/* Pointer to current block node for enclosing block */

+ListNode *CurExGroups=NULL;	/* Current list of exception groups for rule/alts */

+ListNode *CurElementLabels=NULL;

+ListNode *CurAstLabelsInActions=NULL; /* MR27 */

+

+/* MR10  used by <<>>? to set "label_used_in_semantic_pred"  */

+/* MR10  this will force LT(i) assignment even in guess mode */

+

+ListNode *CurActionLabels=NULL;     /* MR10 Element Labels appearing in last action */

+int      numericActionLabel=0 ;     /* MR10 << ... $1 ... >> or << ... $1 ... >>?   */

+ListNode *NumericPredLabels=NULL;   /* MR10 << ... $1 ... >>?  ONLY                 */

+ListNode *ContextGuardPredicateList=NULL;  /* MR13 for re-evaluating predicates

+                                                   after meta tokens are defined    */

+

+int		CurBlockID=0;		/* Unique int for each block */

+int		CurAltNum=0;

+Junction *CurAltStart = NULL;	/* Junction node that starts the alt */

+Junction *OuterAltStart = NULL; /* For chaining exception groups        MR7 */

+int		NumRules=0;			/* Rules are from 1 to n */

+FILE	*output=NULL;		/* current parser output file */

+FILE	*input=NULL;		/* current grammar input file */

+char	*FileStr[MaxNumFiles];/* Ptr to array of file names on command-line */

+int		NumFiles=0;			/* current grammar file number */

+#ifdef __cplusplus

+void	(**fpTrans)(...),	/* array of ptrs to funcs that translate nodes */

+	 	(**fpJTrans)(...);	/*  ... that translate junctions */

+#else

+void	(**fpTrans)(),		/* array of ptrs to funcs that translate nodes */

+	 	(**fpJTrans)();		/*  ... that translate junctions */

+#endif

+int		**FoStack;			/* Array of LL_k ptrs to stacks of rule numbers */

+int		**FoTOS;			/* FOLLOW stack top-of-stack pointers */

+Junction *SynDiag = NULL;	/* Pointer to start of syntax diagram */

+int		BlkLevel=1;			/* Current block level.  Set by antlr.g, used by

+							 * scanner to translate $i.j attributes */

+set		reserved_positions;	/* set of token positions reserved by '#token T=i' cmds */

+set		all_tokens;			/* set of all token types */

+set		imag_tokens;		/* set of all imaginary token types (EpToken, errclasses...) */

+set		tokclasses;			/* set of all token class token types */

+ListNode *ForcedTokens = 0;	/* list of token_id/token_num pairs to remap */

+ListNode *MetaTokenNodes=NULL; /* list of meta token refs such as token classes etc... */

+int		*TokenInd=NULL;		/* an indirection level between token num and position

+							 * of that token def in TokenStr and ExprStr */

+int		LastTokenCounted=0;	/* ==TokenNum if no token renumbering (same as old TokenNum) */

+int		TokenNum=TokenStart;

+char	**TokenStr=NULL;	/* map token # to token name */

+char	**ExprStr=NULL;		/* map token # to expr */

+Junction **RulePtr=NULL;	/* map rule # to RuleBlk node of rule */

+ListNode *ExprOrder=NULL;	/* list of exprs as they are found in grammar */

+ListNode *BeforeActions=NULL;/* list of grammar actions before rules */

+ListNode *AfterActions=NULL;/* list of grammar actions after rules */

+ListNode *LexActions=NULL;	/* list of lexical actions */

+

+/* MR1              									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class     */

+/* MR1				via #lexmember <<....>>			            */

+/* MR1				via #lexprefix <<....>>			            */

+/* MR1				                					    */

+

+ListNode *LexMemberActions=NULL;/* list of lexical header member decl   MR1 */

+ListNode *LexPrefixActions=NULL;/* list of lexical header #include decl MR1 */

+ListNode **Cycles=NULL;		/* list of cycles (for each k) found when

+							   doing FOLLOWs */

+ListNode *eclasses=NULL;	/* list of error classes */

+ListNode *tclasses=NULL;	/* list of token classes */

+LClass	 lclass[MaxLexClasses]; /* array of lex class definitions */

+int		 CurrentLexClass;	/* index into lclass */

+int		 NumLexClasses=0;	/* in range 1..MaxLexClasses (init 0) */

+

+char	*HdrAction=NULL;	/* action defined with #header */

+char    *FirstAction=NULL;  /* action defined with #first MR11 */

+FILE	*ErrFile;			/* sets and error recovery stuff */

+FILE	*DefFile=NULL;		/* list of tokens, return value structs, setwd defs */

+FILE    *MRinfoFile=NULL;   /* MR10 information file */

+int     MRinfo=0;           /* MR10 */

+int     MRinfoSeq=0;        /* MR10 */

+int     InfoP=0;            /* MR10 predicates        */

+int     InfoT=0;            /* MR10 tnodes            */

+int     InfoF=0;            /* MR10 first/follow sets */

+int     InfoM=0;            /* MR10 monitor progress  */

+int     InfoO=0;            /* MR12 orphan rules      */

+int     TnodesInUse=0;      /* MR10 */

+int     TnodesPeak=0;       /* MR10 */

+int     TnodesAllocated=0;  /* MR10 */

+int     TnodesReportThreshold=0;    /* MR11 */

+int     PotentialSuppression=0; /* MR10 */

+int     PotentialDummy=0;       /* MR10 */

+int		CannotContinue=FALSE;

+int		OutputLL_k = 1;		/* LL_k for parsing must be power of 2 */

+int		action_file;		/* used to track start of action */

+int		action_line;

+int		FoundGuessBlk=0;	/* there is a (...)? block somewhere in grammar */

+int		FoundException=0;	/* there is an exception somewhere in grammar */

+/* MR6	Distinguish between @ operator and real exception 		    */

+/* MR6    by keeping separate flags for @ operator and real exceptions 	    */

+int		FoundAtOperator=0;					                     /* MR6 */

+int		FoundExceptionGroup=0;			                             /* MR6 */

+int		pLevel=0;			/* print Level */

+int		pAlt1,pAlt2;		/* print "==>" in front of these alts */

+

+/* C++ output stuff */

+FILE	*Parser_h,			/* where subclass of ANTLRParser goes */

+		*Parser_c;			/* where code for subclass of ANTLRParser goes */

+char	Parser_h_Name[MaxFileName+1] = "";

+char	Parser_c_Name[MaxFileName+1] = "";

+char    MRinfoFile_Name[MaxFileName+1] = "";                /* MR10 */

+char    *ClassDeclStuff=NULL;                               /* MR10 */

+char    *BaseClassName=NULL;                                /* MR22 */

+/* list of actions inside the #class {...} defs */

+ListNode *class_before_actions=NULL;

+ListNode *class_after_actions=NULL;

+

+char	CurrentClassName[MaxRuleName]="";

+int		no_classes_found=1;

+char	*UserTokenDefsFile;

+int		UserDefdTokens=0;	/* found #tokdefs? */

+char	*OutputDirectory=TopDirectory;

+ExceptionGroup *DefaultExGroup = NULL;

+int		NumSignals = NumPredefinedSignals;

+int		ContextGuardTRAV=0;

+

+char    *MR_AmbAidRule=NULL;        /* MR11 */

+int     MR_AmbAidLine=0;            /* MR11 */

+int     MR_AmbAidDepth=0;           /* MR11 */

+int     MR_AmbAidMultiple=0;        /* MR11 */

+int     MR_skipped_e3_report=0;     /* MR11 */

+int     MR_usingPredNames=0;        /* MR11 */

+int     MR_BadExprSets=0;           /* MR13 */

+int     MR_Inhibit_Tokens_h_Gen=0;  /* MR13 */

+int     NewAST=0;                   /* MR13 */

+int		tmakeInParser=0;            /* MR23 */

+int     AlphaBetaTrace=0;           /* MR14 */

+int		MR_BlkErr=0;				/* MR21 */

+int     MR_AlphaBetaMessageCount=0; /* MR14 */

+int     MR_AlphaBetaWarning=0;      /* MR14 */

+int     MR_ErrorSetComputationActive=0;     /* MR14 */

+int     MR_MaintainBackTrace=0;             /* MR14 */

+set     MR_CompromisedRules;        /* MR14 */

+

+Junction    *MR_RuleBlkWithHalt;    /* MR10 */

+

+					/* C m d - L i n e  O p t i o n s */

+

+int		LL_k=1;				/* how many tokens of full lookahead */

+int		CLL_k= -1;			/* how many tokens of compressed lookahead */

+int		PrintOut = FALSE;	/* print out the grammar */

+int		PrintAnnotate = FALSE;/* annotate printout with FIRST sets */

+int		CodeGen=TRUE;		/* Generate output code? */

+int		LexGen=TRUE;		/* Generate lexical files? (tokens.h, parser.dlg) */

+int		GenAST=FALSE;		/* Generate AST's? */

+int		GenANSI=FALSE;		/* Generate ANSI code where necessary */

+int		GenExprSetsOpt=TRUE;/* use sets not (LA(1)==tok) expression lists */

+int		GenCR=FALSE;		/* Generate cross reference? */

+int		GenLineInfo=FALSE;	/* Generate # line "file" stuff? */

+int		GenLineInfoMS=FALSE;/* Like -gl but replace "\" with "/" for MS C/C++ systems */

+int		TraceGen=FALSE;		/* Generate code to trace rule invocation */

+int		elevel=1;			/* error level for ambiguity messages */

+int		GenEClasseForRules=0;/* don't generate eclass for each rule */

+int		TreeResourceLimit= -1;/* don't limit tree resource */

+int		DemandLookahead = 0;/* demand/delayed lookahead or not */

+char	*RulePrefix = "";	/* prefix each generated rule with this */

+char	*stdpccts = "stdpccts.h";/* where to generate std pccts include file */

+int		GenStdPccts = 0;	/* don't gen stdpccts.h? */

+int		ParseWithPredicates = 1;

+int		WarningLevel = 1;

+int		UseStdout = 0;					/* MR6 */

+int		TabWidth = 2;					/* MR6 */ /* MR27 */

+int		HoistPredicateContext = 0;

+int     MRhoisting = 0;                 /* MR9 */

+int     MRhoistingk = 0;                /* MR13 */

+int     MR_debugGenRule=0;              /* MR11 */

+

+int		GenCC = 0;			/* Generate C++ output */

+

+PointerStack MR_BackTraceStack={0,0,NULL};            /* MR10 */

+PointerStack MR_PredRuleRefStack={0,0,NULL};          /* MR10 */

+PointerStack MR_RuleBlkWithHaltStack={0,0,NULL};      /* MR10 */

+

+/* DontCopyTokens and Pragma_DupLabeledTokens were a bad idea.  I've just

+   turned them off rather than backpatching the code.  Who knows?  We

+   may need them in the future.

+ */

+int		DontCopyTokens = 1;	/* in C++, don't copy ANTLRToken passed to ANTLR */

+

+/* Remember if LT(i), LA(i), or LATEXT(i) used in an action which is not

+   a predicate.  If so, give a warning for novice users.

+*/

+

+int     LTinTokenAction = 0; /* MR23 */

+int     PURIFY = 1;          /* MR23 */

+

+int     CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */

+int     CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */

diff --git a/Source/Pccts/antlr/hash.c b/Source/Pccts/antlr/hash.c
new file mode 100644
index 0000000..68fe8fd
--- /dev/null
+++ b/Source/Pccts/antlr/hash.c
@@ -0,0 +1,221 @@
+/*

+ * hash.c

+ *

+ * Manage hash tables.

+ *

+ * The following functions are visible:

+ *

+ *		char	*mystrdup(char *);		Make space and copy string

+ *		Entry 	**newHashTable();		Create and return initialized hash table

+ *		Entry	*hash_add(Entry **, char *, Entry *)

+ *		Entry	*hash_get(Entry **, char *)

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#include "hash.h"

+

+#ifdef __USE_PROTOS

+#include <stdlib.h>

+#else

+#ifdef VAXC

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif

+#endif

+#include <string.h>

+

+#define StrSame		0

+

+#define fatal(err)															\

+			{fprintf(stderr, "%s(%d):", __FILE__, __LINE__);				\

+			fprintf(stderr, " %s\n", err); exit(PCCTS_EXIT_FAILURE);}

+#define require(expr, err) {if ( !(expr) ) fatal(err);}

+

+static unsigned size = HashTableSize;

+static char *strings = NULL;

+static char *strp;

+static unsigned strsize = StrTableSize;

+

+/* create the hash table and string table for terminals (string table only once) */

+Entry **

+#ifdef __USE_PROTOS

+newHashTable( void )

+#else

+newHashTable( )

+#endif

+{

+	Entry **table;

+	

+	table = (Entry **) calloc(size, sizeof(Entry *));

+	require( table != NULL, "cannot allocate hash table");

+	if ( strings == NULL )

+	{

+		strings = (char *) calloc(strsize, sizeof(char));

+		require( strings != NULL, "cannot allocate string table");

+		strp = strings;

+	}

+	return table;

+}

+

+void

+#ifdef __USE_PROTOS

+killHashTable( Entry **table )

+#else

+killHashTable( table )

+Entry **table;

+#endif

+{

+	/* for now, just free table, forget entries */

+	free( (char *) table );     /* MR10 cast */

+}

+

+/* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */

+Entry *

+#ifdef __USE_PROTOS

+hash_add( Entry **table, char *key, Entry *rec )

+#else

+hash_add( table, key, rec )

+Entry **table;

+char *key;

+Entry *rec;

+#endif

+{

+	unsigned h=0;

+	char *p=key;

+	require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition");

+	

+	Hash(p,h,size);

+	rec->next = table[h];			/* Add to singly-linked list */

+	table[h] = rec;

+	return rec;

+}

+

+/* Return ptr to 1st entry found in table under key (return NULL if none found) */

+Entry *

+#ifdef __USE_PROTOS

+hash_get( Entry **table, char *key )

+#else

+hash_get( table, key )

+Entry **table;

+char *key;

+#endif

+{

+	unsigned h=0;

+	char *p=key;

+	Entry *q;

+/*	require(table!=NULL && key!=NULL, "get: invalid table and/or key");*/

+	if ( !(table!=NULL && key!=NULL) ) *((char *) 34) = 3;

+	

+	Hash(p,h,size);

+	for (q = table[h]; q != NULL; q = q->next)

+	{

+		if ( strcmp(key, q->str) == StrSame ) return( q );

+	}

+	return( NULL );

+}

+

+#ifdef DEBUG_HASH

+void

+#ifdef __USE_PROTOS

+hashStat( Entry **table )

+#else

+hashStat( table )

+Entry **table;

+#endif

+{

+	static unsigned short count[20];

+	int i,n=0,low=0, hi=0;

+	Entry **p;

+	float avg=0.0;

+	

+	for (i=0; i<20; i++) count[i] = 0;

+	for (p=table; p<&(table[size]); p++)

+	{

+		Entry *q = *p;

+		int len;

+		

+		if ( q != NULL && low==0 ) low = p-table;

+		len = 0;

+		if ( q != NULL ) fprintf(stderr, "[%d]", p-table);

+		while ( q != NULL )

+		{

+			len++;

+			n++;

+			fprintf(stderr, " %s", q->str);

+			q = q->next;

+			if ( q == NULL ) fprintf(stderr, "\n");

+		}

+		count[len]++;

+		if ( *p != NULL ) hi = p-table;

+	}

+

+	fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n",

+					n, size-count[0], size);

+	fprintf(stderr, "%f %% utilization\n",

+					((float)(size-count[0]))/((float)size));

+	for (i=0; i<20; i++)

+	{

+		if ( count[i] != 0 )

+		{

+			avg += (((float)(i*count[i]))/((float)n)) * i;

+			fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n",

+							i, count[i], ((float)(i*count[i]))/((float)n));

+		}

+	}

+	fprintf(stderr, "Avg bucket length %f\n", avg);

+	fprintf(stderr, "Range of hash function: %d..%d\n", low, hi);

+}

+#endif

+

+/* Add a string to the string table and return a pointer to it.

+ * Bump the pointer into the string table to next avail position.

+ */

+char *

+#ifdef __USE_PROTOS

+mystrdup( char *s )

+#else

+mystrdup( s )

+char *s;

+#endif

+{

+	char *start=strp;

+	require(s!=NULL, "mystrdup: NULL string");

+

+	while ( *s != '\0' )

+	{

+		require( strp <= &(strings[strsize-2]),

+				 "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n");

+		*strp++ = *s++;

+	}

+	*strp++ = '\0';

+

+	return( start );

+}

diff --git a/Source/Pccts/antlr/hash.h b/Source/Pccts/antlr/hash.h
new file mode 100644
index 0000000..3969c40
--- /dev/null
+++ b/Source/Pccts/antlr/hash.h
@@ -0,0 +1,73 @@
+/*

+ * hash.h -- define hash table entries, sizes, hash function...

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+				/* H a s h  T a b l e  S t u f f */

+

+#ifndef HashTableSize

+#define HashTableSize	553

+#endif

+

+#ifndef StrTableSize

+#ifdef PC32

+#define StrTableSize	1000000

+#endif

+#endif

+

+#ifndef StrTableSize

+#ifdef PC

+#define StrTableSize 655200

+#endif

+#endif

+

+#ifndef StrTableSize

+#define StrTableSize 1000000

+#endif

+

+typedef struct _entry {		/* Minimum hash table entry -- superclass */

+			char *str;

+			struct _entry *next;

+		} Entry;

+

+/* Hash 's' using 'size', place into h (s is modified) */

+#define Hash(s,h,size)								\

+	{while ( *s != '\0' ) h = (h<<1) + *s++;		\

+	h %= size;}

+

+#ifdef __USE_PROTOS

+Entry	*hash_get(Entry **, char *),

+		**newHashTable(void),

+		*hash_add(Entry **, char *, Entry *);

+

+void	killHashTable(Entry **);

+

+#else

+Entry *hash_get(), **newHashTable(), *hash_add();

+void	killHashTable();        /* MR9 23-Sep-97 */

+#endif

diff --git a/Source/Pccts/antlr/lex.c b/Source/Pccts/antlr/lex.c
new file mode 100644
index 0000000..8c524fe
--- /dev/null
+++ b/Source/Pccts/antlr/lex.c
@@ -0,0 +1,878 @@
+/*

+ * lex.c	--	Generate all of the lexical type files: parser.dlg tokens.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <ctype.h>

+/* MR1						                                                */

+/* MR1  10-Apr-97  MR1	Replace use of __STDC__ with __USE_PROTOS	    */

+/* MR1				                                                        */

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+

+#define DLGErrorString "invalid token"

+

+/* Generate a complete lexical description of the lexemes found in the grammar */

+void

+#ifdef __USE_PROTOS

+genLexDescr( void )

+#else

+genLexDescr( )

+#endif

+{

+	ListNode *p;

+	FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w");

+	require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) );

+#ifdef SPECIAL_FOPEN

+	special_fopen_actions(OutMetaName(DlgFileName));	             /* MR1 */

+#endif

+	fprintf(dlgFile, "<<\n");

+	fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);

+	fprintf(dlgFile, " *\n");

+	fprintf(dlgFile, " * Generated from:");

+	{int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}

+	fprintf(dlgFile, "\n");

+	fprintf(dlgFile, " *\n");

+	fprintf(dlgFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(dlgFile, " * Purdue University Electrical Engineering\n");

+	fprintf(dlgFile, " * With AHPCRC, University of Minnesota\n");

+	fprintf(dlgFile, " * ANTLR Version %s\n", Version);

+	fprintf(dlgFile, " */\n\n");

+    if (FirstAction != NULL ) dumpAction( FirstAction, dlgFile, 0, -1, 0, 1 );  /* MR11 MR15b */

+    fprintf(dlgFile, "#define ANTLR_VERSION	%s\n", VersionDef);

+	if ( GenCC )

+	{

+		if ( !UserDefdTokens ) fprintf(dlgFile, "#include \"%s\"\n", DefFileName);

+		else fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);

+		fprintf(dlgFile, "#include \"%s\"\n", ATOKEN_H);

+		if ( GenAST ) fprintf(dlgFile, "#include \"%s\"\n", ASTBASE_H);

+		if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );

+	}

+	else

+	{

+		fprintf(dlgFile, "#include \"pcctscfg.h\"\n");

+		fprintf(dlgFile, "#include \"pccts_stdio.h\"\n");

+		if ( strcmp(ParserName, DefaultParserName)!=0 )

+			fprintf(dlgFile, "#define %s %s\n", DefaultParserName, ParserName);

+		if ( strcmp(ParserName, DefaultParserName)!=0 )

+			fprintf(dlgFile, "#include \"%s\"\n", RemapFileName);

+		if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );

+		if ( FoundGuessBlk )

+		{

+			fprintf(dlgFile, "#define ZZCAN_GUESS\n");

+			fprintf(dlgFile, "#include \"pccts_setjmp.h\"\n");

+		}

+		if ( OutputLL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);

+		if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");

+        if (TraceGen) {

+          fprintf(dlgFile,"#ifndef zzTRACE_RULES\n");  /* MR20 */

+          fprintf(dlgFile,"#define zzTRACE_RULES\n");  /* MR20 */

+          fprintf(dlgFile,"#endif\n");  /* MR22 */

+        };

+		fprintf(dlgFile, "#include \"antlr.h\"\n");

+		if ( GenAST ) {

+			fprintf(dlgFile, "#include \"ast.h\"\n");

+		}

+		if ( UserDefdTokens )

+			fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);

+		/* still need this one as it has the func prototypes */

+		fprintf(dlgFile, "#include \"%s\"\n", DefFileName);

+		fprintf(dlgFile, "#include \"dlgdef.h\"\n");

+		fprintf(dlgFile, "LOOKAHEAD\n");

+		fprintf(dlgFile, "\n");

+		fprintf(dlgFile, "void\n");

+		fprintf(dlgFile, "#ifdef __USE_PROTOS\n");

+		fprintf(dlgFile, "zzerraction(void)\n");

+		fprintf(dlgFile, "#else\n");

+		fprintf(dlgFile, "zzerraction()\n");

+		fprintf(dlgFile, "#endif\n");

+		fprintf(dlgFile, "{\n");

+		fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);

+		fprintf(dlgFile, "\tzzadvance();\n");

+		fprintf(dlgFile, "\tzzskip();\n");

+		fprintf(dlgFile, "}\n");

+	}

+	fprintf(dlgFile, ">>\n\n");

+

+	/* dump all actions */

+

+/* MR1									                                    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class     */

+/* MR1	 	   	  via <<%%lexmember ....>> & <<%%lexprefix ...>>            */

+/* MR1				                					    */

+          if (LexActions != NULL) {

+            for (p = LexActions->next; p!=NULL; p=p->next)

+		{

+/* MR1 */	fprintf(dlgFile, "<<%%%%lexaction\n");

+			dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );

+			fprintf(dlgFile, ">>\n\n");

+		}

+	  };

+

+/* MR1 */ if (GenCC) {

+/* MR1 */   fprintf(dlgFile,"<<%%%%parserclass %s>>\n\n",CurrentClassName);

+/* MR1 */ };

+

+/* MR1 */ if (LexPrefixActions != NULL) {

+/* MR1 */   for (p = LexPrefixActions->next; p!=NULL; p=p->next)

+/* MR1 */       {

+/* MR1 */               fprintf(dlgFile, "<<%%%%lexprefix\n");

+/* MR1 */               dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );

+/* MR1 */               fprintf(dlgFile, ">>\n\n");

+/* MR1 */       }

+/* MR1 */ };

+

+/* MR1 */ if (LexMemberActions != NULL) {

+/* MR1 */   for (p = LexMemberActions->next; p!=NULL; p=p->next)

+/* MR1 */       {

+/* MR1 */               fprintf(dlgFile, "<<%%%%lexmember\n");

+/* MR1 */               dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );

+/* MR1 */               fprintf(dlgFile, ">>\n\n");

+/* MR1 */       }

+/* MR1 */ };

+

+	/* dump all regular expression rules/actions (skip sentinel node) */

+	if ( ExprOrder == NULL ) {

+		warnNoFL("no regular expressions found in grammar");

+	}

+	else dumpLexClasses(dlgFile);

+	fprintf(dlgFile, "%%%%\n");

+	fclose( dlgFile );

+}

+

+/* For each lexical class, scan ExprOrder looking for expressions

+ * in that lexical class.  Print out only those that match.

+ * Each element of the ExprOrder list has both an expr and an lclass

+ * field.

+ */

+void

+#ifdef __USE_PROTOS

+dumpLexClasses( FILE *dlgFile )

+#else

+dumpLexClasses( dlgFile )

+FILE *dlgFile;

+#endif

+{

+	int i;

+	TermEntry *t;

+	ListNode *p;

+	Expr *q;

+

+	for (i=0; i<NumLexClasses; i++)

+	{

+		fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].classnum);

+		for (p=ExprOrder->next; p!=NULL; p=p->next)

+		{

+			q = (Expr *) p->elem;

+			if ( q->lclass != i ) continue;

+			lexmode(i);

+			t = (TermEntry *) hash_get(Texpr, q->expr);

+			require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );

+			if ( t->token == EpToken ) continue;

+			fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));

+			/* replace " killed by StripQuotes() */

+			q->expr[ strlen(q->expr) ] = '"';

+			if ( !GenCC ) {

+				if ( TokenString(t->token) != NULL )

+					fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token));

+				else

+					fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);

+			}

+			if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );

+			if ( GenCC ) {

+				if ( TokenString(t->token) != NULL )

+					fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token));

+				else

+					fprintf(dlgFile, "\t\treturn (ANTLRTokenType)%d;\n", t->token);

+			}

+			fprintf(dlgFile, "\t>>\n\n");

+		}

+	}

+}

+

+/* Strip the leading path (if any) from a filename */

+char *

+#ifdef __USE_PROTOS

+StripPath( char *fileName )

+#else

+StripPath( fileName )

+char *fileName;

+#endif

+{

+	char *p;

+	static char dirSym[2] = DirectorySymbol;

+

+	if(NULL != (p = strrchr(fileName, dirSym[0])))

+		p++;

+	else

+		p = fileName;

+

+	return(p);

+}

+

+/* Generate a list of #defines && list of struct definitions for

+ * aggregate retv's */

+void

+#ifdef __USE_PROTOS

+genDefFile( void )

+#else

+genDefFile( )

+#endif

+{

+	int i;

+

+	/* If C++ mode and #tokdef used, then don't need anything in here since

+	 * C++ puts all definitions in the class file name.

+	 */

+	if ( GenCC && UserTokenDefsFile ) return;

+    if ( MR_Inhibit_Tokens_h_Gen) return;

+

+	DefFile = fopen(OutMetaName(DefFileName), "w");

+	require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) );

+#ifdef SPECIAL_FOPEN

+	special_fopen_actions(OutMetaName(DefFileName));	             /* MR1 */

+#endif

+	fprintf(DefFile, "#ifndef %s\n", StripPath(gate_symbol(DefFileName)));

+	fprintf(DefFile, "#define %s\n", StripPath(gate_symbol(DefFileName)));

+

+	fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName);

+	fprintf(DefFile, " *\n");

+	fprintf(DefFile, " * Generated from:");

+	for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);

+	fprintf(DefFile, "\n");

+	fprintf(DefFile, " *\n");

+	fprintf(DefFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");

+	fprintf(DefFile, " * Purdue University Electrical Engineering\n");

+	fprintf(DefFile, " * ANTLR Version %s\n", Version);

+	fprintf(DefFile, " */\n");

+

+	if ( !GenCC && LexGen ) {

+		fprintf(DefFile,"#define zzEOF_TOKEN %d\n",

+				TokenInd!=NULL?TokenInd[EofToken]:EofToken);

+	}

+

+	if ( !UserDefdTokens )

+	{

+		int first=1;

+

+		if ( GenCC ) fprintf(DefFile, "enum ANTLRTokenType {\n");

+		for (i=1; i<TokenNum; i++)

+		{

+			/* Don't do EpToken or expr w/o labels */

+			if ( TokenString(i)!=NULL && i != EpToken )

+			{

+				TermEntry *p;

+				

+				if ( WarningLevel>1 )

+				{

+					int j;

+					/* look in all lexclasses for the reg expr */

+

+/* MR10  Derek Pappas                                                */

+/* MR10     A #tokclass doesn't have associated regular expressiones */

+/* MR10        so don't warn user about it's omission                */

+

+                    p = (TermEntry *) hash_get(Tname, TokenString(i));

+

+                    if (p != NULL && ! p->classname) {

+    					for (j=0; j<NumLexClasses; j++)

+    					{

+    						lexmode(j);

+    						if ( ExprString(i)!=NULL ) break;

+    					}

+    					if ( j>=NumLexClasses )

+    					{

+    						warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i)));

+    					}

+                    };

+				}

+				require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL,

+						"token not in sym tab when it should be");

+				if ( !p->classname )

+				{

+					if ( GenCC ) {

+						if ( !first ) fprintf(DefFile, ",\n");

+						first = 0;

+						fprintf(DefFile, "\t%s=%d", TokenString(i), i);

+					}

+					else

+						fprintf(DefFile, "#define %s %d\n", TokenString(i), i);

+				}

+			}

+		}

+/* MR1									                                    */

+/* MR1  10-Apr-97 133MR1	Prevent use of varying sizes of integer	    */

+/* MR1				for the enum ANTLRTokenType                             */

+/* MR1								           */

+		if ( GenCC ) {				                                 /* MR1 */

+ 		 	 if ( !first ) fprintf(DefFile, ",\n");                  /* MR14 */

+		     fprintf(DefFile, "\tDLGminToken=0");                 /* MR1 */

+		     fprintf(DefFile, ",\n\tDLGmaxToken=9999};\n");          /* MR1 */

+                };						                             /* MR1 */

+	}

+

+	if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag);

+

+	fprintf(DefFile, "\n#endif\n");

+}

+

+void

+#ifdef __USE_PROTOS

+GenRemapFile( void )

+#else

+GenRemapFile( )

+#endif

+{

+	if ( strcmp(ParserName, DefaultParserName)!=0 )

+	{

+		FILE *f;

+		int i;

+

+		f = fopen(OutMetaName(RemapFileName), "w");

+		require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) );

+#ifdef SPECIAL_FOPEN

+		special_fopen_actions(OutMetaName(RemapFileName));           /* MR1 */

+#endif

+		fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName);

+		fprintf(f, " *\n");

+		fprintf(f, " * Generated from:");

+		for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);

+		fprintf(f, "\n");

+		fprintf(f, " *\n");

+		fprintf(f, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");

+		fprintf(f, " * Purdue University Electrical Engineering\n");

+		fprintf(f, " * ANTLR Version %s\n", Version);

+		fprintf(f, " */\n");

+

+		GenRuleFuncRedefs(f, SynDiag);

+		GenPredefinedSymbolRedefs(f);

+		if ( GenAST ) GenASTSymbolRedefs(f);

+		GenSetRedefs(f);

+

+		fclose(f);

+	}

+}

+

+/* Generate a bunch of #defines that rename all functions to be "ParserName_func" */

+void

+#ifdef __USE_PROTOS

+GenRuleFuncRedefs( FILE *f, Junction *p )

+#else

+GenRuleFuncRedefs( f, p )

+FILE *f;

+Junction *p;

+#endif

+{

+	fprintf(f, "\n/* rename rule functions to be 'ParserName_func' */\n");

+	while ( p!=NULL )

+	{

+		fprintf(f, "#define %s %s_%s\n", p->rname, ParserName, p->rname);

+		p = (Junction *)p->p2;

+	}

+}

+

+/* Generate a bunch of #defines that rename all standard symbols to be

+ * "ParserName_symbol".  The list of standard symbols to change is in

+ * globals.c.

+ */

+void

+#ifdef __USE_PROTOS

+GenPredefinedSymbolRedefs( FILE *f )

+#else

+GenPredefinedSymbolRedefs( f )

+FILE *f;

+#endif

+{

+	char **p;

+

+	fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n");

+	for (p = &StandardSymbols[0]; *p!=NULL; p++)

+	{

+		fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);

+	}

+}

+

+/* Generate a bunch of #defines that rename all AST symbols to be

+ * "ParserName_symbol".  The list of AST symbols to change is in

+ * globals.c.

+ */

+void

+#ifdef __USE_PROTOS

+GenASTSymbolRedefs( FILE *f )

+#else

+GenASTSymbolRedefs( f )

+FILE *f;

+#endif

+{

+	char **p;

+

+	fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n");

+	for (p = &ASTSymbols[0]; *p!=NULL; p++)

+	{

+		fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);

+	}

+}

+

+/* redefine all sets generated by ANTLR; WARNING:  'zzerr', 'setwd' must match

+ * use in bits.c (DumpSetWd() etc...)

+ */

+void

+#ifdef __USE_PROTOS

+GenSetRedefs( FILE *f )

+#else

+GenSetRedefs( f )

+FILE *f;

+#endif

+{

+	int i;

+

+	for (i=1; i<=wordnum; i++)

+	{

+		fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i);

+	}

+	for (i=1; i<=esetnum; i++)

+	{

+		fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i);

+	}

+}

+

+/* Find all return types/parameters that require structs and def

+ * all rules with ret types.

+ *

+ * This is for the declaration, not the definition.

+ */

+void

+#ifdef __USE_PROTOS

+GenRulePrototypes( FILE *f, Junction *p )

+#else

+GenRulePrototypes( f, p )

+FILE *f;

+Junction *p;

+#endif

+{

+	int i;

+

+	i = 1;

+	while ( p!=NULL )

+	{

+		if ( p->ret != NULL )

+		{

+/* MR23 */	if ( hasMultipleOperands(p->ret) )

+			{

+				DumpRetValStruct(f, p->ret, i);

+			}

+			fprintf(f, "\n#ifdef __USE_PROTOS\n");

+/* MR23 */	if ( hasMultipleOperands(p->ret) ) 

+			{

+				fprintf(f, "extern struct _rv%d", i);

+			}

+			else

+			{

+				fprintf(f, "extern ");

+				DumpType(p->ret, f);

+			}

+			fprintf(f, " %s%s(", RulePrefix, p->rname);

+			DumpANSIFunctionArgDef(f,p,1 /* emit initializers ? */);

+			fprintf(f, ";\n");

+			fprintf(f, "#else\n");

+/* MR23 */	if ( hasMultipleOperands(p->ret) )

+			{

+				fprintf(f, "extern struct _rv%d", i);

+			}

+			else

+			{

+				fprintf(f, "extern ");

+				DumpType(p->ret, f);

+			}

+			fprintf(f, " %s%s();\n", RulePrefix, p->rname);

+			fprintf(f, "#endif\n");

+		}

+		else

+		{

+			fprintf(f, "\n#ifdef __USE_PROTOS\n");

+			fprintf(f, "void %s%s(", RulePrefix, p->rname);

+			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );

+			fprintf(f, ";\n");

+#ifdef OLD

+			if ( p->pdecl != NULL || GenAST )

+			{

+				if ( GenAST ) {

+					fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");

+				}

+				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);

+			}

+			else fprintf(f, "void");

+			fprintf(f, ");\n");

+#endif

+			fprintf(f, "#else\n");

+			fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname);

+			fprintf(f, "#endif\n");

+		}

+		i++;

+		p = (Junction *)p->p2;

+	}

+}

+

+/* Define all rules in the class.h file; generate any required

+ * struct definitions first, however.

+ */

+void

+#ifdef __USE_PROTOS

+GenRuleMemberDeclarationsForCC( FILE *f, Junction *q )

+#else

+GenRuleMemberDeclarationsForCC( f, q )

+FILE *f;

+Junction *q;

+#endif

+{

+	Junction *p = q;

+	int i;

+

+	fprintf(f, "private:\n");

+

+	/* Dump dflt handler declaration */

+	fprintf(f, "\tvoid zzdflthandlers( int _signal, int *_retsignal );\n\n");

+

+	fprintf(f, "public:\n");

+

+	/* Dump return value structs */

+	i = 1;

+	while ( p!=NULL )

+	{

+		if ( p->ret != NULL )

+		{

+/* MR23 */	if ( hasMultipleOperands(p->ret) )

+			{

+				DumpRetValStruct(f, p->ret, i);

+			}

+		}

+		i++;

+		p = (Junction *)p->p2;

+	}

+

+	/* Dump member func defs && CONSTRUCTOR */

+	fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName);

+/*

+	fprintf(f, "\t%s(ANTLRTokenBuffer *input, ANTLRTokenType eof);\n",

+			   CurrentClassName);

+*/

+

+	i = 1;

+	p = q;

+	while ( p!=NULL )

+	{

+		if ( p->ret != NULL )

+		{

+/* MR23 */	if ( hasMultipleOperands(p->ret) )

+			{

+				fprintf(f, "\tstruct _rv%d", i);

+			}

+			else

+			{

+				fprintf(f, "\t");

+				DumpType(p->ret, f);

+			}

+			fprintf(f, " %s%s(",RulePrefix,p->rname);

+			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );

+			fprintf(f, ";\n");

+#ifdef OLD

+			if ( p->pdecl != NULL || GenAST )

+			{

+				if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");

+				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);

+			}

+			fprintf(f, ");\n");

+#endif

+		}

+		else

+		{

+			fprintf(f, "\tvoid %s%s(",RulePrefix,p->rname);

+			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */);

+			fprintf(f, ";\n");

+#ifdef OLD

+			if ( p->pdecl != NULL || GenAST )

+			{

+				if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");

+				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);

+			}

+			fprintf(f, ");\n");

+#endif

+		}

+		i++;

+		p = (Junction *)p->p2;

+	}

+}

+

+/* Given a list of ANSI-style parameter declarations, print out a

+ * comma-separated list of the symbols (w/o types).

+ * Basically, we look for a comma, then work backwards until start of

+ * the symbol name.  Then print it out until 1st non-alnum char.  Now,

+ * move on to next parameter.

+ *

+ */

+

+/* MR5 	Jan Mikkelsen 26-May-97 - added initalComma parameter              */

+

+void

+#ifdef __USE_PROTOS

+DumpListOfParmNames(char *pdecl, FILE *output, int initialComma)    /* MR5 */

+#else

+DumpListOfParmNames(pdecl, output, initialComma)		            /* MR5 */

+char *pdecl;	             		 			  	                /* MR5 */

+FILE *output;							                            /* MR5 */

+int initialComma;			                                        /* MR5 */

+#endif

+{

+	int firstTime = 1, done = 0;

+	require(output!=NULL, "DumpListOfParmNames: NULL parm");

+

+	if ( pdecl == NULL ) return;

+	while ( !done )

+	{

+		if ( !firstTime || initialComma ) putc(',', output);        /* MR5 */

+		done = DumpNextNameInDef(&pdecl, output);

+		firstTime = 0;

+	}

+}

+

+/* given a list of parameters or return values, dump the next

+ * name to output.  Return 1 if last one just printed, 0 if more to go.

+ */

+

+/* MR23 Total rewrite */

+

+int

+#ifdef __USE_PROTOS

+DumpNextNameInDef( char **q, FILE *output )

+#else

+DumpNextNameInDef( q, output )

+char **q;

+FILE *output;

+#endif

+{

+	char *p;

+	char *t;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+	int nest = 0;

+

+	p = endFormal(*q,

+			      &pDataType,

+				  &pSymbol,

+				  &pEqualSign,

+				  &pValue,

+				  &pSeparator,

+				  &nest);

+

+    /* MR26 Handle rule arguments such as: IIR_Bool (IIR_Decl::*contstraint)()

+       For this we need to strip off anything which follows the symbol.

+     */

+

+/* MR26 */  t = pSymbol;

+/* MR26 */	if (t != NULL) {

+/* MR26 */		for (t = pSymbol; *t != 0; t++) {

+/* MR26 */			if (! (isalpha(*t) || isdigit(*t) || *t == '_' || *t == '$')) break;

+/* MR26 */		}

+/* MR26 */	}

+/* MR26 */	fprintf(output,strBetween(pSymbol, t, pSeparator));

+

+    *q = p;

+    return (*pSeparator  == 0);

+}

+

+/* Given a list of ANSI-style parameter declarations, dump K&R-style

+ * declarations, one per line for each parameter.  Basically, convert

+ * comma to semi-colon, newline.

+ */

+void

+#ifdef __USE_PROTOS

+DumpOldStyleParms( char *pdecl, FILE *output )

+#else

+DumpOldStyleParms( pdecl, output )

+char *pdecl;

+FILE *output;

+#endif

+{

+	require(output!=NULL, "DumpOldStyleParms: NULL parm");

+

+	if ( pdecl == NULL ) return;

+	while ( *pdecl != '\0' )

+	{

+		if ( *pdecl == ',' )

+		{

+			pdecl++;

+			putc(';', output); putc('\n', output);

+			while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;

+		}

+		else {putc(*pdecl, output); pdecl++;}

+	}

+	putc(';', output);

+	putc('\n', output);

+}

+

+/* Take in a type definition (type + symbol) and print out type only */

+/* MR23 Total rewrite */

+

+void

+#ifdef __USE_PROTOS

+DumpType( char *s, FILE *f )

+#else

+DumpType( s, f )

+char *s;

+FILE *f;

+#endif

+{

+	char *p;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+	int nest = 0;

+

+	require(s!=NULL, "DumpType: invalid type string"); 

+

+	p = endFormal(s,

+			      &pDataType,

+				  &pSymbol,

+				  &pEqualSign,

+				  &pValue,

+				  &pSeparator,

+				  &nest);

+	fprintf(f,strBetween(pDataType, pSymbol, pSeparator));

+}

+

+/* check to see if string e is a word in string s */

+int

+#ifdef __USE_PROTOS

+strmember( char *s, char *e )

+#else

+strmember( s, e )

+char *s;

+char *e;

+#endif

+{

+    register char *p;

+    require(s!=NULL&&e!=NULL, "strmember: NULL string");

+

+    if ( *e=='\0' ) return 1;   /* empty string is always member */

+    do {

+	while ( *s!='\0' && !isalnum(*s) && *s!='_' )

+	++s;

+	p = e;

+	while ( *p!='\0' && *p==*s ) {p++; s++;}

+	if ( *p=='\0' ) {

+	    if ( *s=='\0' ) return 1;

+	    if ( !isalnum (*s) && *s != '_' ) return 1;

+	}

+	while ( isalnum(*s) || *s == '_' )

+	++s;

+    } while ( *s!='\0' );

+    return 0;

+}

+

+#if 0

+

+/* MR23 Replaced by hasMultipleOperands() */

+

+int

+#ifdef __USE_PROTOS

+HasComma( char *s )

+#else

+HasComma( s )

+char *s;

+#endif

+{

+	while (*s!='\0')

+		if ( *s++ == ',' ) return 1;

+	return 0;

+}

+#endif

+

+

+/* MR23 Total rewrite */

+

+void

+#ifdef __USE_PROTOS

+DumpRetValStruct( FILE *f, char *ret, int i )

+#else

+DumpRetValStruct( f, ret, i )

+FILE *f;

+char *ret;

+int i;

+#endif

+{

+	char *p = ret;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+    int nest = 0;

+

+	fprintf(f, "\nstruct _rv%d {\n", i);

+	while (*p != 0 && nest == 0) {

+		p = endFormal(p,

+			          &pDataType,

+					  &pSymbol,

+					  &pEqualSign,

+					  &pValue,

+					  &pSeparator,

+					  &nest);

+		fprintf(f,"\t");

+		fprintf(f,strBetween(pDataType, pSymbol, pSeparator));

+		fprintf(f," ");

+		fprintf(f,strBetween(pSymbol, pEqualSign, pSeparator));

+		fprintf(f,";\n");

+    }

+	fprintf(f,"};\n");

+}

+

+/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */

+char *

+#ifdef __USE_PROTOS

+StripQuotes( char *s )

+#else

+StripQuotes( s )

+char *s;

+#endif

+{

+	if ( *s == '"' )

+	{

+		s[ strlen(s)-1 ] = '\0';    /* remove last quote */

+		return( s+1 );				/* return address past initial quote */

+	}

+	return( s );

+}

diff --git a/Source/Pccts/antlr/main.c b/Source/Pccts/antlr/main.c
new file mode 100644
index 0000000..051ee4e
--- /dev/null
+++ b/Source/Pccts/antlr/main.c
@@ -0,0 +1,1747 @@
+/*

+ * main.c -- main program for PCCTS ANTLR.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+/* To set a breakpoint just before exit look for "cleanUp".    */

+/* To set a breakpoint for fatal error look for "fatal_intern" */

+

+#include <stdio.h>

+

+#include "pcctscfg.h"

+#include "stdpccts.h"

+

+#define MAX_INT_STACK 50

+static int istack[MAX_INT_STACK];		/* Int stack */

+static int isp = MAX_INT_STACK;

+

+static int DontAcceptFiles = 0;			/* if stdin, don't read files */

+static int DontAcceptStdin = 0;			/* if files seen first, don't accept stdin */

+

+static int tnodes_used_in_guard_predicates_etc;     /* MR10 */

+

+		/* C m d - L i n e  O p t i o n  S t r u c t  &  F u n c s */

+

+typedef struct _Opt {

+			char *option;

+			int  arg;

+#ifdef __cplusplus

+			void (*process)(...);

+#else

+			void (*process)();

+#endif

+			char *descr;

+		} Opt;

+

+#ifdef __USE_PROTOS

+extern void ProcessArgs(int, char **, Opt *);

+#else

+extern void ProcessArgs();

+#endif

+

+#ifdef __USE_PROTOS

+int ci_strequ(char *a,char *b)

+#else

+int ci_strequ(a,b)

+  char  *a;

+  char  *b;

+#endif

+{

+  for ( ;*a != 0 && *b != 0; a++, b++) {

+    if (toupper(*a) != toupper(*b)) return 0;

+  }

+  return (*a == *b);

+}

+

+static void

+#ifdef __USE_PROTOS

+pStdin( void )

+#else

+pStdin( )

+#endif

+{

+	if ( DontAcceptStdin )

+	{

+		warnNoFL("'-' (stdin) ignored as files were specified first");

+		return;

+	}

+

+	require(NumFiles<MaxNumFiles,"exceeded max # of input files");

+	FileStr[NumFiles++] = "stdin";

+	DontAcceptFiles = 1;

+}

+

+static void

+#ifdef __USE_PROTOS

+pFile( char *s )

+#else

+pFile( s )

+char *s;

+#endif

+{

+	if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; }

+	if ( DontAcceptFiles )

+	{

+		warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s));

+		return;

+	}

+

+	require(NumFiles<MaxNumFiles,"exceeded max # of input files");

+	FileStr[NumFiles++] = s;

+	DontAcceptStdin = 1;

+}

+

+/* MR14

+        Allow input to be a file containing a list of files

+        Bernard Giroud (b_giroud@decus.ch)

+*/

+

+static void

+#ifdef __USE_PROTOS

+pFileList( char *s, char *t )

+#else

+pFileList( s, t )

+char *s;

+char *t;

+#endif

+{

+#define MaxFLArea 1024

+	FILE *fl;

+	static char Fn_in_Fl[MaxFLArea] = "";

+        char one_fn[MaxFileName];

+	char *flp = &Fn_in_Fl[0];

+	int fnl, left = MaxFLArea, i;

+

+	if ( *t=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",t) ); return; }

+	if ( DontAcceptFiles )

+	{

+		warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",t));

+		return;

+	}

+

+        if ((fl = fopen(t, "r")) == NULL)

+	{

+		warnNoFL(eMsg1("file '%s' can't be opened", t));

+		return;

+	}

+        for (;;)

+	{

+		if (fgets(one_fn, 128 - 1, fl) == NULL)

+			break;

+		fnl = strlen(one_fn);

+		require(fnl<=left, "no more room in File List Area");

+		/* drop the trailing LF */

+		if (one_fn[fnl - 1] == 0x0a) one_fn[fnl - 1] = ' ';

+		strcat(Fn_in_Fl, one_fn);

+		left = left - fnl;

+		require(NumFiles<MaxNumFiles,"exceeded max # of input files");

+		FileStr[NumFiles++] = flp;

+		flp = flp + fnl;

+	}

+	fclose(fl);

+	for (i=0;i < MaxFLArea;i++) if (Fn_in_Fl[i] == ' ') Fn_in_Fl[i] = '\0';

+	DontAcceptStdin = 1;

+}

+

+static void

+#ifdef __USE_PROTOS

+pLLK( char *s, char *t )

+#else

+pLLK( s, t )

+char *s;

+char *t;

+#endif

+{

+	LL_k = atoi(t);

+	if ( LL_k <= 0 ) {

+		warnNoFL("must have at least one token of lookahead (setting to 1)");

+		LL_k = 1;

+	}

+}

+

+static void

+#ifdef __USE_PROTOS

+pCk( char *s, char *t )

+#else

+pCk( s, t )

+char *s;

+char *t;

+#endif

+{

+	CLL_k = atoi(t);

+	if ( CLL_k <= 0 ) {

+		warnNoFL("must have at least one token of look-ahead (setting to 1)");

+		CLL_k = 1;

+	}

+}

+

+static void						                                     /* MR6 */

+#ifdef __USE_PROTOS

+pTab( char *s, char *t )			                        	     /* MR6 */

+#else

+pTab( s, t )				                    		             /* MR6 */

+char *s;							                                 /* MR6 */

+char *t;							                                 /* MR6 */

+#endif

+{								                                     /* MR6 */

+	TabWidth = atoi(t);					                             /* MR6 */

+	if ( TabWidth < 0 || TabWidth > 8 ) {	            		     /* MR6 */

+		warnNoFL("tab width must be between 1 and 8");               /* MR6 */

+	  TabWidth=0;						                             /* MR6 */

+	}							                                     /* MR6 */

+}							                                         /* MR6 */

+

+static int ambAidDepthSpecified=0;                                   /* MR11 */

+

+static void						                                     /* MR11 */

+#ifdef __USE_PROTOS

+pAAd( char *s, char *t )			                        	     /* MR11 */

+#else

+pAAd( s, t )				                    		             /* MR11 */

+char *s;							                                 /* MR11 */

+char *t;							                                 /* MR11 */

+#endif

+{								                                     /* MR11 */

+    ambAidDepthSpecified=1;                                          /* MR11 */

+	MR_AmbAidDepth = atoi(t);				                         /* MR11 */

+}							                                         /* MR11 */

+

+static void						                                     /* MR11 */

+#ifdef __USE_PROTOS

+pTreport( char *s, char *t )			                       	     /* MR11 */

+#else

+pTreport( s, t )				                  		             /* MR11 */

+    char *s;							                             /* MR11 */

+    char *t;							                             /* MR11 */

+#endif

+{								                                     /* MR11 */

+	TnodesReportThreshold = atoi(t);				                 /* MR11 */

+}							                                         /* MR11 */

+

+#ifdef __USE_PROTOS

+void chkGTFlag(void)	                                    /* 7-Apr-97 MR1 */

+#else

+void chkGTFlag()                                            /* 7-Apr-97 MR1 */

+#endif

+{

+	if ( !GenAST )

+		warn("#-variable or other AST item referenced w/o -gt option");

+}

+

+

+#ifdef __USE_PROTOS

+static void pInfo(char *s, char *t)                         /* MR10 */

+#else

+static void pInfo(s,t)                                      /* MR10 */

+  char  *s;

+  char  *t;

+#endif

+{

+  char  *p;

+  int   q;

+  for (p=t; *p != 0; p++) {

+    q=tolower(*p);

+    if (q=='t') {

+      InfoT=1;

+    } else if (q=='p') {

+      InfoP=1;

+    } else if (q=='m') {

+      InfoM=1;

+    } else if (q=='o') {

+      InfoO=1;

+    } else if (q=='0') {

+      ; /* nothing */

+    } else if (q=='f') {

+      InfoF=1;

+    } else {

+      warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p));

+    };

+  };

+}

+

+#ifdef __USE_PROTOS

+static void pCGen(void)	{ CodeGen = FALSE; LexGen = FALSE; }

+static void pLGen(void)	{ LexGen = FALSE; }

+static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; }

+static void pTGen(void)	{ TraceGen = TRUE; }

+static void pSGen(void)	{ GenExprSetsOpt = FALSE; }

+static void pPrt(void)	{ PrintOut = TRUE; pCGen(); pLGen(); }

+static void pPrtA(void)	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }

+static void pAst(void)	{ GenAST = TRUE; }

+static void pANSI(void)	{ GenANSI = TRUE; }

+static void pCr(void)	{ GenCR = TRUE; }

+static void pNOPURIFY(void)	{ PURIFY = FALSE; }

+/*static void pCt(void)	{ warnNoFL("-ct option is now the default"); }*/

+static void pLI(void)	{ GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */

+static void pLIms(void)	{ GenLineInfo = TRUE; GenLineInfoMS = TRUE; }  /* MR14 */

+static void pFr(char *s, char *t) {RemapFileName = t;}

+static void pFe(char *s, char *t) {ErrFileName = t;}

+static void pFl(char *s, char *t) {DlgFileName = t;}

+static void pFm(char *s, char *t) {ModeFileName = t;}

+static void pFt(char *s, char *t) {DefFileName = t;}

+

+static void pE1(void)	{ elevel = 1; }

+static void pE2(void)	{ elevel = 2; }

+static void pE3(void)	{ elevel = 3; }

+static void pEGen(void)	{ GenEClasseForRules = 1; }

+static void pDL(void)

+	{

+	    DemandLookahead = 1;

+	    if ( GenCC ) {

+			warnNoFL("-gk does not work currently in C++ mode; -gk turned off");

+			DemandLookahead = 0;

+	    }

+	}

+

+static void pAA(char *s,char *t) {MR_AmbAidRule = t;}               /* MR11 */

+static void pAAm(char *s){MR_AmbAidMultiple = 1;}                   /* MR11 */

+static void pGHdr(void)	{ GenStdPccts = 1; }

+static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }

+static void pW1(void) { WarningLevel = 1; }

+static void pNewAST(void) { NewAST = 1; }                           /* MR13 */

+static void ptmakeInParser(void) { tmakeInParser = 1; }             /* MR23 */

+static void pAlpha(void) { AlphaBetaTrace = 1; }                    /* MR14 */

+static void pMR_BlkErr(void) { MR_BlkErr = 1; }                     /* MR21 */

+static void pStdout(void) {UseStdout = 1; }		                    /* MR6 */

+static void pW2(void) { WarningLevel = 2; }

+static void pCC(void) { GenCC = TRUE; }

+#else

+static void pCGen()	{ CodeGen = FALSE; LexGen = FALSE; }

+static void pLGen()	{ LexGen = FALSE; }

+static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; }             /* MR14 */

+static void pTGen()	{ TraceGen = TRUE; }

+static void pSGen()	{ GenExprSetsOpt = FALSE; }

+static void pPrt()		{ PrintOut = TRUE; pCGen(); pLGen(); }

+static void pPrtA()	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }

+static void pAst()		{ GenAST = TRUE; }

+static void pANSI()	{ GenANSI = TRUE; }

+static void pCr()		{ GenCR = TRUE; }

+static void pNOPURIFY()	{ PURIFY = FALSE; }

+

+/*static void pCt()		{ warnNoFL("-ct option is now the default"); }*/

+static void pLI()	    { GenLineInfo = TRUE; GenLineInfoMS = FALSE; }  /* MR14 */

+static void pLIms()	    { GenLineInfo = TRUE; GenLineInfoMS = TRUE; }   /* MR14 */

+static void pFr(s,t) char *s, *t; {RemapFileName = t;}

+static void pFe(s,t) char *s, *t; {ErrFileName = t;}

+static void pFl(s,t) char *s, *t; {DlgFileName = t;}

+static void pFm(s,t) char *s, *t; {ModeFileName = t;}

+static void pFt(s,t) char *s, *t; {DefFileName = t;}

+

+static void pE1()		{ elevel = 1; }

+static void pE2()		{ elevel = 2; }

+static void pE3()		{ elevel = 3; }

+static void pEGen()	{ GenEClasseForRules = 1; }

+static void pDL()

+	{

+	    DemandLookahead = 1;

+	    if ( GenCC ) {

+          warnNoFL("-gk does not work currently in C++ mode; -gk turned off");

+	      DemandLookahead = 0;

+	    }

+	}

+

+static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;}          /* MR11 BJS 20-Mar-98 */

+static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;}                /* MR11 BJS 20-Mar-98 */

+static void pGHdr()	{ GenStdPccts = 1; }

+static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }

+static void pW1() { WarningLevel = 1; }

+static void pNewAST() { NewAST = 1; }                                /* MR13 */

+static void ptmakeInParser() { tmakeInParser = 1; }                  /* MR23 */

+static void pAlpha() { AlphaBetaTrace = 1; }                         /* MR14 */

+static void pMR_BlkErr() { MR_BlkErr = 1; }                          /* MR21 */

+static void pStdout() {UseStdout = 1; }	                             /* MR6 */

+static void pW2() { WarningLevel = 2; }

+static void pCC() { GenCC = TRUE; }

+#endif

+

+static void

+#ifdef __USE_PROTOS

+pPre( char *s, char *t )

+#else

+pPre( s, t )

+char *s;

+char *t;

+#endif

+{

+	RulePrefix = t;

+}

+

+static void

+#ifdef __USE_PROTOS

+pOut( char *s, char *t )

+#else

+pOut( s, t )

+char *s;

+char *t;

+#endif

+{

+	OutputDirectory = t;

+}

+

+static void

+#ifdef __USE_PROTOS

+pPred( void )

+#else

+pPred( )

+#endif

+{

+	warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk");

+/*

+**	if ( DemandLookahead )

+**		warnNoFL("-gk conflicts with -pr; -gk turned off");

+**	DemandLookahead = 0;

+**	HoistPredicateContext = 0;

+*/

+}

+

+static void

+#ifdef __USE_PROTOS

+pPredCtx( char *s, char *t )

+#else

+pPredCtx(s,t)

+char *s;

+char *t;

+#endif

+{

+	if ( ci_strequ(t,"on")) HoistPredicateContext = 1;

+	else if ( ci_strequ(t,"off")) HoistPredicateContext = 0;

+	if ( DemandLookahead )

+	{

+		warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off");

+		DemandLookahead = 0;

+	}

+}

+

+static void

+#ifdef __USE_PROTOS

+pMRhoist( char *s, char *t )

+#else

+pMRhoist(s,t)

+char *s;

+char *t;

+#endif

+{

+	if ( ci_strequ(t,"on")) MRhoisting = 1;

+	else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0;

+    if (MRhoisting) {

+        fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n");

+        fprintf(stderr,"  No longer considered experimental\n");

+        fprintf(stderr,"  Can't consider suppression for predicates with lookahead depth > 1\n");

+        fprintf(stderr,"  Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n");

+        fprintf(stderr,"  This is a reminder, not a warning or error.\n");

+    };

+}

+

+static void

+#ifdef __USE_PROTOS

+pMRhoistk( char *s, char *t )

+#else

+pMRhoistk(s,t)

+char *s;

+char *t;

+#endif

+{

+	if ( ci_strequ(t,"on")) MRhoistingk = 1;

+	else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0;

+    if (MRhoistingk) {

+        fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n");

+        fprintf(stderr,"  Applies to predicates with lookahead depth > 1\n");

+        fprintf(stderr,"  Implies -prc on and -mrhoist on\n");

+    };

+}

+

+static void

+#ifdef __USE_PROTOS

+pTRes( char *s, char *t )

+#else

+pTRes( s, t )

+char *s;

+char *t;

+#endif

+{

+	TreeResourceLimit = atoi(t);

+	if ( TreeResourceLimit <= 0 )

+	{

+		warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0");

+		TreeResourceLimit = -1; /* set to no limit */

+	}

+}

+

+Opt options[] = {

+#ifdef __cplusplus

+    { "-CC", 0, (void (*)(...)) pCC,	"Generate C++ output (default=FALSE)"},

+    { "-ck", 1, (void (*)(...)) pCk,	"Set compressed lookahead depth; fast approximate lookahead"},

+    { "-cr", 0, (void (*)(...)) pCr,	"Generate cross reference (default=FALSE)"},

+    { "-e1", 0, (void (*)(...)) pE1,	"Ambiguities/errors shown in low detail (default)"},

+    { "-e2", 0, (void (*)(...)) pE2,	"Ambiguities/errors shown in more detail"},

+    { "-e3", 0, (void (*)(...)) pE3,

+    	"Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},

+    { "-f",  1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */

+    { "-fe", 1, (void (*)(...)) pFe,	"Rename err.c"},

+    { "-fh", 1, (void (*)(...)) pFHdr,	"Rename stdpccts.h header (turns on -gh)"},

+    { "-fl", 1, (void (*)(...)) pFl,	"Rename lexical output--parser.dlg"},

+    { "-fm", 1, (void (*)(...)) pFm,	"Rename mode.h"},

+    { "-fr", 1, (void (*)(...)) pFr,	"Rename remap.h"},

+    { "-ft", 1, (void (*)(...)) pFt,	"Rename tokens.h"},

+    { "-ga", 0, (void (*)(...)) pANSI,	"Generate ANSI-compatible code (default=FALSE)"},

+    { "-gc", 0, (void (*)(...)) pCGen,	"Do not generate output parser code (default=FALSE)"},

+    { "-gd", 0, (void (*)(...)) pTGen,	"Generate code to trace rule invocation (default=FALSE)"},

+    { "-ge", 0, (void (*)(...)) pEGen,	"Generate an error class for each non-terminal (default=FALSE)"},

+    { "-gh", 0, (void (*)(...)) pGHdr,	"Generate stdpccts.h for non-ANTLR-generated-files to include"},

+    { "-gk", 0, (void (*)(...)) pDL,	"Generate parsers that delay lookahead fetches until needed"},

+    { "-gl", 0, (void (*)(...)) pLI,	"Generate line info about grammar actions in parser"},

+    { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},

+    { "-gp", 1, (void (*)(...)) pPre,	"Prefix all generated rule functions with a string"},

+    { "-gs", 0, (void (*)(...)) pSGen,	"Do not generate sets for token expression lists (default=FALSE)"},

+    { "-gt", 0, (void (*)(...)) pAst,	"Generate code for Abstract-Syntax-Trees (default=FALSE)"},

+    { "-gx", 0, (void (*)(...)) pLGen,	"Do not generate lexical (dlg-related) files (default=FALSE)"},

+    { "-gxt",0, (void (*)(...)) pXTGen,	"Do not generate tokens.h (default=FALSE)"},

+    { "-k",  1, (void (*)(...)) pLLK,	"Set full LL(k) lookahead depth (default==1)"},

+    { "-o",  1, (void (*)(...)) pOut,	OutputDirectoryOption},

+    { "-p",  0, (void (*)(...)) pPrt,	"Print out the grammar w/o actions (default=no)"},

+    { "-pa", 0, (void (*)(...)) pPrtA,	"Print out the grammar w/o actions & w/FIRST sets (default=no)"},

+    { "-pr",0, (void (*)(...)) pPred,	"no longer used; predicates employed if present"},

+    { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"},

+   	{ "-rl", 1, (void (*)(...)) pTRes,	"Limit max # of tree nodes used by grammar analysis"},

+    { "-stdout",0,  (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"},           /* MR6 */

+	{ "-tab", 1, (void (*)(...)) pTab,	"Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */

+	{ "-w1", 0, (void (*)(...)) pW1,	"Set the warning level to 1 (default)"},

+	{ "-w2", 0, (void (*)(...)) pW2,	"Ambiguities yield warnings even if predicates or (...)? block"},

+	{ "-",   0, (void (*)(...)) pStdin,	"Read grammar from stdin" },

+    { "-mrhoist",1, (void (*)(...)) pMRhoist,                                                  /* MR9 */

+                                        "Turn on/off k=1 Maintenance Release style hoisting"},  /* MR9 */

+    { "-mrhoistk",1, (void (*)(...)) pMRhoistk,                                                  /* MR9 */

+                                        "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"},  /* MR13 */

+    { "-aa"  , 1, (void (*)(...)) pAA,  "Ambiguity aid for a rule (rule name or line number)"},          /* MR11 */

+    { "-aam" , 0, (void (*)(...)) pAAm,

+                                         "Lookahead token may appear multiple times in -aa listing"},    /* MR11 */

+    { "-aad" , 1, (void (*)(...)) pAAd,

+                                         "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */

+	{ "-info", 1, (void (*)(...)) pInfo,

+      "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"},                          /* MR12 */

+    { "-treport",1,(void (*)(...)) pTreport,

+                        "Report when tnode usage exceeds value during ambiguity resolution"},            /* MR11 */

+	{ "-newAST", 0, (void (*)(...)) pNewAST,

+                 "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""},                        /* MR13 */

+	{ "-tmake", 0, (void (*)(...)) ptmakeInParser,

+                 "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""},			 /* MR23 */

+    { "-alpha",0,(void (*)(...)) pAlpha,

+                 "Provide additional information for \"(alpha)? beta\" error messages"},                 /* MR14 */

+    { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr,                                        /* MR21 */

+                 "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"},        /* MR21 */

+	{ "-nopurify",0,(void (*)(...)) pNOPURIFY,

+		"Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"},   /* MR23 */

+    { "*",   0, (void (*)(...)) pFile, 	"" },	/* anything else is a file */

+#else

+    { "-CC", 0, pCC,	"Generate C++ output (default=FALSE)"},

+    { "-cr", 0, pCr,	"Generate cross reference (default=FALSE)"},

+    { "-ck", 1, pCk,	"Set compressed lookahead depth; fast approximate lookahead"},

+    { "-e1", 0, pE1,	"Ambiguities/errors shown in low detail (default)"},

+    { "-e2", 0, pE2,	"Ambiguities/errors shown in more detail"},

+    { "-e3", 0, pE3,   	"Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},

+    { "-f",  1, pFileList,"Read names of grammar files from specified file"},   /* MR14 */

+    { "-fe", 1, pFe,	"Rename err.c"},

+    { "-fh", 1, pFHdr,	"Rename stdpccts.h header (turns on -gh)"},

+    { "-fl", 1, pFl,	"Rename lexical output--parser.dlg"},

+    { "-fm", 1, pFm,	"Rename mode.h"},

+    { "-fr", 1, pFr,	"Rename remap.h"},

+    { "-ft", 1, pFt,	"Rename tokens.h"},

+    { "-ga", 0, pANSI,	"Generate ANSI-compatible code (default=FALSE)"},

+    { "-gc", 0, pCGen,	"Do not generate output parser code (default=FALSE)"},

+    { "-gd", 0, pTGen,	"Generate code to trace rule invocation (default=FALSE)"},

+    { "-ge", 0, pEGen,	"Generate an error class for each non-terminal (default=FALSE)"},

+    { "-gh", 0, pGHdr,	"Generate stdpccts.h for non-ANTLR-generated-files to include"},

+    { "-gk", 0, pDL,	"Generate parsers that delay lookahead fetches until needed"},

+    { "-gl", 0, pLI,	"Generate line info about grammar actions in C parser"},

+    { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},

+    { "-gp", 1, pPre,	"Prefix all generated rule functions with a string"},

+    { "-gs", 0, pSGen,	"Do not generate sets for token expression lists (default=FALSE)"},

+    { "-gt", 0, pAst,	"Generate code for Abstract-Syntax-Trees (default=FALSE)"},

+    { "-gx", 0, pLGen,	"Do not generate lexical (dlg-related) files (default=FALSE)"},

+    { "-gxt",0, pXTGen,	"Do not generate tokens.h (default=FALSE)"},

+    { "-k",  1, pLLK,	"Set full LL(k) lookahead depth (default==1)"},

+    { "-o",  1, pOut,	OutputDirectoryOption},

+    { "-p",  0, pPrt,	"Print out the grammar w/o actions (default=no)"},

+    { "-pa", 0, pPrtA,	"Print out the grammar w/o actions & w/FIRST sets (default=no)"},

+    { "-pr",0, pPred,	"no longer used; predicates employed if present"},

+    { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"},

+    { "-rl", 1, pTRes,	"Limit max # of tree nodes used by grammar analysis"},

+    { "-stdout",0, pStdout,	"Send grammar.c/grammar.cpp to stdout"},               /* MR6 */

+    { "-tab", 1, pTab,	"Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */

+	{ "-w1", 0, pW1,	"Set the warning level to 1 (default)"},

+	{ "-w2", 0, pW2,	"Ambiguities yield warnings even if predicates or (...)? block"},

+    { "-mrhoist",1,pMRhoist,                                                       /* MR9 */

+                         "Turn on/off k=1 Maintenance Release style hoisting"},  /* MR9 */

+    { "-mrhoistk",1,pMRhoistk,                                                       /* MR13 */

+                         "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"},  /* MR13 */

+    { "-aa"  ,1,pAA,     "Ambiguity aid for a rule (rule name or line number)"},          /* MR11 */

+    { "-aam" ,0,pAAm,

+                         "Lookahead token may appear multiple times in -aa listing"},     /* MR11 */

+    { "-aad" ,1,pAAd,

+                         "Limits exp growth of -aa listing - default=1 (max=ck value)"},  /* MR11 */

+	{ "-info",1,pInfo,

+      "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"},           /* MR11 */

+    { "-treport",1,pTreport,

+                        "Report when tnode usage exceeds value during ambiguity resolution"},   /* MR11 */

+	{ "-newAST", 0, pNewAST,

+                 "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""},         /* MR13 */

+	{ "-tmake", 0, ptmakeInParser,

+                 "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""},   /* MR23 */

+    { "-alpha",0, pAlpha,

+                 "Provide additional information for \"(alpha)? beta\" error messages"},  /* MR14 */

+    { "-mrblkerr",0,pMR_BlkErr,                                                           /* MR21 */

+                 "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"},           /* MR21 */

+	{ "-nopurify",0,pNOPURIFY,

+		"Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"},   /* MR23 */

+	{ "-",   0, pStdin,	"Read grammar from stdin" },

+	{ "*",   0, pFile, 	"" },	/* anything else is a file */

+#endif

+	{ NULL,  0, NULL }

+ };

+

+void readDescr();

+void cleanUp();

+

+#ifdef __USE_PROTOS

+static void buildRulePtr( void );

+static void help( void );

+static void init( void );

+static void CompleteTokenSetRefs( void );

+static void ensure_no_C_file_collisions(char *);

+static void CompleteContextGuards(void);

+#else

+static void buildRulePtr( );

+static void help( );

+static void init( );

+static void CompleteTokenSetRefs( );

+static void ensure_no_C_file_collisions();

+static void CompleteContextGuards();

+#endif

+

+static void

+#ifdef __USE_PROTOS  /* <BJS> */

+report_numericPredLabels(ActionNode *a)

+#else

+report_numericPredLabels(a)

+ActionNode *a;

+#endif

+{                                                                           /* MR10 */

+  warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode",  /* MR10 */

+            FileStr[a->file],a->line);                                      /* MR10 */

+}                                                                           /* MR10 */

+

+								/* M a i n */

+

+int

+#ifdef __USE_PROTOS

+main( int argc, char *argv[] )

+#else

+main( argc, argv )

+int argc;

+char *argv[];

+#endif

+{

+	int i;

+	static char EPSTR[] = "[Ep]";

+

+    Save_argc=argc;                                                  /* MR10 */

+    Save_argv=argv;                                                  /* MR10 */

+

+/*	malloc_debug(8);*/

+

+#ifdef SPECIAL_INITS

+    special_inits();                                                 /* MR1 */

+#endif

+	fprintf(stderr, "Antlr parser generator   Version %s   1989-2001\n", Version);

+	if ( argc == 1 ) { help(); zzDIE; }

+	ProcessArgs(argc-1, &(argv[1]), options);

+

+/* MR14 */    if (MR_AmbAidRule && AlphaBetaTrace) {

+/* MR14 */       fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)");

+/* MR14 */    }

+

+    if (MRhoistingk) {              /* MR13 */

+      HoistPredicateContext=1;      /* MR13 */

+      MRhoisting=1;                 /* MR13 */

+    };                              /* MR13 */

+    if (MRhoisting && ! HoistPredicateContext) {

+/***      warnNoFL("Using \"-mrhoist\" forces \"-prc on\"");    ***/

+      HoistPredicateContext=1;

+    };

+    if (HoistPredicateContext && ! MRhoisting) {

+        warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended");

+    }

+	/* Fix lookahead depth */

+	/* Compressed lookahead must always be larger than or equal to full lookahead */

+	if ( CLL_k < LL_k  && CLL_k>0 )

+	{

+		warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)");

+		CLL_k = LL_k;

+	}

+	if ( CLL_k == -1 ) CLL_k = LL_k;

+	OutputLL_k = CLL_k;

+	if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */

+		int n;

+		for(n=1; n<CLL_k; n<<=1) {;}

+		OutputLL_k = n;

+	};

+

+	if (MR_BlkErr) {

+		warnNoFL("The -mrblkerr option is EXPERIMENTAL");

+        if (LL_k > 1) {

+    		warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars");

+        }

+	};

+

+    if ( ! ambAidDepthSpecified) {

+      MR_AmbAidDepth=1;

+    } else {

+      if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) {

+        warnNoFL(eMsgd(

+            "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k));

+        MR_AmbAidDepth=1;

+      };

+      if (MR_AmbAidDepth == 0) {

+        MR_AmbAidDepth=2;

+      };

+    };

+

+    if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule);

+

+	fpTrans = &(C_Trans[0]);		/* Translate to C Language */

+	fpJTrans = &(C_JTrans[0]);

+	init();

+	lexclass(LexStartSymbol);

+

+	readDescr();

+	LastTokenCounted = TokenNum;

+	RemapForcedTokens();

+	if ( CannotContinue ) {cleanUp(); zzDIE;}

+	if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)");

+	if ( WarningLevel>1 && HdrAction == NULL )

+	   warnNoFL("no #header action was found");

+	if ( FoundAtOperator && ! FoundExceptionGroup) {

+	   warnNoFL("found the exception operator '@' - but no exception group was found");

+	};

+	EpToken = addTname(EPSTR);		/* add imaginary token epsilon */

+	set_orel(EpToken, &imag_tokens);

+

+	/* this won't work for hand-built scanners since EofToken is not

+	 * known.  Forces EOF to be token type 1.

+	 */

+	set_orel(EofToken, &imag_tokens);

+

+	set_size(NumWords(TokenNum-1));

+

+	/* compute the set of all known token types

+	 * It represents the set of tokens from 1 to last_token_num + the

+	 * reserved positions above that (if any).  Don't include the set of

+	 * imaginary tokens such as the token/error classes or EOF.

+	 */

+	{

+		set a;

+		a = set_dup(reserved_positions);

+		for (i=1; i<TokenNum; i++) { set_orel(i, &a); }

+		all_tokens = set_dif(a, imag_tokens);

+		set_free(a);

+	}

+

+	ComputeTokSets();				/* Compute #tokclass sets */

+	CompleteTokenSetRefs();			/* Change complex nodes in syn diag */

+    CompleteContextGuards();        /* MR13 */

+

+	if ( CodeGen ) genDefFile();	/* create tokens.h */

+	if ( LexGen ) genLexDescr();	/* create parser.dlg */

+

+	if ( GenStdPccts )

+	{

+		FILE *f = fopen(OutMetaName(stdpccts), "w");

+		if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );}

+		else

+		{

+#ifdef SPECIAL_FOPEN

+			special_fopen_actions(OutMetaName(stdpccts));            /* MR1 */

+#endif

+            if (strcmp(stdpccts,"stdpccts.h") == 0) {                /* MR10 */

+ 	  	      genStdPCCTSIncludeFile(f,NULL);                        /* MR10 */

+            } else {                                                 /* MR10 */

+ 	  	      genStdPCCTSIncludeFile(f,pcctsBaseName(stdpccts));     /* MR32 */

+            };

+			fclose(f);

+		}

+	}

+

+	buildRulePtr();					/* create mapping from rule # to RuleBlk junction */

+	ComputeErrorSets();

+	FoLink( (Node *)SynDiag );		/* add follow links to end of all rules */

+	

+	if ( GenCR ) GenCrossRef( SynDiag );

+

+	if ( CodeGen )

+	{

+		if ( SynDiag == NULL )

+		{

+			warnNoFL("no grammar description recognized");

+			cleanUp();

+			zzDIE;

+		}

+		else if ( !GenCC ) {

+			ErrFile = fopen(OutMetaName(ErrFileName), "w");

+			require(ErrFile != NULL, "main: can't open err file");

+#ifdef SPECIAL_FOPEN

+	              special_fopen_actions(OutMetaName(ErrFileName));   /* MR1 */

+#endif

+			NewSetWd();

+			GenErrHdr();

+			TRANS(SynDiag);			/* Translate to the target language */

+			DumpSetWd();

+			DumpRemainingTokSets();

+			fclose( ErrFile );

+		}

+		else {

+			strcpy(Parser_h_Name, CurrentClassName);

+			strcat(Parser_h_Name, ".h");

+			strcpy(Parser_c_Name, CurrentClassName);

+			strcat(Parser_c_Name, CPP_FILE_SUFFIX);

+			ensure_no_C_file_collisions(Parser_c_Name);

+			Parser_h = fopen(OutMetaName(Parser_h_Name), "w");

+			require(Parser_h != NULL, "main: can't open class Parserx.h file");

+#ifdef SPECIAL_FOPEN

+		    special_fopen_actions(OutMetaName(Parser_h_Name));       /* MR1 */

+#endif

+			Parser_c = fopen(OutMetaName(Parser_c_Name), "w");

+			require(Parser_c != NULL, "main: can't open class Parserx.c file");

+#ifdef SPECIAL_FOPEN

+		    special_fopen_actions(OutMetaName(Parser_c_Name));       /* MR1 */

+#endif

+			GenParser_h_Hdr();

+			if ( class_before_actions != NULL )

+			{

+				ListNode *p;

+				for (p = class_before_actions->next; p!=NULL; p=p->next)

+				{

+					UserAction *ua = (UserAction *)p->elem;

+					dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);

+				}

+			}

+			GenParser_c_Hdr();

+			fprintf(Parser_h, "protected:\n");  /* MR20 */

+			NewSetWd();

+			TRANS(SynDiag);			/* Translate to the target language */

+			DumpSetWd();

+			GenRuleMemberDeclarationsForCC(Parser_h, SynDiag);

+			if ( class_after_actions != NULL )

+			{

+				ListNode *p;

+				for (p = class_after_actions->next; p!=NULL; p=p->next)

+				{

+					UserAction *ua = (UserAction *)p->elem;

+					dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);

+				}

+			}

+			DumpRemainingTokSets();

+			fprintf(Parser_h, "};\n");

+			fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName);

+			fclose( Parser_h );

+			fclose( Parser_c );

+		}

+	}

+

+    MR_orphanRules(stderr);

+    if (LTinTokenAction && WarningLevel >= 2) {

+		if (GenCC) {

+			warnNoFL("At least one <<action>> following a token match contains a reference to LT(...)\n      this will reference the immediately preceding token,\n      not the one which follows as is the case with semantic predicates.");

+		}

+			warnNoFL("At least one <<action>> following a token match contains a reference to LA(...) or LATEXT(...)\n      this will reference the immediately preceding token,\n      not the one which follows as is the case with semantic predicates.");

+	}

+

+	if ( PrintOut )

+	{

+		if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");}

+		else PRINT(SynDiag);

+	}

+

+#ifdef DBG_LL1

+#endif

+	GenRemapFile();					/* create remap.h */

+/* MR10 */    if (FoundGuessBlk) {

+#ifdef __cplusplus__

+/* MR10 */      list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);

+#else

+#ifdef __USE_PROTOS

+/* MR10 */      list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);

+#else

+/* MR10 */      list_apply(NumericPredLabels,report_numericPredLabels);

+#endif

+#endif

+/* MR10 */    };

+

+    if (InfoT && TnodesAllocated > 0) {

+      if (TnodesPeak > 10000) {

+        fprintf(stdout,"\nTree Nodes:  peak %dk  created %dk  lost %d\n",

+                        (TnodesPeak/1000),

+                        (TnodesAllocated/1000),

+                        TnodesInUse-tnodes_used_in_guard_predicates_etc);

+       } else {

+         fprintf(stdout,"\nTree Nodes:  peak %d  created %d  lost %d\n",

+                        TnodesPeak,

+                        TnodesAllocated,

+                        TnodesInUse-tnodes_used_in_guard_predicates_etc);

+       };

+    };

+    if (InfoF) {

+      DumpFcache();

+    };

+    if (MR_skipped_e3_report) {

+      fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n");

+    };

+    if (MR_BadExprSets != 0) {

+      fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n");

+      fprintf(stderr,"        probably due to undefined rules or infinite left recursion.\n");

+      fprintf(stderr,"      To locate: search the generated code for \"empty set expression\"\n");

+    };

+    if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) {

+      RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule);

+      if (MR_AmbAidLine == 0 && q == NULL) {

+         warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match",

+                                                        MR_AmbAidRule,MR_AmbAidRule));

+      } else {

+        warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule));

+      };

+    };

+    if (AlphaBetaTrace) {

+

+      if (MR_AlphaBetaMessageCount == 0) {

+         fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n");

+      } else {

+         fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n",

+                    MR_AlphaBetaMessageCount);

+      }

+

+      if (set_null(MR_CompromisedRules)) {

+         fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n");

+      } else {

+         fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n");

+         fprintf(stderr,"      follow sets computed as a result of an \"(alpha)? beta\" block\n");

+         fprintf(stderr,"\n");

+         MR_dumpRuleSet(MR_CompromisedRules);

+         fprintf(stderr,"\n");

+      }

+    }

+	cleanUp();

+	exit(PCCTS_EXIT_SUCCESS);

+    return 0;           /* MR11 make compilers happy */ 

+}

+

+static void 

+#ifdef __USE_PROTOS 

+init( void )

+#else

+init( )

+#endif

+{

+	SignalEntry *q;

+

+	Tname = newHashTable();

+	Rname = newHashTable();

+	Fcache = newHashTable();

+	Tcache = newHashTable();

+	Sname = newHashTable();

+    Pname = newHashTable();     /* MR11 */

+

+	/* Add default signal names */

+	q = (SignalEntry *)hash_add(Sname,

+							  "NoViableAlt",

+							  (Entry *)newSignalEntry("NoViableAlt"));

+	require(q!=NULL, "cannot alloc signal entry");

+	q->signum = sigNoViableAlt;

+	q = (SignalEntry *)hash_add(Sname,

+							  "MismatchedToken",

+							  (Entry *)newSignalEntry("MismatchedToken"));

+	require(q!=NULL, "cannot alloc signal entry");

+	q->signum = sigMismatchedToken;

+	q = (SignalEntry *)hash_add(Sname,

+							  "NoSemViableAlt",

+							  (Entry *)newSignalEntry("NoSemViableAlt"));

+	require(q!=NULL, "cannot alloc signal entry");

+	q->signum = sigNoSemViableAlt;

+	

+	reserved_positions = empty;

+	all_tokens = empty;

+	imag_tokens = empty;

+	tokclasses = empty;

+	TokenStr = (char **) calloc(TSChunk, sizeof(char *));

+	require(TokenStr!=NULL, "main: cannot allocate TokenStr");

+	FoStack = (int **) calloc(CLL_k+1, sizeof(int *));

+	require(FoStack!=NULL, "main: cannot allocate FoStack");

+	FoTOS = (int **) calloc(CLL_k+1, sizeof(int *));

+	require(FoTOS!=NULL, "main: cannot allocate FoTOS");

+	Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *));

+	require(Cycles!=NULL, "main: cannot allocate Cycles List");

+    MR_CompromisedRules=empty;  /* MR14 */

+}

+

+static void

+#ifdef __USE_PROTOS

+help( void )

+#else

+help( )

+#endif

+{

+	Opt *p = options;

+	fprintf(stderr, "antlr [options] f1 f2 ... fn\n");

+	while ( *(p->option) != '*' )

+	{

+		fprintf(stderr, "    %-9s%s   %s\n",

+						p->option,

+						(p->arg)?"___":"   ",

+						p->descr);

+		p++;

+	}

+}

+

+/* The RulePtr array is filled in here.  RulePtr exists primarily

+ * so that sets of rules can be maintained for the FOLLOW caching

+ * mechanism found in rJunc().  RulePtr maps a rule num from 1 to n

+ * to a pointer to its RuleBlk junction where n is the number of rules.

+ */

+static void

+#ifdef __USE_PROTOS

+buildRulePtr( void )

+#else

+buildRulePtr( )

+#endif

+{

+	int r=1;

+	Junction *p  = SynDiag;

+	RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *));

+	require(RulePtr!=NULL, "cannot allocate RulePtr array");

+	

+	while ( p!=NULL )

+	{

+		require(r<=NumRules, "too many rules???");

+		RulePtr[r++] = p;

+		p = (Junction *)p->p2;

+	}

+}

+

+void

+#ifdef __USE_PROTOS

+dlgerror(const char *s)

+#else

+dlgerror(s)

+char *s;

+#endif

+{

+	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);

+	fprintf(stderr, " lexical error: %s (text was '%s')\n",

+					((s == NULL) ? "Lexical error" : s), zzlextext);

+}

+

+void

+#ifdef __USE_PROTOS

+readDescr( void )

+#else

+readDescr( )

+#endif

+{

+	zzerr = dlgerror;

+	input = NextFile();

+	if ( input==NULL ) fatal("No grammar description found (exiting...)");

+	ANTLR(grammar(), input);

+    tnodes_used_in_guard_predicates_etc=TnodesInUse;    /* MR10 */

+}

+

+FILE *

+#ifdef __USE_PROTOS

+NextFile( void )

+#else

+NextFile( )

+#endif

+{

+	FILE *f;

+

+	for (;;)

+	{

+		CurFile++;

+		if ( CurFile >= NumFiles ) return(NULL);

+		if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin;

+		f = fopen(FileStr[CurFile], "r");

+		if ( f == NULL )

+		{

+			warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );

+		}

+		else

+		{

+			return(f);

+		}

+	}

+}

+

+/*

+ * Return a string corresponding to the output file name associated

+ * with the input file name passed in.

+ *

+ * Observe the following rules:

+ *

+ *		f.e		--> f".c"

+ *		f		--> f".c"

+ *		f.		--> f".c"

+ *		f.e.g	--> f.e".c"

+ *

+ * Where f,e,g are arbitrarily long sequences of characters in a file

+ * name.

+ *

+ * In other words, if a ".x" appears on the end of a file name, make it

+ * ".c".  If no ".x" appears, append ".c" to the end of the file name.

+ *

+ * C++ mode using .cpp not .c.

+ *

+ * Use malloc() for new string.

+ */

+

+char *

+#ifdef __USE_PROTOS

+outname( char *fs )

+#else

+outname( fs )

+char *fs;

+#endif

+{

+    if ( GenCC) {

+      return outnameX(fs,CPP_FILE_SUFFIX);

+    } else {

+      return outnameX(fs,".c");

+    };

+}

+

+char *

+#ifdef __USE_PROTOS

+outnameX( char *fs ,char *suffix)

+#else

+outnameX( fs , suffix )

+char *fs;

+char *suffix;

+#endif

+{

+	static char buf[MaxFileName+1];

+	char *p;

+	require(fs!=NULL&&*fs!='\0', "outname: NULL filename");

+

+	p = buf;

+	strcpy(buf, fs);

+	while ( *p != '\0' )  {p++;}			/* Stop on '\0' */

+	while ( *p != '.' && p != buf ) {--p;}	/* Find '.' */

+	if ( p != buf ) *p = '\0';				/* Found '.' */

+	require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big");

+    strcat(buf,suffix);

+	return( buf );

+}

+

+void

+#ifdef __USE_PROTOS

+fatalFL( char *err_, char *f, int l )

+#else

+fatalFL( err_, f, l )

+char *err_;

+char *f;

+int l;

+#endif

+{

+	fprintf(stderr, ErrHdr, f, l);

+	fprintf(stderr,	" %s\n", err_);

+	cleanUp();

+	exit(PCCTS_EXIT_FAILURE);

+}

+

+void

+#ifdef __USE_PROTOS

+fatal_intern( char *err_, char *f, int l )

+#else

+fatal_intern( err_, f, l )

+char *err_;

+char *f;

+int l;

+#endif

+{

+	fprintf(stderr, ErrHdr, f, l);

+	fprintf(stderr,	" #$%%*&@# internal error: %s\n", err_);

+	fprintf(stderr, ErrHdr, f, l);

+	fprintf(stderr, " [complain to nearest government official\n");

+	fprintf(stderr, ErrHdr, f, l);

+	fprintf(stderr, "  or send hate-mail to parrt@parr-research.com;\n");

+	fprintf(stderr, ErrHdr, f, l);

+	fprintf(stderr, "  please pray to the ``bug'' gods that there is a trival fix.]\n");

+	cleanUp();

+	exit(PCCTS_EXIT_FAILURE);

+}

+

+void

+#ifdef __USE_PROTOS

+cleanUp( void )

+#else

+cleanUp( )

+#endif

+{

+	if ( DefFile != NULL) fclose( DefFile );

+}

+

+/* sprintf up to 3 strings */

+char *

+#ifdef __USE_PROTOS

+eMsg3( char *s, char *a1, char *a2, char *a3 )

+#else

+eMsg3( s, a1, a2, a3 )

+char *s;

+char *a1;

+char *a2;

+char *a3;

+#endif

+{

+	static char buf[250];			/* DANGEROUS as hell !!!!!! */

+	

+	sprintf(buf, s, a1, a2, a3);

+	return( buf );

+}

+

+/* sprintf a decimal */

+char *

+#ifdef __USE_PROTOS

+eMsgd( char *s, int d )

+#else

+eMsgd( s, d )

+char *s;

+int d;

+#endif

+{

+	static char buf[250];			/* DANGEROUS as hell !!!!!! */

+	

+	sprintf(buf, s, d);

+	return( buf );

+}

+

+char *

+#ifdef __USE_PROTOS

+eMsgd2( char *s, int d1,int d2)

+#else

+eMsgd2( s, d1, d2 )

+char *s;

+int d1;

+int d2;

+#endif

+{

+	static char buf[250];			/* DANGEROUS as hell !!!!!! */

+	

+	sprintf(buf, s, d1, d2);

+	return( buf );

+}

+

+void

+#ifdef __USE_PROTOS

+s_fprT( FILE *f, set e )

+#else

+s_fprT( f, e )

+FILE *f;

+set e;

+#endif

+{

+	register unsigned *p;

+	unsigned *q;

+

+	if ( set_nil(e) ) return;

+	if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq");

+	fprintf(f, "{");

+	while ( *p != nil )

+	{

+		fprintf(f, " %s", TerminalString(*p));

+		p++;

+	}

+	fprintf(f, " }");

+	free((char *)q);

+}

+

+/* Return the token name or regular expression for a token number. */

+char *

+#ifdef __USE_PROTOS

+TerminalString( int token )

+#else

+TerminalString( token )

+int token;

+#endif

+{

+	int     j;

+        static    char    imag_name[20];

+

+	/* look in all lexclasses for the token */

+	if ( TokenString(token) != NULL ) return TokenString(token);

+	for (j=0; j<NumLexClasses; j++)

+	{

+		lexmode(j);

+		if ( ExprString(token) != NULL ) return ExprString(token);

+	}

+

+    if (1) {

+      sprintf(imag_name,"UnknownToken#%d",token);           /* MR13 */

+      return imag_name;                                     /* MR13 */

+    }

+

+	require(j<NumLexClasses, eMsgd("No label or expr for token %d",token));

+	return "invalid";

+}

+

+                    /* S i m p l e  I n t  S t a c k */

+

+void

+#ifdef __USE_PROTOS

+pushint( int i )

+#else

+pushint( i )

+int i;

+#endif

+{

+	require(isp>0, "pushint: stack overflow");

+	istack[--isp] = i;

+}

+

+int

+#ifdef __USE_PROTOS

+popint( void )

+#else

+popint( )

+#endif

+{

+	require(isp<MAX_INT_STACK, "popint: stack underflow");

+	return istack[isp++];

+}

+

+int

+#ifdef __USE_PROTOS

+istacksize( void )

+#else

+istacksize( )

+#endif

+{

+	return MAX_INT_STACK-isp;

+}

+

+void

+#ifdef __USE_PROTOS

+istackreset( void )

+#else

+istackreset( )

+#endif

+{

+	isp = MAX_INT_STACK;

+}

+

+int

+#ifdef __USE_PROTOS

+istackempty( void )

+#else

+istackempty( )

+#endif

+{

+	return isp==MAX_INT_STACK;

+}

+

+int

+#ifdef __USE_PROTOS

+topint( void )

+#else

+topint( )

+#endif

+{

+	require(isp<MAX_INT_STACK, "topint: stack underflow");

+	return istack[isp];

+}

+

+void

+#ifdef __USE_PROTOS

+ProcessArgs( int argc, char **argv, Opt *options )

+#else

+ProcessArgs( argc, argv, options )

+int argc;

+char **argv;

+Opt *options;

+#endif

+{

+	Opt *p;

+	require(argv!=NULL, "ProcessArgs: command line NULL");

+

+	while ( argc-- > 0 )

+	{

+		p = options;

+		while ( p->option != NULL )

+		{

+			if ( strcmp(p->option, "*") == 0 ||

+				 ci_strequ(p->option, *argv) == 1 )

+			{

+				if ( p->arg )

+				{

+/* MR9  26-Sep-97   Check for argv valid                */

+                    if (argc-- > 0) {

+  				     	(*p->process)( *argv, *(argv+1) );

+					    argv++;

+                    } else {

+fprintf(stderr,"error: required argument for option %s omitted\n",*argv);

+exit(PCCTS_EXIT_FAILURE);

+                    };

+				}

+				else

+					(*p->process)( *argv );

+				break;

+			}

+			p++;

+		}

+		argv++;

+	}

+}

+

+static void 

+#ifdef __USE_PROTOS

+CompleteContextGuards(void)

+#else

+CompleteContextGuards()

+#endif

+{

+    ListNode *      p;

+    Predicate *     pred;

+

+    if (ContextGuardPredicateList == NULL) return;

+

+    for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) {

+      pred=(Predicate *)p->elem;

+      recomputeContextGuard(pred);

+    }

+}

+

+/* Go back into the syntax diagram and compute all meta tokens; i.e.

+ * turn all '.', ranges, token class refs etc... into actual token sets

+ */

+static void

+#ifdef __USE_PROTOS

+CompleteTokenSetRefs(void)

+#else

+CompleteTokenSetRefs()

+#endif

+{

+	ListNode *p;

+

+	if ( MetaTokenNodes==NULL ) return;

+	for (p = MetaTokenNodes->next; p!=NULL; p=p->next)

+	{

+		set a,b;

+

+		TokNode *q = (TokNode *)p->elem;

+		if ( q->wild_card )

+		{

+			q->tset = all_tokens;

+		}

+		else if ( q->tclass!=NULL )

+		{

+			if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset);

+			else q->tset = q->tclass->tset;

+		}

+		else if ( q->upper_range!=0 )

+		{

+			/* we have a range on our hands: make a set from q->token .. q->upper_range */

+			int i;

+			a = empty;

+			for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); }   /* MR13 */

+

+/* MR13 */    if (q->complement) {

+/* MR13 */      q->tset = set_dif(all_tokens, a);

+/* MR13 */        set_free(a);

+/* MR13 */      } else {

+/* MR13 */	      q->tset = a;

+/* MR13 */      }

+

+        }

+

+		/* at this point, it can only be a complemented single token */

+		else if ( q->complement )

+		{

+			a = set_of(q->token);

+			b = set_dif(all_tokens, a);

+			set_free(a);

+			q->tset=b;

+		}

+		else fatal("invalid meta token");

+	}

+}

+

+/* MR10: Jeff Vincent

+   MR10: Changed to remove directory information from n only if

+   MR10: if OutputDirectory was changed by user (-o option)

+*/

+

+char *

+#ifdef __USE_PROTOS

+OutMetaName(char *n)

+#else

+OutMetaName(n)

+char *n;

+#endif

+{	

+    static char *dir_sym = DirectorySymbol;

+    static char newname[MaxFileName+1];

+    char *p;

+

+	/* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */

+    if (strcmp(OutputDirectory, TopDirectory) == 0)		/* TopDirectory is "." on Unix. */

+		return n;

+

+	/* p will point to filename without path information */

+	if ((p = strrchr(n, *dir_sym)) != NULL)				/* Directory symbol is "/" on Unix. */

+		p++;

+	else

+		p = n;

+

+	/* Copy new output directory into newname[] */

+	strcpy(newname, OutputDirectory);

+

+	/* if new output directory does not have trailing dir_sym, add it! */

+	if (newname[strlen(newname)-1] != *dir_sym) {

+		strcat(newname, dir_sym);

+	}

+	strcat(newname, p);

+	return newname;

+}

+

+char *

+#ifdef __USE_PROTOS

+pcctsBaseName(char *n) /* MR32 */

+#else

+pcctsBaseName(n)

+char *n;

+#endif

+{

+    static char newname[MaxFileName+1];

+    static char* dir_sym = DirectorySymbol;

+    int count = 0;

+    char *p;

+

+    p = n;

+

+    while ( *p != '\0' )  {p++;}                    /* go to end of string */

+    while ( (*p != *dir_sym) && (p != n) ) {--p;}   /* Find last DirectorySymbol */

+    while ( *p == *dir_sym) p++;                    /* step forward if we're on a dir symbol */

+    while ( *p != '\0' && *p != '.')

+    {

+        newname[count++] = *p;

+        p++;

+    }                                               /* create a new name */

+    newname[count] = '\0';

+    return newname;

+}

+

+static void

+#ifdef __USE_PROTOS

+ensure_no_C_file_collisions(char *class_c_file)

+#else

+ensure_no_C_file_collisions(class_c_file)

+char *class_c_file;

+#endif

+{

+	int i;

+

+	for (i=0; i<NumFiles; i++)

+	{

+

+#ifdef PCCTS_CASE_INSENSITIVE_FILE_NAME

+		/* assume that file names are case insensitive */

+		if ( STRICMP(outname(FileStr[i]), class_c_file)==0 )

+#else

+		if ( strcmp(outname(FileStr[i]), class_c_file)==0 )

+#endif

+		{

+			fatal(eMsg1("class def output file conflicts with parser output file: %s",

+						outname(FileStr[i])));

+		}

+	}

+}

+

+void

+#ifdef __USE_PROTOS

+warnNoFL(char *err)

+#else

+warnNoFL(err)

+char *err;

+#endif

+{

+	fprintf(stderr, "warning: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+warnFL(char *err,char *f,int l)

+#else

+warnFL(err,f,l)

+char *f;

+int l;

+char *err;

+#endif

+{

+	fprintf(stderr, ErrHdr, f, l);						

+	fprintf(stderr, " warning: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+warn(char *err)												

+#else

+warn(err)												

+char *err;

+#endif

+{

+	/* back up the file number if we hit an error at the end of the last file */

+	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;

+	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);

+	fprintf(stderr, " warning: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+warnNoCR( char *err )

+#else

+warnNoCR( err )											

+char *err;

+#endif

+{

+	/* back up the file number if we hit an error at the end of the last file */

+	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;

+	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);

+	fprintf(stderr, " warning: %s", err);

+}

+

+void

+#ifdef __USE_PROTOS

+errNoFL(char *err)

+#else

+errNoFL(err)

+char *err;

+#endif

+{

+	fprintf(stderr, "error: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+errFL(char *err,char *f,int l)

+#else

+errFL(err,f,l)

+char *err;

+char *f;

+int l;

+#endif

+{

+	fprintf(stderr, ErrHdr, f, l);						

+	fprintf(stderr, " error: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+err(char *err)												

+#else

+err(err)												

+char *err;

+#endif

+{

+	/* back up the file number if we hit an error at the end of the last file */

+	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;

+	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);

+	fprintf(stderr, " error: %s\n", err);

+}

+

+void

+#ifdef __USE_PROTOS

+errNoCR( char *err )											

+#else

+errNoCR( err )											

+char *err;

+#endif

+{

+	/* back up the file number if we hit an error at the end of the last file */

+	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;

+	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);

+	fprintf(stderr, " error: %s", err);

+}

+

+UserAction *

+#ifdef __USE_PROTOS

+newUserAction(char *s)

+#else

+newUserAction(s)

+char *s;

+#endif

+{

+	UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction));

+	require(ua!=NULL, "cannot allocate UserAction");

+

+	ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));

+	strcpy(ua->action, s);

+	return ua;

+}

+

+/* Added by TJP September 1994 */

+/* Take in file.h and return file_h; names w/o '.'s are left alone */

+char *

+#ifdef __USE_PROTOS

+gate_symbol(char *name)

+#else

+gate_symbol(name)

+char *name;

+#endif

+{

+	static char buf[100];

+	char *p;

+	sprintf(buf, "%s", name);

+

+	for (p=buf; *p!='\0'; p++)

+	{

+		if ( *p=='.' ) *p = '_';

+	}

+	return buf;

+}

+

+char *

+#ifdef __USE_PROTOS

+makeAltID(int blockid, int altnum)

+#else

+makeAltID(blockid, altnum)

+int blockid;

+int altnum;

+#endif

+{

+	static char buf[100];

+	char *p;

+	sprintf(buf, "_blk%d_alt%d", blockid, altnum);

+	p = (char *)malloc(strlen(buf)+1);

+	strcpy(p, buf);

+	return p;

+}

diff --git a/Source/Pccts/antlr/makefile b/Source/Pccts/antlr/makefile
new file mode 100644
index 0000000..2aa6cdf
--- /dev/null
+++ b/Source/Pccts/antlr/makefile
@@ -0,0 +1,218 @@
+#

+# Makefile for ANTLR 1.33

+#

+# SOFTWARE RIGHTS

+#

+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+# Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+# company may do whatever they wish with source code distributed with

+# PCCTS or the code generated by PCCTS, including the incorporation of

+# PCCTS, or its output, into commerical software.

+# 

+# We encourage users to develop software with PCCTS.  However, we do ask

+# that credit is given to us for developing PCCTS.  By "credit",

+# we mean that if you incorporate our source code into one of your

+# programs (commercial product, research project, or otherwise) that you

+# acknowledge this fact somewhere in the documentation, research report,

+# etc...  If you like PCCTS and have developed a nice tool with the

+# output, please mention that you developed it using PCCTS.  In

+# addition, we ask that this header remain intact in our source code.

+# As long as these guidelines are kept, we expect to continue enhancing

+# this system and expect to make other tools available as they are

+# completed.

+#

+# ANTLR 1.33

+# Terence Parr

+# Parr Research Corporation

+# with Purdue University

+# and AHPCRC, University of Minnesota

+# 1989-1995

+#

+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+##

+## Uncomment the appropriate section to build

+## (both targets and 'make' variable definitions)

+## Note that UNIX is the default

+##

+

+#

+#   OS/2 & DOS 16 bit using MSC 6.0

+#

+#CC=cl

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=/NOD:LLIBCE LLIBCEP

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egamn.obj

+#       link @<<

+#$** /NOI

+#$@ /STACK:14336

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        bind $@ c:\os2\doscalls.lib

+#        copy *.exe ..\bin

+#

+

+#

+#   Borland C++ for DOS

+#

+#CC=bcc

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= emu mathl cl

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#       tlink @&&|

+#C0L $**

+#$@ /Tde /c

+#

+#$(LIBS)

+#$(DEF_FILE) $(LFLAGS) ;

+#|

+#        copy *.exe ..\bin

+#

+

+#

+# C-Set/2 for OS/2

+#

+#CC=icc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__

+#OUT_OBJ = -Fo

+#LIBS=

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#        link386 @<<

+#$** /NOI

+#$@ /STACK:32768

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        copy *.exe ..\bin

+#

+

+#

+# Borland C++ for OS/2

+#

+#CC=bcc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= c2 os2

+#

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#        tlink @&&|

+#c02 $** -c -v

+#antlr.exe

+#

+#C2 os2

+#

+#|

+#        copy *.exe ..\bin

+#

+

+# *********** Target list of PC machines ***********

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+#	$(ANTLR) antlr.g

+#

+#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h

+#

+#scan.$(OBJ_EXT): scan.c mode.h tokens.h

+#

+#scan.c mode.h: parser.dlg

+#	$(DLG) -C2 parser.dlg scan.c

+#

+#set.$(OBJ_EXT): $(SET)/set.c

+#	$(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c

+

+

+

+#

+#   UNIX  (default)

+#

+CC=gcc

+COPT=-O

+ANTLR=${BIN_DIR}/antlr

+DLG=${BIN_DIR}/dlg

+OBJ_EXT=o

+OUT_OBJ = -o

+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536

+#

+# SGI Users, use this CFLAGS

+#

+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262

+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o  \

+        globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o

+

+antlr : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o $(BIN_DIR)/antlr $(OBJ)

+

+# what files does PCCTS generate (both ANTLR and DLG)

+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h

+

+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \

+	hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c

+

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+#	$(ANTLR) -gh antlr.g

+

+antlr.o : antlr.c mode.h tokens.h

+

+scan.o : scan.c mode.h tokens.h

+

+#scan.c mode.h: parser.dlg

+#	$(DLG) -C2 parser.dlg scan.c

+

+set.o : $(SET)/set.c

+	$(CC) $(CFLAGS) -c -o set.o $(SET)/set.c

+

+

+#

+# ****** These next targets are common to UNIX and PC world ********

+#

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

+

+#remove everything in clean plus the PCCTS files generated

+scrub:

+	rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core

diff --git a/Source/Pccts/antlr/makefile.cygwin b/Source/Pccts/antlr/makefile.cygwin
new file mode 100644
index 0000000..956de0b
--- /dev/null
+++ b/Source/Pccts/antlr/makefile.cygwin
@@ -0,0 +1,219 @@
+#

+# Makefile for ANTLR 1.33

+#

+# SOFTWARE RIGHTS

+#

+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+# Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+# company may do whatever they wish with source code distributed with

+# PCCTS or the code generated by PCCTS, including the incorporation of

+# PCCTS, or its output, into commerical software.

+# 

+# We encourage users to develop software with PCCTS.  However, we do ask

+# that credit is given to us for developing PCCTS.  By "credit",

+# we mean that if you incorporate our source code into one of your

+# programs (commercial product, research project, or otherwise) that you

+# acknowledge this fact somewhere in the documentation, research report,

+# etc...  If you like PCCTS and have developed a nice tool with the

+# output, please mention that you developed it using PCCTS.  In

+# addition, we ask that this header remain intact in our source code.

+# As long as these guidelines are kept, we expect to continue enhancing

+# this system and expect to make other tools available as they are

+# completed.

+#

+# ANTLR 1.33

+# Terence Parr

+# Parr Research Corporation

+# with Purdue University

+# and AHPCRC, University of Minnesota

+# 1989-1995

+#

+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+##

+## Uncomment the appropriate section to build

+## (both targets and 'make' variable definitions)

+## Note that UNIX is the default

+##

+

+#

+#   OS/2 & DOS 16 bit using MSC 6.0

+#

+#CC=cl

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=/NOD:LLIBCE LLIBCEP

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egamn.obj

+#       link @<<

+#$** /NOI

+#$@ /STACK:14336

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        bind $@ c:\os2\doscalls.lib

+#        copy *.exe ..\bin

+#

+

+#

+#   Borland C++ for DOS

+#

+#CC=bcc

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= emu mathl cl

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#       tlink @&&|

+#C0L $**

+#$@ /Tde /c

+#

+#$(LIBS)

+#$(DEF_FILE) $(LFLAGS) ;

+#|

+#        copy *.exe ..\bin

+#

+

+#

+# C-Set/2 for OS/2

+#

+#CC=icc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__

+#OUT_OBJ = -Fo

+#LIBS=

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#        link386 @<<

+#$** /NOI

+#$@ /STACK:32768

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        copy *.exe ..\bin

+#

+

+#

+# Borland C++ for OS/2

+#

+#CC=bcc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= c2 os2

+#

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \

+#        fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \

+#        misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj

+#        tlink @&&|

+#c02 $** -c -v

+#antlr.exe

+#

+#C2 os2

+#

+#|

+#        copy *.exe ..\bin

+#

+

+# *********** Target list of PC machines ***********

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+#	$(ANTLR) antlr.g

+#

+#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h

+#

+#scan.$(OBJ_EXT): scan.c mode.h tokens.h

+#

+#scan.c mode.h: parser.dlg

+#	$(DLG) -C2 parser.dlg scan.c

+#

+#set.$(OBJ_EXT): $(SET)/set.c

+#	$(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c

+

+

+

+#

+#   UNIX  (default)

+#

+BIN_DIR=../../../../bin

+CC=gcc

+COPT=-O

+ANTLR=$(BIN_DIR)/antlr.exe

+DLG=${BIN_DIR}/dlg.exe

+OBJ_EXT=o

+OUT_OBJ = -o

+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536

+#

+# SGI Users, use this CFLAGS

+#

+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262

+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o  \

+        globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o

+

+antlr : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o $(BIN_DIR)/antlr.exe $(OBJ)

+

+# what files does PCCTS generate (both ANTLR and DLG)

+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h

+

+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \

+	hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c

+

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+#	$(ANTLR) -gh antlr.g

+

+antlr.o : antlr.c mode.h tokens.h

+

+scan.o : scan.c mode.h tokens.h

+

+#scan.c mode.h: parser.dlg

+#	$(DLG) -C2 parser.dlg scan.c

+

+set.o : $(SET)/set.c

+	$(CC) $(CFLAGS) -c -o set.o $(SET)/set.c

+

+

+#

+# ****** These next targets are common to UNIX and PC world ********

+#

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

+

+#remove everything in clean plus the PCCTS files generated

+scrub:

+	rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core

diff --git a/Source/Pccts/antlr/makefile1 b/Source/Pccts/antlr/makefile1
new file mode 100644
index 0000000..dffc709
--- /dev/null
+++ b/Source/Pccts/antlr/makefile1
@@ -0,0 +1,96 @@
+#

+# Makefile for ANTLR 1.33

+#

+# SOFTWARE RIGHTS

+#

+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+# Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+# company may do whatever they wish with source code distributed with

+# PCCTS or the code generated by PCCTS, including the incorporation of

+# PCCTS, or its output, into commerical software.

+# 

+# We encourage users to develop software with PCCTS.  However, we do ask

+# that credit is given to us for developing PCCTS.  By "credit",

+# we mean that if you incorporate our source code into one of your

+# programs (commercial product, research project, or otherwise) that you

+# acknowledge this fact somewhere in the documentation, research report,

+# etc...  If you like PCCTS and have developed a nice tool with the

+# output, please mention that you developed it using PCCTS.  In

+# addition, we ask that this header remain intact in our source code.

+# As long as these guidelines are kept, we expect to continue enhancing

+# this system and expect to make other tools available as they are

+# completed.

+#

+# ANTLR 1.33

+# Terence Parr

+# Parr Research Corporation

+# with Purdue University

+# and AHPCRC, University of Minnesota

+# 1989-1995

+#

+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+#

+#   UNIX  (default)

+#

+CC=cc

+ANTLR=${WORKSPACE}/Tools/bin/antlr

+DLG=${WORKSPACE}/Tools/bin/dlg

+OBJ_EXT=o

+OUT_OBJ = -o

+ANSI=-ansi

+AOTHER=

+CFLAGS= -O0 -g -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000

+#

+# SGI Users, use this CFLAGS

+#

+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262

+

+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \

+        globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o $(OBJOTHER)

+

+antlr : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o antlr $(OBJ)

+		mv antlr ${WORKSPACE}/Tools/bin

+

+# what files does PCCTS generate (both ANTLR and DLG)

+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h

+

+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \

+	hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c

+

+#

+# Don't worry about the ambiguity messages coming from antlr

+# for making antlr.c etc...  [should be 10 of them, I think]

+#

+antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g

+	$(ANTLR) -gh antlr.g $(AOTHER)

+

+antlr.o : antlr.c mode.h tokens.h

+

+scan.o : scan.c mode.h tokens.h

+

+scan.c mode.h: parser.dlg

+	$(DLG) -C2 parser.dlg scan.c

+

+set.o : $(SET)/set.c

+	$(CC) $(CFLAGS) -c -o set.o $(SET)/set.c

+

+

+#

+# ****** These next targets are common to UNIX and PC world ********

+#

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

+

+#remove everything in clean plus the PCCTS files generated

+scrub:

+	rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core

diff --git a/Source/Pccts/antlr/misc.c b/Source/Pccts/antlr/misc.c
new file mode 100644
index 0000000..3f58da3
--- /dev/null
+++ b/Source/Pccts/antlr/misc.c
@@ -0,0 +1,1864 @@
+/*

+ * misc.c

+ *

+ * Manage tokens, regular expressions.

+ * Print methods for debugging

+ * Compute follow lists onto tail ends of rules.

+ *

+ * The following functions are visible:

+ *

+ *		int		addTname(char *);		Add token name

+ *		int		addTexpr(char *);		Add token expression

+ *		int		Tnum(char *);			Get number of expr/token

+ *		void	Tklink(char *, char *);	Link a name with an expression

+ *		int		hasAction(expr);		Does expr already have action assigned?

+ *		void	setHasAction(expr);		Indicate that expr now has an action

+ *		Entry	*newEntry(char *,int);	Create new table entry with certain size

+ *		void	list_add(ListNode **list, char *e)

+ *      void    list_free(ListNode **list, int freeData);   *** MR10 ***

+ *		void	list_apply(ListNode *list, void (*f)())

+ *		void	lexclass(char *m);		switch to new/old lexical class

+ *		void	lexmode(int i);			switch to old lexical class i

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+#include <ctype.h>

+

+static int tsize=TSChunk;		/* size of token str arrays */

+

+static void

+#ifdef __USE_PROTOS

+RemapForcedTokensInSyntaxDiagram(Node *);

+#else

+RemapForcedTokensInSyntaxDiagram();

+#endif

+

+				/* T o k e n  M a n i p u l a t i o n */

+

+/*

+ * add token 't' to the TokenStr/Expr array.  Make more room if necessary.

+ * 't' is either an expression or a token name.

+ *

+ * There is only one TokenStr array, but multiple ExprStr's.  Therefore,

+ * for each lex class (element of lclass) we must extend the ExprStr array.

+ * ExprStr's and TokenStr are always all the same size.

+ *

+ * Also, there is a Texpr hash table for each automaton.

+ */

+static void

+#ifdef __USE_PROTOS

+Ttrack( char *t )

+#else

+Ttrack( t )

+char *t;

+#endif

+{

+	if ( TokenNum >= tsize )	/* terminal table overflow? */

+	{

+		char **p;

+		int i, more, j;

+

+		more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk));

+		tsize += more;

+		TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *));

+		require(TokenStr != NULL, "Ttrack: can't extend TokenStr");

+		for (i=0; i<NumLexClasses; i++)

+		{

+			lclass[i].exprs = (char **)

+							  realloc((char *)lclass[i].exprs, tsize*sizeof(char *));

+			require(lclass[i].exprs != NULL, "Ttrack: can't extend ExprStr");

+			for (p= &lclass[i].exprs[tsize-more],j=1; j<=more; j++) *p++ = NULL;

+		}

+		for (p= &TokenStr[tsize-more],i=1; i<=more; i++) *p++ = NULL;

+		lexmode( CurrentLexClass ); /* reset ExprStr in case table moved */

+	}

+	/* note: we use the actual ExprStr/TokenStr array

+	 * here as TokenInd doesn't exist yet

+	 */

+	if ( *t == '"' ) ExprStr[TokenNum] = t;

+	else TokenStr[TokenNum] = t;

+}

+

+static Expr *

+#ifdef __USE_PROTOS

+newExpr( char *e )

+#else

+newExpr( e )

+char *e;

+#endif

+{

+	Expr *p = (Expr *) calloc(1, sizeof(Expr));

+	require(p!=NULL, "newExpr: cannot alloc Expr node");

+

+	p->expr = e;

+	p->lclass = CurrentLexClass;

+	return p;

+}

+

+/* switch to lexical class/mode m.  This amounts to creating a new

+ * lex mode if one does not already exist and making ExprStr point

+ * to the correct char string array.  We must also switch Texpr tables.

+ *

+ * BTW, we need multiple ExprStr arrays because more than one automaton

+ * may have the same label for a token, but with different expressions.

+ * We need to track an expr for each automaton.  If we disallowed this

+ * feature, only one ExprStr would be required.

+ */

+void

+#ifdef __USE_PROTOS

+lexclass( char *m )

+#else

+lexclass( m )

+char *m;

+#endif

+{

+	int i;

+	TermEntry *p;

+	static char EOFSTR[] = "\"@\"";

+

+	if ( hash_get(Tname, m) != NULL )

+	{

+		warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m));

+	}

+	/* does m already exist? */

+	i = LexClassIndex(m);

+	if ( i != -1 ) {lexmode(i); return;}

+	/* must make new one */

+	NumLexClasses++;

+	CurrentLexClass = NumLexClasses-1;

+	require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files");

+	lclass[CurrentLexClass].classnum = m;

+	lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *));

+	require(lclass[CurrentLexClass].exprs!=NULL,

+			"lexclass: cannot allocate ExprStr");

+	lclass[CurrentLexClass].htable = newHashTable();

+	ExprStr = lclass[CurrentLexClass].exprs;

+	Texpr = lclass[CurrentLexClass].htable;

+	/* define EOF for each automaton */

+	p = newTermEntry( EOFSTR );

+	p->token = EofToken;	/* couldn't have remapped tokens yet, use EofToken */

+	hash_add(Texpr, EOFSTR, (Entry *)p);

+	list_add(&ExprOrder, (void *)newExpr(EOFSTR));

+	/* note: we use the actual ExprStr array

+	 * here as TokenInd doesn't exist yet

+	 */

+	ExprStr[EofToken] = EOFSTR;

+}

+

+void

+#ifdef __USE_PROTOS

+lexmode( int i )

+#else

+lexmode( i )

+int i;

+#endif

+{

+	require(i<NumLexClasses, "lexmode: invalid mode");

+	ExprStr = lclass[i].exprs;

+	Texpr = lclass[i].htable;

+	CurrentLexClass = i;

+}

+

+/* return index into lclass array of lexical class. return -1 if nonexistent */

+int

+#ifdef __USE_PROTOS

+LexClassIndex( char *cl )

+#else

+LexClassIndex( cl )

+char *cl;

+#endif

+{

+	int i;

+

+	for (i=0; i<NumLexClasses; i++)

+	{

+		if ( strcmp(lclass[i].classnum, cl) == 0 ) return i;

+	}

+	return -1;

+}

+

+int

+#ifdef __USE_PROTOS

+hasAction( char *expr )

+#else

+hasAction( expr )

+char *expr;

+#endif

+{

+	TermEntry *p;

+	require(expr!=NULL, "hasAction: invalid expr");

+

+	p = (TermEntry *) hash_get(Texpr, expr);

+	require(p!=NULL, eMsg1("hasAction: expr '%s' doesn't exist",expr));

+	return (p->action!=NULL);

+}

+

+void

+#ifdef __USE_PROTOS

+setHasAction( char *expr, char *action )

+#else

+setHasAction( expr, action )

+char *expr;

+char *action;

+#endif

+{

+	TermEntry *p;

+	require(expr!=NULL, "setHasAction: invalid expr");

+

+	p = (TermEntry *) hash_get(Texpr, expr);

+	require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr));

+	p->action = action;

+}

+

+ForcedToken *

+#ifdef __USE_PROTOS

+newForcedToken(char *token, int tnum)

+#else

+newForcedToken(token, tnum)

+char *token;

+int tnum;

+#endif

+{

+	ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken));

+	require(ft!=NULL, "out of memory");

+	ft->token = token;

+	ft->tnum = tnum;

+	return ft;

+}

+

+/*

+ * Make a token indirection array that remaps token numbers and then walk

+ * the appropriate symbol tables and SynDiag to change token numbers

+ */

+void

+#ifdef __USE_PROTOS

+RemapForcedTokens(void)

+#else

+RemapForcedTokens()

+#endif

+{

+	ListNode *p;

+	ForcedToken *q;

+	int max_token_number=0;     /* MR9 23-Sep-97 Removed "unsigned" */

+	int i;

+

+	if ( ForcedTokens == NULL ) return;

+

+	/* find max token num */

+	for (p = ForcedTokens->next; p!=NULL; p=p->next)

+	{

+		q = (ForcedToken *) p->elem;

+		if ( q->tnum > max_token_number ) max_token_number = q->tnum;

+	}

+	fprintf(stderr, "max token number is %d\n", max_token_number);

+

+	/* make token indirection array */

+	TokenInd = (int *) calloc(max_token_number+1, sizeof(int));

+	LastTokenCounted = TokenNum;

+	TokenNum = max_token_number+1;

+	require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd");

+

+	/* fill token indirection array and change token id htable ; swap token indices */

+	for (i=1; i<TokenNum; i++) TokenInd[i] = i;

+	for (p = ForcedTokens->next; p!=NULL; p=p->next)

+	{

+		TermEntry *te;

+		int old_pos, t;

+

+		q = (ForcedToken *) p->elem;

+		fprintf(stderr, "%s forced to %d\n", q->token, q->tnum);

+		te = (TermEntry *) hash_get(Tname, q->token);

+		require(te!=NULL, "RemapForcedTokens: token not in hash table");

+		old_pos = te->token;

+		fprintf(stderr, "Before: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);

+		fprintf(stderr, "Before: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);

+		q = (ForcedToken *) p->elem;

+		t = TokenInd[old_pos];

+		TokenInd[old_pos] = q->tnum;

+		TokenInd[q->tnum] = t;

+		te->token = q->tnum;		/* update token type id symbol table */

+		fprintf(stderr, "After: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);

+		fprintf(stderr, "After: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);

+

+		/* Change the token number in the sym tab entry for the exprs

+		 * at the old position of the token id and the target position

+		 */

+		/* update expr at target (if any) of forced token id */

+		if ( q->tnum < TokenNum )	/* is it a valid position? */

+		{

+			for (i=0; i<NumLexClasses; i++)

+			{

+				if ( lclass[i].exprs[q->tnum]!=NULL )

+				{

+					/* update the symbol table for this expr */

+					TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]);

+					require(e!=NULL, "RemapForcedTokens: expr not in hash table");

+					e->token = old_pos;

+					fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %d\n",

+							lclass[i].exprs[q->tnum], q->tnum, i, old_pos);

+				}

+			}

+		}

+		/* update expr at old position (if any) of forced token id */

+		for (i=0; i<NumLexClasses; i++)

+		{

+			if ( lclass[i].exprs[old_pos]!=NULL )

+			{

+				/* update the symbol table for this expr */

+				TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[old_pos]);

+				require(e!=NULL, "RemapForcedTokens: expr not in hash table");

+				e->token = q->tnum;

+				fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %d\n",

+						lclass[i].exprs[old_pos], q->token, i, q->tnum);

+			}

+		}

+	}

+

+	/* Update SynDiag */

+	RemapForcedTokensInSyntaxDiagram((Node *)SynDiag);

+}

+

+static void

+#ifdef __USE_PROTOS

+RemapForcedTokensInSyntaxDiagram(Node *p)

+#else

+RemapForcedTokensInSyntaxDiagram(p)

+Node *p;

+#endif

+{

+	Junction *j = (Junction *) p;

+	RuleRefNode *r = (RuleRefNode *) p;

+	TokNode *t = (TokNode *)p;

+

+	if ( p==NULL ) return;

+	require(p->ntype>=1 && p->ntype<=NumNodeTypes,	"Remap...: invalid diagram node");

+	switch ( p->ntype )

+	{

+		case nJunction :

+			if ( j->visited ) return;

+			if ( j->jtype == EndRule ) return;

+			j->visited = TRUE;

+			RemapForcedTokensInSyntaxDiagram( j->p1 );

+			RemapForcedTokensInSyntaxDiagram( j->p2 );

+			j->visited = FALSE;

+			return;

+		case nRuleRef :

+			RemapForcedTokensInSyntaxDiagram( r->next );

+			return;

+		case nToken :

+			if ( t->remapped ) return;	/* we've been here before */

+			t->remapped = 1;

+			fprintf(stderr, "remapping %d to %d\n", t->token, TokenInd[t->token]);

+			t->token = TokenInd[t->token];

+			RemapForcedTokensInSyntaxDiagram( t->next );

+			return;

+		case nAction :

+			RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next );

+			return;

+		default :

+			fatal_internal("invalid node type");

+	}

+}

+

+/*

+ * Add a token name.  Return the token number associated with it.  If it already

+ * exists, then return the token number assigned to it.

+ *

+ * Track the order in which tokens are found so that the DLG output maintains

+ * that order.  It also lets us map token numbers to strings.

+ */

+int

+#ifdef __USE_PROTOS

+addTname( char *token )

+#else

+addTname( token )

+char *token;

+#endif

+{

+	TermEntry *p;

+	require(token!=NULL, "addTname: invalid token name");

+

+	if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;

+	p = newTermEntry( token );

+	Ttrack( p->str );

+	p->token = TokenNum++;

+	hash_add(Tname, token, (Entry *)p);

+	return p->token;

+}

+

+/* This is the same as addTname except we force the TokenNum to be tnum.

+ * We don't have to use the Forced token stuff as no tokens will have

+ * been defined with #tokens when this is called.  This is only called

+ * when a #tokdefs meta-op is used.

+ */

+int

+#ifdef __USE_PROTOS

+addForcedTname( char *token, int tnum )

+#else

+addForcedTname( token, tnum )

+char *token;

+int tnum;

+#endif

+{

+	TermEntry *p;

+	require(token!=NULL, "addTname: invalid token name");

+

+	if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;

+	p = newTermEntry( token );

+	Ttrack( p->str );

+	p->token = tnum;

+	hash_add(Tname, token, (Entry *)p);

+	return p->token;

+}

+

+/*

+ * Add a token expr.  Return the token number associated with it.  If it already

+ * exists, then return the token number assigned to it.

+ */

+int

+#ifdef __USE_PROTOS

+addTexpr( char *expr )

+#else

+addTexpr( expr )

+char *expr;

+#endif

+{

+	TermEntry *p;

+	require(expr!=NULL, "addTexpr: invalid regular expression");

+

+	if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token;

+	p = newTermEntry( expr );

+	Ttrack( p->str );

+	/* track the order in which they occur */

+	list_add(&ExprOrder, (void *)newExpr(p->str));

+	p->token = TokenNum++;

+	hash_add(Texpr, expr, (Entry *)p);

+	return p->token;

+}

+

+/* return the token number of 'term'.  Return 0 if no 'term' exists */

+int

+#ifdef __USE_PROTOS

+Tnum( char *term )

+#else

+Tnum( term )

+char *term;

+#endif

+{

+	TermEntry *p;

+	require(term!=NULL, "Tnum: invalid terminal");

+	

+	if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term);

+	else p = (TermEntry *) hash_get(Tname, term);

+	if ( p == NULL ) return 0;

+	else return p->token;

+}

+

+/* associate a Name with an expr.  If both have been already assigned

+ * token numbers, then an error is reported.  Add the token or expr

+ * that has not been added if no error.  This 'represents' the #token

+ * ANTLR pseudo-op.  If both have not been defined, define them both

+ * linked to same token number.

+ */

+void

+#ifdef __USE_PROTOS

+Tklink( char *token, char *expr )

+#else

+Tklink( token, expr )

+char *token;

+char *expr;

+#endif

+{

+	TermEntry *p, *q;

+	require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr");

+

+	p = (TermEntry *) hash_get(Tname, token);

+	q = (TermEntry *) hash_get(Texpr, expr);

+	if ( p != NULL && q != NULL )	/* both defined */

+	{

+		warn( eMsg2("token name %s and rexpr %s already defined; ignored",

+					token, expr) );

+		return;

+	}

+	if ( p==NULL && q==NULL )		/* both not defined */

+	{

+		int t = addTname( token );

+		q = newTermEntry( expr );

+		hash_add(Texpr, expr, (Entry *)q);

+		q->token = t;

+		/* note: we use the actual ExprStr array

+		 * here as TokenInd doesn't exist yet

+		 */

+		ExprStr[t] = q->str;

+		/* track the order in which they occur */

+		list_add(&ExprOrder, (void *)newExpr(q->str));

+		return;

+	}

+	if ( p != NULL )				/* one is defined, one is not */

+	{

+		q = newTermEntry( expr );

+		hash_add(Texpr, expr, (Entry *)q);

+		q->token = p->token;

+		ExprStr[p->token] = q->str;	/* both expr and token str defined now */

+		list_add(&ExprOrder, (void *)newExpr(q->str));

+	}

+	else							/* trying to associate name with expr here*/

+	{

+		p = newTermEntry( token );

+		hash_add(Tname, token, (Entry *)p);

+		p->token = q->token;

+		TokenStr[p->token] = p->str;/* both expr and token str defined now */

+	}

+}

+

+/*

+ * Given a string, this function allocates and returns a pointer to a

+ * hash table record of size 'sz' whose "str" pointer is reset to a position

+ * in the string table.

+ */

+Entry *

+#ifdef __USE_PROTOS

+newEntry( char *text, int sz )

+#else

+newEntry( text, sz )

+char *text;

+int sz;

+#endif

+{

+	Entry *p;

+	require(text!=NULL, "new: NULL terminal");

+	

+	if ( (p = (Entry *) calloc(1,sz)) == 0 )

+	{

+		fatal_internal("newEntry: out of memory for terminals\n");

+		exit(PCCTS_EXIT_FAILURE);

+	}

+	p->str = mystrdup(text);

+	

+	return(p);

+}

+

+/*

+ * add an element to a list.

+ *

+ * Any non-empty list has a sentinel node whose 'elem' pointer is really

+ * a pointer to the last element.  (i.e. length(list) = #elemIn(list)+1).

+ * Elements are appended to the list.

+ */

+void

+#ifdef __USE_PROTOS

+list_add( ListNode **list, void *e )

+#else

+list_add( list, e )

+ListNode **list;

+void *e;

+#endif

+{

+	ListNode *p, *tail;

+	require(e!=NULL, "list_add: attempting to add NULL list element");

+

+	p = newListNode;

+	require(p!=NULL, "list_add: cannot alloc new list node");

+	p->elem = e;

+	if ( *list == NULL )

+	{

+		ListNode *sentinel = newListNode;

+		require(sentinel!=NULL, "list_add: cannot alloc sentinel node");

+		*list=sentinel;

+		sentinel->next = p;

+		sentinel->elem = (char *)p;		/* set tail pointer */

+	}

+	else								/* find end of list */

+	{

+		tail = (ListNode *) (*list)->elem;	/* get tail pointer */

+		tail->next = p;

+		(*list)->elem = (char *) p;		/* reset tail */

+	}

+}

+

+/* MR10 list_free() frees the ListNode elements in the list       */

+/* MR10   if freeData then free the data elements of the list too */

+

+void

+#ifdef __USE_PROTOS

+list_free(ListNode **list,int freeData)

+#else

+list_free(list,freeData)

+  ListNode      **list;

+  int           freeData;

+#endif

+{

+	ListNode *p;

+    ListNode *next;

+

+	if (list == NULL) return;

+    if (*list == NULL) return;

+	for (p=*list; p != NULL; p=next) {

+      next=p->next;

+      if (freeData && p->elem != NULL) {

+        free( (char *) p->elem);

+      };

+      free( (char *) p);

+    };

+    *list=NULL;

+}

+

+void

+#ifdef __USE_PROTOS

+list_apply( ListNode *list, void (*f)(void *) )

+#else

+list_apply( list, f )

+ListNode *list;

+void (*f)();

+#endif

+{

+	ListNode *p;

+	require(f!=NULL, "list_apply: NULL function to apply");

+

+	if ( list == NULL ) return;

+	for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem );

+}

+

+/* MR27 */

+

+#ifdef __USE_PROTOS

+int list_search_cstring(ListNode *list, char * cstring)

+#else

+int list_search_cstring(list, cstring)

+  ListNode * list;

+  char * cstring;

+#endif

+{

+	ListNode *p;

+	if (list == NULL ) return 0;

+	for (p = list->next; p!=NULL; p=p->next) {

+		if (p->elem == NULL) continue;

+		if (0 == strcmp((char *) p->elem , cstring)) return 1;

+	}

+	return 0;

+}

+

+			/* F O L L O W  C y c l e  S t u f f */

+		

+/* make a key based upon (rulename, computation, k value).

+ * Computation values are 'i'==FIRST, 'o'==FOLLOW.

+ */

+

+/* MR10  Make the key all characters so it can be read easily   */

+/* MR10    by a simple dump program.  Also, separates           */

+/* MR10   'o' and 'i' from rule name                            */

+

+char *

+#ifdef __USE_PROTOS

+Fkey( char *rule, int computation, int k )

+#else

+Fkey( rule, computation, k )

+char *rule;

+int computation;

+int k;

+#endif

+{

+	static char key[MaxRuleName+2+2+1];                                 /* MR10 */

+	int i;

+	

+	if ( k > 99 )                                                       /* MR10 */

+		fatal("k>99 is too big for this implementation of ANTLR!\n");   /* MR10 */

+	if ( (i=strlen(rule)) > MaxRuleName )                               /* MR10 */

+		fatal( eMsgd("rule name > max of %d\n", MaxRuleName) );         /* MR10 */

+	strcpy(key,rule);

+

+/* MR10 */     key[i]='*';

+/* MR10 */     key[i+1] = (char) computation; /* MR20 G. Hobbelt */

+/* MR10 */     if (k < 10) {

+/* MR10 */       key[i+2] = (char) ( '0' + k);

+/* MR10 */  	 key[i+3] = '\0';

+/* MR10 */     } else {

+/* MR10 */       key[i+2] = (char) ( '0' + k/10);

+/* MR10 */       key[i+3] = (char) ( '0' + k % 10);

+/* MR10 */       key[i+4] = '\0';

+/* MR10 */     };

+

+	return key;

+}

+

+/* Push a rule onto the kth FOLLOW stack */

+void

+#ifdef __USE_PROTOS

+FoPush( char *rule, int k )

+#else

+FoPush( rule, k )

+char *rule;

+int k;

+#endif

+{

+	RuleEntry *r;

+	require(rule!=NULL, "FoPush: tried to push NULL rule");

+	require(k<=CLL_k,	"FoPush: tried to access non-existent stack");

+

+	/*fprintf(stderr, "FoPush(%s)\n", rule);*/

+	r = (RuleEntry *) hash_get(Rname, rule);

+	if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );}

+	if ( FoStack[k] == NULL )		/* Does the kth stack exist yet? */

+	{

+		/*fprintf(stderr, "allocating FoStack\n");*/

+		FoStack[k] = (int *) calloc(FoStackSize, sizeof(int));

+		require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n");

+	}

+	if ( FoTOS[k] == NULL )

+	{

+		FoTOS[k]=FoStack[k];

+		*(FoTOS[k]) = r->rulenum;

+	}

+	else

+	{

+#ifdef MEMCHK

+		require(valid(FoStack[k]), "FoPush: invalid FoStack");

+#endif

+		if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) )

+			fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n",

+						FoStackSize) );

+		require(FoTOS[k]>=FoStack[k],

+				eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox",

+					  rule));

+		++(FoTOS[k]);

+		*(FoTOS[k]) = r->rulenum;

+	}

+	{

+		/*

+****		int *p;

+****		fprintf(stderr, "FoStack[k=%d]:\n", k);

+****		for (p=FoStack[k]; p<=FoTOS[k]; p++)

+****		{

+****			fprintf(stderr, "\t%s\n", RulePtr[*p]->rname);

+****		}

+		*/

+	}

+}

+

+/* Pop one rule off of the FOLLOW stack.  TOS ptr is NULL if empty. */

+void

+#ifdef __USE_PROTOS

+FoPop( int k )

+#else

+FoPop( k )

+int k;

+#endif

+{

+	require(k<=CLL_k, "FoPop: tried to access non-existent stack");

+	/*fprintf(stderr, "FoPop\n");*/

+	require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),

+			"FoPop: FoStack stack-ptr is playing out of its sandbox");

+	if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL;

+	else (FoTOS[k])--;

+}

+

+/* Compute FOLLOW cycle.

+ * Mark all FOLLOW sets for rules in cycle as incomplete.

+ * Then, save cycle on the cycle list (Cycles) for later resolution.

+ * The Cycle is stored in the form:

+ *		(head of cycle==croot, rest of rules in cycle==cyclicDep)

+ *

+ * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on)

+ *

+ *		Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x)

+ *										   ^----Infinite recursion (cycle)

+ *

+ * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}).  Fo(x) depends

+ * on the FOLLOW of a,b, and c.  The root of a cycle is always complete after

+ * Fo(x) finishes.  Fo(a,b,c) however are not.  It turns out that all rules

+ * in a FOLLOW cycle have the same FOLLOW set.

+ */

+void

+#ifdef __USE_PROTOS

+RegisterCycle( char *rule, int k )

+#else

+RegisterCycle( rule, k )

+char *rule;

+int k;

+#endif

+{

+	CacheEntry *f;

+	Cycle *c;

+	int *p;

+	RuleEntry *r;

+	require(rule!=NULL, "RegisterCycle: tried to register NULL rule");

+	require(k<=CLL_k,	"RegisterCycle: tried to access non-existent stack");

+

+	/*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/

+	/* Find cycle start */

+	r = (RuleEntry *) hash_get(Rname, rule);

+	require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule));

+	require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),

+			eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox",

+				  rule));

+/***	if ( FoTOS[k]<FoStack[k]||FoTOS[k]>&(FoStack[k][FoStackSize-1]) )

+****	{

+****		fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n",

+****						rule);

+****		fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n",

+****						FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1]));

+****		exit(PCCTS_EXIT_FAILURE);

+****	}

+****/

+

+#ifdef MEMCHK

+	require(valid(FoStack[k]), "RegisterCycle: invalid FoStack");

+#endif

+	for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;}

+	require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief");

+	if ( p == FoTOS[k] ) return;	/* don't worry about cycles to oneself */

+	

+	/* compute cyclic dependents (rules in cycle except head) */

+	c = newCycle;

+	require(c!=NULL, "RegisterCycle: couldn't alloc new cycle");

+	c->cyclicDep = empty;

+	c->croot = *p++;		/* record root of cycle */

+	for (; p<=FoTOS[k]; p++)

+	{

+		/* Mark all dependent rules as incomplete */

+		f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k));

+		if ( f==NULL )

+		{

+			f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) );

+			hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f);

+		}

+		f->incomplete = TRUE;

+		

+		set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */

+	}

+	list_add(&(Cycles[k]), (void *)c);

+}

+

+/* make all rules in cycle complete

+ *

+ * while ( some set has changed ) do

+ *		for each cycle do

+ *			if degree of FOLLOW set for croot > old degree then

+ *				update all FOLLOW sets for rules in cyclic dependency

+ *				change = TRUE

+ *			endif

+ *		endfor

+ * endwhile

+ */

+void

+#ifdef __USE_PROTOS

+ResolveFoCycles( int k )

+#else

+ResolveFoCycles( k )

+int k;

+#endif

+{

+	ListNode *p, *q;

+	Cycle *c;

+	int changed = 1;

+	CacheEntry *f,*g;

+	int r;

+/*  int i;  */  /* MR10 not useful */

+	unsigned d;

+

+    unsigned    *cursor;        /* MR10 */

+    unsigned    *origin;        /* MR10 */

+	

+	/*fprintf(stderr, "Resolving following cycles for %d\n", k);*/

+	while ( changed )

+	{

+		changed = 0;

+/* MR10 i = 0;  */

+		for (p = Cycles[k]->next; p!=NULL; p=p->next)

+		{

+			c = (Cycle *) p->elem;

+			/*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/

+			/*s_fprT(stderr, c->cyclicDep);*/

+			/*fprintf(stderr, "\n");*/

+			f = (CacheEntry *)

+					hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k));

+			require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) );

+			if ( (d=set_deg(f->fset)) > c->deg )

+			{

+				/*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/

+				changed = 1;

+				c->deg = d;		/* update cycle FOLLOW set degree */

+

+/* MR10 */      origin=set_pdq(c->cyclicDep);

+/* MR10 */      for (cursor=origin; *cursor != nil; cursor++) {

+/* MR10 */         r=*cursor;

+

+/********		while ( !set_nil(c->cyclicDep) ) {      *****/

+/********					r = set_int(c->cyclicDep);  *****/

+/********					set_rm(r, c->cyclicDep);    *****/

+

+					/*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/

+					g = (CacheEntry *)

+							hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k));

+					require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) );

+					set_orin(&(g->fset), f->fset);

+					g->incomplete = FALSE;

+				}

+/* MR10 */      free( (char *) origin);

+/* MR10 */      origin=NULL;

+			}

+		}

+/* MR10 - this if statement appears to be meaningless since i is always 0 */

+/* MR10		if ( i == 1 ) changed = 0;	*/ /* if only 1 cycle, no need to repeat */

+	}

+	/* kill Cycle list */

+	for (q = Cycles[k]->next; q != NULL; q=p)

+	{

+		p = q->next;

+		set_free( ((Cycle *)q->elem)->cyclicDep );

+		free((char *)q);

+	}

+	free( (char *)Cycles[k] );

+	Cycles[k] = NULL;

+}

+

+

+			/* P r i n t i n g  S y n t a x  D i a g r a m s */

+

+static void

+#ifdef __USE_PROTOS

+pBlk( Junction *q, int btype )

+#else

+pBlk( q, btype )

+Junction *q;

+int btype;

+#endif

+{

+	int k,a;

+	Junction *alt, *p;

+

+	q->end->pvisited = TRUE;

+	if ( btype == aLoopBegin )

+	{

+		require(q->p2!=NULL, "pBlk: invalid ()* block");

+		PRINT(q->p1);

+		alt = (Junction *)q->p2;

+		PRINT(alt->p1);

+		if ( PrintAnnotate )

+		{

+			printf(" /* Opt ");

+			k = 1;

+			while ( !set_nil(alt->fset[k]) )

+			{

+				s_fprT(stdout, alt->fset[k]);

+				if ( k++ == CLL_k ) break;

+				if ( !set_nil(alt->fset[k]) ) printf(", ");

+			}

+			printf(" */\n");

+		}

+		return;

+	}

+	for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++)

+	{

+		if ( alt->p1 != NULL ) PRINT(alt->p1);

+		if ( PrintAnnotate )

+		{

+			printf( " /* [%d] ", alt->altnum);

+			k = 1;

+			while ( !set_nil(alt->fset[k]) )

+			{

+				s_fprT(stdout, alt->fset[k]);

+				if ( k++ == CLL_k ) break;

+				if ( !set_nil(alt->fset[k]) ) printf(", ");

+			}

+			if ( alt->p2 == NULL && btype == aOptBlk )

+				printf( " (optional branch) */\n");

+			else printf( " */\n");

+		}

+

+		/* ignore implied empty alt of Plus blocks */

+		if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break;

+

+		if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) )

+		{

+			if ( pLevel == 1 )

+			{

+				printf("\n");

+				if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>");

+				printf("\t");

+			}

+			else printf(" ");

+			printf("|");

+			if ( pLevel == 1 )

+			{

+				p = (Junction *) ((Junction *)alt->p2)->p1;

+				while ( p!=NULL )

+				{

+					if ( p->ntype==nAction )

+					{

+						p=(Junction *)((ActionNode *)p)->next;

+						continue;

+					}

+					if ( p->ntype!=nJunction )

+					{

+						break;

+					}

+					if ( p->jtype==EndBlk || p->jtype==EndRule )

+					{

+						p = NULL;

+						break;

+					}

+					p = (Junction *)p->p1;

+				}

+				if ( p==NULL ) printf("\n\t");	/* Empty alt? */

+			}

+		}

+	}

+	q->end->pvisited = FALSE;

+}

+

+/* How to print out a junction */

+void

+#ifdef __USE_PROTOS

+pJunc( Junction *q )

+#else

+pJunc( q )

+Junction *q;

+#endif

+{

+	int dum_k;

+	int doing_rule;

+	require(q!=NULL, "pJunc: NULL node");

+	require(q->ntype==nJunction, "pJunc: not junction");

+	

+	if ( q->pvisited == TRUE ) return;

+	q->pvisited = TRUE;

+	switch ( q->jtype )

+	{

+		case aSubBlk :

+			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);

+			if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction &&

+				 ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1;

+			else doing_rule = 0;

+			pLevel++;

+			if ( pLevel==1 )

+			{

+				if ( pAlt1==1 ) printf("=>");

+				printf("\t");

+			}

+			else printf(" ");

+			if ( doing_rule )

+			{

+				if ( pLevel==1 ) printf(" ");

+				pBlk(q,q->jtype);

+			}

+			else {

+				printf("(");

+				if ( pLevel==1 ) printf(" ");

+				pBlk(q,q->jtype);

+				if ( pLevel>1 ) printf(" ");

+				printf(")");

+			}

+			if ( q->guess ) printf("?");

+			pLevel--;

+			if ( PrintAnnotate ) freeBlkFsets(q);

+			if ( q->end->p1 != NULL ) PRINT(q->end->p1);

+			break;

+		case aOptBlk :

+			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);

+			pLevel++;

+			if ( pLevel==1 )

+			{

+				if ( pAlt1==1 ) printf("=>");

+				printf("\t");

+			}

+			else printf(" ");

+			printf("{");

+			if ( pLevel==1 ) printf(" ");

+			pBlk(q,q->jtype);

+			if ( pLevel>1 ) printf(" ");

+			else printf("\n\t");

+			printf("}");

+			pLevel--;

+			if ( PrintAnnotate ) freeBlkFsets(q);

+			if ( q->end->p1 != NULL ) PRINT(q->end->p1);

+			break;

+		case aLoopBegin :

+			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);

+			pLevel++;

+			if ( pLevel==1 )

+			{

+				if ( pAlt1==1 ) printf("=>");

+				printf("\t");

+			}

+			else printf(" ");

+			printf("(");

+			if ( pLevel==1 ) printf(" ");

+			pBlk(q,q->jtype);

+			if ( pLevel>1 ) printf(" ");

+			else printf("\n\t");

+			printf(")*");

+			pLevel--;

+			if ( PrintAnnotate ) freeBlkFsets(q);

+			if ( q->end->p1 != NULL ) PRINT(q->end->p1);

+			break;

+		case aLoopBlk :

+			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);

+			pBlk(q,q->jtype);

+			if ( PrintAnnotate ) freeBlkFsets(q);

+			break;

+		case aPlusBlk :

+			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);

+			pLevel++;

+			if ( pLevel==1 )

+			{

+				if ( pAlt1==1 ) printf("=>");

+				printf("\t");

+			}

+			else printf(" ");

+			printf("(");

+			if ( pLevel==1 ) printf(" ");

+			pBlk(q,q->jtype);

+			if ( pLevel>1 ) printf(" ");

+			printf(")+");

+			pLevel--;

+			if ( PrintAnnotate ) freeBlkFsets(q);

+			if ( q->end->p1 != NULL ) PRINT(q->end->p1);

+			break;

+		case EndBlk :

+			break;

+		case RuleBlk :

+			printf( "\n%s :\n", q->rname);

+			PRINT(q->p1);

+			if ( q->p2 != NULL ) PRINT(q->p2);

+			break;

+		case Generic :

+			if ( q->p1 != NULL ) PRINT(q->p1);

+			q->pvisited = FALSE;

+			if ( q->p2 != NULL ) PRINT(q->p2);

+			break;

+		case EndRule :

+			printf( "\n\t;\n");

+			break;

+	}

+	q->pvisited = FALSE;

+}

+

+/* How to print out a rule reference node */

+void

+#ifdef __USE_PROTOS

+pRuleRef( RuleRefNode *p )

+#else

+pRuleRef( p )

+RuleRefNode *p;

+#endif

+{

+	require(p!=NULL, "pRuleRef: NULL node");

+	require(p->ntype==nRuleRef, "pRuleRef: not rule ref node");

+	

+	printf( " %s", p->text);

+	PRINT(p->next);

+}

+

+/* How to print out a terminal node */

+void

+#ifdef __USE_PROTOS

+pToken( TokNode *p )

+#else

+pToken( p )

+TokNode *p;

+#endif

+{

+	require(p!=NULL, "pToken: NULL node");

+	require(p->ntype==nToken, "pToken: not token node");

+

+	if ( p->wild_card ) printf(" .");

+	printf( " %s", TerminalString(p->token));

+	PRINT(p->next);

+}

+

+/* How to print out a terminal node */

+void

+#ifdef __USE_PROTOS

+pAction( ActionNode *p )

+#else

+pAction( p )

+ActionNode *p;

+#endif

+{

+	require(p!=NULL, "pAction: NULL node");

+	require(p->ntype==nAction, "pAction: not action node");

+	

+	PRINT(p->next);

+}

+

+					/* F i l l  F o l l o w  L i s t s */

+

+/*

+ * Search all rules for all rule reference nodes, q to rule, r.

+ * Add q->next to follow list dangling off of rule r.

+ * i.e.

+ *

+ *		r: -o-R-o-->o--> Ptr to node following rule r in another rule

+ *					|

+ *					o--> Ptr to node following another reference to r.

+ *

+ * This is the data structure employed to avoid FOLLOW set computation.  We

+ * simply compute the FIRST (reach) of the EndRule Node which follows the

+ * list found at the end of all rules which are referenced elsewhere.  Rules

+ * not invoked by other rules have no follow list (r->end->p1==NULL).

+ * Generally, only start symbols are not invoked by another rule.

+ *

+ * Note that this mechanism also gives a free cross-reference mechanism.

+ *

+ * The entire syntax diagram is layed out like this:

+ *

+ * SynDiag

+ *	|

+ *	v

+ *	o-->R1--o

+ *	|

+ *	o-->R2--o

+ *	|

+ *	...

+ *	|

+ *	o-->Rn--o

+ *

+ */

+void

+#ifdef __USE_PROTOS

+FoLink( Node *p )

+#else

+FoLink( p )

+Node *p;

+#endif

+{

+	RuleEntry *q;

+	Junction *j = (Junction *) p;

+	RuleRefNode *r = (RuleRefNode *) p;

+

+	if ( p==NULL ) return;

+	require(p->ntype>=1 && p->ntype<=NumNodeTypes,

+			eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype));

+	switch ( p->ntype )

+	{

+		case nJunction :

+			if ( j->fvisited ) return;

+			if ( j->jtype == EndRule ) return;

+			j->fvisited = TRUE;

+			FoLink( j->p1 );

+			FoLink( j->p2 );

+/* MR14 */

+/* MR14 */  /* Need to determine whether the guess block is an         */

+/* MR14 */  /* of the form (alpha)? beta before follow sets are        */

+/* MR14 */  /* computed.  This is necessary to solve problem           */

+/* MR14 */  /* of doing follow on the alpha of an (alpha)? beta block. */

+/* MR14 */

+/* MR14 */  /* This is performed by analysis_point as a side-effect.   */

+/* MR14 */

+/* MR14 */

+/* MR14 */  if (j->jtype == aSubBlk && j->guess) {

+/* MR14 */    Junction *ignore;

+/* MR14 */    ignore=analysis_point(j);

+/* MR14 */  }

+/* MR14 */

+			return;

+		case nRuleRef :

+			if ( r->linked ) return;

+			q = (RuleEntry *) hash_get(Rname, r->text);

+			if ( q == NULL )

+			{

+				warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line );

+			}

+			else

+			{

+				if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL )

+				{

+					warnFL( eMsg1("rule %s accepts no parameter(s)", r->text),

+							FileStr[r->file], r->line );

+				}

+				if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL )

+				{

+					warnFL( eMsg1("rule %s requires parameter(s)", r->text),

+							FileStr[r->file], r->line );

+				}

+				if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL )

+				{

+					warnFL( eMsg1("rule %s yields no return value(s)", r->text),

+							FileStr[r->file], r->line );

+				}

+				if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL )

+				{

+					warnFL( eMsg1("rule %s returns a value(s)", r->text),

+							FileStr[r->file], r->line );

+				}

+				if ( !r->linked )

+				{

+					addFoLink(	r->next, r->rname, RulePtr[q->rulenum] );

+					r->linked = TRUE;

+				}

+			}

+			FoLink( r->next );

+			return;

+		case nToken :

+			FoLink( ((TokNode *)p)->next );

+			return;

+		case nAction :

+			FoLink( ((ActionNode *)p)->next );

+			return;

+		default :

+			fatal_internal("invalid node type");

+	}

+}

+

+/*

+ * Add a reference to the end of a rule.

+ *

+ * 'r' points to the RuleBlk node in a rule.  r->end points to the last node

+ * (EndRule jtype) in a rule.

+ *

+ * Initial:

+ *		r->end --> 	o

+ *

+ * After:

+ *		r->end --> 	o-->o--> Ptr to node following rule r in another rule

+ *						|

+ *						o--> Ptr to node following another reference to r.

+ *

+ * Note that the links are added to the head of the list so that r->end->p1

+ * always points to the most recently added follow-link.  At the end, it should

+ * point to the last reference found in the grammar (starting from the 1st rule).

+ */

+void

+#ifdef __USE_PROTOS

+addFoLink( Node *p, char *rname, Junction *r )

+#else

+addFoLink( p, rname, r )

+Node *p;

+char *rname;

+Junction *r;

+#endif

+{

+	Junction *j;

+	require(r!=NULL,				"addFoLink: incorrect rule graph");

+	require(r->end!=NULL,			"addFoLink: incorrect rule graph");

+	require(r->end->jtype==EndRule,	"addFoLink: incorrect rule graph");

+	require(p!=NULL,				"addFoLink: NULL FOLLOW link");

+

+	j = newJunction();

+	j->rname = rname;			/* rname on follow links point to target rule */

+	j->p1 = p;					/* link to other rule */

+	j->p2 = (Node *) r->end->p1;/* point to head of list */

+	r->end->p1 = (Node *) j;	/* reset head to point to new node */

+}

+

+void

+#ifdef __USE_PROTOS

+GenCrossRef( Junction *p )

+#else

+GenCrossRef( p )

+Junction *p;

+#endif

+{

+	set a;

+	Junction *j;

+	RuleEntry *q;

+	unsigned e;

+	require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?");

+

+	printf("Cross Reference:\n\n");

+	a = empty;

+	for (; p!=NULL; p = (Junction *)p->p2)

+	{

+		printf("Rule %20s referenced by {", p->rname);

+		/* make a set of rules for uniqueness */

+		for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2)

+		{

+			q = (RuleEntry *) hash_get(Rname, j->rname);

+			require(q!=NULL, "GenCrossRef: FoLinks are screwed up");

+			set_orel(q->rulenum, &a);

+		}

+		for (; !set_nil(a); set_rm(e, a))

+		{

+			e = set_int(a);

+			printf(" %s", RulePtr[e]->rname);

+		}

+		printf(" }\n");

+	}

+	set_free( a );

+}

+

+/*

+   The single argument is a pointer to the start of an element of a

+   C++ style function prototypet list.  Given a pointer to the start of

+   an formal we must locate the comma (or the end of the string)

+   and locate the datatype, formal name, and initial value expression.

+

+   The function returns a pointer to the character following the comma

+   which terminates the formal declaration, or a pointer to the end of

+   the string if none was found.

+

+   I thought we were parsing specialists, how come I'm doing this by

+   hand written code ?

+

+   Examples of input:

+ 

+        Foo f,

+        Foo f = Foo(1),

+        Foo f = Foo(1,2),

+        Foo f = &farray[1,2],

+        Foo f = ",",

+        Foo f = ',',

+        TFoo<int,char> f = TFoo<int,char>(1,2),

+

+   A non-zero value for nesting indicates a problem matching '(' and ')',

+   '[' and ']', '<' and '>', '{' and '}', or improperly terminated string

+   or character literal.

+

+*/

+

+

+/*

+ *  Don't care if it is a valid string literal or not, just find the end

+ *  Start with pointer to leading "\""

+ */

+

+#ifdef __USE_PROTOS

+char * skipStringLiteral(char *pCurrent)

+#else

+char * skipStringLiteral(pCurrent)

+char *pCurrent;

+#endif

+{

+  char *p = pCurrent;

+  if (*p == 0) return p;

+  require (*p == '\"', "skipStringLiteral")

+  p++;

+  for (p = p; *p != 0; p++) {

+    if (*p == '\\') {

+      p++;

+      if (*p == 0) break;

+      p++;

+    }

+    if (*p == '\"') {

+      p++;

+      break;

+    }

+  }

+  return p;

+}

+

+/*

+ *  Don't care if it is a valid character literal or not, just find the end

+ *  Start with pointer to leading "'"

+ */

+

+#ifdef __USE_PROTOS

+char * skipCharLiteral(char *pStart)

+#else

+char * skipCharLiteral(pStart)

+ char *pStart;

+#endif

+{

+  char *p = pStart;

+  if (*p == 0) return p;

+  require (*p == '\'', "skipCharLiteral")

+  p++;

+  for (p = p; *p != 0; p++) {

+    if (*p == '\\') {

+      p++;

+      if (*p == 0) break;

+      p++;

+    }

+    if (*p == '\'') {

+      p++;

+      break;

+    }

+  }

+  return p;

+}

+

+#ifdef __USE_PROTOS

+char * skipSpaces(char *pStart)

+#else

+char * skipSpaces(pStart)

+char * pStart;

+#endif

+{

+  char *p = pStart;

+  while (*p != 0 && isspace(*p)) p++;

+  return p;

+}

+

+#ifdef __USE_PROTOS

+char * skipToSeparatorOrEqualSign(char *pStart, int *pNest)

+#else

+char * skipToSeparatorOrEqualSign(pStart, pNest)

+char *pStart;

+int *pNest;

+#endif

+{

+  char *p = pStart;

+  

+  int nest = 0;

+

+  *pNest = (-1);

+

+  while (*p != 0) {

+    switch (*p) {

+

+      case '(' :

+      case '[' :

+      case '<' :

+      case '{' :

+        nest++;

+        p++;

+        break;

+

+      case ')' :

+      case ']' :

+      case '>' :

+      case '}' :

+        nest--;

+        p++;

+        break;

+      

+      case '"' :

+        p = skipStringLiteral(p);

+        break;

+  

+      case '\'' :

+        p = skipCharLiteral(p);

+        break;

+

+      case '\\':

+        p++;

+        if (*p == 0) goto EXIT;

+        p++;

+        break;

+

+      case ',':

+      case '=':

+        if (nest == 0) goto EXIT;

+		p++;

+        break;

+

+      default:

+        p++;

+    }

+  }

+EXIT:

+  *pNest = nest;

+  return p;

+}

+

+#ifdef __USE_PROTOS

+char * skipToSeparator(char *pStart, int *pNest)

+#else

+char * skipToSeparator(pStart, pNest)

+char *pStart;

+int *pNest;

+#endif

+{

+  char * p = pStart;

+  for ( ; ; ) {

+    p = skipToSeparatorOrEqualSign(p, pNest);

+    if (*pNest != 0) return p;

+    if (*p == ',') return p;

+    if (*p == 0) return p;

+	p++;

+  }

+}

+

+/* skip to just past the "=" separating the declaration from the initialization value */

+

+#ifdef __USE_PROTOS

+char * getInitializer(char *pStart)

+#else

+char * getInitializer(pStart)

+char * pStart;

+#endif

+{

+	char *p;

+	char *pDataType;

+	char *pSymbol;

+	char *pEqualSign;

+	char *pValue;

+	char *pSeparator;

+	int nest = 0;

+

+	require(pStart!=NULL, "getInitializer: invalid string"); 

+

+	p = endFormal(pStart,

+			      &pDataType,

+				  &pSymbol,

+				  &pEqualSign,

+				  &pValue,

+				  &pSeparator,

+				  &nest);

+    if (nest != 0) return NULL;

+    if (pEqualSign == NULL) return NULL;

+    if (pValue == NULL) return NULL;

+	return strBetween(pValue, NULL, pSeparator);

+}

+

+/*

+   Examines the string from pStart to pEnd-1.

+   If the string has 0 length or is entirely white space

+   returns 1.  Otherwise 0.

+*/

+

+#ifdef __USE_PROTOS

+int isWhiteString(const char *pStart, const char *pEnd)

+#else

+int isWhiteString(pStart, pEnd)

+const char *pStart;

+const char *pEnd;

+#endif

+{

+  const char *p;

+  for (p = pStart; p < pEnd; p++) {

+    if (! isspace(*p)) return 0;

+  }

+  return 1;

+}

+

+/*

+   This replaces HasComma() which couldn't distinguish

+

+        foo ["a,b"]

+

+   from:

+

+        foo[a,b]

+

+*/

+

+#ifdef __USE_PROTOS

+int hasMultipleOperands(char *pStart)

+#else

+int hasMultipleOperands(pStart)

+char *pStart;

+#endif

+{

+  char *p = pStart;

+  int nest = 0;

+

+  p = skipSpaces(p);

+  if (*p == 0) return 0;

+  p = skipToSeparator(p, &nest);

+  if (nest == 0 && *p == ',') return 1;

+  return 0;

+}

+

+

+#define MAX_STR_BETWEEN_WORK_AREA 1000

+

+static char strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA];

+

+

+/*

+	strBetween(pStart, pNext, pStop)

+

+    Creates a null terminated string by copying the text between two pointers

+	to a work area.  The start of the string is pStart.  The end of the string

+	is the character before pNext, or if pNext is null then the character before

+	pStop.  Trailing spaces are not included in the copy operation.

+	

+	This is used when a string contains several parts.  The pNext part may be

+	optional.  The pStop will stop the scan when the optional part is not present

+	(is a null pointer).

+*/

+

+#ifdef __USE_PROTOS

+char *strBetween(char *pStart, char *pNext, char *pStop)

+#else

+char *strBetween(pStart, pNext, pStop)

+char *pStart;

+char *pNext;

+char *pStop;

+#endif

+{

+  char *p;

+  char *q = strBetweenWorkArea;

+  const char *pEnd;

+

+  pEnd = (pNext != NULL) ? pNext : pStop;

+

+  require (pEnd != NULL, "pEnd == NULL");

+  require (pEnd >= pStart, "pEnd < pStart");

+  for (pEnd--; pEnd >= pStart; pEnd--) { /* MR31 */

+	if (! isspace(*pEnd)) break;

+  }

+  for (p = pStart;

+       p <= pEnd && q < &strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA-2];

+	   p++, q++) {

+	 *q = *p;

+  }

+  *q = 0;

+  return strBetweenWorkArea;

+}

+

+/*

+   function     Returns pointer to character following separator at

+   value        which to continue search for next formal.  If at the

+                end of the string a pointer to the null byte at the

+                end of the string is returned.

+

+   pStart       Pointer to the starting position of the formal list

+

+                This may be the middle of a longer string, for example

+                when looking for the end of formal #3 starting from

+                the middle of the complete formal list.

+

+   ppDataType   Returns a pointer to the start of the data type in the

+                formal. Example: pointer to "Foo".

+

+   ppSymbol     Returns a pointer to the start of the formal symbol.

+                Example: pointer to "f".

+

+   ppEqualSign  Returns a pointer to the equal sign separating the

+                formal symbol from the initial value.  If there is 

+                no "=" then this will be NULL.

+

+   ppValue      Returns a pointer to the initial value part of the

+                formal declaration.  Example: pointer to "&farray[1,2]"

+

+   ppSeparator  Returns a pointer to the character which terminated the

+                scan.  This should be a pointer to a comma or a null

+                byte which terminates the string.

+

+   pNest        Returns the nesting level when a separator was found.

+                This is non-zero for any kind of error.  This is zero

+                for a successful parse of this portion of the formal

+                list.

+

+*/ 

+ 

+#ifdef __USE_PROTOS

+char * endFormal(char *pStart,

+                 char **ppDataType,

+                 char **ppSymbol,

+                 char **ppEqualSign,

+                 char **ppValue,

+                 char **ppSeparator,

+                 int *pNest)

+#else

+char * endFormal(pStart,

+			     ppDataType,

+				 ppSymbol,

+				 ppEqualSign,

+				 ppValue,

+				 ppSeparator,

+				 pNest)

+char *pStart;

+char **ppDataType;

+char **ppSymbol;

+char **ppEqualSign;

+char **ppValue;

+char **ppSeparator;

+int *pNest;

+

+#endif

+{

+  char *p = pStart;

+  char *q;

+

+  *ppDataType = NULL;

+  *ppSymbol = NULL;

+  *ppEqualSign = NULL;

+  *ppValue = NULL;

+  *ppSeparator = NULL;

+

+  *pNest = 0;

+

+  /* The first non-blank is the start of the datatype */

+

+  p = skipSpaces(p);

+  if (*p == 0) goto EXIT;

+  *ppDataType = p;

+

+  /* We are not looking for the symbol, we are looking

+     for the separator that follows the symbol.  Then

+     we'll back up.

+   

+     Search for the ',' or '=" or null terminator.

+   */

+

+  p = skipToSeparatorOrEqualSign(p, pNest);

+

+  if (*pNest != 0) goto EXIT;

+

+  /*

+     Work backwards to find start of symbol

+     Skip spaces between the end of symbol and separator

+     Assume that there are no spaces in the formal, but

+     there is a space preceding the formal

+  */

+

+  for (q = &p[-1]; q >= *ppDataType; q--) {

+    if (! isspace(*q)) break;

+  }

+  if (q < *ppDataType) goto EXIT;

+

+  /*

+     MR26 Handle things like: IIR_Bool (IIR_Decl::*constraint)()

+     Backup until we hit the end of a symbol string, then find the

+     start of the symbol string.  This wont' work for functions

+     with prototypes, but works for the most common cases.  For

+     others, use typedef names.

+   */

+

+/* MR26 */  for (q = q; q >= *ppDataType; q--) {

+/* MR26 */    if (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$') break;

+/* MR26 */  }

+/* MR26 */  if (q < *ppDataType) goto EXIT;

+

+  for (q = q; q >= *ppDataType; q--) {

+    if ( ! (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$')) break;

+  }

+

+  *ppSymbol = &q[1];

+

+  if (*p == ',' || *p == 0) {

+    *ppSeparator = p;

+    goto EXIT;

+  }

+

+  *ppEqualSign = p;

+  p = skipSpaces(++p);

+  *ppValue = p;

+  if (*p == 0) goto EXIT;

+

+

+  while (*p != 0 && *pNest == 0 && *p != ',') {

+      p = skipToSeparator(p, pNest);

+  }

+  if (*pNest == 0) *ppSeparator = p;

+

+EXIT:

+  if (*p == ',') p++;

+  return p;

+}

diff --git a/Source/Pccts/antlr/mode.h b/Source/Pccts/antlr/mode.h
new file mode 100644
index 0000000..c08bf31
--- /dev/null
+++ b/Source/Pccts/antlr/mode.h
@@ -0,0 +1,12 @@
+#define START 0

+#define STRINGS 1

+#define ACTION_STRINGS 2

+#define ACTION_CHARS 3

+#define ACTION_COMMENTS 4

+#define TOK_DEF_COMMENTS 5

+#define TOK_DEF_CPP_COMMENTS 6

+#define ACTION_CPP_COMMENTS 7

+#define CPP_COMMENTS 8

+#define COMMENTS 9

+#define ACTIONS 10

+#define PARSE_ENUM_FILE 11

diff --git a/Source/Pccts/antlr/mrhoist.c b/Source/Pccts/antlr/mrhoist.c
new file mode 100644
index 0000000..110bf59
--- /dev/null
+++ b/Source/Pccts/antlr/mrhoist.c
@@ -0,0 +1,3030 @@
+/*

+ * mrhoist.c

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33MR10

+ *

+ */

+

+#include <stdio.h>

+

+#include "pcctscfg.h"

+

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+#include <ctype.h>

+

+#ifdef __USE_PROTOS

+void dumppred(Predicate *);

+#else

+void dumppred();

+#endif

+

+/*

+  Try to determine whether predicate "first" is true for

+    all cases where "second" is true.  Comparison takes place

+    without regard to context.

+  Assumes that predicate symbols have been expanded.

+  Assumes that there are no NAND or NOR nodes

+

+*/

+

+#ifdef __USE_PROTOS

+int MR_secondPredicateUnreachable(Predicate *first,Predicate *second)

+#else

+int MR_secondPredicateUnreachable(first,second)

+  Predicate     *first;

+  Predicate     *second;

+#endif

+{

+  Predicate     *f;

+  Predicate     *s;

+

+  if (first == NULL) {

+    return 1;

+  } else if (second == NULL) {

+    return 0;

+  } else if (first->down == NULL && second->down == NULL) {

+    if (first->source == second->source &&

+        first->inverted == second->inverted) {

+      return 1; /* look identical - will never reach alt2 */

+    } else {

+      return 0; /* look different */

+    };

+  } else if (first->down == NULL && second->down != NULL) {

+

+    if (second->expr == PRED_AND_LIST) {

+

+      /* unreachable if first covers any child of second */

+

+      for (s=second->down; s != NULL; s=s->right) {

+        if (MR_secondPredicateUnreachable(first,s)) {

+          return 1;

+        };

+      };

+      return 0;

+    } else if (second->expr == PRED_OR_LIST) {

+

+      /* unreachable if first covers every child of second */

+

+      for (s=second->down; s != NULL; s=s->right) {

+        if (!MR_secondPredicateUnreachable(first,s)) {

+          return 0;

+        };

+      };

+      return 1;

+    } else {

+      require (0,"Illegal pred->expr");

+      return 0; /* MR20 Make compiler happy */

+    };

+  } else if (first->down != NULL && second->down == NULL) {

+    if (first->expr == PRED_AND_LIST) {

+

+      /* unreachable if every child of first covers second */

+

+      for (f=first->down; f != NULL; f=f->right) {

+        if (!MR_secondPredicateUnreachable(f,second)) {

+          return 0;

+        };

+      };

+      return 1;

+    } else if (first->expr == PRED_OR_LIST) {

+

+      /* unreachable if any child of first covers second */

+

+      for (f=first->down; f != NULL; f=f->right) {

+        if (MR_secondPredicateUnreachable(f,second)) {

+          return 1;

+        };

+      };

+      return 0;

+    } else {

+      require (0,"Illegal predicate->expr");

+      return 0; /* MR20 Make compiler happy */

+    };

+  } else {

+

+    if (first->expr == PRED_AND_LIST && second->expr == PRED_AND_LIST) {

+

+      /* unreachable if each child of first covers at least one child of second */

+

+      for (f=first->down; f != NULL ; f=f->right) {

+        for (s=second->down; s != NULL ; s=s->right) {

+          if (MR_secondPredicateUnreachable(f,s)) goto A_next_f;

+        };

+        return 0;

+A_next_f:

+        continue;

+      };

+      return 1;

+

+    } else if (first->expr == PRED_AND_LIST && second->expr == PRED_OR_LIST) {

+

+      /* unreachable if each child of first covers ALL of second's children */

+

+      for (f=first->down; f != NULL ; f=f->right) {

+        for (s=second->down; s != NULL ; s=s->right) {

+          if (!MR_secondPredicateUnreachable(f,s)) return 0;

+        };

+      };

+      return 1;

+

+    } else if (first->expr == PRED_OR_LIST && second->expr == PRED_AND_LIST) {

+

+      /* unreachable if any child of second is covered by any child of first */

+

+      for (f=first->down; f != NULL ; f=f->right) {

+        for (s=second->down; s != NULL ; s=s->right) {

+          if (MR_secondPredicateUnreachable(f,s)) return 1;

+        };

+      };

+      return 0;

+

+    } else if (first->expr == PRED_OR_LIST && second->expr == PRED_OR_LIST) {

+

+      /* unreachable if every child of second is covered by some child of first */

+

+      for (f=first->down; f != NULL ; f=f->right) {

+        for (s=second->down; s != NULL ; s=s->right) {

+          if (MR_secondPredicateUnreachable(f,s)) goto B_next_f;

+        };

+        return 0;

+B_next_f:

+       continue;

+      };

+      return 1;

+

+    } else {

+      require (0,"Illegal predicate->expr");

+      return 0; /* MR20 Make compiler happy */

+    };

+  };

+  return 0; /* MR20 MSVC 5.0 complains about missing return statement */

+}

+

+#ifdef __USE_PROTOS

+void MR_xxxIndent(FILE *f,int depth)

+#else

+void MR_xxxIndent(f,depth)

+  FILE  *f;

+  int   depth;

+#endif

+{

+  int   i;

+

+  for (i=0; i<depth ; i++) {

+    fprintf(f,"  ");

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_stderrIndent(int depth)

+#else

+void MR_stderrIndent(depth)

+  int   depth;

+#endif

+{

+  MR_xxxIndent(stderr,depth);

+}

+

+#ifdef __USE_PROTOS

+void MR_outputIndent(int depth)

+#else

+void MR_outputIndent(depth)

+  int   depth;

+#endif

+{

+  MR_xxxIndent(output,depth);

+}

+

+#ifdef __USE_PROTOS

+void MR_set_reuse(set *s)

+#else

+void MR_set_reuse(s)

+  set   *s;

+#endif

+{

+  set_free(*s);

+  *s=empty;

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpPredRuleRefStack(FILE *iounit,int indent)

+#else

+void MR_dumpPredRuleRefStack(iounit,indent)

+  FILE  *iounit;

+  int   indent;

+#endif

+{

+    int             i;

+    int             j;

+    int             count=MR_PredRuleRefStack.count;

+    RuleRefNode     *rrn=NULL;

+    Junction        *lastOne;

+

+    if (count == 0) {

+      fprintf(iounit,"empty\n");

+      return;

+    };

+    for (i=0; i < count; i++) {

+      rrn=(RuleRefNode *) MR_PredRuleRefStack.data[i];

+      for (j=0; j<indent; j++) fprintf(iounit," ");

+      fprintf(iounit,"#%-2d in rule %s (line %d %s) to rule %s\n",

+            i,rrn->rname,rrn->line,FileStr[rrn->file],rrn->text);

+    };

+    lastOne=MR_ruleReferenced(rrn);

+    if (lastOne != NULL) {

+      for (j=0; j<indent; j++) fprintf(iounit," ");

+      fprintf(iounit,"#%-2d in rule %s (line %d %s)\n",

+        count,lastOne->rname,lastOne->line,FileStr[lastOne->file]);

+    };

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpTreeF(FILE *f,int depth,Tree *tree,int across)

+#else

+void MR_dumpTreeF(f,depth,tree,across)

+  FILE  *f;

+  Tree  *tree;

+  int   depth;

+  int   across;

+#endif

+{

+    int     newAcross=across;

+

+	if (tree == NULL ) return;

+	if (tree->down != NULL ) {

+      fprintf(output,"\n");

+      MR_outputIndent(depth);

+      fprintf(output, "(root =");

+    };

+	if (tree->token == ALT ) {

+      fprintf(output," %-16s","Alt");

+	} else if (tree->token==EpToken ) {

+      fprintf(output,"(%d)%13s",tree->v.rk," ");

+	} else {

+      fprintf(output," %-16s",TerminalString(tree->token));

+    };

+    if (tree->down != NULL) {

+      fprintf(output,"\n");

+      MR_outputIndent(depth+1);

+      MR_dumpTreeF(f,depth+1,tree->down,1);

+      newAcross=0;

+      fprintf(output,"\n");

+      MR_outputIndent(depth);

+      fprintf(output,")");

+    };

+    if (newAcross > 3) {

+      fprintf(output,"\n");

+      MR_outputIndent(depth);

+      newAcross=0;

+    };

+    MR_dumpTreeF(f,depth,tree->right,newAcross+1);

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpTreeX(int depth,Tree *tree,int across)

+#else

+void MR_dumpTreeX(depth,tree,across)

+  Tree  *tree;

+  int   depth;

+  int   across;

+#endif

+{

+  MR_dumpTreeF(output,depth,tree,across);

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpTokenSet(FILE *f,int depth,set s)

+#else

+void MR_dumpTokenSet(f,depth,s)

+  FILE  *f;

+  int   depth;

+  set   s;

+#endif

+{

+    int     i;

+    int     j;

+

+    unsigned  *pdq;

+

+    if (set_nil(s)) {

+      fprintf(f,"\n");

+      MR_xxxIndent(f,depth+1);

+      fprintf(f,"nil\n");

+      return;

+    };

+

+    pdq=set_pdq(s);

+    require(pdq != NULL,"set_pdq failed");

+    i=0;

+    for (i=0 ; ; i=i+4) {

+      fprintf(f,"\n");

+      MR_xxxIndent(f,depth+1);

+      for (j=0; j < 4 ; j++) {

+        if (pdq[i+j] == nil) break;

+        fprintf(f," %-16s",TerminalString(pdq[i+j]));

+      };

+      if (pdq[i+j] == nil) break;

+    };

+    fprintf(f,"\n");

+    free( (char *) pdq);

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpPred1(int depth,Predicate *p,int withContext)

+#else

+void MR_dumpPred1(depth,p,withContext)

+  int           depth;

+  Predicate     *p;

+  int           withContext;

+#endif

+{

+  unsigned      k;

+

+  if (p == NULL) {

+    MR_outputIndent(depth);

+    fprintf(output,"The predicate is empty (or always true)\n\n");

+    return;

+  };

+  if (p->down != NULL) {

+    MR_outputIndent(depth);

+    if (p->inverted) {

+

+        /* MR14a Left out print expression in fprintf

+                 Reported by Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de)

+        */

+

+      if (p->expr == PRED_AND_LIST) fprintf(output,"%s NAND (not AND) expr\n\n",p->expr);

+      if (p->expr == PRED_OR_LIST) fprintf(output,"%s NOR (not OR) expr\n\n",p->expr);

+    } else {

+      fprintf(output,"%s expr\n\n",p->expr);

+    };

+  } else {

+    MR_outputIndent(depth);

+    fprintf(output,"pred %s <<%s>>?\n",

+            (p->inverted ? " *not*" : ""),

+            (p->expr == NULL ? "null expr" : p->expr));

+    MR_outputIndent(depth+1);

+    fprintf(output,"              ");

+    fprintf(output,"  depth=k=%d",p->k);

+    if (p->source != NULL && p->source->guardpred) {

+      fprintf(output,"  (\"=>\" guard)");

+    }

+    if (p->source != NULL && p->source->ampersandPred != NULL) {

+      fprintf(output,"  (\"&&\" guard)");

+    };

+    k=set_int(p->completionSet);

+    if (k != nil) {

+      fprintf(output," Incomplete Set at k=%d !",k);

+    };

+    k=set_int(p->completionTree);

+    if (k != nil) {

+      fprintf(output," Incomplete Tree at k=%d !",k);

+    };

+    if (p->source != NULL) {

+      fprintf(output,"  rule %s  line %d  %s",

+                    p->source->rname,p->source->line,FileStr[p->source->file]);

+    };

+    fprintf(output,"\n");

+    if (withContext &&

+            (HoistPredicateContext ||

+             ! set_nil(p->scontext[1]) ||

+             p->tcontext != NULL)) {

+      if (p->k == 1) {

+        MR_outputIndent(depth+1);

+        fprintf(output,"set context: ");

+        MR_dumpTokenSet(output,depth+1,p->scontext[1]);

+      }

+      if (p->k != 1) {

+        MR_outputIndent(depth+1);

+        fprintf(output,"tree context:");

+        if (p->tcontext == NULL) {

+          fprintf(output," null");

+        } else {

+          MR_dumpTreeX(depth+2,p->tcontext,0);

+        };

+        fprintf(output,"\n");

+      };

+    };

+    fprintf(output,"\n");

+  };

+  if (p->down != NULL) {

+    MR_dumpPred1(depth+1,p->down,withContext);

+  };

+  if (p->right != NULL) {

+    MR_dumpPred1(depth,p->right,withContext);

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpPred(Predicate *p,int withContext)

+#else

+void MR_dumpPred(p,withContext)

+  Predicate     *p;

+  int           withContext;

+#endif

+{

+  MR_dumpPred1(0,p,withContext);

+}

+

+#ifdef __USE_PROTOS

+Tree * MR_make_tree_from_set(set s)

+#else

+Tree * MR_make_tree_from_set(s)

+  set   s;

+#endif

+{

+  Tree  *t=NULL;

+  Tree  *node;

+  Tree  **tp=&t;

+  int   i;

+

+  unsigned *pdq=set_pdq(s);

+

+  if (pdq != NULL) {

+    for (i=0 ; pdq[i] != nil ; i++) {

+      node=tnode( (int) pdq[i]);

+      *tp=node;

+      tp=&(node->right);

+    };

+    *tp=NULL;

+    free ( (char *) pdq);

+  };

+  return t;

+}

+

+#ifdef __USE_PROTOS

+void MR_check_pred_too_long(Predicate *p,set completion)

+#else

+void MR_check_pred_too_long(p,completion)

+  Predicate     *p;

+  set           completion;

+#endif

+{

+  if (p != NULL &&

+      p->source != NULL &&

+      ! p->source->predTooLong) {

+    if ( !set_nil(completion)) {

+      p->source->predTooLong=1;

+warnFL("It is unusual (but ok) for a semantic predicate to test context past the end of its own rule",

+                                FileStr[p->source->file],p->source->line);

+    };

+  };

+}

+

+#ifdef __USE_PROTOS

+int MR_predicate_context_completed(Predicate *p)

+#else

+int MR_predicate_context_completed(p)

+  Predicate     *p;

+#endif

+{

+  if (p == NULL) return 1;

+  if (p->expr != PRED_AND_LIST &&

+      p->expr != PRED_OR_LIST) {

+    if ( ! set_nil(p->completionSet)) return 0;

+    if ( ! set_nil(p->completionTree)) return 0;

+  };

+  return MR_predicate_context_completed(p->down) &

+         MR_predicate_context_completed(p->right);

+}

+

+#ifdef __USE_PROTOS

+Node * MR_advance(Node *n)

+#else

+Node * MR_advance(n)

+  Node  *n;

+#endif

+{

+    if (n == NULL) return NULL;

+    switch (n->ntype) {

+      case nJunction:   return ((Junction *)n)->p1;

+      case nToken:      return ((TokNode *)n)->next;

+      case nRuleRef:    return ((RuleRefNode *)n)->next;

+      case nAction:     return ((ActionNode *)n)->next;

+      default:          return NULL;

+    };

+  return NULL; /* MSVC 5.0 complains about missing return statement */

+}

+

+#ifdef __USE_PROTOS

+Junction * MR_find_endRule(Node *n)

+#else

+Junction * MR_find_endRule(n)

+  Node  *n;

+#endif

+{

+    Node    *next;

+    if (n == NULL) return NULL;

+    for (next=n; next != NULL; next=MR_advance(next)) {

+      if (next->ntype == nJunction &&

+            ( (Junction *) next)->jtype == EndRule) {

+        break;

+      };

+    };

+    return (Junction *)next;

+}

+

+/*

+   Intersection:  a branch which is shorter is chosen

+   over one which is longer: (A B C) intersect (A B) yields (A B).

+

+   AND: a branch which is longer is chosen over the one

+   which is shorter: (A B C) AND (A B) yields (A B C)

+

+*/

+

+#ifdef __USE_PROTOS

+Tree *MR_computeTreeIntersection(Tree *l,Tree *r)

+#else

+Tree *MR_computeTreeIntersection(l,r)

+    Tree    *l;

+    Tree    *r;

+#endif

+{

+    Tree    *result=NULL;

+    Tree    **tail;

+    Tree    *p;

+    Tree    *q;

+    Tree    *match;

+

+    if (l == NULL || r == NULL) return NULL;

+    for (p=l; p != NULL; p=p->right) {

+      require(p->token != EpToken,"MR_computeTreeIntersection: p->EpToken unexpected\n");

+      require (p->token != ALT,"MR_computeTreeIntersection: p->ALT unexpected\n");

+    };

+    for (q=r; q != NULL; q=q->right) {

+      require(q->token != EpToken,"MR_computeTreeIntersection: q->EpToken unexpected\n");

+      require(q->token != ALT,"MR_computeTreeIntersection: q->ALT unexpected\n");

+    };

+

+    result=tnode(ALT);

+    tail=&(result->down);

+

+    for (p=l; p != NULL ; p=p->right) {

+      for (q=r; q != NULL ; q=q->right) {

+        if (p->token == q->token) {

+          match=tnode(p->token);

+          match->down=MR_computeTreeIntersection(p->down,q->down);

+          *tail=match;

+          tail=&(match->right);

+        };

+      };

+    };

+

+    *tail=NULL;

+    result=tshrink(result);

+    result=tflatten( result );

+    result=tleft_factor( result );

+    return result;

+}

+

+/* the predicates which are ANDed together have a common

+   context:  they must all have common roots.  Thus the

+   AND operation is more like an OR operation because

+   branches which are longer are grafted onto shorter

+   branches of the AND tree.  For instance combining

+   (A B C) with (A B C D) gives (A B C D).  There

+   should never be a case of (A B C) and (A B D) because

+   they have the same context.

+

+   Actually, this may not be true once one throws in

+   guard predicates which are defined by the user, not

+   the context.

+*/

+

+/* requires input trees to be in "canonical" format */

+

+#ifdef __USE_PROTOS

+Tree *MR_computeTreeAND(Tree *l,Tree *r)

+#else

+Tree *MR_computeTreeAND(l,r)

+    Tree    *l;

+    Tree    *r;

+#endif

+{

+    Tree    *result=NULL;

+    Tree    **tail;

+    Tree    *p;

+    Tree    *q;

+    Tree    *match;

+

+    if (l == NULL) return tdup(r);

+    if (r == NULL) return tdup(l);

+

+    for (p=l; p != NULL; p=p->right) {

+/**** require(p->token != EpToken,"MR_computeTreeAND: p->EpToken unexpected\n"); ****/

+      require (p->token != ALT,"MR_computeTreeAND: p->ALT unexpected\n");

+    };

+    for (q=r; q != NULL; q=q->right) {

+/**** require(q->token != EpToken,"MR_computeTreeAND: q->EpToken unexpected\n"); ****/

+      require(q->token != ALT,"MR_computeTreeAND: q->ALT unexpected\n");

+    };

+

+    result=tnode(ALT);

+    tail=&(result->down);

+

+    for (p=l; p != NULL ; p=p->right) {

+      for (q=r; q != NULL ; q=q->right) {

+        if (p->token == q->token) {

+          match=tnode(p->token);

+          match->down=MR_computeTreeAND(p->down,q->down);

+          *tail=match;

+          tail=&(match->right);

+        };

+      };

+    };

+

+    *tail=NULL;

+    result=tshrink(result);

+    result=tflatten( result );

+    result=tleft_factor( result );

+    return result;

+}

+

+#ifdef __USE_PROTOS

+void MR_union_plain_sets1(Predicate *p,set *theUnion)

+#else

+void MR_union_plain_sets1(p,theUnion)

+  Predicate     *p;

+  set           *theUnion;

+#endif

+{

+  if (p == NULL) return;

+  MR_union_plain_sets1(p->down,theUnion);

+  MR_union_plain_sets1(p->right,theUnion);

+  set_orin(theUnion,p->plainSet);

+  return;

+}

+

+#ifdef __USE_PROTOS

+set MR_union_plain_sets(Predicate *p)

+#else

+set MR_union_plain_sets(p)

+  Predicate     *p;

+#endif

+{

+  set   theUnion;

+

+  theUnion=empty;

+

+  MR_union_plain_sets1(p,&theUnion);

+  return theUnion;

+}

+

+/* does NOT left factor: do not want to merge

+     (A B) with (A) to get (A B)

+   in fact the opposite: (A B) with (A) gives (A)

+*/

+

+#ifdef __USE_PROTOS

+Tree *MR_compute_pred_tree_ctxXX(Predicate *p)

+#else

+Tree *MR_compute_pred_tree_ctxXX(p)

+  Predicate     *p;

+#endif

+{

+    Tree        *result=NULL;

+    Predicate   *q;

+    Tree        *t;

+

+    if (p == NULL) return NULL;

+

+/* this appears strange: why do we OR the context

+   of and AND predicate ?  It is because of the way

+   that predicates are evaluated: if the context is

+   wrong then it's the same as if the predicate was

+   true.  That means that even when one leg of an

+   AND has unmatched context, if the other leg has

+   matched context and is true then the predicate

+   succeeds.  It's only when all the legs have unmatched

+   context that this one can skip evaluation of the

+   predicates.

+*/

+    if (p->expr == PRED_OR_LIST ||

+        p->expr == PRED_AND_LIST) {

+      for (q=p->down; q != NULL ; q=q->right) {

+        t=MR_compute_pred_tree_ctxXX(q);

+        result=tappend(result,t);

+        t=NULL;

+      };

+

+      result=tshrink(result);

+      result=tflatten( result );

+

+/* does NOT left factor: do not want to merge

+     (A B) with (A) to get (A B)

+   in fact the opposite: (A B) with (A) gives (A)

+*/

+

+/**** result=tleft_factor( result ); ****/

+      return result;

+    };

+

+#if 0

+**    if (p->expr == PRED_AND_LIST) {

+**

+**      Predicate     *l;

+**      Predicate     *r;

+**      Tree          *l1;

+**      Tree          *r1;

+**      Tree          *prevl1;

+**

+**      l=p->down;

+**      require (l->right != NULL,"MR_compute_pred_tree - AND has only one child");

+**

+**/* l1 and r1 should already be in "canonical" format */

+**

+**      l1=MR_compute_pred_tree(l);

+**      for (r=l->right; r != NULL; r=r->right) {

+**        r1=MR_compute_pred_tree(r);

+**        prevl1=l1;

+**        l1=MR_computeTreeAND(l1,r1);

+**        Tfree(r1);

+**        Tfree(prevl1);

+**      };

+**

+**/* result from computeTreeAND should be in "canonical" format */

+**

+**      result=l1;

+**

+**/* result of MR_computeTreeAND should be in "canonical" format */

+**

+**      return result;

+**    };

+#endif

+

+    if (p->k == 1) {

+      result=MR_make_tree_from_set(p->scontext[1]);

+    } else {

+      result=tdup(p->tcontext);

+      result=MR_remove_epsilon_from_tree(result);

+      result=tshrink(result);

+      result=tflatten(result);

+      result=tleft_factor(result);

+    };

+    return result;

+}

+

+#ifdef __USE_PROTOS

+void MR_pred_depth(Predicate *p,int *maxDepth)

+#else

+void MR_pred_depth(p,maxDepth)

+  Predicate     *p;

+  int           *maxDepth;

+#endif

+{

+  if (p == NULL) return;

+  if (p->expr != PRED_OR_LIST &&

+      p->expr != PRED_AND_LIST) {

+    if (p->k > *maxDepth) *maxDepth=p->k;

+  };

+  MR_pred_depth(p->down,maxDepth);

+  MR_pred_depth(p->right,maxDepth);

+}

+

+/* this computes the OR of all the contexts */

+

+#ifdef __USE_PROTOS

+set MR_compute_pred_set(Predicate *p)

+#else

+set MR_compute_pred_set(p)

+  Predicate     *p;

+#endif

+{

+    set         result;

+    Predicate   *q;

+

+    result=empty;

+

+    if (p == NULL) return empty;

+

+    if (p->expr == PRED_OR_LIST ||

+        p->expr == PRED_AND_LIST) {         /* yes, I do mean PRED_AND_LIST !   */

+                                            /* remember: r1: (A)? => <<p>>? r2; */

+                                            /*           r2: (B)? => <<q>>? r3; */

+      set   t;

+

+      t=empty;

+      result=empty;

+

+      for (q=p->down; q != NULL; q=q->right) {

+        t=MR_compute_pred_set(q);

+        set_orin(&result,t);

+        set_free(t);

+      };

+      return result;

+    } else if (p->k > 1) {

+      return empty;

+    } else {

+      return set_dup(p->scontext[1]);

+    };

+}

+

+#ifdef __USE_PROTOS

+set MR_First(int ck,Junction *j,set *incomplete)

+#else

+set MR_First(ck,j,incomplete)

+  int       ck;

+  Junction  *j;

+  set       *incomplete;

+#endif

+{

+    Junction    *p;

+    set         tokensUsed;

+

+    tokensUsed=empty;

+

+	require(j->ntype==nJunction, "MR_First: non junction passed");

+

+	p = analysis_point((Junction *)j->p1);

+

+	REACH(p,ck,incomplete,tokensUsed);

+

+    return tokensUsed;

+}

+

+#ifdef __USE_PROTOS

+void MR_cleanup_pred_trees(Predicate *p)

+#else

+void MR_cleanup_pred_trees(p)

+  Predicate     *p;

+#endif

+{

+  Tree      *t;

+

+  if (p == NULL) return;

+  if (p->expr != PRED_OR_LIST &&

+      p->expr != PRED_AND_LIST) {

+    t=p->tcontext;

+    t=tshrink(t);

+    t=tflatten(t);

+    t=tleft_factor(t);

+    p->tcontext=t;

+  };

+  MR_cleanup_pred_trees(p->down);

+  MR_cleanup_pred_trees(p->right);

+}

+

+/* does NOT return canonical tree */

+

+#ifdef __USE_PROTOS

+Tree * MR_remove_epsilon_from_tree(Tree *t)

+#else

+Tree * MR_remove_epsilon_from_tree(t)

+  Tree  *t;

+#endif

+{

+  if (t == NULL) return NULL;

+

+  /* I think ALT can be ignored as a special case */

+

+  if (t->token != EpToken) {

+    t->down=MR_remove_epsilon_from_tree(t->down);

+    t->right=MR_remove_epsilon_from_tree(t->right);

+    return t;

+  } else {

+    Tree    *u;

+    u=MR_remove_epsilon_from_tree(t->right);

+    t->right=NULL;

+    Tfree(t);

+    return u;

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_complete_set(int predDepth,set *tokensUsed,set *incomplete)

+#else

+void MR_complete_set(predDepth,tokensUsed,incomplete)

+  int       predDepth;

+  set       *tokensUsed;

+  set       *incomplete;

+#endif

+{

+    int             i;

+    RuleRefNode     *ruleRef;

+	set             rk2;

+    set             b;

+	int             k2;

+    Junction        *save_MR_RuleBlkWithHalt;

+

+    if (set_int(*incomplete) > (unsigned) predDepth) {

+      return;

+    };

+

+    require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count,

+                "RuleRefStack and RuleBlkWithHaltStack not same size");

+

+    require(MR_RuleBlkWithHalt == NULL ||

+         (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),

+                     "RuleBlkWithHalt has no halt set");

+

+    save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;

+

+    if (MR_RuleBlkWithHalt != NULL) {

+      MR_RuleBlkWithHalt->end->halt=FALSE;

+    };

+

+    for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) {

+      ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i];

+      if (ruleRef == NULL) continue;

+

+      MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i];

+      if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE;

+

+      rk2=empty;

+      b=empty;

+

+      while ( !set_nil(*incomplete) ) {

+		k2=set_int(*incomplete);

+        if (k2 > predDepth) break;                    /* <=== another exit from loop */

+		set_rm(k2,*incomplete);

+        REACH(ruleRef->next,k2,&rk2,b);

+		set_orin(tokensUsed,b);

+		set_free(b);

+      };

+

+      if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE;

+

+	  set_orin(incomplete,rk2);                       /* remember what we couldn't do */

+      set_free(rk2);

+	  if (set_int(*incomplete) > (unsigned) predDepth) break;    /* <=== another exit from loop */

+    };

+

+    MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt;

+    if (MR_RuleBlkWithHalt != NULL) {

+      MR_RuleBlkWithHalt->end->halt=TRUE;

+    };

+}

+

+#ifdef __USE_PROTOS

+void MR_complete_tree(int predDepth,Tree **t,set *incomplete)

+#else

+void MR_complete_tree(predDepth,t,incomplete)

+  int       predDepth;

+  Tree      **t;

+  set       *incomplete;

+#endif

+{

+    int             i;

+    RuleRefNode     *ruleRef;

+	set             rk2;

+    Tree            *u;

+	unsigned        k2;

+    Junction        *save_MR_RuleBlkWithHalt;

+    int             saveConstrainSearch;

+

+    if (set_int(*incomplete) > (unsigned) predDepth) {

+      return;

+    };

+

+    require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count,

+                "RuleRefStack and RuleBlkWithHaltStack not same size");

+

+    require(MR_RuleBlkWithHalt == NULL ||

+         (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),

+                     "RuleBlkWithHalt has no halt set");

+

+    save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;

+    saveConstrainSearch=ConstrainSearch;

+    ConstrainSearch=0;

+

+    if (MR_RuleBlkWithHalt != NULL) {

+      MR_RuleBlkWithHalt->end->halt=FALSE;

+    };

+

+    for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) {

+      ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i];

+      if (ruleRef == NULL) continue;

+

+      MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i];

+

+      if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE;

+

+      rk2=empty;

+

+      while ( !set_nil(*incomplete) ) {	

+		k2 = set_int(*incomplete);

+        if (k2 > (unsigned) predDepth) break;       /* <=== another exit from loop */

+		set_rm(k2,*incomplete);

+		u = NULL;

+

+        TRAV(ruleRef->next,k2,&rk2,u);

+

+			/* any subtrees missing k2 tokens, add u onto end */

+

+		*t=tlink(*t,u,k2);

+        Tfree(u);

+      }

+

+	  set_orin(incomplete,rk2);         /* remember what we couldn't do */

+      set_free(rk2);

+

+      if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE;

+

+	  if (set_int(*incomplete) > (unsigned) predDepth) break;    /* <=== another exit from loop */

+    };

+

+    MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt;

+

+    if (MR_RuleBlkWithHalt != NULL) {

+      MR_RuleBlkWithHalt->end->halt=TRUE;

+    };

+    ConstrainSearch=saveConstrainSearch;

+}

+

+#ifdef __USE_PROTOS

+void MR_complete_predicates(int predDepth,Predicate *pred)

+#else

+void MR_complete_predicates(predDepth,pred)

+  int           predDepth;

+  Predicate     *pred;

+#endif

+{

+  if (pred == NULL) return;

+  if (pred->expr != PRED_AND_LIST &&

+      pred->expr != PRED_OR_LIST) {

+    MR_complete_set(predDepth,&(pred->scontext[1]),&(pred->completionSet));

+    MR_complete_tree(predDepth,&(pred->tcontext),&(pred->completionTree));

+  };

+  MR_complete_predicates(predDepth,pred->down);

+  MR_complete_predicates(predDepth,pred->right);

+}

+

+#ifdef __USE_PROTOS

+Junction * MR_junctionWithoutP2(Junction *j)

+#else

+Junction * MR_junctionWithoutP2(j)

+  Junction  *j;

+#endif

+{

+  Junction  *thisAlt;

+

+/* don't want to follow p2 to the next alternative of this rule */

+/* insert a generic node with null p2 if necessary              */

+/* however FIRST requires a junction                            */

+

+  thisAlt=j;

+  if (thisAlt->p2 != NULL) {

+    if (thisAlt->p1->ntype == nJunction) {

+      thisAlt=(Junction *) thisAlt->p1;

+    } else {

+      thisAlt=newJunction();

+      thisAlt->p1=j->p1;

+      thisAlt->rname=j->rname;

+      thisAlt->file=j->file;

+      thisAlt->line=j->line;

+      j->p1=(Node *)thisAlt;

+    };

+  };

+  return thisAlt;

+}

+

+#ifdef __USE_PROTOS

+int MR_tree_equ(Tree *big, Tree *small) {

+#else

+int MR_tree_equ(big,small)

+  Tree  *big;

+  Tree  *small;

+{

+#endif

+

+  Tree      *b;

+  Tree      *s;

+  int       bcount=0;

+  int       scount=0;

+

+  if (small == NULL && big == NULL) return 1;

+  if (small == NULL) return 0;

+  if (big == NULL) return 0;

+

+  if (small->token == ALT) {

+    require(small->right == NULL,

+                "MR_tree_equ: small: ALT node has siblings");

+    return MR_tree_equ(big,small->down);

+  };

+  if (big->token == ALT) {

+    require(big->right == NULL,

+                "MR_tree_equ: big: ALT node has siblings");

+    return MR_tree_equ(big->down,small);

+  };

+  for (s=small; s != NULL; s=s->right) {

+    scount++;

+    require(s->token != EpToken,"MR_tree_equ: s->EpToken unexpected\n");

+  };

+  for (b=big; b != NULL; b=b->right) {

+    bcount++;

+    require(b->token != EpToken,"MR_tree_equ: b->EpToken unexpected\n");

+  };

+

+  if (bcount != scount) return 0;

+

+  for (s=small; s != NULL; s=s->right) {

+    for (b=big; b!= NULL; b=b->right) {

+      if (s->token == b->token) {

+        if (MR_tree_equ(b->down,s->down)) goto next_s;

+      };

+    };

+    return 0;

+next_s:

+    continue;

+  };

+  return 1;

+}

+

+/* this does not compare sources - only contexts ! */

+

+#ifdef __USE_PROTOS

+int MR_identicalContext(Predicate *p,Predicate *q)

+#else

+int MR_identicalContext(p,q)

+  Predicate     *p;

+  Predicate     *q;

+#endif

+{

+  if (p->k != q->k) return 0;

+  require ( (p->tcontext == NULL) == (q->tcontext == NULL),

+        "tcontext inconsistent");

+  if (p->k == 1) {

+    return set_equ(p->scontext[1],q->scontext[1]);

+  } else {

+    return MR_tree_equ(p->tcontext,q->tcontext);

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_reportSetSuppression(int predDepth,

+            set predSet,set plainSet,Junction *jPred,Junction *jPlain,Predicate *p)

+#else

+void MR_reportSetSuppression(predDepth,predSet,plainSet,jPred,jPlain,p)

+  int       predDepth;

+  set       predSet;

+  set       plainSet;

+  Junction  *jPred;

+  Junction  *jPlain;

+  Predicate *p;

+#endif

+{

+  if (InfoP) {

+    fprintf(output,"\n#if 0\n\n");

+    fprintf(output,"Hoisting of predicate suppressed by alternative without predicate.\n");

+    fprintf(output,"The alt without the predicate includes all cases where the predicate is false.\n\n");

+    fprintf(output,"   WITH predicate: line %d  %s\n",jPred->line,FileStr[jPred->file]);

+    if (jPlain != NULL) {

+      fprintf(output,"   WITHOUT predicate: line %d  %s\n",jPlain->line,FileStr[jPlain->file]);

+    } else {

+      fprintf(output,"   WITHOUT predicate: all alternatives without predicates (combined)\n");

+    };

+    if (predDepth == 1) {

+      fprintf(output,"\nThe context set for the predicate:\n");

+      MR_dumpTokenSet(output,1,predSet);

+    };

+    fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n");

+    MR_dumpTokenSet(output,1,plainSet);

+    fprintf(output,"\nThe predicate:\n\n");

+    MR_dumpPred1(1,p,1);

+    fprintf(output,"Chain of referenced rules:\n\n");

+    MR_dumpPredRuleRefStack(output,4);

+    fprintf(output,"\n#endif\n");

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_reportSetRestriction(int predDepth,set predSet,set plainSet,

+            Junction *jPred,Junction *jPlain,Predicate *origPred,Predicate *newPred)

+#else

+void MR_reportSetRestriction(predDepth,predSet,plainSet,jPred,jPlain,origPred,newPred)

+  int       predDepth;

+  set       predSet;

+  set       plainSet;

+  Junction  *jPred;

+  Junction  *jPlain;

+  Predicate *origPred;

+  Predicate *newPred;

+#endif

+{

+  set       intersect;

+

+  intersect=empty;

+

+  if (! InfoP) return;

+  fprintf(output,"\n#if 0\n\n");

+  fprintf(output,"Restricting the context of a predicate because of overlap in the lookahead set\n");

+  fprintf(output,"  between the alternative with the semantic predicate and one without\n");

+  fprintf(output,"Without this restriction the alternative without the predicate could not\n");

+  fprintf(output,"  be reached when input matched the context of the predicate and the predicate\n");

+  fprintf(output,"  was false.\n\n");

+

+  fprintf(output,"   WITH predicate: line %d  %s\n",jPred->line,FileStr[jPred->file]);

+  if (jPlain != NULL) {

+    fprintf(output,"   WITHOUT predicate: line %d  %s\n",jPlain->line,FileStr[jPlain->file]);

+  } else {

+    fprintf(output,"   WITHOUT predicate: all alternatives without predicates (combined)\n");

+  };

+  if (predDepth == 1) {

+    fprintf(output,"\nThe original context set for the predicate:\n");

+    MR_dumpTokenSet(output,1,predSet);

+  };

+  fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n");

+  MR_dumpTokenSet(output,1,plainSet);

+  if (predDepth == 1) {

+    fprintf(output,"\nThe intersection of the two sets\n");

+    intersect=set_and(predSet,plainSet);

+    MR_dumpTokenSet(output,1,intersect);

+    set_free(intersect);

+  };

+  fprintf(output,"\nThe original predicate:\n\n");

+  MR_dumpPred1(1,origPred,1);

+  fprintf(output,"The new (modified) form of the predicate:\n\n");

+  MR_dumpPred1(1,newPred,1);

+  fprintf(output,"#endif\n");

+}

+

+/* don't use Pass3 by itself unless you know that inverted is not important */

+

+#ifdef __USE_PROTOS

+Predicate * MR_removeRedundantPredPass3(Predicate *p)

+#else

+Predicate * MR_removeRedundantPredPass3(p)

+  Predicate *p;

+#endif

+{

+  Predicate     *q;

+

+  if (p == NULL) return NULL;

+  p->right=MR_removeRedundantPredPass3(p->right);

+  p->down=MR_removeRedundantPredPass3(p->down);

+  if (p->redundant) {

+    q=p->right;

+    p->right=NULL;

+    predicate_free(p);

+    return q;

+  };

+  if (p->expr == PRED_AND_LIST ||

+      p->expr == PRED_OR_LIST) {

+    if (p->down == NULL) {

+      q=p->right;

+      p->right=NULL;

+      predicate_free(p);

+      return q;

+    };

+    if (p->down != NULL && p->down->right == NULL) {

+      q=p->down;

+      q->right=p->right;

+      p->right=NULL;

+      p->down=NULL;

+      return q;

+    };

+  };

+  return p;

+}

+

+#ifdef __USE_PROTOS

+void MR_removeRedundantPredPass2(Predicate *p)

+#else

+void MR_removeRedundantPredPass2(p)

+  Predicate *p;

+#endif

+{

+  Predicate     *q;

+

+  if (p == NULL) return;

+

+  if (p->expr == PRED_AND_LIST) {

+    for (q=p->down ; q != NULL ; q=q->right) {

+      MR_removeRedundantPredPass2(q);

+      if (q->isConst) {

+        if (q->constValue == 0) {

+          p->isConst=1;

+          p->constValue=0;

+          return;

+        } else {

+          q->redundant=1;

+        };

+      };

+    };

+  };

+

+  if (p->expr == PRED_OR_LIST) {

+    for (q=p->down ; q != NULL ; q=q->right) {

+      MR_removeRedundantPredPass2(q);

+      if (q->isConst) {

+        if (q->constValue == 0) {

+          q->redundant=1;

+        } else {

+          p->isConst=1;

+          p->constValue=1;

+          return;

+        };

+      };

+    };

+  };

+

+  return;

+}

+

+#if 0

+   this totally ignores the implications of guarded predicates

+     in which the part after the guard could possibly cover a predicate.

+   that would be much harder:

+

+        rule : (A)? => <<p>>? sub1;     /* 1 */

+             | (B)? => <<r>>? sub2      /* 2 */

+        sub1 : (A)? => <<q>>? A B       /* 3 */

+             | B                        /* 4 - suppresses line 2 */

+             ;

+#endif

+

+#ifdef __USE_PROTOS

+void MR_apply_restriction1(Predicate *pred,set *plainSet,int *changed)

+#else

+void MR_apply_restriction1(pred,plainSet,changed)

+  Predicate     *pred;

+  set           *plainSet;

+  int           *changed;

+#endif

+{

+  if (pred == NULL) return;

+  MR_apply_restriction1(pred->right,plainSet,changed);

+  if (pred->down != NULL) {

+    MR_apply_restriction1(pred->down,plainSet,changed);

+  } else {

+    set     t;

+    if (pred->k == 1) {

+      t=set_dif(pred->scontext[1],*plainSet);

+      if (*changed == 0 &&

+          !set_equ(t,pred->scontext[1])) {

+        *changed=1;

+      };

+      if (set_nil(t)) {

+        pred->redundant=1;

+      };

+      set_free(pred->scontext[1]);

+      pred->scontext[1]=t;

+    };

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_orin_plainSet(Predicate *p,set plainSet)

+#else

+void MR_orin_plainSet(p,plainSet)

+  Predicate     *p;

+  set           plainSet;

+#endif

+{

+  if (p == NULL) return;

+  MR_orin_plainSet(p->down,plainSet);

+  MR_orin_plainSet(p->right,plainSet);

+  set_orin(&p->plainSet,plainSet);

+}

+

+Predicate   *PRED_SUPPRESS;

+

+#ifdef __USE_PROTOS

+Predicate * MR_find_in_aSubBlk(Junction *alt)

+#else

+Predicate * MR_find_in_aSubBlk(alt)

+  Junction  *alt;

+#endif

+{

+    Predicate       *root=NULL;

+    Predicate       **tail=NULL;

+

+	Junction        *p;

+

+    int             nAlts=0;

+    Junction        **jList;

+    Predicate       **predList;

+    int             *matchList;

+    set             predSet;

+    int             i;

+    int             j;

+    int             m;

+    int             predDepth;

+    set             incomplete;

+    set             union_plainSet;

+    set             setChange;

+    int             changed;

+    Predicate       *newPred;

+    set             setDif;

+    Predicate       *origPred;

+    int             depth1=1;             /* const int */

+    set             *plainContext;

+    set             plainSet;

+

+    predSet=empty;

+    incomplete=empty;

+    union_plainSet=empty;

+    setChange=empty;

+    setDif=empty;

+    plainSet=empty;

+

+    if (PRED_SUPPRESS == NULL) {

+      PRED_SUPPRESS=new_pred();

+      PRED_SUPPRESS->expr="Predicate Suppressed";

+    };

+

+    /* this section just counts the number of "interesting" alternatives  */

+    /*   in order to allocate arrays                                      */

+

+	for (p=alt; p!=NULL; p=(Junction *)p->p2) {

+	  /* ignore empty alts */

+	  if ( p->p1->ntype != nJunction ||

+	        ((Junction *)p->p1)->jtype != EndBlk )	{

+        nAlts++;

+      };

+    };

+

+    /* if this is a (...)+ block then don't count the last alt because

+       it can't be taken until at least one time through the block.

+       In other words it isn't a real choice until the (...)+ is entered

+         at which point the hoisting issue is moot.

+       Maybe look at "ignore" instead ?

+    */

+

+    if (alt->jtype == aPlusBlk) {

+      nAlts--;

+    };

+

+    jList=(Junction **)calloc(nAlts,sizeof(Junction *));

+    require(jList!=NULL,"cannot allocate MR_find_in_aSubBlk jList");

+

+    plainContext=(set *)calloc(nAlts,sizeof(set));

+    require(plainContext!=NULL,"cannot allocate MR_find_in_aSubBlk plainContext");

+    for (m=0; m < nAlts; m++) plainContext[m]=empty;

+

+    predList=(Predicate **)calloc(nAlts,sizeof(Predicate *));

+    require(predList!=NULL,"cannot allocate MR_find_in_aSubBlk predList");

+

+    matchList=(int *)calloc(nAlts,sizeof(int));

+    require(matchList!=NULL,"cannot allocate MR_find_in_aSubBlk matchList");

+

+    /* this section just fills in the arrays previously allocated       */

+    /* the most interesting one is matchList[]                          */

+    /*                                                                  */

+    /*   bit 0 => this alt has a semantic pred which is "covered"       */

+    /*              by an alt without a semantic pred.  Don't hoist.    */

+

+	for (i=0,p=alt;

+         p!=NULL && i<nAlts;

+         i++,p=(Junction *)p->p2) {

+

+	  /* ignore empty alts */

+

+	  if ( p->p1->ntype != nJunction ||

+	        ((Junction *)p->p1)->jtype != EndBlk )	{

+        jList[i]=MR_junctionWithoutP2(p);

+        predList[i]=find_predicates(p->p1);      /* should be jList ????? */

+        if (predList[i] != NULL) {

+          MR_cleanup_pred_trees(predList[i]);    /* flatten & left factor */

+          plainContext[i]=MR_union_plain_sets(predList[i]);

+        } else {

+          MR_set_reuse(&plainSet);

+          MR_set_reuse(&incomplete);

+          plainSet=MR_First(depth1,jList[i],&incomplete);

+          MR_complete_set(depth1,&plainSet,&incomplete);

+          require(set_nil(incomplete),"couldn't complete k=1");

+          plainContext[i]=plainSet;

+          plainSet=empty;

+        };

+        set_orin(&union_plainSet,plainContext[i]);

+      };

+    };

+

+    if (nAlts == 1) {

+      goto EXIT_SIMPLE;

+    };

+

+/*

+ *  Looking for cases where alt i has a semantic pred and alt j does not.

+ *  Don't care about cases where lookahead for semantic predicates overlap

+ *    because normal predicate hoisting does the correct thing automatically.

+ *  Don't care about cases where lookahead for alts without semantic predicates

+ *    overlap because normal prediction does the correct thing automatically.

+ *

+ *  When we find such a case check for one of three subcases:

+ *

+ *      1.  if lookahead for alt i is contained in the lookahead for any

+ *          alt j then ignore semantic predicate of alt i

+ *      2.  if lookahead for alt i is not contained in the lookahead for

+ *          any alt j then add add predicate i to the OR list to be hoisted

+ *      3.  if lookahead for alt i overlaps the lookahead for some alt j then

+ *          add a dummy semantic predicate for alt j

+ *

+ *  There is an implicit assumption that the context of all alternatives following

+ *  the rule being processed here are identical (but may vary from hoist to

+ *  hoist depending on the place where the rule was invoked that led to hoisting

+ *  these predicates.  In othere words in the fragment:

+ *

+ *            ( <<a>>? a1 a2 a3 | <<b>>? b1 b2 b3 )

+ *

+ *  both a3 and b3 have the same follow sets  because they are both at the end of

+ *  alternatives in the same block.

+ */

+

+    for (i=0; i < nAlts; i++) {

+      if (jList[i] == NULL) continue;

+      if (predList[i] == NULL) continue;

+

+        /* if the predicate depth turns out to be one token only */

+        /*   then it is can be easily represented as a set and   */

+        /*   compared to the junction set create by MR_First()   */

+

+      predDepth=0;

+      MR_pred_depth(predList[i],&predDepth);

+      require (predDepth >= 1,"MR_find_in_aSubBlk: pred depth < 1");

+      require (predDepth <= CLL_k,"MR_find_in_aSubBlk: predDepth > CLL_k");

+

+        /* complete predicates to predDepth

+           If completed to depth=1 then the context would be incomplete.

+           The context would be truncated and the predicate simplify routine

+             would have incomplete information.  It would lead to

+             either false matches of failure to find true matches.

+        */

+

+      MR_complete_predicates(predDepth,predList[i]);

+

+      if (predList[i] != NULL) {

+        MR_cleanup_pred_trees(predList[i]);    /* flatten & left factor */

+      };

+

+      /* If the predicate depth is 1 then it is possible to suppress

+           a predicate completely using a single plain alt.  Check for suppression

+           by a single plain alt first because it gives better messages.  If that

+           fails try the union of all the plain alts.

+      */

+

+      if (predDepth == 1) {

+

+        MR_set_reuse(&predSet);

+        predSet=MR_compute_pred_set(predList[i]);   /* ignores k>1 predicates */

+

+        for (j=0; j < nAlts; j++) {

+          if (jList[j] == NULL) continue;

+          if (j == i) continue;

+

+          MR_set_reuse(&setDif);

+          setDif=set_dif(predSet,plainContext[j]);

+          if (set_nil(setDif)) {

+            matchList[i] |= 1;

+            MR_reportSetSuppression(predDepth,predSet,plainContext[j],jList[i],jList[j],predList[i]);

+            predicate_free(predList[i]);

+            predList[i]=PRED_SUPPRESS;

+            goto next_i;

+          };

+

+        }; /* end loop on j */

+

+        changed=0;

+

+        /* predicate_dup is only to give good error messages */

+        /* remember to do a predicate_free()                 */

+

+        origPred=predicate_dup(predList[i]);

+        MR_apply_restriction1(predList[i],&union_plainSet,&changed);

+        if (changed) {

+

+          /* don't use Pass3 by itself unless you know that inverted is not important */

+

+          newPred=MR_removeRedundantPredPass3(predList[i]);

+          newPred=MR_predSimplifyALL(newPred);

+          if (newPred == NULL) {

+            matchList[i] |= 1;

+            MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i],

+                                                            NULL,origPred);

+            predList[i]=PRED_SUPPRESS;

+          } else {

+            MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i],

+                                                    NULL,origPred,newPred);

+            predList[i]=newPred;

+          };

+        };

+        predicate_free(origPred);

+        origPred=NULL;

+      };

+

+      /*

+         If the predicate depth is > 1 then it can't be suppressed completely

+           because the code doesn't support inspection of such things.  They're

+           much messier than k=1 sets.

+      */

+

+      if (predDepth > 1 ) {

+

+        changed=0;

+

+        /* predicate_dup is only to give good error messages */

+        /* remember to do a predicate_free()                 */

+

+        origPred=predicate_dup(predList[i]);

+        MR_apply_restriction1(predList[i],&union_plainSet,&changed);

+        if (changed) {

+          newPred=MR_removeRedundantPredPass3(predList[i]);

+          newPred=MR_predSimplifyALL(newPred);

+          if (newPred == NULL) {

+            matchList[i] |= 1;

+            MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i],

+                                                            NULL,origPred);

+            predList[i]=PRED_SUPPRESS;

+          } else {

+            MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i],

+                                                    NULL,origPred,newPred);

+            predList[i]=newPred;

+          };

+        };

+        predicate_free(origPred);

+        origPred=NULL;

+      };

+next_i:

+      continue;

+    };

+

+EXIT_SIMPLE:

+

+    root = new_pred();

+    root->expr=PRED_OR_LIST;

+    tail = &(root->down);

+

+    for (i=0 ; i< nAlts ; i++) {

+      if (jList[i] == NULL) continue;

+

+      if (predList[i] == NULL) {

+        continue;

+      } else if ( (matchList[i] & 1) != 0) {

+        if (predList[i] != PRED_SUPPRESS) {

+          predicate_free(predList[i]);

+        };

+        continue;

+      };

+

+      /* make an OR list of predicates */

+

+      *tail=predList[i];

+      tail=&(predList[i]->right);

+    };

+

+	/* if just one pred, remove OR root */

+

+	if (root->down == NULL) {

+      predicate_free(root);

+      root=NULL;

+    } else if (root->down->right == NULL) {

+      Predicate     *p=root->down;

+      root->down=NULL;

+      predicate_free(root);

+      root=p;

+	}

+

+    root=MR_predSimplifyALL(root);

+

+    MR_orin_plainSet(root,union_plainSet);

+

+    set_free(predSet);

+    set_free(union_plainSet);

+    set_free(incomplete);

+    set_free(setChange);

+    set_free(setDif);

+

+    for (m=0; m < nAlts; m++) set_free(plainContext[m]);

+

+    free ( (char *) jList);

+    free ( (char *) predList);

+    free ( (char *) matchList);

+    free ( (char *) plainContext);

+

+	return root;

+}

+

+#ifdef __USE_PROTOS

+void MR_predContextPresent(Predicate *p,int *allHaveContext,int *noneHaveContext)

+#else

+void MR_predContextPresent(p,allHaveContext,noneHaveContext)

+  Predicate     *p;

+  int           *allHaveContext;

+  int           *noneHaveContext;

+#endif

+{

+  if (p == NULL) return;

+  MR_predContextPresent(p->right,allHaveContext,noneHaveContext);

+  if (p->expr != PRED_AND_LIST &&

+      p->expr != PRED_OR_LIST) {

+    if (set_nil(p->scontext[1]) == 0 ||

+            (p->tcontext != NULL)) {

+      *noneHaveContext=0;

+    } else {

+      *allHaveContext=0;

+    };

+  };

+  MR_predContextPresent(p->down,allHaveContext,noneHaveContext);

+}

+

+#ifdef __USE_PROTOS

+int MR_pointerStackPush(PointerStack *ps,void *dataPointer)

+#else

+int MR_pointerStackPush(ps,dataPointer)

+  PointerStack  *ps;

+  void          *dataPointer;

+#endif

+{

+  void             **newStack;

+  int              newSize;

+  int              i;

+

+  if (ps->count == ps->size) {

+    newSize=20+ps->size*2;

+    newStack=(void **)calloc(newSize,sizeof(void *));

+    require (newStack != NULL,"cannot allocate PointerStack");

+    for (i=0; i < ps->size; i++) {

+      newStack[i]=ps->data[i];

+    };

+    if (ps->data != NULL) free( (char *) ps->data);

+    ps->data=newStack;

+    ps->size=newSize;

+  };

+  ps->data[ps->count]=dataPointer;

+  ps->count++;

+  return ps->count-1;

+}

+

+#ifdef __USE_PROTOS

+void * MR_pointerStackPop(PointerStack *ps)

+#else

+void * MR_pointerStackPop(ps)

+  PointerStack  *ps;

+#endif

+{

+  void  *dataPointer;

+

+  require(ps->count > 0,"MR_pointerStackPop underflow");

+

+  dataPointer=ps->data[ps->count-1];

+  ps->data[ps->count-1]=NULL;

+  (ps->count)--;

+  return dataPointer;

+}

+

+#ifdef __USE_PROTOS

+void * MR_pointerStackTop(PointerStack *ps)

+#else

+void * MR_pointerStackTop(ps)

+  PointerStack  *ps;

+#endif

+{

+  require(ps->count > 0,"MR_pointerStackTop underflow");

+  return ps->data[ps->count-1];

+}

+

+#ifdef __USE_PROTOS

+void MR_pointerStackReset(PointerStack *ps)

+#else

+void MR_pointerStackReset(ps)

+  PointerStack  *ps;

+#endif

+{

+  int i;

+  if (ps->data != NULL) {

+    for (i=0; i < ps->count ; i++) {

+       ps->data[i]=NULL;

+    };

+  };

+  ps->count=0;

+}

+

+#ifdef __USE_PROTOS

+Junction *MR_nameToRuleBlk(char *name)

+#else

+Junction *MR_nameToRuleBlk(name)

+  char  *name;

+#endif

+{

+    RuleEntry *q;

+

+    require (RulePtr != NULL,"MR_nameToRule: RulePtr not initialized");

+

+    if (name == NULL) return NULL;

+

+    q = (RuleEntry *) hash_get(Rname,name);

+

+	if ( q == NULL ) {

+      return NULL;

+    } else {

+      return RulePtr[q->rulenum];

+    };

+}

+

+#ifdef __USE_PROTOS

+Junction * MR_ruleReferenced(RuleRefNode *rrn)

+#else

+Junction * MR_ruleReferenced(rrn)

+  RuleRefNode   *rrn;

+#endif

+{

+    return MR_nameToRuleBlk(rrn->text);

+}

+

+#ifdef __USE_PROTOS

+void MR_comparePredLeaves(Predicate *me,Predicate *myParent,Predicate *him,Predicate *hisParent)

+#else

+void MR_comparePredLeaves(me,myParent,him,hisParent)

+    Predicate *me;

+    Predicate *myParent;

+    Predicate *him;

+    Predicate *hisParent;

+#endif

+{

+    if (me == NULL) return;

+    if (me == him) {

+      MR_comparePredLeaves(me->right,myParent,him,hisParent);

+      return;

+    } else if (me->expr == PRED_AND_LIST ||

+               me->expr == PRED_OR_LIST) {

+      MR_comparePredLeaves(me->down,me,him,hisParent);

+      MR_comparePredLeaves(me->right,myParent,him,hisParent);

+      return;

+    } else {

+      if (me->source != NULL) {

+

+        /* predicate->invert can be set only in the predEntry predicates        */

+        /* thus they are only visible after the predEntry predicates have been "unfolded" */

+

+        int     sameSource=(me->source == him->source);

+        int     sameInvert=1 &

+                 (1 + me->inverted + him->inverted + me->source->inverted + him->source->inverted);

+        int     samePredEntry=(me->source->predEntry != NULL

+                                 && him->source->predEntry != NULL

+                                    && me->source->predEntry == him->source->predEntry);

+        if (sameInvert && (sameSource || samePredEntry)) {

+          if (MR_identicalContext(me,him)) {

+

+            /* identical predicates */

+

+            if (hisParent->expr == PRED_OR_LIST &&

+                myParent->expr == PRED_OR_LIST) {

+              me->redundant=1;

+            } else if (hisParent->expr == PRED_AND_LIST &&

+                       myParent->expr == PRED_AND_LIST) {

+              me->redundant=1;

+            } else if (  (hisParent->expr == PRED_OR_LIST &&

+                          myParent->expr == PRED_AND_LIST)

+                       ||

+                         (hisParent->expr == PRED_AND_LIST &&

+                          myParent->expr == PRED_OR_LIST)

+                      ) {

+              myParent->redundant=1;

+            } else {

+              require (0,"MR_comparePredLeaves: not both PRED_LIST");

+            };

+          };

+        };  /* end same source or same predEntrr with same invert sense */

+

+        /* same predEntry but opposite invert sense */

+

+        if (!sameInvert && (sameSource || samePredEntry)) {

+          if (MR_identicalContext(me,him)) {

+            if (hisParent->expr == PRED_OR_LIST &&

+                myParent->expr == PRED_OR_LIST) {

+              myParent->isConst=1;

+              myParent->constValue=1;

+            } else if (hisParent->expr == PRED_AND_LIST &&

+                       myParent->expr == PRED_AND_LIST) {

+              myParent->isConst=1;

+              myParent->constValue=0;

+            } else if (  (hisParent->expr == PRED_OR_LIST &&

+                          myParent->expr == PRED_AND_LIST)

+                       ||

+                         (hisParent->expr == PRED_AND_LIST &&

+                          myParent->expr == PRED_OR_LIST)

+                      ) {

+              me->redundant=1;

+            } else {

+              require (0,"MR_comparePredLeaves: not both PRED_LIST");

+            };

+          };

+        };  /* end same predEntry with opposite invert sense */

+      };

+

+      MR_comparePredLeaves(me->right,myParent,him,hisParent);

+      return;

+    };

+}

+

+#ifdef __USE_PROTOS

+void MR_removeRedundantPredPass1(Predicate *me,Predicate *myParent)

+#else

+void MR_removeRedundantPredPass1(me,myParent)

+  Predicate     *me;

+  Predicate     *myParent;

+#endif

+{

+    if (me == NULL) return;

+    if (me->redundant) {

+      MR_removeRedundantPredPass1(me->right,myParent);

+      return;

+    };

+    if (me->expr == PRED_AND_LIST ||

+        me->expr == PRED_OR_LIST) {

+      MR_removeRedundantPredPass1(me->down,me);

+      MR_removeRedundantPredPass1(me->right,myParent);

+    } else {

+      require (me->source != NULL,"me->source == NULL");

+      if (myParent != NULL) {

+        MR_comparePredLeaves(myParent->down,myParent,me,myParent);

+      };

+      MR_removeRedundantPredPass1(me->right,myParent);

+    };

+}

+

+/* pretty much ignores things with the inverted bit set */

+

+#ifdef __USE_PROTOS

+Predicate *MR_predFlatten(Predicate *p)

+#else

+Predicate *MR_predFlatten(p)

+  Predicate     *p;

+#endif

+{

+    if (p == NULL) return NULL;

+    if (p->expr == PRED_OR_LIST

+        || p->expr == PRED_AND_LIST) {

+

+      Predicate     *child;

+      Predicate     *gchild;

+      Predicate     **tail;

+      Predicate     *next;

+      char          *PRED_XXX_LIST=p->expr;

+

+      require (p->down != NULL,"MR_predFlatten AND/OR no child");

+

+

+      p->down=MR_predFlatten(p->down);

+      p->right=MR_predFlatten(p->right);

+      child=p->down;

+      if (child->right == NULL) {

+        child->right=p->right;

+        p->right=NULL;

+        p->down=NULL;

+        if (p->inverted) child->inverted=!child->inverted;

+        predicate_free(p);

+        return child;

+      };

+

+      /* make a single list of all children and grandchildren */

+

+      tail=&(p->down);

+      for (child=p->down; child != NULL; child=next) {

+        if (child->expr != PRED_XXX_LIST

+              || child->inverted

+                || child->predEntry != NULL) {

+          *tail=child;

+          tail=&(child->right);

+          next=child->right;

+        } else {

+          for (gchild=child->down;

+               gchild != NULL;

+               gchild=gchild->right) {

+            *tail=gchild;

+            tail=&(gchild->right);

+          };

+          next=child->right;

+          child->right=NULL;

+          child->down=NULL;

+          predicate_free(child);

+        };

+      };

+      *tail=NULL;

+      return p;

+    } else {

+      p->right=MR_predFlatten(p->right);

+      return p;

+    };

+}

+

+static char *alwaysFalseWarning=NULL;

+

+#ifdef __USE_PROTOS

+Predicate *checkPredicateConflict(Predicate *p)

+#else

+Predicate *checkPredicateConflict(p)

+  Predicate     *p;

+#endif

+{

+  if (p->isConst) {

+    if (p->constValue == 1) {

+      predicate_free(p);

+      return NULL;

+    } else {

+      if (InfoP && !p->conflictReported) {

+        p->conflictReported=1;

+        fprintf(output,"\n#if 0\n\n");

+        fprintf(output,"The following predicate expression will always be false:\n\n");

+        MR_dumpPred1(1,p,1);

+        fprintf(output,"\n#endif\n");

+      };

+

+      if (alwaysFalseWarning != CurRule) {

+        alwaysFalseWarning=CurRule;

+        if (InfoP) {

+          warnNoFL(eMsg1("one (or more) predicate expression hoisted into rule \"%s\" are always false \

+- see output file for more information",CurRule));

+        } else {

+          warnNoFL(eMsg1("one (or more) predicate expressions hoisted into rule \"%s\" are always false \

+- use \"-info p\" for more information",CurRule));

+        };

+      };

+    };

+  };

+  return p;

+}

+

+

+#ifdef __USE_PROTOS

+int MR_countPredNodes(Predicate *p)

+#else

+int MR_countPredNodes(p)

+  Predicate     *p;

+#endif

+{

+  if (p == NULL) return 0;

+  return 1 + MR_countPredNodes(p->down) + MR_countPredNodes(p->right);

+}

+

+#ifdef __USE_PROTOS

+Predicate *MR_predSimplifyALLX(Predicate *p,int skipPass3)

+#else

+Predicate *MR_predSimplifyALLX(p,skipPass3)

+  Predicate     *p;

+  int           skipPass3;

+#endif

+{

+  int       countBefore;

+  int       countAfter;

+

+  countAfter=MR_countPredNodes(p);

+

+  do {

+      if (p == NULL) return NULL;

+      if (p->right == NULL && p->down == NULL) return p;

+      countBefore=countAfter;

+      MR_simplifyInverted(p,0);

+      p=MR_predFlatten(p);

+      MR_removeRedundantPredPass1(p,NULL);

+      MR_removeRedundantPredPass2(p);

+      if (! skipPass3) {

+        p=checkPredicateConflict(p);

+        p=MR_removeRedundantPredPass3(p);

+      };

+      countAfter=MR_countPredNodes(p);

+  } while (countBefore != countAfter);

+

+  return p;

+}

+

+#ifdef __USE_PROTOS

+Predicate *MR_predSimplifyALL(Predicate *p)

+#else

+Predicate *MR_predSimplifyALL(p)

+  Predicate     *p;

+#endif

+{

+  return MR_predSimplifyALLX(p,0);

+}

+

+#ifdef __USE_PROTOS

+void MR_releaseResourcesUsedInRule(Node *n)

+#else

+void MR_releaseResourcesUsedInRule(n)

+  Node  *n;

+#endif

+{

+   Node         *next;

+   Junction     *j;

+   int          i;

+

+   if (n == NULL) return;

+   if (n->ntype == nJunction) {

+     j=(Junction *) n;

+

+     if (j->predicate != NULL) {

+       predicate_free(j->predicate);

+       j->predicate=NULL;

+     };

+     for (i=0; i< CLL_k; i++) {

+       set_free(j->fset[i]);

+       j->fset[i]=empty;

+     };

+     if (j->ftree != NULL) {

+       Tfree(j->ftree);

+       j->ftree=NULL;

+     };

+     if (j->jtype == EndRule) return;

+     if (j->jtype != RuleBlk && j->jtype != EndBlk) {

+       if (j->p2 != NULL && !j->ignore) {   /* MR11 */

+          MR_releaseResourcesUsedInRule(j->p2);

+       };

+     };

+   };

+   next=MR_advance(n);

+   MR_releaseResourcesUsedInRule(next);

+}

+

+#ifdef __USE_PROTOS

+int MR_allPredLeaves(Predicate *p)

+#else

+int MR_allPredLeaves(p)

+  Predicate *p;

+#endif

+{

+  Predicate     *q;

+

+  if (p == NULL) return 1;

+

+  for (q=p; q != NULL; q=q->right) {

+   if (q->down != NULL) return 0;

+  };

+  return 1;

+}

+

+/* make sure it works for the last rule in a file */

+

+#ifdef __USE_PROTOS

+int MR_offsetFromRule(Node *n)

+#else

+int MR_offsetFromRule(n)

+  Node      *n;

+#endif

+{

+  Junction  *j;

+  int       offset=(-1);

+

+  for (j=SynDiag; j != NULL; j=(Junction *)j->p2) {

+

+    require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block");

+

+    if (n->file < j->file) {

+      return offset;

+    };

+    if (n->file == j->file) {

+      if (n->line < j->line) {

+        return (offset < 0) ? 0 : offset;

+      } else {

+        offset=n->line - j->line;

+        if (offset == 0) return 0;

+      };

+    };

+  };

+  return offset;

+}

+

+#define ruleNameMax 50

+

+static char ruleNameStatic1[ruleNameMax];

+static char ruleNameStatic2[ruleNameMax+10];

+

+#ifdef __USE_PROTOS

+char * MR_ruleNamePlusOffset(Node *n)

+#else

+char * MR_ruleNamePlusOffset(n)

+  Node      *n;

+#endif

+{

+    int     offset=MR_offsetFromRule(n);

+

+    strncpy(ruleNameStatic1,n->rname,ruleNameMax);

+    if (offset < 0) {

+      sprintf(ruleNameStatic2,"%s/?",ruleNameStatic1);

+    } else {

+      sprintf(ruleNameStatic2,"%s/%d",ruleNameStatic1,offset+1);

+    };

+    return ruleNameStatic2;

+}

+

+#ifdef __USE_PROTOS

+int MR_max_height_of_tree(Tree *t)

+#else

+int MR_max_height_of_tree(t)

+  Tree  *t;

+#endif

+{

+  int       h;

+  int       height=0;

+  Tree      *u;

+

+  if (t == NULL) return 0;

+

+  require (t->token != ALT && t->token != EpToken,"MR_max_height_of_tree ALT or EpToken");

+

+  for (u=t; u != NULL; u=u->right) {

+    h=MR_max_height_of_tree(u->down)+1;

+    if (h > height) height=h;

+  };

+  return height;

+}

+

+#ifdef __USE_PROTOS

+int MR_all_leaves_same_height(Tree *t,int depth)

+#else

+int MR_all_leaves_same_height(t,depth)

+  Tree  *t;

+  int   depth;

+#endif

+{

+  if (t == NULL) {

+    return (depth==0);

+  };

+

+  require (t->token != ALT && t->token != EpToken,"MR_all_leaves_same_height ALT or EpToken");

+

+  if (depth == 0) {

+    return 0;

+  } else {

+    if ( ! MR_all_leaves_same_height(t->down,depth-1)) {

+      return 0;

+    };

+    if (t->right == NULL) {

+      return 1;

+    } else {

+      return MR_all_leaves_same_height(t->right,depth);

+    };

+  };

+}

+

+#ifdef __USE_PROTOS

+void MR_projectTreeOntoSet(Tree *tree,int ck,set *ckset)

+#else

+void MR_projectTreeOntoSet(tree,ck,ckset)

+  Tree  *tree;

+  int   ck;

+  set   *ckset;

+#endif

+{

+    if (tree == NULL) return;

+

+    require(tree->token != EpToken,"MR_projectTreeOntoSet: EpToken unexpected\n");

+

+    MR_projectTreeOntoSet(tree->right,ck,ckset);

+    if (tree->token == ALT) {

+      MR_projectTreeOntoSet(tree->down,ck,ckset);

+    } else {

+      if (ck > 1) {

+        MR_projectTreeOntoSet(tree->down,ck-1,ckset);

+      } else {

+        set_orel(tree->token,ckset);

+      };

+    };

+}

+

+#ifdef __USE_PROTOS

+int MR_comparePredicates(Predicate *a,Predicate *b)

+#else

+int MR_comparePredicates(a,b)

+  Predicate     *a;

+  Predicate     *b;

+#endif

+{

+  Predicate     *p;

+  Predicate     *q;

+

+  if (a == b) return 1;

+  if (a == NULL || b == NULL ) return 0;

+  if (a->down == NULL && b->down == NULL) {

+

+    /* predicate->invert can be set only in the predEntry predicates                  */

+    /* thus they are only visible after the predEntry predicates have been "unfolded" */

+

+    int     sameSource=(a->source == b->source);

+    int     sameInvert= 1 & (1 +a->inverted + b->inverted +

+                                a->source->inverted + b->source->inverted);

+    int     samePredEntry=(a->source->predEntry != NULL

+                                 && b->source->predEntry != NULL

+                                    && a->source->predEntry == b->source->predEntry);

+    if (sameInvert && (sameSource || samePredEntry)) {

+      if (MR_identicalContext(a,b)) {

+         return 1;

+      };

+    };

+    return 0;

+  };

+  if (a->down == NULL || b->down == NULL) return 0;

+  if (a->expr != b->expr) return 0;

+

+  for (p=a->down; p != NULL; p=p->right) {

+    for (q=b->down; q != NULL; q=q->right) {

+      if (MR_comparePredicates(p,q)) goto NEXT_P;

+    };

+    return 0;

+NEXT_P:

+    continue;

+  };

+  return 1;

+}

+

+/*

+ *  action->inverted can be set only when a predicate symbol appears in

+ *      a rule:  "rule : <<!XXX>>? X".  It cannot be set under any

+ *      other circumstances.  In particular it cannot be set by

+ *      "#pred NotA !A" or by "#pred Nota <<!A>>?".  The first case

+ *      creates a predEntry and the predicate expression of that predEntry

+ *      has inverted set.  In the second case, the code for handling "!"

+ *      is only present in buildAction, which is not called by the #pred

+ *      semantic routines, only when a <<...>>? is recognized as part of

+ *      a rule definition.

+ *

+ *  predicate->inverted can only be set by a predicate created by a #pred

+ *      expression, such as "#pred NotA !A" or "#pred NotXY ! (X && Y) or

+ *      "#pred XbarY !(X && Y)".  In particular, it cannot be set by any

+ *      predicate expression occurring under any other circumstances.

+ *      The #pred predicate expresssions are stored with in predEntry->pred

+ *      and do not normally appear anywhere else until the predicates are

+ *      "unfolded" in order to recognize redundancies, conflicts, and

+ *      tautologies.

+ *

+ *  The unfold routine expands all references to #pred expressions.

+ *

+ *  The simplifyInvert goes through and propagates the invert bit so that

+ *      all OR and AND nodes are un-inverted.

+ *

+ *  Note that !(A and B) => (!A or !B)

+ *            !(A or B)  => (!A and !B)

+ *

+ *  MR_unfold() is called to expand predicate symbols by replacing predicates

+ *    that reference predicate entries with the copies of the predicate entries.

+ *    Each reference receives a duplicate of the original.  This is necessary

+ *    because the next phase involves simplification and removal of redundant

+ *    predicate nodes.  Anyway, the point I'm making is that predicate->invert

+ *    should not be set in any predicate until it has been expanded.

+ *

+ *    This is a recursive structure, but there is no need for "recursive expansion"

+ *    by which I mean a predicate symbol refers to other predicate symbols which

+ *    must also be expanded.

+ *

+ *    Recursive expansion is *not* performed by this routine because it is not

+ *    necessary.  Expansion of references is performed by predPrimary when

+ *    a new predicate symbol is created by referring to others in the pred expr.

+ */

+

+#ifdef __USE_PROTOS

+Predicate *MR_unfold(Predicate *pred)

+#else

+Predicate *MR_unfold(pred)

+  Predicate     *pred;

+#endif

+{

+  Predicate     *result;

+

+  if (pred == NULL) return NULL;

+

+  pred->right=MR_unfold(pred->right);

+

+  if (pred->down == NULL) {

+    if (pred->source->predEntry != NULL) {

+      if (pred->source->predEntry->pred == NULL) {

+        ; /* do nothing */ /* a reference to a literal #pred (perhaps with "!" */

+      } else {

+        result=predicate_dup_without_context(pred->source->predEntry->pred);

+        if (pred->inverted) {

+          result->inverted=!result->inverted;

+        };

+        if (pred->source->inverted) {

+          result->inverted=!result->inverted;

+        };

+        result->right=pred->right;

+        pred->right=NULL;

+        predicate_free(pred);

+/***    result=MR_unfold(result); *** not necessary */    /* recursive expansion */

+        return result;

+      };

+    } else {

+      ; /* do nothing */ /* an inline literal predicate */

+    };

+  } else {

+    pred->down=MR_unfold(pred->down);

+  };

+  return pred;

+}

+

+/* this should be called immediately after MR_unfold() and

+   at no other times

+*/

+

+#ifdef __USE_PROTOS

+void MR_simplifyInverted(Predicate *pred,int inverted)

+#else

+void MR_simplifyInverted(pred,inverted)

+  Predicate     *pred;

+  int           inverted;

+#endif

+{

+  int       newInverted;

+

+  if (pred == NULL) return;

+

+  MR_simplifyInverted(pred->right,inverted);

+

+  newInverted= 1 & (inverted + pred->inverted);

+

+  if (pred->down == NULL) {

+    pred->inverted=newInverted;

+  } else {

+    if (newInverted != 0) {

+      if (pred->expr == PRED_AND_LIST) {

+        pred->expr=PRED_OR_LIST;

+      } else {

+        pred->expr=PRED_AND_LIST;

+      };

+    };

+    pred->inverted=0;

+    MR_simplifyInverted(pred->down,newInverted);

+  };

+}

+

+/* only remove it from AND and OR nodes, not leaves */

+

+#ifdef __USE_PROTOS

+void MR_clearPredEntry(Predicate *p)

+#else

+void MR_clearPredEntry(p)

+  Predicate     *p;

+#endif

+{

+   if (p == NULL) return;

+   MR_clearPredEntry(p->down);

+   MR_clearPredEntry(p->right);

+   if (p->down != NULL) p->predEntry=NULL;

+}

+

+

+#ifdef __USE_PROTOS

+void MR_orphanRules(FILE *f)

+#else

+void MR_orphanRules(f)

+  FILE      *f;

+#endif

+{

+	set         a;

+    Junction    *p;

+    unsigned    e;

+    RuleEntry   *re;

+

+	a=empty;

+

+    if (! InfoO) return;

+

+	for (p=SynDiag; p!=NULL; p = (Junction *)p->p2)	{

+      if ( (Junction *) (p->end)->p1 == NULL) {

+        re=(RuleEntry *) hash_get(Rname,p->rname);

+        require (re != NULL,"RuleEntry == NULL");

+		set_orel(re->rulenum, &a);

+      }

+  	}

+

+    if (set_deg(a) > 1) {

+      fprintf(f,"note: Start rules: {");

+      for (; !set_nil(a); set_rm(e,a)) {

+        e=set_int(a);

+        fprintf(f," %s",RulePtr[e]->rname);

+      };

+      fprintf(f," }\n");

+    };

+	set_free( a );

+}

+

+/*  merge (X Y) and (X) to create (X)  */

+

+static int      *mergeChain;

+static Tree     *mergeTree;

+

+#ifdef __USE_PROTOS

+Tree *MR_merge_tree_contexts_client(Tree *t,int chain[])

+#else

+Tree *MR_merge_tree_contexts_client(t,chain)

+  Tree  *t;

+  int   chain[];

+#endif

+{

+  if (t == NULL)  return NULL;

+  if (chain[0] == 0) {

+    Tree    *u=t->right;

+    t->right=NULL;

+    Tfree(t);

+    return MR_merge_tree_contexts_client(u,&chain[0]);

+  }

+  if (chain[0] == t->token) {

+    t->down=MR_merge_tree_contexts_client(t->down,&chain[1]);

+  };

+  t->right=MR_merge_tree_contexts_client(t->right,&chain[0]);

+  return t;

+}

+

+#ifdef __USE_PROTOS

+void MR_iterateOverTreeContexts(Tree *t,int chain[])

+#else

+void MR_iterateOverTreeContexts(t,chain)

+  Tree          *t;

+  int           chain[];

+#endif

+{

+  if (t == NULL) return;

+  chain[0]=t->token;

+  if (t->down != NULL) {

+    MR_iterateOverTreeContexts(t->down,&chain[1]);

+  } else {

+    MR_merge_tree_contexts_client(mergeTree,mergeChain);

+  };

+  MR_iterateOverTreeContexts(t->right,&chain[0]);

+  chain[0]=0;

+}

+

+#ifdef __USE_PROTOS

+Tree *MR_merge_tree_contexts(Tree *t)

+#else

+Tree *MR_merge_tree_contexts(t)

+  Tree  *t;

+#endif

+{

+    int     h=MR_max_height_of_tree(t);

+

+    mergeTree=t;

+    mergeChain=(int *) calloc(h+1,sizeof(int));

+    require (mergeChain != NULL,"MR_merge_tree_contexts: can't alloc chain");

+    MR_iterateOverTreeContexts(t,mergeChain);

+    t=tshrink(t);

+    t=tflatten(t);

+    t=tleft_factor(t);

+    free ( (char *) mergeChain);

+    mergeChain=NULL;

+    return t;

+}

+

+#ifdef __USE_PROTOS

+Tree *MR_compute_pred_tree_context(Predicate *p)

+#else

+Tree *MR_compute_pred_tree_context(p)

+  Predicate *p;

+#endif

+{

+  Tree  *t;

+

+  t=MR_compute_pred_tree_ctxXX(p);

+  MR_merge_tree_contexts(t);

+  return t;

+}

+

+#ifdef __USE_PROTOS

+void MR_guardPred_plainSet(ActionNode *anode,Predicate *pred)

+#else

+void MR_guardPred_plainSet(anode,pred)

+  ActionNode    *anode;

+  Predicate     *pred;

+#endif

+{

+  Junction      *j;

+  Predicate     *workPred;

+  set           maskSet;

+

+  maskSet=empty;

+

+  if (!MRhoisting) return;

+

+  /* it doesn't really matter whether the predicate has

+     depth k=1 or k>1 because we're not really looking

+     at the predicate itself, just the stuff "behind"

+     the predicate.

+  */

+

+  /* shouldn't have to worry about REACHing off the end

+     of the rule containing the predicate because the

+     Rule->end->halt should have been set already by the

+     the code which handles RuleRef nodes.

+

+     We don't want to REACH off the end of the rule because

+     this would give the "global" follow context rather than

+     the "local" context.

+

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

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

+         r2  : ();

+

+     For r1a we want follow of predicate = {A B}

+             we want plainSet = {B}

+     For r1b we want follow of predicate = {A C}

+             we want plainSet = {C}

+  */

+

+  require (anode->next->ntype == nJunction,"MR_guardpred_plainSet not Junction");

+  j=(Junction *)(anode->next);

+

+  workPred=predicate_dup_without_context(pred);

+  workPred->k=1;

+  workPred->scontext[1]=MR_First(1,j, &(workPred->completionSet) );

+  MR_complete_predicates(1,workPred);

+  if (pred->k == 1) {

+    maskSet=pred->scontext[1];

+  } else {

+    MR_projectTreeOntoSet(pred->tcontext,1,&maskSet);

+  }

+  pred->plainSet=set_dif(workPred->scontext[1],maskSet);

+  predicate_free(workPred);

+}

+

+/*******************************************************************************/

+

+static Tree *       suppressTree;

+static int *        suppressChain;  /* element 0 not used */

+static set *        suppressSets;

+static Node *       suppressNode;

+static int          suppressChainLength;

+int                 MR_SuppressSearch=0;

+static int          suppressSucceeded;

+static Predicate *  suppressPredicate;

+

+#ifdef __USE_PROTOS

+int MR_isChain(Tree *t)

+#else

+int MR_isChain(t)

+  Tree  *t;

+#endif

+{

+  Tree  *u;

+

+  for (u=t; u != NULL; u=u->down) {

+    if (u->right != NULL) return 0;

+  }

+  return 1;

+}

+

+#ifdef __USE_PROTOS

+int MR_suppressK_client(Tree *tree,int tokensInChain[])

+#else

+int MR_suppressK_client(tree,tokensInChain)

+  Tree      *tree;

+  int       tokensInChain[];

+#endif

+{

+  int       i;

+  set       *save_fset;

+  int       save_ConstrainSearch;

+  set       incomplete;

+  Tree      *t;

+

+  suppressSucceeded=0;  /* volatile */

+

+  if (suppressSets == NULL) {

+    suppressSets=(set *) calloc (CLL_k+1,sizeof(set));

+    require (suppressSets != NULL,"MR_suppressK_client: suppressSets alloc");

+  };

+

+  for (suppressChainLength=1;

+       tokensInChain[suppressChainLength+1] != 0;

+       suppressChainLength++) {};

+

+  require (suppressChainLength != 0,"MR_suppressK_client: chain empty");

+

+  for (i=1 ; i <= suppressChainLength ; i++) {

+    set_clr(suppressSets[i]);

+    set_orel( (unsigned) tokensInChain[i],

+                              &suppressSets[i]);

+  };

+

+  save_fset=fset;

+  save_ConstrainSearch=ConstrainSearch;

+

+  fset=suppressSets;

+

+  MR_SuppressSearch=1;

+  MR_AmbSourceSearch=1;

+  MR_MaintainBackTrace=1;

+  ConstrainSearch=1;

+

+  maxk = suppressChainLength;

+

+  incomplete=empty;

+  t=NULL;

+

+/***  constrain = &(fset[1]); ***/

+

+  MR_setConstrainPointer(&(fset[1]));	/* MR18 */

+  

+  MR_pointerStackReset(&MR_BackTraceStack);

+

+  TRAV(suppressNode,maxk,&incomplete,t);

+

+  Tfree(t);

+

+  require (set_nil(incomplete),"MR_suppressK_client TRAV incomplete");

+  require (MR_BackTraceStack.count == 0,

+            "MR_suppressK_client: MR_BackTraceStack.count != 0");

+  set_free(incomplete);

+

+  ConstrainSearch=save_ConstrainSearch;

+  fset=save_fset;

+

+  MR_AmbSourceSearch=0;

+  MR_MaintainBackTrace=0;

+  MR_SuppressSearch=0;

+  return suppressSucceeded;

+}

+

+#ifdef __USE_PROTOS

+Tree * MR_iterateOverTreeSuppressK(Tree *t,int chain[])

+#else

+Tree * MR_iterateOverTreeSuppressK(t,chain)

+  Tree          *t;

+  int           chain[];

+#endif

+{

+  if (t == NULL) return NULL;

+  t->right=MR_iterateOverTreeSuppressK(t->right,&chain[0]);

+  chain[0]=t->token;

+  if (t->down != NULL) {

+    t->down=MR_iterateOverTreeSuppressK(t->down,&chain[1]);

+    if (t->down == NULL) {

+      Tree *u=t->right;

+      t->right=NULL;

+      Tfree(t);

+      chain[0]=0;

+      return u;

+    };

+  } else {

+    MR_suppressK_client(suppressTree,suppressChain);

+    if (suppressSucceeded) {

+      Tree  *u=t->right;

+      t->right=NULL;

+      Tfree(t);

+      chain[0]=0;

+      return u;

+    };

+  };

+  chain[0]=0;

+  return t;

+}

+

+/* @@@ */

+

+#ifdef __USE_PROTOS

+Predicate * MR_suppressK(Node *j,Predicate *p)

+#else

+Predicate * MR_suppressK(j,p)

+  Node          *j;

+  Predicate     *p;

+#endif

+{

+  Predicate     *result;

+  int           guardPred=0;

+  int           ampersandPred=0;

+  Node          *nodePrime;

+

+  if (! MRhoistingk) {

+     return p;

+  }

+

+  if (! MRhoisting) return p;

+  if (CLL_k == 1) return p;

+

+  if (suppressChain == NULL) {

+    suppressChain=(int *) calloc(CLL_k+2,sizeof(int));

+    require (suppressChain != NULL,"MR_suppressK: can't allocate chain");

+  }

+

+  if (p == NULL) return NULL;

+

+  if (j->ntype == nJunction) {

+    nodePrime=(Node *) MR_junctionWithoutP2( (Junction *) j);

+  } else {

+    nodePrime=j;

+  };

+

+  p->down=MR_suppressK(j,p->down);

+  p->right=MR_suppressK(j,p->right);

+  if (p->down != NULL) {

+    result=p;

+    goto EXIT;

+  };

+  if (p->k == 1) {

+    result=p;

+    goto EXIT;

+  };

+

+  if (p->source != NULL) {

+    if (p->source->guardpred != NULL) guardPred=1;

+    if (p->source->ampersandPred != NULL) ampersandPred=1;

+  }

+

+  suppressPredicate=p;

+  suppressNode=nodePrime;   /* was j*/

+

+  suppressTree=p->tcontext;

+

+  if (guardPred || ampersandPred) {

+    p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]);

+    if (p->tcontext == NULL) {

+      predicate_free(p);

+      result=NULL;

+      goto EXIT;

+    };

+  } else {

+    if (MR_isChain(p->tcontext)) {

+      p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]);

+      if (p->tcontext == NULL) {

+        predicate_free(p);

+        result=NULL;

+        goto EXIT;

+      };

+    }

+  }

+  result=p;

+EXIT:

+  return result;

+}

+

+#ifdef __USE_PROTOS

+void MR_suppressSearchReport(void)

+#else

+void MR_suppressSearchReport()

+#endif

+{

+  int       i;

+  Node      *p;

+  TokNode   *tn;

+  int       depth;

+  set       setAnd;

+

+  /* number of tokens in back trace stack matches length of chain */

+

+  depth=0;

+  for (i=0; i < MR_BackTraceStack.count ; i++) {

+    p=(Node *) MR_BackTraceStack.data[i];

+    if (p->ntype == nToken) depth++;

+  };

+

+  require (depth == suppressChainLength,"depth > suppressChainLength");

+

+  /* token codes match chain */

+

+  depth=0;

+  for (i=0; i < MR_BackTraceStack.count ; i++) {

+    p=(Node *) MR_BackTraceStack.data[i];

+    if (p->ntype != nToken) continue;

+    tn=(TokNode *) p;

+    depth++;

+    if (set_nil(tn->tset)) {

+      require(set_el( (unsigned) tn->token,fset[depth]),

+        "MR_suppressSearchReport: no match to #token in chain");

+    } else {

+      setAnd=set_and(fset[depth],tn->tset);

+      require(!set_nil(setAnd),

+        "MR_suppressSearchReport: no match to #token set in chain");

+      set_free(setAnd);

+    };

+  };

+

+  /* have a match - now remove it from the predicate */

+

+  suppressSucceeded=1;

+

+  if (suppressSucceeded) {

+    fprintf(output,"\n");

+    fprintf(output,"#if 0\n");

+    fprintf(output,"\n");

+    fprintf(output,"Part (or all) of predicate with depth > 1 suppressed by ");

+        fprintf(output,"alternative without predicate\n\n");

+    MR_dumpPred(suppressPredicate,1);

+    fprintf(output,"The token sequence which is suppressed:");

+    fprintf(output," (");

+    for (i=1; i <= suppressChainLength; i++) {

+      fprintf(output," %s",TerminalString(suppressChain[i]));

+    };

+    fprintf(output," )\n");

+    fprintf(output,"The sequence of references which generate that sequence of tokens:\n\n");

+

+    MR_backTraceDumpItemReset();

+

+    for (i=0; i < MR_BackTraceStack.count ; i++) {

+       MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]);

+    };

+    fprintf(output,"\n");

+    fprintf(output,"#endif\n");

+  }

+}

+

+#ifdef __USE_PROTOS

+void MR_markCompromisedRule(Node *n)

+#else

+void MR_markCompromisedRule(n)

+  Node *n;

+#endif

+{

+  RuleEntry     *q;

+  Node          *mark=NULL;

+  Junction      *j;

+

+  if (n->ntype == nRuleRef) {

+    mark=(Node *) MR_ruleReferenced( (RuleRefNode *) n);

+  } else if (n->ntype == nToken) {

+    mark=n;

+  } else if (n->ntype == nJunction) {

+    j=(Junction *)n;

+    switch (j->jtype) {

+      case aOptBlk:

+      case aLoopBlk:

+      case RuleBlk:

+      case EndRule:

+      case aPlusBlk:

+      case aLoopBegin:

+        mark=n;

+        break;

+      default:

+        break;

+    };

+  }

+

+  if (mark == NULL) return;

+

+  require (RulePtr != NULL,"RulePtr not initialized");

+

+  q = (RuleEntry *) hash_get(Rname,mark->rname);

+  require (q != NULL,"RuleEntry not found");

+  set_orel(q->rulenum,&MR_CompromisedRules);

+}

+

+#ifdef __USE_PROTOS

+void MR_alphaBetaTraceReport(void)

+#else

+void MR_alphaBetaTraceReport()

+#endif

+{

+  int       i;

+

+  if (! AlphaBetaTrace) return;

+

+  MR_AlphaBetaMessageCount++;

+

+  fprintf(output,"\n");

+  fprintf(output,"#if 0\n");

+  fprintf(output,"\n");

+  fprintf(output,"Trace of references leading to attempt to compute the follow set of\n");

+  fprintf(output,"alpha in an \"(alpha)? beta\" block. It is not possible for antlr to\n");

+  fprintf(output,"compute this follow set because it is not known what part of beta has\n");

+  fprintf(output,"already been matched by alpha and what part remains to be matched.\n");

+  fprintf(output,"\n");

+  fprintf(output,"Rules which make use of the incorrect follow set will also be incorrect\n");

+  fprintf(output,"\n");

+

+  MR_backTraceDumpItemReset();

+

+  for (i=0; i < MR_BackTraceStack.count ; i++) {

+     MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]);

+     if (i < MR_BackTraceStack.count-1) {

+        MR_markCompromisedRule( (Node *) MR_BackTraceStack.data[i]);

+     };

+  };

+  fprintf(output,"\n");

+  fprintf(output,"#endif\n");

+}

+

+#ifdef __USE_PROTOS

+void MR_dumpRuleSet(set s)

+#else

+void MR_dumpRuleSet(s)

+  set   s;

+#endif

+{

+    unsigned    *cursor;

+    unsigned    *origin=set_pdq(s);

+

+    require(origin != NULL,"set_pdq failed");

+

+    if (RulePtr == NULL) {

+      fprintf(stderr,"RulePtr[] not yet initialized");

+    } else {

+      for (cursor=origin; *cursor != nil ; cursor++) {

+/****   if (cursor != origin) fprintf(stderr,","); ****/

+        fprintf(stderr,"    %s",RulePtr[*cursor]->rname);

+        fprintf(stderr,"\n");

+      };

+      free( (char *) origin);

+    };

+}

diff --git a/Source/Pccts/antlr/parser.dlg b/Source/Pccts/antlr/parser.dlg
new file mode 100644
index 0000000..8c43dff
--- /dev/null
+++ b/Source/Pccts/antlr/parser.dlg
@@ -0,0 +1,1387 @@
+<<

+/* parser.dlg -- DLG Description of scanner

+ *

+ * Generated from: antlr.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include "pcctscfg.h"

+#include "set.h"

+#include <ctype.h>

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#define zzcr_attr(attr,tok,t)

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+LOOKAHEAD

+

+void

+#ifdef __USE_PROTOS

+zzerraction(void)

+#else

+zzerraction()

+#endif

+{

+	(*zzerr)("invalid token");

+	zzadvance();

+	zzskip();

+}

+>>

+

+<<%%lexaction

+

+/* maintained, but not used for now */

+set AST_nodes_refd_in_actions = set_init;

+int inAlt = 0;

+set attribsRefdFromAction = set_init; /* MR20 */

+int UsedOldStyleAttrib = 0;

+int UsedNewStyleLabel = 0;

+#ifdef __USE_PROTOS

+char *inline_set(char *);

+#else

+char *inline_set();

+#endif

+

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	    */

+/* MR1					in DLG action			                    */

+

+int tokenActionActive=0;                                            /* MR1 */

+

+  

+>>

+

+<<%%lexaction

+

+

+static char *

+#ifdef __USE_PROTOS

+getFileNameFromTheLineInfo(char *toStr, char *fromStr)

+#else

+getFileNameFromTheLineInfo(toStr, fromStr)

+char *toStr, *fromStr;

+#endif

+{

+  int i, j, k;

+  

+  if (!fromStr || !toStr) return toStr;

+  

+  /* find the first " */

+  

+  for (i=0;

+  (i<MaxFileName) &&

+  (fromStr[i] != '\n') &&

+  (fromStr[i] != '\r') &&

+  (fromStr[i] != '\"');

+  i++) /* nothing */ ;

+  

+  if ( (i == MaxFileName) ||

+  (fromStr[i] == '\n') ||

+  (fromStr[i] == '\r') ) {

+  return toStr;

+}

+

+  /* find the second " */

+

+  for (j=i+1;

+(j<MaxFileName) &&

+(fromStr[j] != '\n') &&

+(fromStr[j] != '\r') &&

+(fromStr[j] != '\"');

+j++) /* nothing */ ;

+

+  if ((j == MaxFileName) ||

+(fromStr[j] == '\n') ||

+(fromStr[j] == '\r') ) {

+  return toStr;

+}

+

+  /* go back until the last / or \ */

+

+  for (k=j-1;

+(fromStr[k] != '\"') &&

+(fromStr[k] != '/') &&

+(fromStr[k] != '\\');

+k--) /* nothing */ ;

+

+  /* copy the string after " / or \ into toStr */

+

+  for (i=k+1; fromStr[i] != '\"'; i++) {

+toStr[i-k-1] = fromStr[i];

+}

+

+  toStr[i-k-1] = '\0';

+

+  return toStr;

+}

+

+/* MR14 end of a block to support #line in antlr source code */

+

+  

+>>

+

+<<%%lexaction

+

+#ifdef __USE_PROTOS

+void mark_label_used_in_sem_pred(LabelEntry *le)              /* MR10 */

+#else

+void mark_label_used_in_sem_pred(le)                          /* MR10 */

+LabelEntry    *le;

+#endif

+{

+  TokNode   *tn;

+  require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");

+  tn=(TokNode *)le->elem;

+  require (tn->label != 0,"mark_label_used... TokNode has no label");

+  tn->label_used_in_semantic_pred=1;

+}

+>>

+

+

+%%START

+

+@

+	<<

+		NLA = Eof;

+    /* L o o k  F o r  A n o t h e r  F i l e */

+    {

+      FILE *new_input;

+      new_input = NextFile();

+      if ( new_input == NULL ) { NLA=Eof; return; }

+      fclose( input );

+      input = new_input;

+      zzrdstream( input );

+      zzskip();	/* Skip the Eof (@) char i.e continue */

+    }

+	>>

+

+[\t\ ]+

+	<<

+		NLA = 76;

+    zzskip();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 77;

+    zzline++; zzskip();   

+	>>

+

+\[

+	<<

+		NLA = 78;

+    zzmode(ACTIONS); zzmore();

+    istackreset();

+    pushint(']');   

+	>>

+

+\<\<

+	<<

+		NLA = 79;

+    action_file=CurFile; action_line=zzline;

+    zzmode(ACTIONS); zzmore();

+    list_free(&CurActionLabels,0);       /* MR10 */

+    numericActionLabel=0;                /* MR10 */

+    istackreset();

+    pushint('>');   

+	>>

+

+\"

+	<<

+		NLA = 80;

+    zzmode(STRINGS); zzmore();   

+	>>

+

+/\*

+	<<

+		NLA = 81;

+    zzmode(COMMENTS); zzskip();   

+	>>

+

+\*/

+	<<

+		NLA = 82;

+    warn("Missing /*; found dangling */"); zzskip();   

+	>>

+

+//

+	<<

+		NLA = 83;

+    zzmode(CPP_COMMENTS); zzskip();   

+	>>

+

+#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)

+	<<

+		NLA = 84;

+    

+    zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+    getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+	>>

+

+#line ~[\n\r]* (\n|\r|\r\n)

+	<<

+		NLA = 85;

+    

+    zzline++; zzmore();

+	>>

+

+\>\>

+	<<

+		NLA = 86;

+    warn("Missing <<; found dangling \>\>"); zzskip();   

+	>>

+

+.

+	<<

+		NLA = WildCard;

+	>>

+

+\@

+	<<

+		NLA = 88;

+    FoundException = 1;		/* MR6 */

+    FoundAtOperator = 1;  

+	>>

+

+{\\}#pragma

+	<<

+		NLA = Pragma;

+	>>

+

+{\\}#FirstSetSymbol

+	<<

+		NLA = FirstSetSymbol;

+	>>

+

+{\\}#header

+	<<

+		NLA = 94;

+	>>

+

+{\\}#first

+	<<

+		NLA = 95;

+	>>

+

+{\\}#parser

+	<<

+		NLA = 96;

+	>>

+

+{\\}#tokdefs

+	<<

+		NLA = 97;

+	>>

+

+\}

+	<<

+		NLA = 98;

+	>>

+

+class

+	<<

+		NLA = 99;

+	>>

+

+\{

+	<<

+		NLA = 102;

+	>>

+

+!

+	<<

+		NLA = 103;

+	>>

+

+\<

+	<<

+		NLA = 104;

+	>>

+

+\>

+	<<

+		NLA = 105;

+	>>

+

+:

+	<<

+		NLA = 106;

+	>>

+

+;

+	<<

+		NLA = 107;

+	>>

+

+{\\}#lexaction

+	<<

+		NLA = 108;

+	>>

+

+{\\}#lexmember

+	<<

+		NLA = 109;

+	>>

+

+{\\}#lexprefix

+	<<

+		NLA = 110;

+	>>

+

+{\\}#pred

+	<<

+		NLA = 111;

+	>>

+

+\|\|

+	<<

+		NLA = 112;

+	>>

+

+&&

+	<<

+		NLA = 113;

+	>>

+

+\(

+	<<

+		NLA = 114;

+	>>

+

+\)

+	<<

+		NLA = 115;

+	>>

+

+{\\}#lexclass

+	<<

+		NLA = 116;

+	>>

+

+{\\}#errclass

+	<<

+		NLA = 117;

+	>>

+

+{\\}#tokclass

+	<<

+		NLA = 118;

+	>>

+

+..

+	<<

+		NLA = 119;

+	>>

+

+{\\}#token

+	<<

+		NLA = 120;

+	>>

+

+=

+	<<

+		NLA = 121;

+	>>

+

+[0-9]+

+	<<

+		NLA = 122;

+	>>

+

+\|

+	<<

+		NLA = 123;

+	>>

+

+\~

+	<<

+		NLA = 124;

+	>>

+

+^

+	<<

+		NLA = 125;

+	>>

+

+approx

+	<<

+		NLA = 126;

+	>>

+

+LL\(1\)

+	<<

+		NLA = 127;

+	>>

+

+LL\(2\)

+	<<

+		NLA = 128;

+	>>

+

+\*

+	<<

+		NLA = 129;

+	>>

+

+\+

+	<<

+		NLA = 130;

+	>>

+

+?

+	<<

+		NLA = 131;

+	>>

+

+=>

+	<<

+		NLA = 132;

+	>>

+

+exception

+	<<

+		NLA = 133;

+	>>

+

+default

+	<<

+		NLA = 134;

+	>>

+

+catch

+	<<

+		NLA = 135;

+	>>

+

+[a-z] [A-Za-z0-9_]*

+	<<

+		NLA = NonTerminal;

+    

+    while ( zzchar==' ' || zzchar=='\t' ) {

+      zzadvance();

+    }

+    if ( zzchar == ':' && inAlt ) NLA = LABEL;

+	>>

+

+[A-Z] [A-Za-z0-9_]*

+	<<

+		NLA = TokenTerm;

+    

+    while ( zzchar==' ' || zzchar=='\t' ) {

+      zzadvance();

+    }

+    if ( zzchar == ':' && inAlt ) NLA = LABEL;

+	>>

+

+{\\}#[A-Za-z0-9_]*

+	<<

+		NLA = 136;

+    warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip();   

+	>>

+

+

+%%STRINGS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\"

+	<<

+		NLA = QuotedTerm;

+    zzmode(START);   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 3;

+    

+    zzline++;

+    warn("eoln found in string");

+    zzskip();

+	>>

+

+\\(\n|\r|\r\n)

+	<<

+		NLA = 4;

+    zzline++; zzmore();   

+	>>

+

+\\~[]

+	<<

+		NLA = 5;

+    zzmore();   

+	>>

+

+~[\n\r\"\\]+

+	<<

+		NLA = 6;

+    zzmore();   

+	>>

+

+

+%%ACTION_STRINGS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\"

+	<<

+		NLA = 7;

+    zzmode(ACTIONS); zzmore();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 8;

+    

+    zzline++;

+    warn("eoln found in string (in user action)");

+    zzskip();

+	>>

+

+\\(\n|\r|\r\n)

+	<<

+		NLA = 9;

+    zzline++; zzmore();   

+	>>

+

+\\~[]

+	<<

+		NLA = 10;

+    zzmore();   

+	>>

+

+~[\n\r\"\\]+

+	<<

+		NLA = 11;

+    zzmore();   

+	>>

+

+

+%%ACTION_CHARS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+'

+	<<

+		NLA = 12;

+    zzmode(ACTIONS); zzmore();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 13;

+    

+    zzline++;

+    warn("eoln found in char literal (in user action)");

+    zzskip();

+	>>

+

+\\~[]

+	<<

+		NLA = 14;

+    zzmore();   

+	>>

+

+~[\n\r'\\]+

+	<<

+		NLA = 15;

+    zzmore();   

+	>>

+

+

+%%ACTION_COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\*/

+	<<

+		NLA = 16;

+    zzmode(ACTIONS); zzmore();   

+	>>

+

+\*

+	<<

+		NLA = 17;

+    zzmore();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 18;

+    zzline++; zzmore(); DAWDLE;   

+	>>

+

+~[\n\r\*]+

+	<<

+		NLA = 19;

+    zzmore();   

+	>>

+

+

+%%TOK_DEF_COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\*/

+	<<

+		NLA = 20;

+    zzmode(PARSE_ENUM_FILE);

+    zzmore();   

+	>>

+

+\*

+	<<

+		NLA = 21;

+    zzmore();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 22;

+    zzline++; zzmore(); DAWDLE;   

+	>>

+

+~[\n\r\*]+

+	<<

+		NLA = 23;

+    zzmore();   

+	>>

+

+

+%%TOK_DEF_CPP_COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 24;

+    zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE;   

+	>>

+

+~[\n\r]+

+	<<

+		NLA = 25;

+    zzskip();   

+	>>

+

+

+%%ACTION_CPP_COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 26;

+    zzline++; zzmode(ACTIONS); zzmore(); DAWDLE;   

+	>>

+

+~[\n\r]+

+	<<

+		NLA = 27;

+    zzmore();   

+	>>

+

+

+%%CPP_COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 28;

+    zzline++; zzmode(START); zzskip(); DAWDLE;   

+	>>

+

+~[\n\r]+

+	<<

+		NLA = 29;

+    zzskip();   

+	>>

+

+

+%%COMMENTS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\*/

+	<<

+		NLA = 30;

+    zzmode(START); zzskip();   

+	>>

+

+\*

+	<<

+		NLA = 31;

+    zzskip();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 32;

+    zzline++; zzskip(); DAWDLE;   

+	>>

+

+~[\n\r\*]+

+	<<

+		NLA = 33;

+    zzskip();   

+	>>

+

+

+%%ACTIONS

+

+@

+	<<

+		NLA = Eof;

+	>>

+

+\>\>

+	<<

+		NLA = Action;

+    /* these do not nest */

+    zzmode(START);

+    NLATEXT[0] = ' ';

+    NLATEXT[1] = ' ';

+    zzbegexpr[0] = ' ';

+    zzbegexpr[1] = ' ';

+    if ( zzbufovf ) {

+      err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));

+    }

+    

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/

+    /* MR1					in DLG action			*/

+    /* MR1			Doesn't matter what kind of action it is - reset*/

+    

+			      tokenActionActive=0;		 /* MR1 */

+	>>

+

+\>\>?

+	<<

+		NLA = Pred;

+    /* these do not nest */

+    zzmode(START);

+    NLATEXT[0] = ' ';

+    NLATEXT[1] = ' ';

+    zzbegexpr[0] = '\0';

+    if ( zzbufovf ) {

+      err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));

+    };

+#ifdef __cplusplus__

+    /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __STDC__

+    /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __USE_PROTOS

+    /* MRxx */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+    /* MR10 */                    list_apply(CurActionLabels,mark_label_used_in_sem_pred);

+#endif

+#endif

+#endif

+	>>

+

+\]

+	<<

+		NLA = PassAction;

+    if ( topint() == ']' ) {

+      popint();

+      if ( istackempty() )	/* terminate action */

+      {

+        zzmode(START);

+        NLATEXT[0] = ' ';

+        zzbegexpr[0] = ' ';

+        if ( zzbufovf ) {

+          err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));

+        }

+      }

+      else {

+        /* terminate $[..] and #[..] */

+        if ( GenCC ) zzreplstr("))");

+        else zzreplstr(")");

+        zzmore();

+      }

+    }

+    else if ( topint() == '|' ) { /* end of simple [...] */

+      popint();

+      zzmore();

+    }

+    else zzmore();

+	>>

+

+consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)

+	<<

+		NLA = 37;

+    

+    zzmore();

+    zzreplstr(inline_set(zzbegexpr+

+    strlen("consumeUntil(")));

+	>>

+

+consumeUntil\( ~[\)]+ \)

+	<<

+		NLA = 38;

+    zzmore();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 39;

+    zzline++; zzmore(); DAWDLE;   

+	>>

+

+\>

+	<<

+		NLA = 40;

+    zzmore();   

+	>>

+

+$

+	<<

+		NLA = 41;

+    zzmore();   

+	>>

+

+$$

+	<<

+		NLA = 42;

+    if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}

+    else err("$$ use invalid in C++ mode");   

+	>>

+

+$\[\]

+	<<

+		NLA = 43;

+    if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}

+    else err("$[] use invalid in C++ mode");   

+	>>

+

+$\[

+	<<

+		NLA = 44;

+    

+    pushint(']');

+    if ( !GenCC ) zzreplstr("zzconstr_attr(");

+    else err("$[..] use invalid in C++ mode");

+    zzmore();

+	>>

+

+$[0-9]+

+	<<

+		NLA = 45;

+    {

+      static char buf[100];

+      numericActionLabel=1;       /* MR10 */

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("$i attrib ref too big");

+      set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",

+      BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"_t%d%s",

+      BlkLevel-1,zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	>>

+

+$[0-9]+.

+	<<

+		NLA = 46;

+    {

+      static char buf[100];

+      numericActionLabel=1;       /* MR10 */

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("$i.field attrib ref too big");

+      zzbegexpr[strlen(zzbegexpr)-1] = ' ';

+      set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",

+      BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"_t%d%s.",

+      BlkLevel-1,zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	>>

+

+$[0-9]+.[0-9]+

+	<<

+		NLA = 47;

+    {

+      static char buf[100];

+      static char i[20], j[20];

+      char *p,*q;

+      numericActionLabel=1;       /* MR10 */

+      if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");

+      for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {

+        if ( q == &i[20] )

+        fatalFL("i of $i.j attrib ref too big",

+        FileStr[CurFile], zzline );

+        *q++ = *p;

+      }

+      *q = '\0';

+      for (p++, q= &j[0]; *p!='\0'; p++) {

+        if ( q == &j[20] )

+        fatalFL("j of $i.j attrib ref too big",

+        FileStr[CurFile], zzline );

+        *q++ = *p;

+      }

+      *q = '\0';

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);

+      else sprintf(buf,"_t%s%s",i,j);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	>>

+

+$[_a-zA-Z][_a-zA-Z0-9]*

+	<<

+		NLA = 48;

+    { static char buf[300]; LabelEntry *el;

+      zzbegexpr[0] = ' ';

+      if ( CurRule != NULL &&

+      strcmp(CurRule, &zzbegexpr[1])==0 ) {

+        if ( !GenCC ) zzreplstr("zzaRet");

+      }

+      else if ( CurRetDef != NULL &&

+      strmember(CurRetDef, &zzbegexpr[1])) {

+        if ( hasMultipleOperands( CurRetDef ) ) {

+          require (strlen(zzbegexpr)<=(size_t)285,

+          "$retval attrib ref too big");

+          sprintf(buf,"_retv.%s",&zzbegexpr[1]);

+          zzreplstr(buf);

+        }

+        else zzreplstr("_retv");

+      }

+      else if ( CurParmDef != NULL &&

+      strmember(CurParmDef, &zzbegexpr[1])) {

+      ;

+    }

+    else if ( Elabel==NULL ) {

+    { err("$-variables in actions outside of rules are not allowed"); }

+  } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {

+  /* MR10 */

+  /* MR10 */                      /* element labels might exist without an elem when */

+  /* MR10 */                      /*  it is a forward reference (to a rule)          */

+  /* MR10 */

+  /* MR10 */						if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )

+  /* MR10 */							{ err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }

+  /* MR10 */

+  /* MR10 */						if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {

+  /* MR10 */                          err("You can no longer use attributes returned by rules when also using ASTs");

+  /* MR10 */                          err("   Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")");

+  /* MR10 */                      };

+  /* MR10 */

+  /* MR10 */                      /* keep track of <<... $label ...>> for semantic predicates in guess mode */

+  /* MR10 */                      /* element labels contain pointer to the owners node                      */

+  /* MR10 */

+  /* MR10 */                      if (el->elem != NULL && el->elem->ntype == nToken) {

+  /* MR10 */                        list_add(&CurActionLabels,el);

+  /* MR10 */                      };

+}

+else

+warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));

+}

+zzmore();

+	>>

+

+#0

+	<<

+		NLA = 49;

+    zzreplstr("(*_root)"); zzmore(); chkGTFlag();   

+	>>

+

+#\[\]

+	<<

+		NLA = 50;

+    if ( GenCC ) {

+      if (NewAST) zzreplstr("(newAST)");

+      else zzreplstr("(new AST)");}

+    else {zzreplstr("zzastnew()");} zzmore();

+    chkGTFlag();

+	>>

+

+#\(\)

+	<<

+		NLA = 51;

+    zzreplstr("NULL"); zzmore(); chkGTFlag();   

+	>>

+

+#[0-9]+

+	<<

+		NLA = 52;

+    {

+      static char buf[100];

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("#i AST ref too big");

+      if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);

+      chkGTFlag();

+    }

+	>>

+

+#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)

+	<<

+		NLA = 53;

+    

+    zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+    getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+	>>

+

+#line ~[\n\r]* (\n|\r|\r\n)

+	<<

+		NLA = 54;

+    

+    zzline++; zzmore();

+	>>

+

+#[_a-zA-Z][_a-zA-Z0-9]*

+	<<

+		NLA = 55;

+    

+    if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||

+    strcmp(zzbegexpr, "#if")==0 ||

+    strcmp(zzbegexpr, "#else")==0 ||

+    strcmp(zzbegexpr, "#endif")==0 ||

+    strcmp(zzbegexpr, "#ifndef")==0 ||

+    strcmp(zzbegexpr, "#define")==0 ||

+    strcmp(zzbegexpr, "#pragma")==0 ||

+    strcmp(zzbegexpr, "#undef")==0 ||

+    strcmp(zzbegexpr, "#import")==0 ||

+    strcmp(zzbegexpr, "#line")==0 ||

+    strcmp(zzbegexpr, "#include")==0 ||

+    strcmp(zzbegexpr, "#error")==0) )

+    {

+      static char buf[100];

+      sprintf(buf, "%s_ast", zzbegexpr+1);

+      /* MR27 */						list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));

+      zzreplstr(buf);

+      chkGTFlag();

+    }

+    zzmore();

+	>>

+

+#\[

+	<<

+		NLA = 56;

+    

+    pushint(']');

+    if ( GenCC ) {

+      if (NewAST) zzreplstr("(newAST(");

+      else zzreplstr("(new AST("); }

+    else zzreplstr("zzmk_ast(zzastnew(),");

+    zzmore();

+    chkGTFlag();

+	>>

+

+#\(

+	<<

+		NLA = 57;

+    

+    pushint('}');

+    if ( GenCC ) {

+      if (tmakeInParser) {

+        zzreplstr("tmake(");

+      }

+      else {

+        zzreplstr("ASTBase::tmake(");

+      }

+    }

+    else {

+      zzreplstr("zztmake(");

+    }

+    zzmore();

+    chkGTFlag();

+	>>

+

+#

+	<<

+		NLA = 58;

+    zzmore();   

+	>>

+

+\)

+	<<

+		NLA = 59;

+    

+    if ( istackempty() )

+    zzmore();

+    else if ( topint()==')' ) {

+      popint();

+    }

+    else if ( topint()=='}' ) {

+      popint();

+      /* terminate #(..) */

+      zzreplstr(", NULL)");

+    }

+    zzmore();

+	>>

+

+\[

+	<<

+		NLA = 60;

+    

+    pushint('|');	/* look for '|' to terminate simple [...] */

+    zzmore();

+	>>

+

+\(

+	<<

+		NLA = 61;

+    

+    pushint(')');

+    zzmore();

+	>>

+

+\\\]

+	<<

+		NLA = 62;

+    zzreplstr("]");  zzmore();   

+	>>

+

+\\\)

+	<<

+		NLA = 63;

+    zzreplstr(")");  zzmore();   

+	>>

+

+\\>

+	<<

+		NLA = 64;

+    if (! tokenActionActive) zzreplstr(">");	 /* MR1 */

+    zzmore();				         /* MR1 */

+	>>

+

+'

+	<<

+		NLA = 65;

+    zzmode(ACTION_CHARS); zzmore();  

+	>>

+

+\"

+	<<

+		NLA = 66;

+    zzmode(ACTION_STRINGS); zzmore();  

+	>>

+

+\\$

+	<<

+		NLA = 67;

+    zzreplstr("$");  zzmore();   

+	>>

+

+\\#

+	<<

+		NLA = 68;

+    zzreplstr("#");  zzmore();   

+	>>

+

+\\(\n|\r|\r\n)

+	<<

+		NLA = 69;

+    zzline++; zzmore();   

+	>>

+

+\\~[\]\)>$#]

+	<<

+		NLA = 70;

+    zzmore();   

+	>>

+

+/

+	<<

+		NLA = 71;

+    zzmore();   

+	>>

+

+/\*

+	<<

+		NLA = 72;

+    zzmode(ACTION_COMMENTS); zzmore();   

+	>>

+

+\*/

+	<<

+		NLA = 73;

+    warn("Missing /*; found dangling */ in action"); zzmore();   

+	>>

+

+//

+	<<

+		NLA = 74;

+    zzmode(ACTION_CPP_COMMENTS); zzmore();   

+	>>

+

+~[\n\r\)\(\\$#\>\]\[\"'/]+

+	<<

+		NLA = 75;

+    zzmore();   

+	>>

+

+

+%%PARSE_ENUM_FILE

+

+@

+	<<

+		NLA = Eof;

+    ;   

+	>>

+

+[\t\ ]+

+	<<

+		NLA = 137;

+    zzskip();   

+	>>

+

+\n|\r|\r\n

+	<<

+		NLA = 138;

+    zzline++; zzskip();   

+	>>

+

+//

+	<<

+		NLA = 139;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzmore();   

+	>>

+

+/\*

+	<<

+		NLA = 140;

+    zzmode(TOK_DEF_COMMENTS); zzskip();   

+	>>

+

+#ifdef

+	<<

+		NLA = 141;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#if

+	<<

+		NLA = 142;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#ifndef

+	<<

+		NLA = 143;

+    ;   

+	>>

+

+#else

+	<<

+		NLA = 144;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#endif

+	<<

+		NLA = 145;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#undef

+	<<

+		NLA = 146;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#import

+	<<

+		NLA = 147;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	>>

+

+#define

+	<<

+		NLA = 149;

+	>>

+

+enum

+	<<

+		NLA = 151;

+	>>

+

+\{

+	<<

+		NLA = 152;

+	>>

+

+=

+	<<

+		NLA = 153;

+	>>

+

+,

+	<<

+		NLA = 154;

+	>>

+

+\}

+	<<

+		NLA = 155;

+	>>

+

+;

+	<<

+		NLA = 156;

+	>>

+

+[0-9]+

+	<<

+		NLA = INT;

+	>>

+

+[a-zA-Z_][_a-zA-Z0-9]*

+	<<

+		NLA = ID;

+	>>

+

+%%

diff --git a/Source/Pccts/antlr/pred.c b/Source/Pccts/antlr/pred.c
new file mode 100644
index 0000000..eb11c4d
--- /dev/null
+++ b/Source/Pccts/antlr/pred.c
@@ -0,0 +1,821 @@
+/*

+ * pred.c -- source for predicate detection, manipulation

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#include "set.h"

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#include "dlgdef.h"

+#include <ctype.h>

+

+#ifdef __USE_PROTOS

+static void complete_context_sets(RuleRefNode *, Predicate *);

+static void complete_context_trees(RuleRefNode *, Predicate *);

+#else

+static void complete_context_sets();

+static void complete_context_trees();

+#endif

+

+char *PRED_AND_LIST = "AND";

+char *PRED_OR_LIST = "OR";

+

+/*

+ * In C mode, return the largest constant integer found as the

+ * sole argument to LATEXT(i).

+ *

+ * In C++ mode, return the largest constant integer found as the

+ * sole argument to LT(i) given that the char before is nonalpha.

+ */

+

+int

+#ifdef __USE_PROTOS

+predicateLookaheadDepth(ActionNode *a)

+#else

+predicateLookaheadDepth(a)

+ActionNode *a;

+#endif

+{

+	int     max_k=0;

+

+    if (a->predEntry != NULL) {

+       MR_pred_depth(a->predEntry->pred,&max_k);

+       goto PREDENTRY_EXIT;

+    }

+

+	if ( GenCC )

+	{

+		/* scan for LT(i) */

+		int k = 0;

+		char *p = a->action;

+		while ( p!=NULL )

+		{

+			p = strstr(p, "LT(");

+			if ( p!=NULL )

+			{

+				if ( p>=a->action && !isalpha(*(p-1)) )

+				{

+					k = atoi(p+strlen("LT("));

+					if ( k>max_k ) max_k=k;

+				}

+				p += strlen("LT(");

+			}

+		}

+	}

+	else {

+		/* scan for LATEXT(i) */

+		int k = 0;

+		char *p = a->action;

+		while ( p!=NULL )

+		{

+			p = strstr(p, "LATEXT(");

+			if ( p!=NULL )

+			{

+				p += strlen("LATEXT(");

+				k = atoi(p);

+				if ( k>max_k ) max_k=k;

+			}

+		}

+	}

+

+	if (max_k==0) {

+		max_k = 1;	   /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */

+		if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */

+		{

+			if ( !a->frmwarned )

+			{

+				a->frmwarned = 1;

+				warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1",

+							 GenCC?"LT(i)":"LATEXT(i)"),

+					   FileStr[a->file], a->line);

+			}

+		}

+	}

+

+/* MR10 */    if ( max_k > CLL_k) {

+/* MR10 */		if ( !a->frmwarned )

+/* MR10 */        {

+/* MR10 */			a->frmwarned = 1;

+/* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d",

+/* MR10 */                        max_k,CLL_k),

+/* MR10 */                        FileStr[a->file],a->line);

+/* MR10 */          if (max_k >= OutputLL_k) {

+/* MR10 */            if (!GenCC) {

+/* MR10 */              errFL(eMsgd("    the lookahead buffer size in C mode is %d token(s) (including the one just recognized)",

+/* MR10 */                        OutputLL_k),

+/* MR10 */                        FileStr[a->file],a->line);

+/* MR10 */            };

+/* MR10 */          };

+/* MR10 */        };

+/* MR10 */        max_k= CLL_k;

+/* MR10 */    };

+

+PREDENTRY_EXIT:

+	return max_k;

+}

+

+/* Find all predicates in a block of alternatives.  DO NOT find predicates

+ * behind the block because that predicate could depend on things set in

+ * one of the nonoptional blocks

+ */

+

+Predicate *

+#ifdef __USE_PROTOS

+find_in_aSubBlk( Junction *alt )

+#else

+find_in_aSubBlk( alt )

+Junction *alt;

+#endif

+{

+	Predicate *a, *head=NULL, *tail=NULL, *root=NULL;

+	Junction *p = alt;

+

+    if (MRhoisting) {

+      return MR_find_in_aSubBlk(alt);

+    };

+	for (; p!=NULL; p=(Junction *)p->p2)

+	{

+		/* ignore empty alts */

+		if ( p->p1->ntype != nJunction ||

+			 ((Junction *)p->p1)->jtype != EndBlk )

+		{

+			a = find_predicates(p->p1);	/* get preds for this alt */

+			if ( a==NULL ) continue;

+

+			/* make an OR list of predicates */

+			if ( head==NULL )

+			{

+				root = new_pred();

+				root->expr = PRED_OR_LIST;

+				head = tail = a;

+				root->down = head;

+			}

+			else {

+				tail->right = a;

+				a->left = tail;

+				a->up = tail->up;

+				tail = a;

+			}

+		}

+	}

+

+	/* if just one pred, remove OR root */

+	if ( root!=NULL && root->down->right == NULL )

+	{

+		Predicate *d = root->down;

+		free( (char *) root);

+		return d;

+	}

+

+	return root;

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+find_in_aOptBlk( Junction *alt )

+#else

+find_in_aOptBlk( alt )

+Junction *alt;

+#endif

+{

+	return find_in_aSubBlk( alt );

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+find_in_aLoopBegin( Junction *alt )

+#else

+find_in_aLoopBegin( alt )

+Junction *alt;

+#endif

+{

+	return find_in_aSubBlk( (Junction *) alt->p1 );	/* get preds in alts */

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+find_in_aPlusBlk( Junction *alt )

+#else

+find_in_aPlusBlk( alt )

+Junction *alt;

+#endif

+{

+	require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk");

+	return find_in_aSubBlk( alt );

+}

+

+/* Look for a predicate;

+ *

+ * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs.

+ * This means that a "hoisting distance" of zero is the only distance

+ * allowable.  Init actions are ignored.

+ *

+ * WARNING:

+ *		Assumes no (..)? block after predicate for the moment.

+ *		Does not check to see if pred is in production that can generate

+ *			a sequence contained in the set of ambiguous tuples.

+ *

+ * Return the predicate found if any.

+ */

+

+

+Predicate *

+#ifdef __USE_PROTOS

+find_predicates( Node *alt )

+#else

+find_predicates( alt )

+Node *alt;

+#endif

+{

+#ifdef DBG_PRED

+	Junction *j;

+	RuleRefNode *r;

+	TokNode *t;

+#endif

+	Predicate *pred;

+

+	if ( alt==NULL ) return NULL;

+

+#ifdef DBG_PRED

+	switch ( alt->ntype )

+	{

+		case nJunction :

+			j = (Junction *) alt;

+			fprintf(stderr, "Junction(in %s)", j->rname);

+			switch ( j->jtype )

+			{

+				case aSubBlk :

+					fprintf(stderr,"aSubBlk\n");

+					break;

+				case aOptBlk :

+					fprintf(stderr,"aOptBlk\n");

+					break;

+				case aLoopBegin :

+					fprintf(stderr,"aLoopBeginBlk\n");

+					break;

+				case aLoopBlk :

+					fprintf(stderr,"aLoopBlk\n");

+					break;

+				case aPlusBlk :

+					fprintf(stderr,"aPlusBlk\n");

+					break;

+				case EndBlk :

+					fprintf(stderr,"EndBlk\n");

+					break;

+				case RuleBlk :

+					fprintf(stderr,"RuleBlk\n");

+					break;

+				case Generic :

+					fprintf(stderr,"Generic\n");

+					break;

+				case EndRule :

+					fprintf(stderr,"EndRule\n");

+					break;

+			}

+			break;

+		case nRuleRef :

+			r = (RuleRefNode *) alt;

+			fprintf(stderr, "RuleRef(in %s)\n", r->rname);

+			break;

+		case nToken :

+			t = (TokNode *) alt;

+			fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token));

+			break;

+		case nAction :

+			fprintf(stderr, "Action\n");

+			break;

+	}

+#endif

+

+	switch ( alt->ntype )

+	{

+		case nJunction :

+		{

+			Predicate *a, *b;

+			Junction *p = (Junction *) alt;	

+

+			/* lock nodes */

+			if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||

+				 p->jtype==aPlusBlk || p->jtype==EndRule )

+			{

+				require(p->pred_lock!=NULL, "rJunc: lock array is NULL");

+				if ( p->pred_lock[1] )

+				{

+					return NULL;

+				}

+				p->pred_lock[1] = TRUE;

+			}

+

+			switch ( p->jtype )

+			{

+				case aSubBlk :

+					a = find_in_aSubBlk(p);

+					return a;	/* nothing is visible past this guy */

+				case aOptBlk :

+					a = find_in_aOptBlk(p);

+					return a;

+				case aLoopBegin :

+					a = find_in_aLoopBegin(p);

+					return a;

+				case aLoopBlk :

+					a = find_in_aSubBlk(p);

+					p->pred_lock[1] = FALSE;

+					return a;

+				case aPlusBlk :

+					a = find_in_aPlusBlk(p);

+					p->pred_lock[1] = FALSE;

+					return a;	/* nothing is visible past this guy */

+				case RuleBlk :

+					a = find_predicates(p->p1);

+					p->pred_lock[1] = FALSE;

+					return a;

+				case Generic :

+					a = find_predicates(p->p1);

+					b = find_predicates(p->p2);

+					if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE;

+					if ( a==NULL ) return b;

+					if ( b==NULL ) return a;

+					/* otherwise OR the two preds together */

+					{

+					fatal_internal("hit unknown situation during predicate hoisting");

+					}

+				case EndBlk :

+				case EndRule :	/* Find no predicates after a rule ref */

+					return NULL;

+				default:

+					fatal_internal("this cannot be printed\n");

+					break;

+			}

+		}

+		case nAction :

+		{

+			ActionNode *p = (ActionNode *) alt;

+            if ( p->noHoist) return NULL;                           /* MR12c */

+			if ( p->init_action ) return find_predicates(p->next);

+			if ( p->is_predicate )

+			{

+				Tree *t=NULL;

+#ifdef DBG_PRED

+				fprintf(stderr, "predicate: <<%s>>?\n", p->action);

+#endif

+				if ( p->guardpred!=NULL )

+				{

+					pred = predicate_dup(p->guardpred);

+                    MR_guardPred_plainSet(p,pred);                  /* MR12c */

+				}

+				else

+				{

+					pred = new_pred();

+					pred->k = predicateLookaheadDepth(p);

+					pred->source = p;

+					pred->expr = p->action;

+					if ( HoistPredicateContext && pred->k > 1 )

+					{

+						/* MR30 No need to use first_item_is_guess_block_extra

+						   since we know this is an action, not a (...)* or

+						   (...)+ block.

+						*/

+

+						if ( first_item_is_guess_block((Junction *)p->next) )

+						{

+                            warnFL("cannot compute context of predicate in front of (..)? block",

+                            FileStr[p->file], p->line);

+						}

+						else

+						{

+							ConstrainSearch = 0;

+/* MR11 */                  if (p->ampersandPred != NULL) {

+/* MR11 */  					TRAV(p,

+/* MR11 */							 pred->k,

+/* MR11 */  						 &(pred->completionTree), t);

+/* MR11 */                  } else {

+    							TRAV(p->next,

+    								 pred->k,

+    								 &(pred->completionTree), t);

+                            };

+							pred->tcontext = t;

+                            MR_check_pred_too_long(pred,pred->completionTree);

+#ifdef DBG_PRED

+							fprintf(stderr, "LL(%d) context:", pred->k);

+							preorder(t);

+							fprintf(stderr, "\n");

+#endif

+						}

+					}

+					else if ( HoistPredicateContext && pred->k == 1 )

+					{

+						pred->scontext[1] = empty;

+						/* MR30 No need to use first_item_is_guess_block_extra

+						   since we know this is an action.

+						*/

+						if ( first_item_is_guess_block((Junction *)p->next) )

+						{

+                        warnFL("cannot compute context of predicate in front of (..)? block",

+                                             FileStr[p->file], p->line);

+						}

+						else

+						{

+							REACH((Junction *)p->next,

+								  1,

+								  &(pred->completionSet),

+								  pred->scontext[1]);

+                            MR_check_pred_too_long(pred,pred->completionSet);

+#ifdef DBG_PRED

+							fprintf(stderr, "LL(1) context:");

+							s_fprT(stderr, pred->scontext[1]);

+							fprintf(stderr, "\n");

+#endif

+						}

+					}

+				}

+				{

+					Predicate  *d = find_predicates(p->next);

+                    Predicate  *root;

+

+/* Warning: Doesn't seem like the up pointers will all be set correctly;

+ * TJP: that's ok, we're not using them now.

+ */

+					if ( d!=NULL )

+					{

+						root = new_pred();

+						root->expr = PRED_AND_LIST;

+						root->down = pred;

+						pred->right = d;

+						pred->up = root;

+						d->left = pred;

+						d->up = pred->up;

+						return root;

+					}

+				}

+				return pred;

+			}

+			return NULL;

+		}

+		case nRuleRef :

+		{

+			Predicate   *a;

+			RuleRefNode *p = (RuleRefNode *) alt;

+			Junction    *r;

+            Junction    *save_MR_RuleBlkWithHalt;

+

+			RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);

+			if ( q == NULL )

+			{

+				warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );

+				return NULL;

+			}

+			r = RulePtr[q->rulenum];

+			if ( r->pred_lock[1] )

+			{

+				/* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis

+				 * must have seen it earlier.

+				 */

+				return NULL;

+			}

+

+            /* MR10 There should only be one halt set at a time.        */

+            /* MR10 Life would have been easier with a global variable  */

+            /* MR10    (at least for this particular need)              */

+            /* MR10 Unset the old one and set the new one, later undo.  */

+

+            require(r->end->halt == FALSE,"should only have one halt at a time");

+

+/* MR10 */  require(MR_RuleBlkWithHalt == NULL ||

+/* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),

+/* MR10 */             "RuleBlkWithHalt->end not RuleBlk or does not have halt set");

+/* MR10 */  if (MR_RuleBlkWithHalt != NULL) {

+/* MR10 */    MR_RuleBlkWithHalt->end->halt=FALSE;

+/* MR10 */  };

+

+/***        fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq);     ***/

+

+            require(r->end->halt == FALSE,"rule->end->halt already set");

+

+            save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;

+

+/* MR10 */  MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt);

+/* MR10 */  MR_pointerStackPush(&MR_PredRuleRefStack,p);

+

+			r->end->halt = TRUE;

+/* MR10 */  MR_RuleBlkWithHalt=r;

+

+			a = find_predicates((Node *)r);

+

+            require(r->end->halt == TRUE,"rule->end->halt not set");

+            r->end->halt = FALSE;

+

+/* MR10 */  MR_pointerStackPop(&MR_PredRuleRefStack);

+/* MR10 */  MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack);

+

+            require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt,

+                    "RuleBlkWithHaltStack not consistent");

+

+/* MR10 */  require(MR_RuleBlkWithHalt == NULL ||

+/* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE),

+/* MR10 */             "RuleBlkWithHalt->end not RuleBlk or has no halt set");

+/* MR10 */  if (MR_RuleBlkWithHalt != NULL) {

+/* MR10 */    MR_RuleBlkWithHalt->end->halt=TRUE;

+/* MR10 */  };

+

+/***        fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq);   ***/

+

+			if ( a==NULL ) return NULL;

+

+			/* attempt to compute the "local" FOLLOW just like in normal lookahead

+			 * computation if needed

+			 */

+

+			complete_context_sets(p,a);

+			complete_context_trees(p,a);

+

+/* MR10 */  MR_cleanup_pred_trees(a);

+

+			return a;

+		}

+		case nToken :

+			break;

+	}

+

+	return NULL;

+}

+

+#ifdef __USE_PROTOS

+Predicate *MR_find_predicates_and_supp(Node *alt)

+#else

+Predicate *MR_find_predicates_and_supp(alt)

+  Node      *alt;

+#endif

+{

+    Predicate   *p;

+

+    p=find_predicates(alt);

+    p=MR_suppressK(alt,p);

+    return p;

+}

+

+Predicate *

+#ifdef __USE_PROTOS

+new_pred( void )

+#else

+new_pred( )

+#endif

+{

+	Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */

+	require(p!=NULL, "new_pred: cannot alloc predicate");

+    p->scontext[0]=empty;

+    p->scontext[1]=empty;

+    p->completionTree=empty;

+    p->completionSet=empty;

+    p->plainSet=empty;

+	return p;

+}

+

+static void

+#ifdef __USE_PROTOS

+complete_context_sets( RuleRefNode *p, Predicate *a )

+#else

+complete_context_sets( p, a )

+RuleRefNode *p;

+Predicate *a;

+#endif

+{

+	set rk2, b;

+	int k2;

+

+#ifdef DBG_PRED

+	fprintf(stderr, "enter complete_context_sets\n");

+#endif

+	for (; a!=NULL; a=a->right)

+	{

+		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )

+		{

+			complete_context_sets(p,a->down);

+			continue;

+		}

+		rk2 = b = empty;

+		while ( !set_nil(a->completionSet) )

+		{

+			k2 = set_int(a->completionSet);

+			set_rm(k2, a->completionSet);

+

+            REACH(p->next, k2, &rk2, b);

+			set_orin(&(a->scontext[1]), b);

+			set_free(b);

+		}

+

+		set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */

+		set_free(rk2);

+#ifdef DBG_PRED

+		fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a);

+		s_fprT(stderr, a->scontext[1]);

+		fprintf(stderr, "\n");

+#endif

+/*		complete_context_sets(p, a->down);*/

+	}

+#ifdef DBG_PRED

+	fprintf(stderr, "exit complete_context_sets\n");

+#endif

+}

+

+static void

+#ifdef __USE_PROTOS

+complete_context_trees( RuleRefNode *p, Predicate *a )

+#else

+complete_context_trees( p, a )

+RuleRefNode *p;

+Predicate *a;

+#endif

+{

+	set rk2;

+	int k2;

+	Tree *u;

+

+#ifdef DBG_PRED

+	fprintf(stderr, "enter complete_context_trees\n");

+#endif

+	for (; a!=NULL; a=a->right)

+	{

+		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )

+		{

+			complete_context_trees(p, a->down);

+			continue;

+		}

+		rk2 = empty;

+

+		/* any k left to do? if so, link onto tree */

+		while ( !set_nil(a->completionTree) )

+		{	

+			k2 = set_int(a->completionTree);

+			set_rm(k2, a->completionTree);

+			u = NULL;

+

+            TRAV(p->next, k2, &rk2, u);

+

+			/* any subtrees missing k2 tokens, add u onto end */

+			a->tcontext = tlink(a->tcontext, u, k2);

+            Tfree(u);   /* MR10 */

+		}

+		set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */

+		set_free(rk2);

+#ifdef DBG_PRED

+		fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k);

+		preorder(a->tcontext);

+		fprintf(stderr, "\n");

+#endif

+/*		complete_context_trees(p, a->down);*/

+	}

+#ifdef DBG_PRED

+	fprintf(stderr, "exit complete_context_trees\n");

+#endif

+}

+

+/* Walk a list of predicates and return the set of all tokens in scontext[1]'s */

+set

+#ifdef __USE_PROTOS

+covered_set( Predicate *p )

+#else

+covered_set( p )

+Predicate *p;

+#endif

+{

+	set a;

+

+	a = empty;

+	for (; p!=NULL; p=p->right)

+	{

+		if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST )

+		{

+			set_orin(&a, covered_set(p->down));

+			continue;

+		}

+		set_orin(&a, p->scontext[1]);

+		set_orin(&a, covered_set(p->down));

+	}

+	return a;

+}

+

+/* MR10 predicate_free()

+   MR10 Don't free the leaf nodes since they are part of the action node

+*/

+

+#ifdef __USE_PROTOS

+void predicate_free(Predicate *p)

+#else

+void predicate_free(p)

+  Predicate     *p;

+#endif

+{

+  if (p == NULL) return;

+  predicate_free(p->right);

+  predicate_free(p->down);

+  if (p->cloned ||

+      p->source == NULL ||

+      p->source->guardpred == NULL ||

+      p->expr == PRED_AND_LIST ||

+      p->expr == PRED_OR_LIST) {

+    set_free(p->scontext[1]);

+    set_free(p->completionSet);

+    set_free(p->completionTree);

+    set_free(p->plainSet);

+    Tfree(p->tcontext);

+    free( (char *) p);

+  } else {

+    p->right=NULL;

+    p->down=NULL;  /* MR13 *** debug */

+  };

+}

+

+/* MR10 predicate_dup() */

+

+#ifdef __USE_PROTOS

+Predicate * predicate_dup_xxx(Predicate *p,int contextToo)

+#else

+Predicate * predicate_dup_xxx(p,contextToo)

+  Predicate     *p;

+  int           contextToo;

+#endif

+{

+  Predicate     *q;

+

+  if (p == NULL) return NULL;

+  q=new_pred();

+  q->down=predicate_dup(p->down);

+  q->right=predicate_dup(p->right);

+

+  /*

+     don't replicate expr - it is read-only

+     and address comparison is used to look

+     for identical predicates.

+  */

+

+  q->expr=p->expr;

+  q->k=p->k;

+  q->source=p->source;

+  q->cloned=1;

+  q->ampersandStyle=p->ampersandStyle;

+  q->inverted=p->inverted;

+  q->predEntry=p->predEntry;

+  q->plainSet=set_dup(p->plainSet);

+

+  if (contextToo) {

+    q->tcontext=tdup(p->tcontext);

+    q->scontext[0]=set_dup(p->scontext[0]);

+    q->scontext[1]=set_dup(p->scontext[1]);

+    q->completionTree=set_dup(p->completionTree);

+    q->completionSet=set_dup(p->completionSet);

+  };

+

+  /* don't need to dup "redundant" */

+

+  return q;

+

+}

+

+#ifdef __USE_PROTOS

+Predicate * predicate_dup_without_context(Predicate *p)

+#else

+Predicate * predicate_dup_without_context(p)

+  Predicate     *p;

+#endif

+{

+  return predicate_dup_xxx(p,0);

+}

+

+#ifdef __USE_PROTOS

+Predicate * predicate_dup(Predicate *p)

+#else

+Predicate * predicate_dup(p)

+  Predicate     *p;

+#endif

+{

+  return predicate_dup_xxx(p,1);

+}

+

diff --git a/Source/Pccts/antlr/proto.h b/Source/Pccts/antlr/proto.h
new file mode 100644
index 0000000..53035e7
--- /dev/null
+++ b/Source/Pccts/antlr/proto.h
@@ -0,0 +1,852 @@
+/*

+ * proto.h -- function prototypes

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+                           /* V a r i a b l e s */

+

+extern int tp;

+extern Junction *SynDiag;

+extern char Version[];

+extern char VersionDef[];

+#ifdef __cplusplus

+extern void (*fpPrint[])(...);

+#else

+extern void (*fpPrint[])();

+#endif

+#ifdef __cplusplus

+extern struct _set (*fpReach[])(...);

+#else

+extern struct _set (*fpReach[])();

+#endif

+#ifdef __cplusplus

+extern struct _tree *(*fpTraverse[])(...);

+#else

+extern struct _tree *(*fpTraverse[])();

+#endif

+#ifdef __cplusplus

+extern void (**fpTrans)(...);

+#else

+extern void (**fpTrans)();

+#endif

+#ifdef __cplusplus

+extern void (**fpJTrans)(...);

+#else

+extern void (**fpJTrans)();

+#endif

+#ifdef __cplusplus

+extern void (*C_Trans[NumNodeTypes+1])(...);

+#else

+extern void (*C_Trans[])();

+#endif

+#ifdef __cplusplus

+extern void (*C_JTrans[NumJuncTypes+1])(...);

+#else

+extern void (*C_JTrans[])();

+#endif

+extern int BlkLevel;

+extern int CurFile;

+extern char *CurPredName;

+extern char *CurRule;

+extern int  CurRuleDebug;                       /* MR13 */

+extern Junction *CurRuleBlk;

+extern RuleEntry *CurRuleNode;

+extern ListNode *CurElementLabels;

+extern ListNode *CurAstLabelsInActions;         /* MR27 */

+extern ListNode *ContextGuardPredicateList;     /* MR13 */

+extern ListNode *CurActionLabels;

+extern int numericActionLabel;        /* MR10 << ... $1 ... >> or << ... $1 ... >>?   */

+extern ListNode *NumericPredLabels;   /* MR10 << ... $1 ... >>?  ONLY                 */

+extern char *FileStr[];

+extern int NumFiles;

+extern int EpToken;

+extern int WildCardToken;

+extern Entry	**Tname,

+				**Texpr,

+				**Rname,

+				**Fcache,

+				**Tcache,

+				**Elabel,

+				**Sname,

+                **Pname;    /* MR11 */

+extern ListNode *ExprOrder;

+extern ListNode **Cycles;

+extern int TokenNum;

+extern int LastTokenCounted;

+extern ListNode *BeforeActions, *AfterActions, *LexActions;

+

+/* MR1							                        		    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class     */

+/* MR1			  via #lexmember <<....>> & #lexprefix <<...>>              */

+/* MR1									    */

+

+extern ListNode *LexMemberActions;			 	             /* MR1 */

+extern ListNode *LexPrefixActions;				             /* MR1 */

+

+extern set *fset;   /* for constrained search */             /* MR11 */

+extern int maxk;    /* for constrained search */             /* MR11 */

+extern int Save_argc;                                        /* MR10 */

+extern char **Save_argv;                                     /* MR10 */

+extern ListNode *eclasses, *tclasses;

+extern char	*HdrAction;

+extern char *FirstAction;                                    /* MR11 */

+extern FILE	*ErrFile;

+extern char *RemapFileName;

+extern char *ErrFileName;

+extern char *DlgFileName;

+extern char *DefFileName;

+extern char *ModeFileName;

+extern char *StdMsgName;

+extern int NumRules;

+extern Junction **RulePtr;

+extern int LL_k;

+extern int CLL_k;

+extern char *decodeJType[];

+extern int PrintOut;

+extern int PrintAnnotate;

+extern int CodeGen;

+extern int LexGen;

+extern int esetnum;

+extern int setnum;

+extern int wordnum;

+extern int GenAST;

+extern int GenANSI;

+extern int **FoStack;

+extern int **FoTOS;

+extern int GenExprSetsOpt;

+extern FILE *DefFile;

+extern int CannotContinue;

+extern int GenCR;

+extern int GenLineInfo;

+extern int GenLineInfoMS;

+extern int action_file, action_line;

+extern int TraceGen;

+extern int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile;

+extern char *CurAmbigbtype;

+extern int elevel;

+extern int GenEClasseForRules;

+extern FILE *input, *output;

+extern char **TokenStr, **ExprStr;

+extern int CurrentLexClass, NumLexClasses;

+extern LClass lclass[];

+extern char LexStartSymbol[];

+extern char	*CurRetDef;

+extern char	*CurParmDef;

+extern int OutputLL_k;

+extern int TreeResourceLimit;

+extern int DemandLookahead;

+extern char *RulePrefix;

+extern int GenStdPccts;

+extern char *stdpccts;

+extern int ParseWithPredicates;

+extern int ConstrainSearch;

+extern int PURIFY;													/* MR23 */

+

+extern set MR_CompromisedRules;                                     /* MR14 */

+extern int MR_AmbSourceSearch;                                      /* MR11 */

+extern int MR_SuppressSearch;                                       /* MR13 */

+extern int MR_AmbSourceSearchGroup;                                 /* MR11 */

+extern int MR_AmbSourceSearchChoice;                                /* MR11 */

+extern int MR_AmbSourceSearchLimit;                                 /* MR11 */

+extern int MR_usingPredNames;                                       /* MR11 */

+extern int MR_ErrorSetComputationActive;                            /* MR14 */

+extern char *MR_AmbAidRule;                                         /* MR11 */

+extern int   MR_AmbAidLine;                                         /* MR11 */

+extern int   MR_AmbAidMultiple;                                     /* MR11 */

+extern int MR_AmbAidDepth;                                          /* MR11 */

+extern int MR_skipped_e3_report;                                    /* MR11 */

+extern int MR_matched_AmbAidRule;                                   /* MR11 */

+extern int MR_Inhibit_Tokens_h_Gen;                                 /* MR13 */

+extern int NewAST;                                                  /* MR13 */

+extern int tmakeInParser;                                           /* MR23 */

+extern int AlphaBetaTrace;                                          /* MR14 */

+extern int MR_BlkErr;                                               /* MR21 */

+extern int MR_AlphaBetaWarning;                                     /* MR14 */

+extern int MR_AlphaBetaMessageCount;                                /* MR14 */

+extern int MR_MaintainBackTrace;                                    /* MR14 */

+extern int MR_BadExprSets;                                          /* MR13 */

+extern int FoundGuessBlk;

+extern int FoundException;

+extern int FoundAtOperator;				                             /* MR6 */

+extern int FoundExceptionGroup;                                      /* MR6 */

+extern int WarningLevel;

+extern int UseStdout;					                             /* MR6 */

+extern int TabWidth;					                             /* MR6 */

+extern int pLevel;

+extern int pAlt1;

+extern int pAlt2;

+extern int AImode;

+extern int HoistPredicateContext;

+extern int MRhoisting;                                               /* MR9 */

+extern int MRhoistingk;                                              /* MR13 */

+extern int MR_debugGenRule;                                          /* MR11 */

+extern int GenCC;

+extern char *ParserName;

+extern char *StandardSymbols[];

+extern char *ASTSymbols[];

+extern set reserved_positions;

+extern set all_tokens;

+extern set imag_tokens;

+extern set tokclasses;

+extern ListNode *ForcedTokens;

+extern int *TokenInd;

+extern FILE *Parser_h, *Parser_c;

+extern char CurrentClassName[];

+extern int no_classes_found;

+extern char Parser_h_Name[];

+extern char Parser_c_Name[];

+extern char MRinfoFile_Name[];                                      /* MR10 */

+extern FILE *MRinfoFile;                                            /* MR10 */

+extern int MRinfo;                                                  /* MR10 */

+extern int MRinfoSeq;                                               /* MR10 */

+extern int InfoP;                                                   /* MR10 */

+extern int InfoT;                                                   /* MR10 */

+extern int InfoF;                                                   /* MR10 */

+extern int InfoM;                                                   /* MR10 */

+extern int InfoO;                                                   /* MR12 */

+extern int PotentialSuppression;                                    /* MR10 */

+extern int PotentialDummy;                                          /* MR10 */

+extern int TnodesInUse;                                             /* MR10 */

+extern int TnodesPeak;                                              /* MR10 */

+extern int TnodesReportThreshold;                                   /* MR11 */

+extern int TnodesAllocated;                                         /* MR10 */

+extern char *ClassDeclStuff;                                        /* MR10 */

+extern char *BaseClassName;                                         /* MR22 */

+extern ListNode *class_before_actions, *class_after_actions;

+extern char *UserTokenDefsFile;

+extern int UserDefdTokens;

+extern ListNode *MetaTokenNodes;

+extern char *OutputDirectory;

+extern int DontCopyTokens;

+extern int LTinTokenAction;                                         /* MR23 */

+extern set AST_nodes_refd_in_actions;

+extern ListNode *CurExGroups;

+extern int CurBlockID;

+extern int CurAltNum;

+extern Junction *CurAltStart;

+extern Junction *OuterAltStart;               /* chain exception groups MR7 */

+extern ExceptionGroup *DefaultExGroup;

+extern int NumSignals;

+extern int ContextGuardTRAV;

+extern Junction *MR_RuleBlkWithHalt;            /* MR10 */

+extern PointerStack MR_BackTraceStack;          /* MR10 */

+extern PointerStack MR_PredRuleRefStack;        /* MR10 */

+extern PointerStack MR_RuleBlkWithHaltStack;    /* MR10 */

+

+/*									*/

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	    */

+/* MR1					in DLG action			                    */

+/*								                                            */

+extern int tokenActionActive;	                                     /* MR1 */

+

+extern char *PRED_OR_LIST;                                          /* MR10 */

+extern char *PRED_AND_LIST;                                         /* MR10 */

+

+#ifdef __VMS

+#define STRICMP strcasecmp /* MR21 */

+#else

+#define STRICMP stricmp /* MR21 */

+#endif

+

+/* MR26 */

+#ifdef PCCTS_USE_STDARG

+extern Tree *tmake(Tree *root, ...);

+#else

+extern Tree *tmake();

+#endif

+

+#ifdef __USE_PROTOS

+extern int STRICMP(const char*, const char*);

+extern void istackreset(void);

+extern int istacksize(void);

+extern void pushint(int);

+extern int popint( void );

+extern int istackempty( void );

+extern int topint( void );

+extern void NewSetWd( void );

+extern void DumpSetWd( void );

+extern void DumpSetWdForC( void );

+extern void DumpSetWdForCC( void );

+extern void NewSet( void );

+extern void FillSet( set );

+extern void ComputeErrorSets( void );

+extern void ComputeTokSets( void );

+extern void SubstErrorClass( set * );

+extern int DefErrSet( set *, int, char * );

+extern int DefErrSetForC( set *, int, char * );

+extern int DefErrSetForCC( set *, int, char * );

+extern int DefErrSet1(int, set *, int, char *);                         /* MR21 */

+extern int DefErrSetForC1(int, set *, int, char *, const char* );       /* MR21 */

+extern int DefErrSetForCC1(int, set *, int, char *, const char* );      /* MR21 */

+extern int DefErrSetWithSuffix(int, set *, int, char *, const char *);  /* MR21 */

+extern void GenErrHdr( void );

+extern void dumpExpr( FILE *, char * );

+extern void addParm( Node *, char * );

+extern Graph buildAction( char *, int, int, int );

+extern Graph buildToken( char * );

+extern Graph buildWildCard( char * );

+extern Graph buildRuleRef( char * );

+extern Graph Or( Graph, Graph );

+extern Graph Cat( Graph, Graph );

+extern Graph makeOpt( Graph, int, char *);

+extern Graph makeBlk( Graph, int, char *);

+extern Graph makeLoop( Graph, int, char *);

+extern Graph makePlus( Graph, int, char *);

+extern Graph emptyAlt( void );

+extern Graph emptyAlt3( void );

+extern TokNode * newTokNode( void );

+extern RuleRefNode * newRNode( void );

+extern Junction * newJunction( void );

+extern ActionNode * newActionNode( void );

+extern char * makelocks( void );

+extern void preorder( Tree * );

+extern Tree * tnode( int );

+extern void _Tfree( Tree * );

+extern Tree * tdup( Tree * );

+extern int is_single_tuple( Tree * );

+extern Tree * tappend( Tree *, Tree * );

+extern void Tfree( Tree * );

+extern Tree * tlink( Tree *, Tree *, int );

+extern Tree * tshrink( Tree * );

+extern Tree * tflatten( Tree * );

+extern Tree * tJunc( Junction *, int, set * );

+extern Tree * tRuleRef( RuleRefNode *, int, set * );

+extern Tree * tToken( TokNode *, int, set * );

+extern Tree * tAction( ActionNode *, int, set * );

+extern int tmember( Tree *, Tree * );

+extern int tmember_constrained( Tree *, Tree * );

+extern Tree * tleft_factor( Tree * );

+extern Tree * trm_perm( Tree *, Tree * );

+extern void tcvt( set *, Tree * );

+extern Tree * permute( int, int );

+extern Tree * VerifyAmbig( Junction *, Junction *, unsigned **, set *, Tree **, Tree **, int * );

+extern set rJunc( Junction *, int, set * );

+extern set rRuleRef( RuleRefNode *, int, set * );

+extern set rToken( TokNode *, int, set * );

+extern set rAction( ActionNode *, int, set * );

+extern void HandleAmbiguity( Junction *, Junction *, Junction *, int );

+extern set First( Junction *, int, int, int * );

+extern void freeBlkFsets( Junction * );

+extern void genAction( ActionNode * );

+extern void genRuleRef( RuleRefNode * );

+extern void genToken( TokNode * );

+extern void genOptBlk( Junction * );

+extern void genLoopBlk( Junction *, Junction *, Junction *, int );

+extern void genLoopBegin( Junction * );

+extern void genPlusBlk( Junction * );

+extern void genSubBlk( Junction * );

+extern void genRule( Junction * );

+extern void genJunction( Junction * );

+extern void genEndBlk( Junction * );

+extern void genEndRule( Junction * );

+extern void genHdr( int );

+extern void genHdr1( int );

+extern void dumpAction( char *, FILE *, int, int, int, int );

+extern void dumpActionPlus(ActionNode*, char *, FILE *, int, int, int, int );   /* MR21 */

+extern Entry ** newHashTable( void );

+extern Entry * hash_add( Entry **, char *, Entry * );

+extern Entry * hash_get( Entry **, char * );

+extern void hashStat( Entry ** );

+extern char * mystrdup( char * );

+extern void genLexDescr( void );

+extern void dumpLexClasses( FILE * );

+extern void genDefFile( void );

+extern void DumpListOfParmNames( char *, FILE *, int );	/* MR5 janm 26-May-97 */

+extern int DumpNextNameInDef( char **, FILE * );

+extern void DumpOldStyleParms( char *, FILE * );

+extern void DumpType( char *, FILE * );

+extern int strmember( char *, char * );

+/* extern int HasComma( char * ); MR23 Replaced by hasMultipleOperands() */

+extern void DumpRetValStruct( FILE *, char *, int );

+extern char * StripQuotes( char * );

+extern int main( int, char *[] );

+extern void readDescr( void );

+extern FILE * NextFile( void );

+extern char * outnameX( char *, char *);

+extern char * outname( char * );

+extern void fatalFL( char *, char *, int );

+extern void fatal_intern( char *, char *, int );

+extern void cleanUp( void );

+extern char * eMsg3( char *, char *, char *, char * );

+extern char * eMsgd( char *, int );

+extern char * eMsgd2( char *, int, int );

+extern void s_fprT( FILE *, set );

+extern char * TerminalString( int );

+extern void lexclass( char * );

+extern void lexmode( int );

+extern int LexClassIndex( char * );

+extern int hasAction( char * );

+extern void setHasAction( char *, char * );

+extern int addTname( char * );

+extern int addTexpr( char * );

+extern int Tnum( char * );

+extern void Tklink( char *, char * );

+extern Entry * newEntry( char *, int );

+extern void list_add( ListNode **, void * );

+extern void list_free( ListNode **, int freeData );     /* MR10 */

+extern void list_apply( ListNode *, void (*)(void *) );

+extern int list_search_cstring (ListNode *, char *);    /* MR27 */

+extern char * Fkey( char *, int, int );

+extern void FoPush( char *, int );

+extern void FoPop( int );

+extern void RegisterCycle( char *, int );

+extern void ResolveFoCycles( int );

+extern void pJunc( Junction * );

+extern void pRuleRef( RuleRefNode * );

+extern void pToken( TokNode * );

+extern void pAction( ActionNode * );

+extern void FoLink( Node * );

+extern void addFoLink( Node *, char *, Junction * );

+extern void GenCrossRef( Junction * );

+extern void defErr( char *, long, long, long, long, long, long );

+extern void genStdPCCTSIncludeFile(FILE *,char *);                  /* MR10 */

+extern char * pcctsBaseName(char *);                                /* MR32 */

+extern Predicate *find_predicates(Node *);                          /* MR10 */

+extern Predicate *MR_find_predicates_and_supp(Node *);              /* MR13 */

+extern int predicateLookaheadDepth(ActionNode *);                   /* MR10 */

+extern void predicate_free(Predicate *);                            /* MR10 */

+extern Predicate * predicate_dup(Predicate *);                      /* MR10 */

+extern Predicate * predicate_dup_without_context(Predicate *);      /* MR11 */

+extern void GenRulePrototypes(FILE *, Junction *);

+extern Junction *first_item_is_guess_block(Junction *);

+extern Junction *first_item_is_guess_block_extra(Junction * q);		/* MR30 */

+extern Junction *analysis_point(Junction *);

+extern Tree *make_tree_from_sets(set *, set *);

+extern Tree *tdup_chain(Tree *);

+extern Tree *tdif(Tree *, Predicate *, set *, set *);

+extern set covered_set(Predicate *);

+extern void AmbiguityDialog(Junction *, int, Junction *, Junction *, int *, int *);

+extern void dumpAmbigMsg(set *, FILE *, int);

+extern void GenRuleFuncRedefs(FILE *, Junction *);

+extern void GenPredefinedSymbolRedefs(FILE *);

+extern void GenASTSymbolRedefs(FILE *);

+extern void GenRemapFile(void);

+extern void GenSetRedefs(FILE *);

+extern ForcedToken *newForcedToken(char *, int);

+extern void RemapForcedTokens(void);

+extern char *TokenOrExpr(int);

+extern void setUpperRange(TokNode *, char *);

+extern void GenParser_c_Hdr(void);

+extern void GenParser_h_Hdr(void);

+extern void GenRuleMemberDeclarationsForCC(FILE *, Junction *);

+extern int addForcedTname( char *, int );

+extern char *OutMetaName(char *);

+extern void OutFirstSetSymbol(Junction *q, char *);                 /* MR21 */

+extern void warnNoFL(char *err);

+extern void warnFL(char *err,char *f,int l);

+extern void warn(char *err);

+extern void warnNoCR( char *err );

+extern void errNoFL(char *err);

+extern void errFL(char *err,char *f,int l);

+extern void err(char *err);

+extern void errNoCR( char *err );

+extern void genPredTree( Predicate *p, Node *j, int ,int);

+extern UserAction *newUserAction(char *);

+extern char *gate_symbol(char *name);

+extern char *makeAltID(int blockid, int altnum);

+extern void DumpRemainingTokSets(void);

+extern void DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInit);  /* MR23 */

+extern void DumpFormals(FILE *, char *, int bInit);                   /* MR23 */

+extern char* hideDefaultArgs(const char* pdecl);                      /* MR22 VHS */

+extern Predicate *computePredFromContextGuard(Graph,int *msgDone);    /* MR21 */

+extern void recomputeContextGuard(Predicate *);                       /* MR13 */

+extern Predicate *new_pred(void);

+extern void chkGTFlag(void);

+extern void leAdd(LabelEntry *);                                     /* MR7 */

+extern void leFixup(void);                                           /* MR7 */

+extern void egAdd(ExceptionGroup *);                                 /* MR7 */

+extern void egFixup(void);                                           /* MR7 */

+extern void altAdd(Junction *);                                      /* MR7 */

+extern void altFixup(void);                                          /* MR7 */

+extern Predicate * MR_find_in_aSubBlk(Junction *alt);                /* MR10 */

+extern Predicate * MR_predFlatten(Predicate *p);				     /* MR10 */

+extern Predicate * MR_predSimplifyALL(Predicate *p);	             /* MR10 */

+extern Predicate * MR_predSimplifyALLX(Predicate *p,int skipPass3);  /* MR10 */

+extern int MR_allPredLeaves(Predicate *p);                           /* MR10 */

+extern void MR_cleanup_pred_trees(Predicate *p);                     /* MR10 */

+extern int MR_predicate_context_completed(Predicate *p);             /* MR10 */

+extern void MR_check_pred_too_long(Predicate *p,set completion);     /* MR10 */

+extern Tree * MR_remove_epsilon_from_tree(Tree *t);                  /* MR10 */

+extern Tree * MR_computeTreeAND(Tree *l,Tree *r);					 /* MR10 */

+extern int MR_tree_equ(Tree *big, Tree *small);				         /* MR10 */

+extern set MR_First(int ck,Junction *j,set *incomplete);  		     /* MR10 */

+extern set MR_compute_pred_set(Predicate *p);                	     /* MR10 */

+extern Tree * MR_compute_pred_tree_context(Predicate *p);     	     /* MR10 */

+extern int MR_pointerStackPush(PointerStack *,void *);               /* MR10 */

+extern void * MR_pointerStackPop(PointerStack *);                    /* MR10 */

+extern void * MR_pointerStackTop(PointerStack *);                    /* MR10 */

+extern void MR_pointerStackReset(PointerStack *);                    /* MR10 */

+extern void MR_backTraceReport(void);                                /* MR10 */

+extern void MR_alphaBetaTraceReport(void);                           /* MR14 */

+extern void MR_dumpRuleSet(set);                                     /* MR14 */

+extern void MR_predContextPresent(Predicate *p,int *,int *);         /* MR10 */

+extern void MR_dumpPred(Predicate *p,int withContext);               /* MR10 */

+extern void MR_dumpPred1(int,Predicate *p,int withContext);          /* MR10 */

+extern void MR_xxxIndent(FILE *f,int depth);                         /* MR11 */

+extern void MR_outputIndent(int depth);                              /* MR11 */

+extern void MR_stderrIndent(int depth);                              /* MR11 */

+extern Junction * MR_ruleReferenced(RuleRefNode *rrn);               /* MR10 */

+extern Junction * MR_nameToRuleBlk(char *);                          /* MR10 */

+extern void MR_releaseResourcesUsedInRule(Node *);                   /* MR10 */

+extern void MR_dumpTreeX(int depth,Tree *t,int across);              /* MR10 */

+extern void MR_dumpTreeF(FILE *f,int depth,Tree *t,int across);      /* MR10 */

+extern void DumpFcache(void);                                        /* MR10 */

+extern void MR_dumpTokenSet(FILE *f,int depth,set s);                /* MR10 */

+extern void MR_traceAmbSource(set *,Junction *,Junction *);          /* MR11 */

+extern void MR_traceAmbSourceK(Tree *,Junction *a1,Junction *a2);    /* MR11 */

+extern void MR_traceAmbSourceKclient(void);                          /* MR20 */

+extern Node *MR_advance(Node *);                                     /* MR11 */

+extern int  MR_offsetFromRule(Node *);                               /* MR11 */

+extern char *MR_ruleNamePlusOffset(Node *);                          /* MR11 */

+extern int  MR_max_height_of_tree(Tree *);                           /* MR11 */

+extern int  MR_all_leaves_same_height(Tree *,int);                   /* MR11 */

+extern void MR_projectTreeOntoSet(Tree *t,int k,set *);              /* MR11 */

+extern Tree *MR_make_tree_from_set(set);                             /* MR11 */

+extern Predicate *MR_removeRedundantPredPass3(Predicate *);          /* MR11 */

+extern void MR_pred_depth(Predicate *,int *);                        /* MR11 */

+extern int  MR_comparePredicates(Predicate *,Predicate *);           /* MR11 */

+extern Predicate * MR_unfold(Predicate *);                           /* MR11 */

+extern void MR_simplifyInverted(Predicate *,int);                    /* MR11 */

+extern int  MR_secondPredicateUnreachable                            /* MR11 */

+            (Predicate *first,Predicate *second);                    /* MR11 */

+extern void MR_clearPredEntry(Predicate *);                          /* MR11 */

+extern void MR_orphanRules(FILE *);                                  /* MR12 */

+extern void MR_merge_contexts(Tree *);                               /* MR12 */

+extern int  ci_strequ(char *,char *);                                 /* MR12 */

+extern void MR_guardPred_plainSet(ActionNode *anode,Predicate *);    /* MR12c */

+extern void MR_suppressSearchReport(void);                           /* MR12c */

+extern Predicate * MR_suppressK(Node *,Predicate *);                 /* MR13 */

+extern void MR_backTraceDumpItem(FILE *,int skip,Node *n);           /* MR13 */

+extern void MR_backTraceDumpItemReset(void);                         /* MR13 */

+extern Junction * MR_junctionWithoutP2(Junction *);                  /* MR13 */

+extern void MR_setConstrainPointer(set *);							 /* MR18 */

+extern void BlockPreambleOption(Junction *q, char * pSymbol);        /* MR23 */

+extern char* getInitializer(char *);                                 /* MR23 */

+extern char *endFormal(char *pStart,                                 /* MR23 */

+					   char **ppDataType,                            /* MR23 */

+					   char **ppSymbol,                              /* MR23 */

+					   char **ppEqualSign,                           /* MR23 */

+					   char **ppValue,                               /* MR23 */

+					   char **ppSeparator,                           /* MR23 */

+					   int *pNext);                                  /* MR23 */

+extern char *strBetween(char *pStart,                                /* MR23 */

+						char *pNext,                                 /* MR23 */

+						char *pStop);                                /* MR23 */

+extern int hasMultipleOperands(char *);                              /* MR23 */

+extern void DumpInitializers(FILE*, RuleEntry*, char*);              /* MR23 */

+extern int isTermEntryTokClass(TermEntry *);						 /* MR23 */

+extern int isEmptyAlt(Node *, Node *);                               /* MR23 */

+#else

+extern int STRICMP();

+extern void istackreset();

+extern int istacksize();

+extern void pushint();

+extern int popint();

+extern int istackempty();

+extern int topint();

+extern void NewSetWd();

+extern void DumpSetWd();

+extern void DumpSetWdForC();

+extern void DumpSetWdForCC();

+extern void NewSet();

+extern void FillSet();

+extern void ComputeErrorSets();

+extern void ComputeTokSets();

+extern void SubstErrorClass();

+extern int DefErrSet();

+extern int DefErrSetForC();

+extern int DefErrSetForCC();

+extern int DefErrSet1();

+extern int DefErrSetForC1();

+extern int DefErrSetForCC1();

+extern int DefErrSetWithSuffix();                                   /* MR21 */

+extern void GenErrHdr();

+extern void dumpExpr();

+extern void addParm();

+extern Graph buildAction();

+extern Graph buildToken();

+extern Graph buildWildCard();

+extern Graph buildRuleRef();

+extern Graph Or();

+extern Graph Cat();

+extern Graph makeOpt();

+extern Graph makeBlk();

+extern Graph makeLoop();

+extern Graph makePlus();

+extern Graph emptyAlt();

+extern Graph emptyAlt3();

+extern TokNode * newTokNode();

+extern RuleRefNode * newRNode();

+extern Junction * newJunction();

+extern ActionNode * newActionNode();

+extern char * makelocks();

+extern void preorder();

+extern Tree * tnode();

+extern void _Tfree();

+extern Tree * tdup();

+extern int is_single_tuple();

+extern Tree * tappend();

+extern void Tfree();

+extern Tree * tlink();

+extern Tree * tshrink();

+extern Tree * tflatten();

+extern Tree * tJunc();

+extern Tree * tRuleRef();

+extern Tree * tToken();

+extern Tree * tAction();

+extern int tmember();

+extern int tmember_constrained();

+extern Tree * tleft_factor();

+extern Tree * trm_perm();

+extern void tcvt();

+extern Tree * permute();

+extern Tree * VerifyAmbig();

+extern set rJunc();

+extern set rRuleRef();

+extern set rToken();

+extern set rAction();

+extern void HandleAmbiguity();

+extern set First();

+extern void freeBlkFsets();

+extern void genAction();

+extern void genRuleRef();

+extern void genToken();

+extern void genOptBlk();

+extern void genLoopBlk();

+extern void genLoopBegin();

+extern void genPlusBlk();

+extern void genSubBlk();

+extern void genRule();

+extern void genJunction();

+extern void genEndBlk();

+extern void genEndRule();

+extern void genHdr();

+extern void genHdr1();

+extern void dumpAction();

+extern void dumpActionPlus();                           /* MR21 */

+extern Entry ** newHashTable();

+extern Entry * hash_add();

+extern Entry * hash_get();

+extern void hashStat();

+extern char * mystrdup();

+extern void genLexDescr();

+extern void dumpLexClasses();

+extern void genDefFile();

+extern void DumpListOfParmNames();                    /* MR5 janm 26-May-97 */

+extern int DumpNextNameInDef();

+extern void DumpOldStyleParms();

+extern void DumpType();

+extern int strmember();

+/* extern int HasComma(); MR23 Replaced by hasMultipleOperands() */

+extern void DumpRetValStruct();

+extern char * StripQuotes();

+extern int main();

+extern void readDescr();

+extern FILE * NextFile();

+extern char * outnameX();

+extern char * outname();

+extern void fatalFL();

+extern void fatal_intern();

+extern void cleanUp();

+extern char * eMsg3();

+extern char * eMsgd();

+extern char * eMsgd2();

+extern void s_fprT();

+extern char * TerminalString();

+extern void lexclass();

+extern void lexmode();

+extern int LexClassIndex();

+extern int hasAction();

+extern void setHasAction();

+extern int addTname();

+extern int addTexpr();

+extern int Tnum();

+extern void Tklink();

+extern Entry * newEntry();

+extern void list_add();

+extern void list_free();                /* MR10 */

+extern void list_apply();

+extern int list_search_cstring ();      /* MR27 */

+extern char * Fkey();

+extern void FoPush();

+extern void FoPop();

+extern void RegisterCycle();

+extern void ResolveFoCycles();

+extern void pJunc();

+extern void pRuleRef();

+extern void pToken();

+extern void pAction();

+extern void FoLink();

+extern void addFoLink();

+extern void GenCrossRef();

+extern void defErr();

+extern void genStdPCCTSIncludeFile();

+extern char * pcctsBaseName();                                /* MR32 */

+extern Predicate *find_predicates();

+extern Predicate *MR_find_predicates_and_supp();              /* MR13 */

+extern int predicateLookaheadDepth();                         /* MR10 */

+extern void predicate_free();                                 /* MR10 */

+extern Predicate * predicate_dup();                           /* MR10 */

+extern Predicate * predicate_dup_without_context();           /* MR11 */

+extern void GenRulePrototypes();

+extern Junction *first_item_is_guess_block();

+extern Junction *first_item_is_guess_block_extra();			  /* MR30 */

+extern Junction *analysis_point();

+extern Tree *make_tree_from_sets();

+extern Tree *tdup_chain();

+extern Tree *tdif();

+extern set covered_set();

+extern void AmbiguityDialog();

+extern void dumpAmbigMsg();

+extern void GenRuleFuncRedefs();

+extern void GenPredefinedSymbolRedefs();

+extern void GenASTSymbolRedefs();

+extern void GenRemapFile();

+extern void GenSetRedefs();

+extern ForcedToken *newForcedToken();

+extern void RemapForcedTokens();

+extern char *TokenOrExpr();

+extern void setUpperRange();

+extern void GenParser_c_Hdr();

+extern void GenParser_h_Hdr();

+extern void GenRuleMemberDeclarationsForCC();

+extern int addForcedTname();

+extern char *OutMetaName();

+extern void OutFirstSetSymbol();                            /* MR21 */

+extern void warnNoFL();

+extern void warnFL();

+extern void warn();

+extern void warnNoCR();

+extern void errNoFL();

+extern void errFL();

+extern void err();

+extern void errNoCR();

+extern void genPredTree();

+extern UserAction *newUserAction();

+extern char *gate_symbol();

+extern char *makeAltID();

+extern void DumpRemainingTokSets();

+extern void DumpANSIFunctionArgDef();

+extern void DumpFormals();                                           /* MR23 */

+extern char* hideDefaultArgs();                                      /* MR22 VHS */

+extern Predicate *computePredFromContextGuard();

+extern void recomputeContextGuard();                                 /* MR13 */

+extern Predicate *new_pred();

+extern void chkGTFlag();

+extern void leAdd();                                                 /* MR7 */

+extern void leFixup();                                               /* MR7 */

+extern void egAdd();                                                 /* MR7 */

+extern void egFixup();                                               /* MR7 */

+extern void altAdd();                                                /* MR7 */

+extern void altFixup();                                              /* MR7 */

+extern Predicate * MR_find_in_aSubBlk();       		                /* MR10 */

+extern Predicate * MR_predFlatten();						        /* MR10 */

+extern Predicate * MR_predSimplifyALL();                            /* MR10 */

+extern Predicate * MR_predSimplifyALLX();                           /* MR10 */

+extern void MR_cleanup_pred_trees();                                /* MR10 */

+extern int MR_allPredLeaves();                                      /* MR10 */

+extern int MR_predicate_context_completed();                        /* MR10 */

+extern void MR_check_pred_too_long();                               /* MR10 */

+extern Tree * MR_remove_epsilon_from_tree();				        /* MR10 */

+extern Tree * MR_computeTreeAND();					                /* MR10 */

+extern int MR_tree_equ();                   				        /* MR10 */

+extern set MR_First();				                                /* MR10 */

+extern set MR_compute_pred_set();				                    /* MR10 */

+extern Tree * MR_compute_pred_tree_context();				        /* MR10 */

+extern int MR_pointerStackPush();                                   /* MR10 */

+extern void * MR_pointerStackPop();                                 /* MR10 */

+extern void * MR_pointerStackTop();                                 /* MR10 */

+extern void MR_pointerStackReset();                                 /* MR10 */

+extern void MR_backTraceReport();                                   /* MR10 */

+extern void MR_alphaBetaTraceReport();                              /* MR14 */

+extern void MR_dumpRuleSet();                                       /* MR14 */

+extern void MR_predContextPresent();                                /* MR10 */

+extern void MR_dumpPred();                                          /* MR10 */

+extern void MR_dumpPred1();                                         /* MR10 */

+extern void MR_xxxIndent();                                         /* MR11 */

+extern void MR_stderrIndent();                                      /* MR11 */

+extern void MR_outputIndent();                                      /* MR11 */

+extern Junction * MR_ruleReferenced();                              /* MR10 */

+extern void MR_releaseResourcesUsedInRule();                        /* MR10 */

+extern void MR_dumpTreeX();                                         /* MR10 */

+extern void MR_dumpTreeF();                                         /* MR10 */

+extern void DumpFcache();                                           /* MR10 */

+extern void MR_dumpTokenSet();                                      /* MR10 */

+extern void MR_traceAmbSource();                                    /* MR11 */

+extern Node *MR_advance();                                          /* MR11 */

+extern int  MR_offsetFromRule();                                    /* MR11 */

+extern char *MR_ruleNamePlusOffset();                               /* MR11 */

+extern void MR_traceAmbSourceK();                                   /* MR11 */

+extern void MR_traceAmbSourceKclient();                             /* [i_a] added */

+extern int  MR_max_height_of_tree();                                /* MR11 */

+extern int  MR_all_leaves_same_height();                            /* MR11 */

+extern void MR_projectTreeOntoSet();                                /* MR11 */

+extern Tree *MR_make_tree_from_set();                               /* MR11 */

+extern Predicate *MR_removeRedundantPredPass3();                    /* MR11 */

+extern void MR_pred_depth();                                        /* MR11 */

+extern int  MR_comparePredicates();                                 /* MR11 */

+extern Predicate * MR_unfold();                                     /* MR11 */

+extern void MR_simplifyInverted();                                  /* MR11 */

+extern int  MR_secondPredicateUnreachable();                        /* MR11 */

+extern Junction * MR_nameToRuleBlk();                               /* MR10 */

+extern void MR_clearPredEntry();                                    /* MR11 */

+extern void MR_orphanRules();                                       /* MR12 */

+extern void MR_merge_contexts();                                    /* MR12 */

+extern int ci_strequ();                                             /* MR12 */

+extern void MR_guardPred_plainSet();                                /* MR12c */

+extern void MR_suppressSearchReport();                              /* MR12c */

+extern Predicate * MR_suppressK();                                  /* MR13 */

+extern void MR_backTraceDumpItem();                                 /* MR13 */

+extern void MR_backTraceDumpItemReset();                            /* MR13 */

+extern Junction * MR_junctionWithoutP2();                           /* MR13 */

+extern void MR_setConstrainPointer();					  		    /* MR18 */

+extern void BlockPreambleOption();                                  /* MR23 */

+extern char* getInitializer();                                      /* MR23 */

+extern int hasMultipleOperands();                                   /* MR23 */

+extern char *endFormal();                                           /* MR23 */

+extern char *strBetween();                                          /* MR23 */

+extern void DumpInitializers();                                     /* MR23 */

+extern int isTermEntryTokClass();							 	    /* MR23 */

+extern int isEmptyAlt();

+

+#endif

+

+#ifdef __USE_PROTOS

+#include <stdlib.h>

+#endif

+

+/* MR20 G. Hobbelt  Create proper externs for dlg variables */

+

+extern set attribsRefdFromAction;

+extern int inAlt;

+extern int UsedOldStyleAttrib;

+extern int UsedNewStyleLabel;

+

+#define MAX_BLK_LEVEL 100                       /* MR23 */

+extern int     CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */

+extern int     CurAltNum_array[MAX_BLK_LEVEL];  /* MR23 */

diff --git a/Source/Pccts/antlr/scan.c b/Source/Pccts/antlr/scan.c
new file mode 100644
index 0000000..9b4bde0
--- /dev/null
+++ b/Source/Pccts/antlr/scan.c
@@ -0,0 +1,5735 @@
+

+/* parser.dlg -- DLG Description of scanner

+ *

+ * Generated from: antlr.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include "pcctscfg.h"

+#include "set.h"

+#include <ctype.h>

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#define zzcr_attr(attr,tok,t)

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+LOOKAHEAD

+

+void

+#ifdef __USE_PROTOS

+zzerraction(void)

+#else

+zzerraction()

+#endif

+{

+	(*zzerr)("invalid token");

+	zzadvance();

+	zzskip();

+}

+/*

+ * D L G tables

+ *

+ * Generated from: parser.dlg

+ *

+ * 1989-2001 by  Will Cohen, Terence Parr, and Hank Dietz

+ * Purdue University Electrical Engineering

+ * DLG Version 1.33MR33

+ */

+

+#include "mode.h"

+

+

+

+

+/* maintained, but not used for now */

+set AST_nodes_refd_in_actions = set_init;

+int inAlt = 0;

+set attribsRefdFromAction = set_init; /* MR20 */

+int UsedOldStyleAttrib = 0;

+int UsedNewStyleLabel = 0;

+#ifdef __USE_PROTOS

+char *inline_set(char *);

+#else

+char *inline_set();

+#endif

+

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	    */

+/* MR1					in DLG action			                    */

+

+int tokenActionActive=0;                                            /* MR1 */

+

+  

+

+

+

+static char *

+#ifdef __USE_PROTOS

+getFileNameFromTheLineInfo(char *toStr, char *fromStr)

+#else

+getFileNameFromTheLineInfo(toStr, fromStr)

+char *toStr, *fromStr;

+#endif

+{

+  int i, j, k;

+  

+  if (!fromStr || !toStr) return toStr;

+  

+  /* find the first " */

+  

+  for (i=0;

+  (i<MaxFileName) &&

+  (fromStr[i] != '\n') &&

+  (fromStr[i] != '\r') &&

+  (fromStr[i] != '\"');

+  i++) /* nothing */ ;

+  

+  if ( (i == MaxFileName) ||

+  (fromStr[i] == '\n') ||

+  (fromStr[i] == '\r') ) {

+  return toStr;

+}

+

+  /* find the second " */

+

+  for (j=i+1;

+(j<MaxFileName) &&

+(fromStr[j] != '\n') &&

+(fromStr[j] != '\r') &&

+(fromStr[j] != '\"');

+j++) /* nothing */ ;

+

+  if ((j == MaxFileName) ||

+(fromStr[j] == '\n') ||

+(fromStr[j] == '\r') ) {

+  return toStr;

+}

+

+  /* go back until the last / or \ */

+

+  for (k=j-1;

+(fromStr[k] != '\"') &&

+(fromStr[k] != '/') &&

+(fromStr[k] != '\\');

+k--) /* nothing */ ;

+

+  /* copy the string after " / or \ into toStr */

+

+  for (i=k+1; fromStr[i] != '\"'; i++) {

+toStr[i-k-1] = fromStr[i];

+}

+

+  toStr[i-k-1] = '\0';

+

+  return toStr;

+}

+

+/* MR14 end of a block to support #line in antlr source code */

+

+  

+

+

+#ifdef __USE_PROTOS

+void mark_label_used_in_sem_pred(LabelEntry *le)              /* MR10 */

+#else

+void mark_label_used_in_sem_pred(le)                          /* MR10 */

+LabelEntry    *le;

+#endif

+{

+  TokNode   *tn;

+  require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");

+  tn=(TokNode *)le->elem;

+  require (tn->label != 0,"mark_label_used... TokNode has no label");

+  tn->label_used_in_semantic_pred=1;

+}

+

+static void act1()

+{ 

+		NLA = Eof;

+    /* L o o k  F o r  A n o t h e r  F i l e */

+    {

+      FILE *new_input;

+      new_input = NextFile();

+      if ( new_input == NULL ) { NLA=Eof; return; }

+      fclose( input );

+      input = new_input;

+      zzrdstream( input );

+      zzskip();	/* Skip the Eof (@) char i.e continue */

+    }

+	}

+

+

+static void act2()

+{ 

+		NLA = 76;

+    zzskip();   

+	}

+

+

+static void act3()

+{ 

+		NLA = 77;

+    zzline++; zzskip();   

+	}

+

+

+static void act4()

+{ 

+		NLA = 78;

+    zzmode(ACTIONS); zzmore();

+    istackreset();

+    pushint(']');   

+	}

+

+

+static void act5()

+{ 

+		NLA = 79;

+    action_file=CurFile; action_line=zzline;

+    zzmode(ACTIONS); zzmore();

+    list_free(&CurActionLabels,0);       /* MR10 */

+    numericActionLabel=0;                /* MR10 */

+    istackreset();

+    pushint('>');   

+	}

+

+

+static void act6()

+{ 

+		NLA = 80;

+    zzmode(STRINGS); zzmore();   

+	}

+

+

+static void act7()

+{ 

+		NLA = 81;

+    zzmode(COMMENTS); zzskip();   

+	}

+

+

+static void act8()

+{ 

+		NLA = 82;

+    warn("Missing /*; found dangling */"); zzskip();   

+	}

+

+

+static void act9()

+{ 

+		NLA = 83;

+    zzmode(CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act10()

+{ 

+		NLA = 84;

+    

+    zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+    getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+	}

+

+

+static void act11()

+{ 

+		NLA = 85;

+    

+    zzline++; zzmore();

+	}

+

+

+static void act12()

+{ 

+		NLA = 86;

+    warn("Missing <<; found dangling >>"); zzskip();   

+	}

+

+

+static void act13()

+{ 

+		NLA = WildCard;

+	}

+

+

+static void act14()

+{ 

+		NLA = 88;

+    FoundException = 1;		/* MR6 */

+    FoundAtOperator = 1;  

+	}

+

+

+static void act15()

+{ 

+		NLA = Pragma;

+	}

+

+

+static void act16()

+{ 

+		NLA = FirstSetSymbol;

+	}

+

+

+static void act17()

+{ 

+		NLA = 94;

+	}

+

+

+static void act18()

+{ 

+		NLA = 95;

+	}

+

+

+static void act19()

+{ 

+		NLA = 96;

+	}

+

+

+static void act20()

+{ 

+		NLA = 97;

+	}

+

+

+static void act21()

+{ 

+		NLA = 98;

+	}

+

+

+static void act22()

+{ 

+		NLA = 99;

+	}

+

+

+static void act23()

+{ 

+		NLA = 102;

+	}

+

+

+static void act24()

+{ 

+		NLA = 103;

+	}

+

+

+static void act25()

+{ 

+		NLA = 104;

+	}

+

+

+static void act26()

+{ 

+		NLA = 105;

+	}

+

+

+static void act27()

+{ 

+		NLA = 106;

+	}

+

+

+static void act28()

+{ 

+		NLA = 107;

+	}

+

+

+static void act29()

+{ 

+		NLA = 108;

+	}

+

+

+static void act30()

+{ 

+		NLA = 109;

+	}

+

+

+static void act31()

+{ 

+		NLA = 110;

+	}

+

+

+static void act32()

+{ 

+		NLA = 111;

+	}

+

+

+static void act33()

+{ 

+		NLA = 112;

+	}

+

+

+static void act34()

+{ 

+		NLA = 113;

+	}

+

+

+static void act35()

+{ 

+		NLA = 114;

+	}

+

+

+static void act36()

+{ 

+		NLA = 115;

+	}

+

+

+static void act37()

+{ 

+		NLA = 116;

+	}

+

+

+static void act38()

+{ 

+		NLA = 117;

+	}

+

+

+static void act39()

+{ 

+		NLA = 118;

+	}

+

+

+static void act40()

+{ 

+		NLA = 119;

+	}

+

+

+static void act41()

+{ 

+		NLA = 120;

+	}

+

+

+static void act42()

+{ 

+		NLA = 121;

+	}

+

+

+static void act43()

+{ 

+		NLA = 122;

+	}

+

+

+static void act44()

+{ 

+		NLA = 123;

+	}

+

+

+static void act45()

+{ 

+		NLA = 124;

+	}

+

+

+static void act46()

+{ 

+		NLA = 125;

+	}

+

+

+static void act47()

+{ 

+		NLA = 126;

+	}

+

+

+static void act48()

+{ 

+		NLA = 127;

+	}

+

+

+static void act49()

+{ 

+		NLA = 128;

+	}

+

+

+static void act50()

+{ 

+		NLA = 129;

+	}

+

+

+static void act51()

+{ 

+		NLA = 130;

+	}

+

+

+static void act52()

+{ 

+		NLA = 131;

+	}

+

+

+static void act53()

+{ 

+		NLA = 132;

+	}

+

+

+static void act54()

+{ 

+		NLA = 133;

+	}

+

+

+static void act55()

+{ 

+		NLA = 134;

+	}

+

+

+static void act56()

+{ 

+		NLA = 135;

+	}

+

+

+static void act57()

+{ 

+		NLA = NonTerminal;

+    

+    while ( zzchar==' ' || zzchar=='\t' ) {

+      zzadvance();

+    }

+    if ( zzchar == ':' && inAlt ) NLA = LABEL;

+	}

+

+

+static void act58()

+{ 

+		NLA = TokenTerm;

+    

+    while ( zzchar==' ' || zzchar=='\t' ) {

+      zzadvance();

+    }

+    if ( zzchar == ':' && inAlt ) NLA = LABEL;

+	}

+

+

+static void act59()

+{ 

+		NLA = 136;

+    warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip();   

+	}

+

+static unsigned char shift0[257] = {

+  0, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  1, 2, 58, 58, 3, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 1, 40, 6, 9, 58, 58, 45, 

+  58, 46, 47, 8, 52, 58, 58, 18, 7, 16, 

+  14, 15, 16, 16, 16, 16, 16, 16, 16, 41, 

+  42, 5, 48, 17, 53, 19, 56, 56, 56, 56, 

+  56, 26, 56, 56, 56, 56, 56, 51, 56, 56, 

+  56, 56, 56, 56, 29, 56, 56, 56, 56, 56, 

+  56, 56, 4, 20, 58, 50, 57, 58, 23, 31, 

+  38, 34, 13, 35, 24, 33, 11, 55, 36, 10, 

+  25, 12, 32, 21, 55, 22, 27, 28, 54, 55, 

+  55, 43, 30, 55, 39, 44, 37, 49, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 

+  58, 58, 58, 58, 58, 58, 58

+};

+

+

+static void act60()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act61()

+{ 

+		NLA = QuotedTerm;

+    zzmode(START);   

+	}

+

+

+static void act62()

+{ 

+		NLA = 3;

+    

+    zzline++;

+    warn("eoln found in string");

+    zzskip();

+	}

+

+

+static void act63()

+{ 

+		NLA = 4;

+    zzline++; zzmore();   

+	}

+

+

+static void act64()

+{ 

+		NLA = 5;

+    zzmore();   

+	}

+

+

+static void act65()

+{ 

+		NLA = 6;

+    zzmore();   

+	}

+

+static unsigned char shift1[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 2, 5, 5, 3, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act66()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act67()

+{ 

+		NLA = 7;

+    zzmode(ACTIONS); zzmore();   

+	}

+

+

+static void act68()

+{ 

+		NLA = 8;

+    

+    zzline++;

+    warn("eoln found in string (in user action)");

+    zzskip();

+	}

+

+

+static void act69()

+{ 

+		NLA = 9;

+    zzline++; zzmore();   

+	}

+

+

+static void act70()

+{ 

+		NLA = 10;

+    zzmore();   

+	}

+

+

+static void act71()

+{ 

+		NLA = 11;

+    zzmore();   

+	}

+

+static unsigned char shift2[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 2, 5, 5, 3, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act72()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act73()

+{ 

+		NLA = 12;

+    zzmode(ACTIONS); zzmore();   

+	}

+

+

+static void act74()

+{ 

+		NLA = 13;

+    

+    zzline++;

+    warn("eoln found in char literal (in user action)");

+    zzskip();

+	}

+

+

+static void act75()

+{ 

+		NLA = 14;

+    zzmore();   

+	}

+

+

+static void act76()

+{ 

+		NLA = 15;

+    zzmore();   

+	}

+

+static unsigned char shift3[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 2, 5, 5, 3, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act77()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act78()

+{ 

+		NLA = 16;

+    zzmode(ACTIONS); zzmore();   

+	}

+

+

+static void act79()

+{ 

+		NLA = 17;

+    zzmore();   

+	}

+

+

+static void act80()

+{ 

+		NLA = 18;

+    zzline++; zzmore(); DAWDLE;   

+	}

+

+

+static void act81()

+{ 

+		NLA = 19;

+    zzmore();   

+	}

+

+static unsigned char shift4[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 3, 5, 5, 4, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 1, 5, 5, 5, 5, 2, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act82()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act83()

+{ 

+		NLA = 20;

+    zzmode(PARSE_ENUM_FILE);

+    zzmore();   

+	}

+

+

+static void act84()

+{ 

+		NLA = 21;

+    zzmore();   

+	}

+

+

+static void act85()

+{ 

+		NLA = 22;

+    zzline++; zzmore(); DAWDLE;   

+	}

+

+

+static void act86()

+{ 

+		NLA = 23;

+    zzmore();   

+	}

+

+static unsigned char shift5[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 3, 5, 5, 4, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 1, 5, 5, 5, 5, 2, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act87()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act88()

+{ 

+		NLA = 24;

+    zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE;   

+	}

+

+

+static void act89()

+{ 

+		NLA = 25;

+    zzskip();   

+	}

+

+static unsigned char shift6[257] = {

+  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3

+};

+

+

+static void act90()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act91()

+{ 

+		NLA = 26;

+    zzline++; zzmode(ACTIONS); zzmore(); DAWDLE;   

+	}

+

+

+static void act92()

+{ 

+		NLA = 27;

+    zzmore();   

+	}

+

+static unsigned char shift7[257] = {

+  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3

+};

+

+

+static void act93()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act94()

+{ 

+		NLA = 28;

+    zzline++; zzmode(START); zzskip(); DAWDLE;   

+	}

+

+

+static void act95()

+{ 

+		NLA = 29;

+    zzskip();   

+	}

+

+static unsigned char shift8[257] = {

+  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 

+  3, 3, 3, 3, 3, 3, 3

+};

+

+

+static void act96()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act97()

+{ 

+		NLA = 30;

+    zzmode(START); zzskip();   

+	}

+

+

+static void act98()

+{ 

+		NLA = 31;

+    zzskip();   

+	}

+

+

+static void act99()

+{ 

+		NLA = 32;

+    zzline++; zzskip(); DAWDLE;   

+	}

+

+

+static void act100()

+{ 

+		NLA = 33;

+    zzskip();   

+	}

+

+static unsigned char shift9[257] = {

+  0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 3, 5, 5, 4, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 1, 5, 5, 5, 5, 2, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 

+  5, 5, 5, 5, 5, 5, 5

+};

+

+

+static void act101()

+{ 

+		NLA = Eof;

+	}

+

+

+static void act102()

+{ 

+		NLA = Action;

+    /* these do not nest */

+    zzmode(START);

+    NLATEXT[0] = ' ';

+    NLATEXT[1] = ' ';

+    zzbegexpr[0] = ' ';

+    zzbegexpr[1] = ' ';

+    if ( zzbufovf ) {

+      err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));

+    }

+    

+/* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/

+    /* MR1					in DLG action			*/

+    /* MR1			Doesn't matter what kind of action it is - reset*/

+    

+			      tokenActionActive=0;		 /* MR1 */

+	}

+

+

+static void act103()

+{ 

+		NLA = Pred;

+    /* these do not nest */

+    zzmode(START);

+    NLATEXT[0] = ' ';

+    NLATEXT[1] = ' ';

+    zzbegexpr[0] = '\0';

+    if ( zzbufovf ) {

+      err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));

+    };

+#ifdef __cplusplus__

+    /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __STDC__

+    /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+#ifdef __USE_PROTOS

+    /* MRxx */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);

+#else

+    /* MR10 */                    list_apply(CurActionLabels,mark_label_used_in_sem_pred);

+#endif

+#endif

+#endif

+	}

+

+

+static void act104()

+{ 

+		NLA = PassAction;

+    if ( topint() == ']' ) {

+      popint();

+      if ( istackempty() )	/* terminate action */

+      {

+        zzmode(START);

+        NLATEXT[0] = ' ';

+        zzbegexpr[0] = ' ';

+        if ( zzbufovf ) {

+          err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));

+        }

+      }

+      else {

+        /* terminate $[..] and #[..] */

+        if ( GenCC ) zzreplstr("))");

+        else zzreplstr(")");

+        zzmore();

+      }

+    }

+    else if ( topint() == '|' ) { /* end of simple [...] */

+      popint();

+      zzmore();

+    }

+    else zzmore();

+	}

+

+

+static void act105()

+{ 

+		NLA = 37;

+    

+    zzmore();

+    zzreplstr(inline_set(zzbegexpr+

+    strlen("consumeUntil(")));

+	}

+

+

+static void act106()

+{ 

+		NLA = 38;

+    zzmore();   

+	}

+

+

+static void act107()

+{ 

+		NLA = 39;

+    zzline++; zzmore(); DAWDLE;   

+	}

+

+

+static void act108()

+{ 

+		NLA = 40;

+    zzmore();   

+	}

+

+

+static void act109()

+{ 

+		NLA = 41;

+    zzmore();   

+	}

+

+

+static void act110()

+{ 

+		NLA = 42;

+    if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}

+    else err("$$ use invalid in C++ mode");   

+	}

+

+

+static void act111()

+{ 

+		NLA = 43;

+    if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}

+    else err("$[] use invalid in C++ mode");   

+	}

+

+

+static void act112()

+{ 

+		NLA = 44;

+    

+    pushint(']');

+    if ( !GenCC ) zzreplstr("zzconstr_attr(");

+    else err("$[..] use invalid in C++ mode");

+    zzmore();

+	}

+

+

+static void act113()

+{ 

+		NLA = 45;

+    {

+      static char buf[100];

+      numericActionLabel=1;       /* MR10 */

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("$i attrib ref too big");

+      set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",

+      BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"_t%d%s",

+      BlkLevel-1,zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	}

+

+

+static void act114()

+{ 

+		NLA = 46;

+    {

+      static char buf[100];

+      numericActionLabel=1;       /* MR10 */

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("$i.field attrib ref too big");

+      zzbegexpr[strlen(zzbegexpr)-1] = ' ';

+      set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",

+      BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"_t%d%s.",

+      BlkLevel-1,zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	}

+

+

+static void act115()

+{ 

+		NLA = 47;

+    {

+      static char buf[100];

+      static char i[20], j[20];

+      char *p,*q;

+      numericActionLabel=1;       /* MR10 */

+      if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");

+      for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {

+        if ( q == &i[20] )

+        fatalFL("i of $i.j attrib ref too big",

+        FileStr[CurFile], zzline );

+        *q++ = *p;

+      }

+      *q = '\0';

+      for (p++, q= &j[0]; *p!='\0'; p++) {

+        if ( q == &j[20] )

+        fatalFL("j of $i.j attrib ref too big",

+        FileStr[CurFile], zzline );

+        *q++ = *p;

+      }

+      *q = '\0';

+      if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);

+      else sprintf(buf,"_t%s%s",i,j);

+      zzreplstr(buf);

+      zzmore();

+      UsedOldStyleAttrib = 1;

+      if ( UsedNewStyleLabel )

+      err("cannot mix old-style $i with new-style labels");

+    }

+	}

+

+

+static void act116()

+{ 

+		NLA = 48;

+    { static char buf[300]; LabelEntry *el;

+      zzbegexpr[0] = ' ';

+      if ( CurRule != NULL &&

+      strcmp(CurRule, &zzbegexpr[1])==0 ) {

+        if ( !GenCC ) zzreplstr("zzaRet");

+      }

+      else if ( CurRetDef != NULL &&

+      strmember(CurRetDef, &zzbegexpr[1])) {

+        if ( hasMultipleOperands( CurRetDef ) ) {

+          require (strlen(zzbegexpr)<=(size_t)285,

+          "$retval attrib ref too big");

+          sprintf(buf,"_retv.%s",&zzbegexpr[1]);

+          zzreplstr(buf);

+        }

+        else zzreplstr("_retv");

+      }

+      else if ( CurParmDef != NULL &&

+      strmember(CurParmDef, &zzbegexpr[1])) {

+      ;

+    }

+    else if ( Elabel==NULL ) {

+    { err("$-variables in actions outside of rules are not allowed"); }

+  } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {

+  /* MR10 */

+  /* MR10 */                      /* element labels might exist without an elem when */

+  /* MR10 */                      /*  it is a forward reference (to a rule)          */

+  /* MR10 */

+  /* MR10 */						if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )

+  /* MR10 */							{ err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }

+  /* MR10 */

+  /* MR10 */						if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {

+  /* MR10 */                          err("You can no longer use attributes returned by rules when also using ASTs");

+  /* MR10 */                          err("   Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...>>\")");

+  /* MR10 */                      };

+  /* MR10 */

+  /* MR10 */                      /* keep track of <<... $label ...>> for semantic predicates in guess mode */

+  /* MR10 */                      /* element labels contain pointer to the owners node                      */

+  /* MR10 */

+  /* MR10 */                      if (el->elem != NULL && el->elem->ntype == nToken) {

+  /* MR10 */                        list_add(&CurActionLabels,el);

+  /* MR10 */                      };

+}

+else

+warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));

+}

+zzmore();

+	}

+

+

+static void act117()

+{ 

+		NLA = 49;

+    zzreplstr("(*_root)"); zzmore(); chkGTFlag();   

+	}

+

+

+static void act118()

+{ 

+		NLA = 50;

+    if ( GenCC ) {

+      if (NewAST) zzreplstr("(newAST)");

+      else zzreplstr("(new AST)");}

+    else {zzreplstr("zzastnew()");} zzmore();

+    chkGTFlag();

+	}

+

+

+static void act119()

+{ 

+		NLA = 51;

+    zzreplstr("NULL"); zzmore(); chkGTFlag();   

+	}

+

+

+static void act120()

+{ 

+		NLA = 52;

+    {

+      static char buf[100];

+      if ( strlen(zzbegexpr)>(size_t)85 )

+      fatal("#i AST ref too big");

+      if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);

+      else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);

+      zzreplstr(buf);

+      zzmore();

+      set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);

+      chkGTFlag();

+    }

+	}

+

+

+static void act121()

+{ 

+		NLA = 53;

+    

+    zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();

+    getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);

+	}

+

+

+static void act122()

+{ 

+		NLA = 54;

+    

+    zzline++; zzmore();

+	}

+

+

+static void act123()

+{ 

+		NLA = 55;

+    

+    if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||

+    strcmp(zzbegexpr, "#if")==0 ||

+    strcmp(zzbegexpr, "#else")==0 ||

+    strcmp(zzbegexpr, "#endif")==0 ||

+    strcmp(zzbegexpr, "#ifndef")==0 ||

+    strcmp(zzbegexpr, "#define")==0 ||

+    strcmp(zzbegexpr, "#pragma")==0 ||

+    strcmp(zzbegexpr, "#undef")==0 ||

+    strcmp(zzbegexpr, "#import")==0 ||

+    strcmp(zzbegexpr, "#line")==0 ||

+    strcmp(zzbegexpr, "#include")==0 ||

+    strcmp(zzbegexpr, "#error")==0) )

+    {

+      static char buf[100];

+      sprintf(buf, "%s_ast", zzbegexpr+1);

+      /* MR27 */						list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));

+      zzreplstr(buf);

+      chkGTFlag();

+    }

+    zzmore();

+	}

+

+

+static void act124()

+{ 

+		NLA = 56;

+    

+    pushint(']');

+    if ( GenCC ) {

+      if (NewAST) zzreplstr("(newAST(");

+      else zzreplstr("(new AST("); }

+    else zzreplstr("zzmk_ast(zzastnew(),");

+    zzmore();

+    chkGTFlag();

+	}

+

+

+static void act125()

+{ 

+		NLA = 57;

+    

+    pushint('}');

+    if ( GenCC ) {

+      if (tmakeInParser) {

+        zzreplstr("tmake(");

+      }

+      else {

+        zzreplstr("ASTBase::tmake(");

+      }

+    }

+    else {

+      zzreplstr("zztmake(");

+    }

+    zzmore();

+    chkGTFlag();

+	}

+

+

+static void act126()

+{ 

+		NLA = 58;

+    zzmore();   

+	}

+

+

+static void act127()

+{ 

+		NLA = 59;

+    

+    if ( istackempty() )

+    zzmore();

+    else if ( topint()==')' ) {

+      popint();

+    }

+    else if ( topint()=='}' ) {

+      popint();

+      /* terminate #(..) */

+      zzreplstr(", NULL)");

+    }

+    zzmore();

+	}

+

+

+static void act128()

+{ 

+		NLA = 60;

+    

+    pushint('|');	/* look for '|' to terminate simple [...] */

+    zzmore();

+	}

+

+

+static void act129()

+{ 

+		NLA = 61;

+    

+    pushint(')');

+    zzmore();

+	}

+

+

+static void act130()

+{ 

+		NLA = 62;

+    zzreplstr("]");  zzmore();   

+	}

+

+

+static void act131()

+{ 

+		NLA = 63;

+    zzreplstr(")");  zzmore();   

+	}

+

+

+static void act132()

+{ 

+		NLA = 64;

+    if (! tokenActionActive) zzreplstr(">");	 /* MR1 */

+    zzmore();				         /* MR1 */

+	}

+

+

+static void act133()

+{ 

+		NLA = 65;

+    zzmode(ACTION_CHARS); zzmore();  

+	}

+

+

+static void act134()

+{ 

+		NLA = 66;

+    zzmode(ACTION_STRINGS); zzmore();  

+	}

+

+

+static void act135()

+{ 

+		NLA = 67;

+    zzreplstr("$");  zzmore();   

+	}

+

+

+static void act136()

+{ 

+		NLA = 68;

+    zzreplstr("#");  zzmore();   

+	}

+

+

+static void act137()

+{ 

+		NLA = 69;

+    zzline++; zzmore();   

+	}

+

+

+static void act138()

+{ 

+		NLA = 70;

+    zzmore();   

+	}

+

+

+static void act139()

+{ 

+		NLA = 71;

+    zzmore();   

+	}

+

+

+static void act140()

+{ 

+		NLA = 72;

+    zzmode(ACTION_COMMENTS); zzmore();   

+	}

+

+

+static void act141()

+{ 

+		NLA = 73;

+    warn("Missing /*; found dangling */ in action"); zzmore();   

+	}

+

+

+static void act142()

+{ 

+		NLA = 74;

+    zzmode(ACTION_CPP_COMMENTS); zzmore();   

+	}

+

+

+static void act143()

+{ 

+		NLA = 75;

+    zzmore();   

+	}

+

+static unsigned char shift10[257] = {

+  0, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  16, 19, 33, 33, 20, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 16, 33, 28, 27, 21, 33, 33, 

+  30, 15, 18, 32, 33, 33, 33, 25, 31, 23, 

+  24, 24, 24, 24, 24, 24, 24, 24, 24, 33, 

+  33, 33, 33, 1, 2, 33, 26, 26, 26, 26, 

+  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 

+  26, 26, 26, 26, 26, 26, 11, 26, 26, 26, 

+  26, 26, 22, 29, 3, 33, 26, 33, 26, 26, 

+  4, 26, 10, 26, 26, 26, 13, 26, 26, 14, 

+  9, 6, 5, 26, 26, 26, 7, 12, 8, 26, 

+  26, 26, 26, 26, 17, 33, 34, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33

+};

+

+

+static void act144()

+{ 

+		NLA = Eof;

+    ;   

+	}

+

+

+static void act145()

+{ 

+		NLA = 137;

+    zzskip();   

+	}

+

+

+static void act146()

+{ 

+		NLA = 138;

+    zzline++; zzskip();   

+	}

+

+

+static void act147()

+{ 

+		NLA = 139;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzmore();   

+	}

+

+

+static void act148()

+{ 

+		NLA = 140;

+    zzmode(TOK_DEF_COMMENTS); zzskip();   

+	}

+

+

+static void act149()

+{ 

+		NLA = 141;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act150()

+{ 

+		NLA = 142;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act151()

+{ 

+		NLA = 143;

+    ;   

+	}

+

+

+static void act152()

+{ 

+		NLA = 144;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act153()

+{ 

+		NLA = 145;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act154()

+{ 

+		NLA = 146;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act155()

+{ 

+		NLA = 147;

+    zzmode(TOK_DEF_CPP_COMMENTS); zzskip();   

+	}

+

+

+static void act156()

+{ 

+		NLA = 149;

+	}

+

+

+static void act157()

+{ 

+		NLA = 151;

+	}

+

+

+static void act158()

+{ 

+		NLA = 152;

+	}

+

+

+static void act159()

+{ 

+		NLA = 153;

+	}

+

+

+static void act160()

+{ 

+		NLA = 154;

+	}

+

+

+static void act161()

+{ 

+		NLA = 155;

+	}

+

+

+static void act162()

+{ 

+		NLA = 156;

+	}

+

+

+static void act163()

+{ 

+		NLA = INT;

+	}

+

+

+static void act164()

+{ 

+		NLA = ID;

+	}

+

+static unsigned char shift11[257] = {

+  0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  1, 2, 27, 27, 3, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 1, 27, 27, 6, 27, 27, 27, 

+  27, 27, 27, 5, 27, 22, 27, 27, 4, 25, 

+  25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 

+  24, 27, 21, 27, 27, 27, 26, 26, 26, 26, 

+  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 

+  26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 

+  26, 26, 27, 27, 27, 27, 26, 27, 26, 26, 

+  26, 9, 10, 8, 26, 26, 7, 26, 26, 12, 

+  15, 11, 17, 16, 26, 18, 13, 19, 14, 26, 

+  26, 26, 26, 26, 20, 27, 23, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 

+  27, 27, 27, 27, 27, 27, 27

+};

+

+#define DfaStates	436

+typedef unsigned short DfaState;

+

+static DfaState st0[60] = {

+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 

+  11, 11, 11, 12, 13, 13, 13, 14, 15, 16, 

+  17, 11, 11, 18, 11, 11, 19, 11, 11, 19, 

+  11, 11, 11, 11, 20, 11, 11, 21, 22, 23, 

+  24, 25, 26, 11, 27, 28, 29, 30, 31, 32, 

+  33, 34, 35, 36, 11, 11, 19, 436, 436, 436

+};

+

+static DfaState st1[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st2[60] = {

+  436, 2, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st3[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st4[60] = {

+  436, 436, 37, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st5[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st6[60] = {

+  436, 436, 436, 436, 436, 38, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st7[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st8[60] = {

+  436, 436, 436, 436, 436, 436, 436, 39, 40, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st9[60] = {

+  436, 436, 436, 436, 436, 436, 436, 41, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st10[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  42, 43, 43, 44, 43, 43, 43, 436, 436, 436, 

+  436, 45, 43, 43, 43, 43, 46, 43, 47, 43, 

+  43, 43, 43, 48, 43, 49, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st11[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st12[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 51, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st13[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 13, 13, 13, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st14[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 52, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st15[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 53, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st16[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st17[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 54, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st18[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 55, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st19[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  56, 56, 56, 56, 56, 56, 56, 436, 436, 436, 

+  436, 56, 56, 56, 56, 56, 56, 56, 56, 56, 

+  56, 56, 56, 56, 56, 56, 56, 436, 56, 436, 

+  436, 436, 436, 56, 436, 436, 436, 436, 436, 436, 

+  436, 56, 436, 436, 56, 56, 56, 56, 436, 436

+};

+

+static DfaState st20[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 57, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st21[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st22[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  58, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 59, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st23[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st24[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st25[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st26[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st27[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 60, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st28[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 61, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st29[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st30[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st31[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 62, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st32[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st33[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st34[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  56, 56, 56, 56, 56, 56, 56, 436, 436, 436, 

+  436, 56, 56, 56, 56, 56, 56, 56, 56, 56, 

+  56, 56, 56, 56, 56, 56, 56, 436, 56, 436, 

+  436, 436, 436, 56, 436, 436, 436, 436, 436, 436, 

+  436, 63, 436, 436, 56, 56, 56, 56, 436, 436

+};

+

+static DfaState st35[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st36[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st37[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st38[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st39[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st40[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st41[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st42[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 64, 43, 65, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st43[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st44[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 66, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st45[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 67, 68, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st46[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 69, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st47[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 70, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st48[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 71, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st49[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 72, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st50[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st51[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 73, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st52[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st53[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st54[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  74, 43, 43, 44, 43, 43, 43, 436, 436, 436, 

+  436, 45, 43, 43, 43, 43, 46, 43, 47, 43, 

+  43, 43, 43, 48, 43, 49, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st55[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 75, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st56[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  56, 56, 56, 56, 56, 56, 56, 436, 436, 436, 

+  436, 56, 56, 56, 56, 56, 56, 56, 56, 56, 

+  56, 56, 56, 56, 56, 56, 56, 436, 56, 436, 

+  436, 436, 436, 56, 436, 436, 436, 436, 436, 436, 

+  436, 56, 436, 436, 56, 56, 56, 56, 436, 436

+};

+

+static DfaState st57[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 76, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st58[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 77, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st59[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 78, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st60[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st61[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st62[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st63[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  56, 56, 56, 56, 56, 56, 56, 436, 436, 436, 

+  436, 56, 56, 56, 56, 56, 56, 56, 56, 56, 

+  56, 56, 56, 56, 56, 56, 56, 436, 56, 436, 

+  436, 436, 436, 56, 436, 436, 79, 436, 436, 436, 

+  436, 56, 436, 436, 56, 56, 56, 56, 436, 436

+};

+

+static DfaState st64[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 80, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st65[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 81, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st66[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 82, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st67[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 83, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 84, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st68[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 85, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st69[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 86, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st70[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 87, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st71[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 88, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st72[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 89, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st73[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 90, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st74[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 65, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st75[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 91, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st76[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 92, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st77[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 93, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st78[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 94, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st79[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 95, 96, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st80[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 97, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st81[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 98, 43, 99, 43, 100, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 101, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st82[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 102, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st83[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 103, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st84[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 104, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st85[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 105, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st86[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 106, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st87[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 107, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 108, 43, 43, 436, 109, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st88[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 110, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st89[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 111, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st90[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 112, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st91[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 113, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st92[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 114, 50, 50, 50, 436, 436

+};

+

+static DfaState st93[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 115, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st94[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 116, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st95[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 117, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st96[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 118, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st97[60] = {

+  436, 119, 120, 121, 122, 122, 122, 122, 122, 122, 

+  123, 123, 123, 123, 124, 124, 124, 122, 122, 122, 

+  122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 

+  123, 123, 123, 123, 123, 123, 123, 122, 123, 122, 

+  122, 122, 122, 123, 122, 122, 122, 122, 122, 122, 

+  122, 123, 122, 122, 123, 123, 123, 123, 122, 436

+};

+

+static DfaState st98[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 125, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st99[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 126, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st100[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 127, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st101[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  128, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st102[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  129, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st103[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st104[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 130, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st105[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 131, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st106[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 132, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st107[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 133, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st108[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 134, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st109[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  135, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st110[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 136, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st111[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 137, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st112[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 138, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st113[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 139, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st114[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  140, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st115[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st116[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st117[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st118[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st119[60] = {

+  436, 119, 120, 121, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 141, 141, 141, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st120[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st121[60] = {

+  436, 436, 142, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st122[60] = {

+  436, 122, 120, 121, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st123[60] = {

+  436, 122, 120, 121, 122, 122, 122, 122, 122, 122, 

+  123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 

+  122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 

+  123, 123, 123, 123, 123, 123, 123, 122, 123, 122, 

+  122, 122, 122, 123, 122, 122, 122, 122, 122, 122, 

+  122, 123, 122, 122, 123, 123, 123, 123, 122, 436

+};

+

+static DfaState st124[60] = {

+  436, 143, 144, 145, 122, 122, 146, 122, 122, 122, 

+  123, 123, 123, 123, 124, 124, 124, 122, 122, 122, 

+  122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 

+  123, 123, 123, 123, 123, 123, 123, 122, 123, 122, 

+  122, 122, 122, 123, 122, 122, 122, 122, 122, 122, 

+  122, 123, 122, 122, 123, 123, 123, 123, 122, 436

+};

+

+static DfaState st125[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 147, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st126[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 148, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st127[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 149, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st128[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 150, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st129[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 151, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st130[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 152, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st131[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 153, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st132[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 154, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st133[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st134[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 155, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st135[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 156, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st136[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 157, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st137[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st138[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 158, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st139[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st140[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 159, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st141[60] = {

+  436, 143, 144, 145, 122, 122, 146, 122, 122, 122, 

+  122, 122, 122, 122, 141, 141, 141, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st142[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st143[60] = {

+  436, 143, 120, 121, 122, 122, 146, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st144[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st145[60] = {

+  436, 436, 160, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st146[60] = {

+  436, 161, 162, 163, 161, 161, 122, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 436

+};

+

+static DfaState st147[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 164, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st148[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 165, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st149[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 166, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st150[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 167, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st151[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 168, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st152[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st153[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st154[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 169, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st155[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 170, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st156[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 171, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st157[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st158[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 172, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st159[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st160[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st161[60] = {

+  436, 161, 162, 163, 161, 161, 173, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 

+  161, 161, 161, 161, 161, 161, 161, 161, 161, 436

+};

+

+static DfaState st162[60] = {

+  436, 174, 174, 174, 174, 174, 175, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 436

+};

+

+static DfaState st163[60] = {

+  436, 174, 176, 174, 174, 174, 175, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 436

+};

+

+static DfaState st164[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 177, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st165[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 178, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st166[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 179, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st167[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 180, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st168[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 181, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st169[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 182, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st170[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st171[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 183, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st172[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 184, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st173[60] = {

+  436, 185, 144, 145, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 186, 186, 186, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st174[60] = {

+  436, 174, 174, 174, 174, 174, 175, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 436

+};

+

+static DfaState st175[60] = {

+  436, 187, 188, 189, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 190, 190, 190, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st176[60] = {

+  436, 174, 174, 174, 174, 174, 175, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 

+  174, 174, 174, 174, 174, 174, 174, 174, 174, 436

+};

+

+static DfaState st177[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 191, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st178[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 192, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st179[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 193, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st180[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st181[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st182[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 194, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st183[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st184[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  50, 50, 50, 50, 50, 50, 50, 436, 436, 436, 

+  436, 50, 50, 50, 50, 50, 50, 50, 50, 50, 

+  50, 50, 50, 50, 50, 50, 50, 436, 50, 436, 

+  436, 436, 436, 50, 436, 436, 436, 436, 436, 436, 

+  436, 50, 436, 436, 50, 50, 50, 50, 436, 436

+};

+

+static DfaState st185[60] = {

+  436, 185, 144, 145, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 186, 186, 186, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st186[60] = {

+  436, 185, 144, 145, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 186, 186, 186, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 

+  122, 122, 122, 122, 122, 122, 122, 122, 122, 436

+};

+

+static DfaState st187[60] = {

+  436, 187, 188, 189, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 190, 190, 190, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st188[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st189[60] = {

+  436, 436, 195, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st190[60] = {

+  436, 187, 188, 189, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 190, 190, 190, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st191[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st192[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st193[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st194[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  196, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st195[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st196[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 197, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st197[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 198, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st198[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 199, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st199[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  200, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st200[60] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  43, 43, 43, 43, 43, 43, 43, 436, 436, 436, 

+  436, 43, 43, 43, 43, 43, 43, 43, 43, 43, 

+  43, 43, 43, 43, 43, 43, 43, 436, 43, 436, 

+  436, 436, 436, 43, 436, 436, 436, 436, 436, 436, 

+  436, 43, 436, 436, 43, 43, 43, 43, 436, 436

+};

+

+static DfaState st201[7] = {

+  202, 203, 204, 205, 206, 207, 436

+};

+

+static DfaState st202[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st203[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st204[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st205[7] = {

+  436, 436, 208, 436, 436, 436, 436

+};

+

+static DfaState st206[7] = {

+  436, 209, 210, 211, 209, 209, 436

+};

+

+static DfaState st207[7] = {

+  436, 436, 436, 436, 436, 207, 436

+};

+

+static DfaState st208[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st209[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st210[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st211[7] = {

+  436, 436, 212, 436, 436, 436, 436

+};

+

+static DfaState st212[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st213[7] = {

+  214, 215, 216, 217, 218, 219, 436

+};

+

+static DfaState st214[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st215[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st216[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st217[7] = {

+  436, 436, 220, 436, 436, 436, 436

+};

+

+static DfaState st218[7] = {

+  436, 221, 222, 223, 221, 221, 436

+};

+

+static DfaState st219[7] = {

+  436, 436, 436, 436, 436, 219, 436

+};

+

+static DfaState st220[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st221[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st222[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st223[7] = {

+  436, 436, 224, 436, 436, 436, 436

+};

+

+static DfaState st224[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st225[7] = {

+  226, 227, 228, 229, 230, 231, 436

+};

+

+static DfaState st226[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st227[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st228[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st229[7] = {

+  436, 436, 232, 436, 436, 436, 436

+};

+

+static DfaState st230[7] = {

+  436, 233, 233, 233, 233, 233, 436

+};

+

+static DfaState st231[7] = {

+  436, 436, 436, 436, 436, 231, 436

+};

+

+static DfaState st232[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st233[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st234[7] = {

+  235, 236, 237, 238, 239, 237, 436

+};

+

+static DfaState st235[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st236[7] = {

+  436, 436, 240, 436, 436, 436, 436

+};

+

+static DfaState st237[7] = {

+  436, 436, 237, 436, 436, 237, 436

+};

+

+static DfaState st238[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st239[7] = {

+  436, 436, 436, 241, 436, 436, 436

+};

+

+static DfaState st240[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st241[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st242[7] = {

+  243, 244, 245, 246, 247, 245, 436

+};

+

+static DfaState st243[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st244[7] = {

+  436, 436, 248, 436, 436, 436, 436

+};

+

+static DfaState st245[7] = {

+  436, 436, 245, 436, 436, 245, 436

+};

+

+static DfaState st246[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st247[7] = {

+  436, 436, 436, 249, 436, 436, 436

+};

+

+static DfaState st248[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st249[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st250[5] = {

+  251, 252, 253, 254, 436

+};

+

+static DfaState st251[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st252[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st253[5] = {

+  436, 255, 436, 436, 436

+};

+

+static DfaState st254[5] = {

+  436, 436, 436, 254, 436

+};

+

+static DfaState st255[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st256[5] = {

+  257, 258, 259, 260, 436

+};

+

+static DfaState st257[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st258[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st259[5] = {

+  436, 261, 436, 436, 436

+};

+

+static DfaState st260[5] = {

+  436, 436, 436, 260, 436

+};

+

+static DfaState st261[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st262[5] = {

+  263, 264, 265, 266, 436

+};

+

+static DfaState st263[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st264[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st265[5] = {

+  436, 267, 436, 436, 436

+};

+

+static DfaState st266[5] = {

+  436, 436, 436, 266, 436

+};

+

+static DfaState st267[5] = {

+  436, 436, 436, 436, 436

+};

+

+static DfaState st268[7] = {

+  269, 270, 271, 272, 273, 271, 436

+};

+

+static DfaState st269[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st270[7] = {

+  436, 436, 274, 436, 436, 436, 436

+};

+

+static DfaState st271[7] = {

+  436, 436, 271, 436, 436, 271, 436

+};

+

+static DfaState st272[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st273[7] = {

+  436, 436, 436, 275, 436, 436, 436

+};

+

+static DfaState st274[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st275[7] = {

+  436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st276[36] = {

+  277, 278, 279, 280, 281, 279, 279, 279, 279, 279, 

+  279, 279, 279, 279, 279, 282, 279, 279, 283, 284, 

+  285, 286, 287, 279, 279, 279, 279, 288, 289, 290, 

+  291, 292, 293, 279, 279, 436

+};

+

+static DfaState st277[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st278[36] = {

+  436, 294, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st279[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st280[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st281[36] = {

+  436, 436, 279, 436, 279, 295, 279, 279, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st282[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st283[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st284[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st285[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 296, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st286[36] = {

+  436, 436, 436, 436, 297, 297, 297, 297, 297, 297, 

+  297, 297, 297, 297, 297, 436, 436, 436, 436, 436, 

+  436, 298, 299, 300, 300, 436, 297, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st287[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st288[36] = {

+  436, 436, 436, 436, 301, 301, 301, 301, 301, 301, 

+  301, 301, 301, 301, 302, 303, 436, 436, 436, 436, 

+  436, 436, 304, 305, 306, 436, 301, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st289[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st290[36] = {

+  436, 307, 308, 309, 308, 308, 308, 308, 308, 308, 

+  308, 308, 308, 308, 308, 308, 308, 308, 310, 311, 

+  312, 313, 308, 308, 308, 308, 308, 314, 308, 308, 

+  308, 308, 308, 308, 308, 436

+};

+

+static DfaState st291[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st292[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 315, 316, 436, 436, 436

+};

+

+static DfaState st293[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 317, 279, 279, 279, 436

+};

+

+static DfaState st294[36] = {

+  436, 436, 318, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st295[36] = {

+  436, 436, 279, 436, 279, 279, 319, 279, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st296[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st297[36] = {

+  436, 436, 436, 436, 320, 320, 320, 320, 320, 320, 

+  320, 320, 320, 320, 320, 436, 436, 436, 436, 436, 

+  436, 436, 436, 320, 320, 436, 320, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st298[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st299[36] = {

+  436, 436, 436, 321, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st300[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 300, 300, 322, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st301[36] = {

+  436, 436, 436, 436, 323, 323, 323, 323, 323, 323, 

+  323, 323, 323, 323, 323, 436, 436, 436, 436, 436, 

+  436, 436, 436, 323, 323, 436, 323, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st302[36] = {

+  436, 436, 436, 436, 323, 323, 323, 323, 323, 323, 

+  323, 323, 323, 324, 323, 436, 436, 436, 436, 436, 

+  436, 436, 436, 323, 323, 436, 323, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st303[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 325, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st304[36] = {

+  436, 436, 436, 326, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st305[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 306, 306, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st306[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 306, 306, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st307[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st308[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st309[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st310[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st311[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st312[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 327, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st313[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st314[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st315[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st316[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st317[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st318[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st319[36] = {

+  436, 436, 279, 436, 279, 279, 279, 328, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st320[36] = {

+  436, 436, 436, 436, 320, 320, 320, 320, 320, 320, 

+  320, 320, 320, 320, 320, 436, 436, 436, 436, 436, 

+  436, 436, 436, 320, 320, 436, 320, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st321[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st322[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 329, 329, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st323[36] = {

+  436, 436, 436, 436, 323, 323, 323, 323, 323, 323, 

+  323, 323, 323, 323, 323, 436, 436, 436, 436, 436, 

+  436, 436, 436, 323, 323, 436, 323, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st324[36] = {

+  436, 436, 436, 436, 323, 323, 330, 323, 323, 323, 

+  323, 323, 323, 323, 323, 436, 436, 436, 436, 436, 

+  436, 436, 436, 323, 323, 436, 323, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st325[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st326[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st327[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st328[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 331, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st329[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 329, 329, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st330[36] = {

+  436, 436, 436, 436, 323, 323, 323, 323, 323, 323, 

+  332, 323, 323, 323, 323, 436, 436, 436, 436, 436, 

+  436, 436, 436, 323, 323, 436, 323, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st331[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 333, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st332[36] = {

+  436, 334, 334, 334, 335, 335, 335, 335, 335, 335, 

+  335, 335, 335, 335, 335, 334, 336, 334, 334, 337, 

+  338, 334, 334, 339, 339, 334, 335, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st333[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  340, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st334[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 334, 334, 334, 337, 

+  338, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st335[36] = {

+  436, 334, 334, 334, 335, 335, 335, 335, 335, 335, 

+  335, 335, 335, 335, 335, 334, 334, 334, 334, 337, 

+  338, 334, 334, 335, 335, 334, 335, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st336[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 336, 334, 334, 337, 

+  338, 334, 334, 341, 341, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st337[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st338[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 342, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st339[36] = {

+  436, 334, 334, 334, 335, 335, 335, 335, 335, 335, 

+  335, 335, 335, 335, 335, 334, 343, 334, 334, 344, 

+  345, 334, 334, 339, 339, 334, 335, 334, 346, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st340[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 347, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st341[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 343, 334, 334, 344, 

+  345, 334, 334, 341, 341, 334, 334, 334, 346, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st342[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st343[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 343, 334, 334, 337, 

+  338, 334, 334, 334, 334, 334, 334, 334, 346, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st344[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st345[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 348, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st346[36] = {

+  436, 349, 349, 349, 349, 349, 349, 349, 349, 349, 

+  349, 349, 349, 349, 349, 349, 349, 349, 349, 350, 

+  351, 349, 349, 349, 349, 349, 349, 349, 334, 349, 

+  349, 349, 349, 349, 349, 436

+};

+

+static DfaState st347[36] = {

+  436, 436, 279, 436, 279, 279, 352, 279, 279, 279, 

+  279, 279, 279, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st348[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st349[36] = {

+  436, 349, 349, 349, 349, 349, 349, 349, 349, 349, 

+  349, 349, 349, 349, 349, 349, 349, 349, 349, 350, 

+  351, 349, 349, 349, 349, 349, 349, 349, 353, 349, 

+  349, 349, 349, 349, 349, 436

+};

+

+static DfaState st350[36] = {

+  436, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 355, 354, 

+  354, 354, 354, 354, 354, 436

+};

+

+static DfaState st351[36] = {

+  436, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 354, 356, 

+  354, 354, 354, 354, 354, 354, 354, 354, 355, 354, 

+  354, 354, 354, 354, 354, 436

+};

+

+static DfaState st352[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 357, 279, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st353[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 358, 334, 334, 344, 

+  345, 334, 334, 359, 359, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st354[36] = {

+  436, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 355, 354, 

+  354, 354, 354, 354, 354, 436

+};

+

+static DfaState st355[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 360, 436, 436, 361, 

+  362, 436, 436, 363, 363, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st356[36] = {

+  436, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 

+  354, 354, 354, 354, 354, 354, 354, 354, 355, 354, 

+  354, 354, 354, 354, 354, 436

+};

+

+static DfaState st357[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 279, 364, 279, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st358[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 358, 334, 334, 344, 

+  345, 334, 334, 359, 359, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st359[36] = {

+  436, 334, 334, 334, 334, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 334, 358, 334, 334, 344, 

+  345, 334, 334, 359, 359, 334, 334, 334, 334, 334, 

+  334, 334, 334, 334, 334, 436

+};

+

+static DfaState st360[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 360, 436, 436, 361, 

+  362, 436, 436, 363, 363, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st361[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st362[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 365, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st363[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 360, 436, 436, 361, 

+  362, 436, 436, 363, 363, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st364[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 279, 279, 366, 436, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st365[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st366[36] = {

+  436, 436, 279, 436, 279, 279, 279, 279, 279, 279, 

+  279, 279, 279, 279, 279, 367, 279, 279, 436, 436, 

+  436, 436, 436, 279, 279, 279, 279, 436, 436, 436, 

+  436, 436, 279, 279, 279, 436

+};

+

+static DfaState st367[36] = {

+  436, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 368, 369, 370, 436, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 436

+};

+

+static DfaState st368[36] = {

+  436, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 371, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 436

+};

+

+static DfaState st369[36] = {

+  436, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 368, 369, 370, 371, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 436

+};

+

+static DfaState st370[36] = {

+  436, 372, 372, 372, 372, 372, 372, 372, 372, 372, 

+  372, 372, 372, 372, 372, 372, 372, 372, 373, 372, 

+  372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 

+  372, 372, 372, 372, 368, 436

+};

+

+static DfaState st371[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st372[36] = {

+  436, 372, 372, 372, 372, 372, 372, 372, 372, 372, 

+  372, 372, 372, 372, 372, 372, 372, 372, 373, 372, 

+  372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 

+  372, 372, 372, 372, 374, 436

+};

+

+static DfaState st373[36] = {

+  436, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 376, 436

+};

+

+static DfaState st374[36] = {

+  436, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 368, 377, 368, 378, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 436

+};

+

+static DfaState st375[36] = {

+  436, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 

+  375, 375, 375, 375, 376, 436

+};

+

+static DfaState st376[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 379, 436, 380, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st377[36] = {

+  436, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 368, 377, 368, 378, 368, 

+  368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 

+  368, 368, 368, 368, 368, 436

+};

+

+static DfaState st378[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st379[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 379, 436, 380, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st380[36] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436

+};

+

+static DfaState st381[28] = {

+  382, 383, 384, 385, 386, 436, 387, 388, 388, 388, 

+  389, 388, 388, 388, 388, 388, 388, 388, 388, 388, 

+  390, 391, 392, 393, 394, 395, 388, 436

+};

+

+static DfaState st382[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st383[28] = {

+  436, 383, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st384[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st385[28] = {

+  436, 436, 396, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st386[28] = {

+  436, 436, 436, 436, 397, 398, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st387[28] = {

+  436, 436, 436, 436, 436, 436, 436, 399, 436, 400, 

+  401, 436, 436, 436, 402, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st388[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st389[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 404, 403, 403, 403, 403, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st390[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st391[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st392[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st393[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st394[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st395[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 395, 436, 436

+};

+

+static DfaState st396[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st397[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st398[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st399[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 405, 436, 

+  436, 436, 436, 436, 436, 406, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st400[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  407, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st401[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 408, 409, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st402[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 410, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st403[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st404[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 403, 403, 403, 411, 403, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st405[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 412, 

+  436, 413, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st406[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 414, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st407[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 415, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st408[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 416, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st409[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 417, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st410[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 418, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st411[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 403, 403, 403, 403, 419, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st412[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  420, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st413[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 421, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st414[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 422, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st415[28] = {

+  436, 436, 436, 436, 436, 436, 436, 423, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st416[28] = {

+  436, 436, 436, 436, 436, 436, 436, 424, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st417[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  425, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st418[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  426, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st419[28] = {

+  436, 436, 436, 436, 436, 436, 436, 403, 403, 403, 

+  403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 

+  436, 436, 436, 436, 436, 403, 403, 436

+};

+

+static DfaState st420[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 427, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st421[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  428, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st422[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 429, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st423[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 430, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st424[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 431, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st425[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st426[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 432, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st427[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st428[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 433, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st429[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 434, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st430[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  435, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st431[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st432[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st433[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st434[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+static DfaState st435[28] = {

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 

+  436, 436, 436, 436, 436, 436, 436, 436

+};

+

+

+DfaState *dfa[436] = {

+	st0,

+	st1,

+	st2,

+	st3,

+	st4,

+	st5,

+	st6,

+	st7,

+	st8,

+	st9,

+	st10,

+	st11,

+	st12,

+	st13,

+	st14,

+	st15,

+	st16,

+	st17,

+	st18,

+	st19,

+	st20,

+	st21,

+	st22,

+	st23,

+	st24,

+	st25,

+	st26,

+	st27,

+	st28,

+	st29,

+	st30,

+	st31,

+	st32,

+	st33,

+	st34,

+	st35,

+	st36,

+	st37,

+	st38,

+	st39,

+	st40,

+	st41,

+	st42,

+	st43,

+	st44,

+	st45,

+	st46,

+	st47,

+	st48,

+	st49,

+	st50,

+	st51,

+	st52,

+	st53,

+	st54,

+	st55,

+	st56,

+	st57,

+	st58,

+	st59,

+	st60,

+	st61,

+	st62,

+	st63,

+	st64,

+	st65,

+	st66,

+	st67,

+	st68,

+	st69,

+	st70,

+	st71,

+	st72,

+	st73,

+	st74,

+	st75,

+	st76,

+	st77,

+	st78,

+	st79,

+	st80,

+	st81,

+	st82,

+	st83,

+	st84,

+	st85,

+	st86,

+	st87,

+	st88,

+	st89,

+	st90,

+	st91,

+	st92,

+	st93,

+	st94,

+	st95,

+	st96,

+	st97,

+	st98,

+	st99,

+	st100,

+	st101,

+	st102,

+	st103,

+	st104,

+	st105,

+	st106,

+	st107,

+	st108,

+	st109,

+	st110,

+	st111,

+	st112,

+	st113,

+	st114,

+	st115,

+	st116,

+	st117,

+	st118,

+	st119,

+	st120,

+	st121,

+	st122,

+	st123,

+	st124,

+	st125,

+	st126,

+	st127,

+	st128,

+	st129,

+	st130,

+	st131,

+	st132,

+	st133,

+	st134,

+	st135,

+	st136,

+	st137,

+	st138,

+	st139,

+	st140,

+	st141,

+	st142,

+	st143,

+	st144,

+	st145,

+	st146,

+	st147,

+	st148,

+	st149,

+	st150,

+	st151,

+	st152,

+	st153,

+	st154,

+	st155,

+	st156,

+	st157,

+	st158,

+	st159,

+	st160,

+	st161,

+	st162,

+	st163,

+	st164,

+	st165,

+	st166,

+	st167,

+	st168,

+	st169,

+	st170,

+	st171,

+	st172,

+	st173,

+	st174,

+	st175,

+	st176,

+	st177,

+	st178,

+	st179,

+	st180,

+	st181,

+	st182,

+	st183,

+	st184,

+	st185,

+	st186,

+	st187,

+	st188,

+	st189,

+	st190,

+	st191,

+	st192,

+	st193,

+	st194,

+	st195,

+	st196,

+	st197,

+	st198,

+	st199,

+	st200,

+	st201,

+	st202,

+	st203,

+	st204,

+	st205,

+	st206,

+	st207,

+	st208,

+	st209,

+	st210,

+	st211,

+	st212,

+	st213,

+	st214,

+	st215,

+	st216,

+	st217,

+	st218,

+	st219,

+	st220,

+	st221,

+	st222,

+	st223,

+	st224,

+	st225,

+	st226,

+	st227,

+	st228,

+	st229,

+	st230,

+	st231,

+	st232,

+	st233,

+	st234,

+	st235,

+	st236,

+	st237,

+	st238,

+	st239,

+	st240,

+	st241,

+	st242,

+	st243,

+	st244,

+	st245,

+	st246,

+	st247,

+	st248,

+	st249,

+	st250,

+	st251,

+	st252,

+	st253,

+	st254,

+	st255,

+	st256,

+	st257,

+	st258,

+	st259,

+	st260,

+	st261,

+	st262,

+	st263,

+	st264,

+	st265,

+	st266,

+	st267,

+	st268,

+	st269,

+	st270,

+	st271,

+	st272,

+	st273,

+	st274,

+	st275,

+	st276,

+	st277,

+	st278,

+	st279,

+	st280,

+	st281,

+	st282,

+	st283,

+	st284,

+	st285,

+	st286,

+	st287,

+	st288,

+	st289,

+	st290,

+	st291,

+	st292,

+	st293,

+	st294,

+	st295,

+	st296,

+	st297,

+	st298,

+	st299,

+	st300,

+	st301,

+	st302,

+	st303,

+	st304,

+	st305,

+	st306,

+	st307,

+	st308,

+	st309,

+	st310,

+	st311,

+	st312,

+	st313,

+	st314,

+	st315,

+	st316,

+	st317,

+	st318,

+	st319,

+	st320,

+	st321,

+	st322,

+	st323,

+	st324,

+	st325,

+	st326,

+	st327,

+	st328,

+	st329,

+	st330,

+	st331,

+	st332,

+	st333,

+	st334,

+	st335,

+	st336,

+	st337,

+	st338,

+	st339,

+	st340,

+	st341,

+	st342,

+	st343,

+	st344,

+	st345,

+	st346,

+	st347,

+	st348,

+	st349,

+	st350,

+	st351,

+	st352,

+	st353,

+	st354,

+	st355,

+	st356,

+	st357,

+	st358,

+	st359,

+	st360,

+	st361,

+	st362,

+	st363,

+	st364,

+	st365,

+	st366,

+	st367,

+	st368,

+	st369,

+	st370,

+	st371,

+	st372,

+	st373,

+	st374,

+	st375,

+	st376,

+	st377,

+	st378,

+	st379,

+	st380,

+	st381,

+	st382,

+	st383,

+	st384,

+	st385,

+	st386,

+	st387,

+	st388,

+	st389,

+	st390,

+	st391,

+	st392,

+	st393,

+	st394,

+	st395,

+	st396,

+	st397,

+	st398,

+	st399,

+	st400,

+	st401,

+	st402,

+	st403,

+	st404,

+	st405,

+	st406,

+	st407,

+	st408,

+	st409,

+	st410,

+	st411,

+	st412,

+	st413,

+	st414,

+	st415,

+	st416,

+	st417,

+	st418,

+	st419,

+	st420,

+	st421,

+	st422,

+	st423,

+	st424,

+	st425,

+	st426,

+	st427,

+	st428,

+	st429,

+	st430,

+	st431,

+	st432,

+	st433,

+	st434,

+	st435

+};

+

+

+DfaState accepts[437] = {

+  0, 1, 2, 3, 3, 4, 25, 6, 0, 50, 

+  59, 57, 57, 43, 26, 13, 14, 0, 57, 58, 

+  57, 21, 57, 23, 24, 27, 28, 44, 0, 35, 

+  36, 42, 45, 46, 58, 51, 52, 3, 5, 9, 

+  7, 8, 59, 59, 59, 59, 59, 59, 59, 59, 

+  57, 57, 12, 40, 59, 57, 58, 57, 57, 57, 

+  33, 34, 53, 58, 59, 59, 59, 59, 59, 59, 

+  59, 59, 59, 57, 59, 57, 57, 57, 57, 0, 

+  59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 

+  57, 57, 57, 57, 57, 0, 0, 59, 59, 59, 

+  59, 59, 59, 32, 59, 59, 59, 59, 59, 59, 

+  59, 59, 57, 57, 57, 22, 56, 48, 49, 0, 

+  11, 11, 0, 59, 59, 59, 59, 59, 59, 59, 

+  59, 59, 59, 41, 59, 59, 59, 18, 57, 47, 

+  57, 0, 11, 0, 10, 10, 0, 59, 59, 59, 

+  59, 59, 15, 19, 59, 59, 59, 17, 57, 55, 

+  10, 0, 11, 11, 59, 59, 59, 59, 59, 59, 

+  20, 59, 57, 0, 0, 0, 11, 59, 59, 59, 

+  37, 38, 59, 39, 54, 0, 0, 0, 10, 10, 

+  0, 31, 29, 30, 59, 10, 59, 59, 59, 59, 

+  16, 0, 60, 61, 62, 62, 0, 65, 62, 64, 

+  63, 63, 63, 0, 66, 67, 68, 68, 0, 71, 

+  68, 70, 69, 69, 69, 0, 72, 73, 74, 74, 

+  0, 76, 74, 75, 0, 77, 79, 81, 80, 80, 

+  78, 80, 0, 82, 84, 86, 85, 85, 83, 85, 

+  0, 87, 88, 88, 89, 88, 0, 90, 91, 91, 

+  92, 91, 0, 93, 94, 94, 95, 94, 0, 96, 

+  98, 100, 99, 99, 97, 99, 0, 101, 108, 143, 

+  104, 143, 129, 127, 107, 107, 109, 128, 126, 134, 

+  0, 133, 139, 143, 102, 143, 107, 116, 110, 112, 

+  113, 123, 123, 125, 124, 117, 120, 132, 138, 130, 

+  131, 137, 137, 135, 136, 142, 140, 141, 103, 143, 

+  116, 111, 114, 123, 123, 119, 118, 137, 143, 115, 

+  123, 143, 123, 143, 0, 123, 0, 122, 122, 123, 

+  143, 0, 122, 0, 121, 121, 0, 143, 121, 0, 

+  122, 122, 143, 0, 0, 0, 122, 143, 0, 0, 

+  0, 121, 121, 0, 143, 121, 143, 0, 0, 0, 

+  0, 106, 0, 106, 0, 0, 0, 0, 105, 0, 

+  105, 0, 144, 145, 146, 146, 0, 0, 164, 164, 

+  158, 159, 160, 161, 162, 163, 146, 147, 148, 0, 

+  0, 0, 0, 164, 164, 150, 0, 0, 0, 0, 

+  0, 164, 0, 0, 0, 0, 0, 0, 0, 157, 

+  0, 0, 0, 0, 0, 152, 0, 149, 0, 0, 

+  0, 153, 154, 151, 155, 156, 0

+};

+

+void (*actions[165])() = {

+	zzerraction,

+	act1,

+	act2,

+	act3,

+	act4,

+	act5,

+	act6,

+	act7,

+	act8,

+	act9,

+	act10,

+	act11,

+	act12,

+	act13,

+	act14,

+	act15,

+	act16,

+	act17,

+	act18,

+	act19,

+	act20,

+	act21,

+	act22,

+	act23,

+	act24,

+	act25,

+	act26,

+	act27,

+	act28,

+	act29,

+	act30,

+	act31,

+	act32,

+	act33,

+	act34,

+	act35,

+	act36,

+	act37,

+	act38,

+	act39,

+	act40,

+	act41,

+	act42,

+	act43,

+	act44,

+	act45,

+	act46,

+	act47,

+	act48,

+	act49,

+	act50,

+	act51,

+	act52,

+	act53,

+	act54,

+	act55,

+	act56,

+	act57,

+	act58,

+	act59,

+	act60,

+	act61,

+	act62,

+	act63,

+	act64,

+	act65,

+	act66,

+	act67,

+	act68,

+	act69,

+	act70,

+	act71,

+	act72,

+	act73,

+	act74,

+	act75,

+	act76,

+	act77,

+	act78,

+	act79,

+	act80,

+	act81,

+	act82,

+	act83,

+	act84,

+	act85,

+	act86,

+	act87,

+	act88,

+	act89,

+	act90,

+	act91,

+	act92,

+	act93,

+	act94,

+	act95,

+	act96,

+	act97,

+	act98,

+	act99,

+	act100,

+	act101,

+	act102,

+	act103,

+	act104,

+	act105,

+	act106,

+	act107,

+	act108,

+	act109,

+	act110,

+	act111,

+	act112,

+	act113,

+	act114,

+	act115,

+	act116,

+	act117,

+	act118,

+	act119,

+	act120,

+	act121,

+	act122,

+	act123,

+	act124,

+	act125,

+	act126,

+	act127,

+	act128,

+	act129,

+	act130,

+	act131,

+	act132,

+	act133,

+	act134,

+	act135,

+	act136,

+	act137,

+	act138,

+	act139,

+	act140,

+	act141,

+	act142,

+	act143,

+	act144,

+	act145,

+	act146,

+	act147,

+	act148,

+	act149,

+	act150,

+	act151,

+	act152,

+	act153,

+	act154,

+	act155,

+	act156,

+	act157,

+	act158,

+	act159,

+	act160,

+	act161,

+	act162,

+	act163,

+	act164

+};

+

+static DfaState dfa_base[] = {

+	0,

+	201,

+	213,

+	225,

+	234,

+	242,

+	250,

+	256,

+	262,

+	268,

+	276,

+	381

+};

+

+static unsigned char *b_class_no[] = {

+	shift0,

+	shift1,

+	shift2,

+	shift3,

+	shift4,

+	shift5,

+	shift6,

+	shift7,

+	shift8,

+	shift9,

+	shift10,

+	shift11

+};

+

+

+

+#define ZZSHIFT(c) (b_class_no[zzauto][1+c])

+#define MAX_MODE 12

+#include "dlgauto.h"

diff --git a/Source/Pccts/antlr/stdpccts.h b/Source/Pccts/antlr/stdpccts.h
new file mode 100644
index 0000000..ccdc21c
--- /dev/null
+++ b/Source/Pccts/antlr/stdpccts.h
@@ -0,0 +1,31 @@
+#ifndef STDPCCTS_H

+#define STDPCCTS_H

+/*

+ * stdpccts.h -- P C C T S  I n c l u d e

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#ifndef ANTLR_VERSION

+#define ANTLR_VERSION	13333

+#endif

+

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include "pcctscfg.h"

+#include "set.h"

+#include <ctype.h>

+#include "syn.h"

+#include "hash.h"

+#include "generic.h"

+#define zzcr_attr(attr,tok,t)

+#define zzSET_SIZE 20

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "mode.h"

+#endif

diff --git a/Source/Pccts/antlr/syn.h b/Source/Pccts/antlr/syn.h
new file mode 100644
index 0000000..a23d196
--- /dev/null
+++ b/Source/Pccts/antlr/syn.h
@@ -0,0 +1,390 @@
+/*

+ * syn.h

+ *

+ * This file includes definitions and macros associated with syntax diagrams

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include "set.h"

+

+#define NumNodeTypes	4

+#define NumJuncTypes	9

+

+/* List the different node types */

+#define nJunction		1

+#define nRuleRef		2

+#define nToken			3

+#define nAction			4

+

+/* Different types of junctions */

+#define aSubBlk			1

+#define aOptBlk			2

+#define aLoopBlk		3

+#define EndBlk			4

+#define RuleBlk			5

+#define Generic			6	/* just a junction--no unusual characteristics */

+#define EndRule			7

+#define aPlusBlk		8

+#define aLoopBegin		9

+

+typedef int NodeType;

+

+#define TreeBlockAllocSize		500

+#define JunctionBlockAllocSize	200

+#define ActionBlockAllocSize	50

+#define RRefBlockAllocSize		100

+#define TokenBlockAllocSize		100

+

+#ifdef __cplusplus

+class ActionNode;

+class Junction;

+#endif

+

+/* note that 'right' is used by the tree node allocator as a ptr for linked list */

+typedef struct _tree {

+			struct _tree *down, *right;

+			int token;

+			union {

+				int rk;	/* if token==EpToken, => how many more tokens req'd */

+				struct _tree *tref;	/* if token==TREE_REF */

+				set sref;			/* if token==SET */

+			} v;

+#ifdef TREE_DEBUG

+			int in_use;

+            int seq;

+#endif

+		} Tree;

+

+

+/* a predicate is defined to be a predicate action and a token tree with

+ * context info (if used); later, this struct may include the

+ * "hoisting distance" when we hoist past tokens.

+ *

+ * A tree is used to indicate && vs ||

+ *

+ *    p

+ *    |

+ *    q--r

+ *

+ * indicates p && (q||r).

+ *

+ * If expr is PRED_AND_LIST or PRED_OR_LIST, then it's an operation node

+ * and indicates the start of an && or || list.

+ */

+

+typedef struct _Predicate {

+	struct _Predicate *down, *right;	/* these have to be first */

+	struct _Predicate *up, *left;		/* doubly-link me */

+	char *expr;

+	Tree *tcontext;	/* used if lookahead depth of > one is needed (tree) */

+	int k;			/* lookahead depth for this tcontext */

+	set scontext[2];/* used if lookahead depth of one is needed (set) */

+					/* scontext[0] is not used; only needed so genExprSets()

+					   routine works (it expects an array)

+					 */

+	set completionTree;	/* which lookahead depths are required to complete tcontext? */

+    set completionSet;  /* MR10 separate completion set for sets and trees           */

+    struct _PredEntry *predEntry;         /* MR11 */

+

+#ifdef __cplusplus

+	ActionNode *source;	/* where did this predicate come from? */

+#else

+	struct _anode *source;	/* where did this predicate come from? */

+#endif

+

+    char             cloned;               /* MR10 don't want to free original guard pred */

+    char             redundant;            /* MR10 predicate tree simplification          */

+    char             ampersandStyle;       /* MR10  (g)? && <<p>>?                        */

+    char             inverted;             /* MR11 ! predName */

+    char             isConst;              /* MR11 */

+    char             constValue;           /* MR11 */

+    char             conflictReported;     /* MR11 */

+

+    set              plainSet;             /* MR12b */

+

+    /*** remember to change new_predicate() and predicate_dup() when changing this ***/

+

+} Predicate;

+

+typedef struct _ExceptionHandler {

+			char *signalname;

+			char *action;

+		} ExceptionHandler;

+

+typedef struct _ExceptionGroup {

+			struct _ListNode *handlers; /* list of ExceptionHandler's */

+			char *label;		/* label==""; implies not attached to any

+								 * particular rule ref.

+								 */

+			char *altID;		/* which alt did it come from (blk#:alt#) */

+

+            struct _ExceptionGroup  *pendingLink; /* for alternative EG MR7 */

+            struct _ExceptionGroup  *outerEG;     /* for alternative EG MR7 */

+            struct _LabelEntry      *labelEntry;  /* for alternative EG MR7 */

+            int                     forRule;                         /* MR7 */

+            int                     used;                            /* MR7 */

+		} ExceptionGroup ;

+

+

+#define TokenString(_i)			((TokenInd!=NULL)?TokenStr[TokenInd[_i]]:TokenStr[_i])

+#define ExprString(_i)			((TokenInd!=NULL)?ExprStr[TokenInd[_i]]:ExprStr[_i])

+

+

+				/* M e s s a g e  P a s s i n g  T o  N o d e s */

+

+/*

+ * assumes a 'Junction *r' exists.  This macro calls a function with

+ * the pointer to the node to operate on and a pointer to the rule

+ * in which it is enclosed.

+ */

+#define TRANS(p)	{if ( (p)==NULL ) fatal("TRANS: NULL object");		\

+					if ( (p)->ntype == nJunction ) (*(fpJTrans[((Junction *)(p))->jtype]))( p );\

+					else (*(fpTrans[(p)->ntype]))( p );}

+

+#define PRINT(p)	{if ( (p)==NULL ) fatal("PRINT: NULL object");\

+					(*(fpPrint[(p)->ntype]))( p );}

+

+#define REACH(p,k,rk,a) {if ( (p)==NULL ) fatal("REACH: NULL object");\

+					(a) = (*(fpReach[(p)->ntype]))( p, k, rk );}

+

+#define TRAV(p,k,rk,a) {if ( (p)==NULL ) {\

+					  if ( ContextGuardTRAV ) (a)=NULL; \

+					  else fatal("TRAV: NULL object");\

+				    } \

+					else (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );}

+

+/**

+*** #define TRAV(p,k,rk,a) {if ( (p)==NULL ) fatal("TRAV: NULL object");\

+***					(a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );}

+**/

+

+/* All syntax diagram nodes derive from Node -- superclass

+ */

+#ifdef __cplusplus

+class Node {

+public:

+			NodeType ntype;

+			char *rname;		/* what rule does this element live in? */

+			int file;			/* index in FileStr */

+			int line;			/* line number that element occurs on */

+		};

+#else

+typedef struct _node {

+			NodeType ntype;

+			char *rname;		/* what rule does this element live in? */

+			int file;			/* index in FileStr */

+			int line;			/* line number that element occurs on */

+		} Node;

+#endif

+

+#ifdef __cplusplus

+class ActionNode : public Node {

+public:

+#else

+typedef struct _anode {

+			NodeType ntype;

+			char *rname;		/* what rule does this action live in? */

+			int file;			/* index in FileStr (name of file with action) */

+			int line;			/* line number that action occurs on */

+#endif

+			Node *next;

+			char *action;

+			int is_predicate;	/* true if action is a <<...>>? predicate action */

+			int done;			/* don't dump if action dumped (used for predicates) */

+			int init_action;	/* is this the 1st action of 1st prod of block? */

+			char *pred_fail;	/* what to do/print when predicate fails */

+			Predicate  *guardpred;	/* if '(context)? =>' was present, already done */

+			unsigned char frmwarned;/* have we dumped a warning for pred yet? */

+			unsigned char ctxwarned;/* have we dumped a warning for pred yet? */

+            unsigned char predTooLong;     /* MR10 have we dumped warning for pred yet */

+            unsigned char noHoist;         /* MR12 literally "noHoist" */

+            Predicate         *ampersandPred;     /* MR10   (g)? && <<p>>? expr   */

+#ifdef __cplusplus

+            Junction          *guardNodes;        /* MR11 */

+#else

+            struct _junct     *guardNodes;        /* MR11 */

+#endif

+            struct _PredEntry *predEntry;         /* MR11 */

+            int               inverted;           /* MR11 <<!predSymbol>>? */

+#ifdef __cplusplus

+		};

+#else

+		} ActionNode;

+#endif

+

+#ifdef __cplusplus

+class TokNode : public Node {

+public:

+#else

+typedef struct _toknode {

+			NodeType ntype;

+			char *rname;		/* name of rule it's in */

+			int file;			/* index in FileStr (name of file with rule) */

+			int line;			/* line number that token occurs on */

+#endif

+			Node *next;

+			int token;

+			int astnode;		/* leaf/root/excluded (used to build AST's) */

+			unsigned char label;/* token label or expression ? */

+			unsigned char remapped;

+								/* used if token id's are forced to certain positions;

+								 * a function walks the tree reassigning token numbers */

+			int upper_range;    /* MR13 - was char */

+								/* used only if Token is of type T1..T2; in this case,

+								 * use token..upper_range as the range; else

+								 * upper_range must be 0 */

+			unsigned char wild_card;

+								/* indicates that the token is the "." wild-card;

+								 * field token is ignored if wild_card is set

+								 */

+			unsigned int elnum; /* element number within the alternative */

+#ifdef __cplusplus

+			Junction *altstart;	/* pointer to node that starts alt */

+#else

+			struct _junct *altstart;	/* pointer to node that starts alt */

+#endif

+			struct _TCnode *tclass;		/* token class if tokclass ref */

+			set tset;			/* set of tokens represented by meta token */

+			char *el_label;		/* el_label:toknode */

+			unsigned char complement;	/* complement the set? */

+			ExceptionGroup *ex_group;	/* any exception[el_label] attached? */

+            unsigned char use_def_MT_handler;

+            unsigned char label_used_in_semantic_pred;  /* MR10 */

+#ifdef __cplusplus

+		};

+#else

+		} TokNode;

+#endif

+

+#ifdef __cplusplus

+class RuleRefNode : public Node {

+public:

+#else

+typedef struct _rrnode {

+			NodeType ntype;

+			char *rname;		/* name of rule it's in */

+			int file;			/* index in FileStr (name of file with rule)

+								   it's in */

+			int line;			/* line number that rule ref occurs on */

+#endif

+			Node *next;

+			char *text;			/* reference to which rule */

+			char *parms;		/* point to parameters of rule invocation

+								   (if present) */

+			char *assign;		/* point to left-hand-side of assignment

+								   (if any) */

+			int linked;			/* Has a FoLink already been established? */

+			int astnode;		/* excluded? (used to build AST's) */

+			unsigned int elnum; /* element number within the alternative */

+#ifdef __cplusplus

+			Junction *altstart;

+#else

+			struct _junct *altstart;

+#endif

+			char *el_label;		/* el_label:rrnode */

+			ExceptionGroup *ex_group;	/* any exception[el_label] attached? */

+#ifdef __cplusplus

+		};

+#else

+		} RuleRefNode;

+#endif

+

+#ifdef __cplusplus

+class Junction : public Node {

+public:

+#else

+typedef struct _junct {

+			NodeType ntype;

+			char *rname;		/* name of rule junction is in */

+			int file;			/* index in FileStr (name of file with rule)

+								   if blk == RuleBlk */

+			int line;			/* line number that rule occurs on */

+#endif

+            int seq;            /* MR10 sequence number */

+			char ignore;		/* used by FIRST computation to ignore

+								   empty alt added for the (...)+ blks */

+			char visited;		/* used by recursive routines to avoid

+								   infinite recursion */

+			char pvisited;		/* used by print routines to avoid

+								   infinite recursion */

+			char fvisited;		/* used by FoLink() to avoid

+								   infinite recursion */

+			char *lock;			/* used by REACH to track infinite recursion */

+			char *pred_lock;	/* used by find_predicates to track infinite recursion */

+			int altnum;			/* used in subblocks. altnum==0 means not an

+								   alt of subrule */

+			int jtype;			/* annotation for code-gen/FIRST/FOLLOW.

+								   Junction type */

+#ifdef __cplusplus

+			Junction *end;		/* pointer to node with EndBlk in it

+								   if blk == a block type */

+#else

+			struct _junct *end;	/* pointer to node with EndBlk in it

+								   if blk == a block type */

+#endif

+			Node *p1, *p2;

+			char  halt;			/* never move past a junction with halt==TRUE */ /* MR10 was int */

+			char *pdecl;		/* point to declaration of parameters on rule

+								   (if present) */

+			char *parm;			/* point to parameter of block invocation

+								   (if present) */

+			char predparm;		/* indicates that the 'parm' is a predicate

+								 * to be used in the while loop generated

+								 * for blocks */ /* MR10 was int */

+			char *ret;			/* point to return type of rule (if present) */

+			char *erraction;	/* point to error action (if present) */

+			int blockid;		/* this is a unique ID */

+			char *exception_label;	/* goto label for this alt */

+			set *fset;			/* used for code generation */

+			Tree *ftree;		/* used for code generation */

+			Predicate *predicate;/* predicate that can be used to disambiguate */

+			char guess;			/* true if (...)? block */

+            char alpha_beta_guess_end;      /* MR14 1 => end block of guess sub block  */

+            Node *guess_analysis_point;     /* MR14 */

+			char approx;		/* limit block to use linear approx lookahead? */

+			set tokrefs;		/* if ith element of alt is tokref then i is member */

+			set rulerefs;		/* if ith element of alt is rule ref then i is member */

+			struct _ListNode *exceptions; /* list of exceptions groups for rule */

+			struct _ListNode *el_labels;  /* list of element labels for rule */

+            ExceptionGroup   *outerEG;                               /* MR7 */

+            int              curAltNum;                              /* MR7 */

+            char* pFirstSetSymbol;   /* #pragma FirstSetSymbol(Foo)     MR21 */

+#ifdef __cplusplus

+            Junction         *pendingLink;                           /* MR7 */

+#else

+            struct _junct    *pendingLink;                           /* MR7 */

+#endif

+            char             overlap_warning;                        /* MR10 */

+#ifdef __cplusplus

+		};

+#else

+		} Junction;

+#endif

+

+typedef struct { Node *left, *right;} Graph;

+

diff --git a/Source/Pccts/antlr/tokens.h b/Source/Pccts/antlr/tokens.h
new file mode 100644
index 0000000..91a53a8
--- /dev/null
+++ b/Source/Pccts/antlr/tokens.h
@@ -0,0 +1,246 @@
+#ifndef tokens_h

+#define tokens_h

+/* tokens.h -- List of labelled tokens and stuff

+ *

+ * Generated from: antlr.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * ANTLR Version 1.33MR33

+ */

+#define zzEOF_TOKEN 1

+#define Eof 1

+#define QuotedTerm 2

+#define Action 34

+#define Pred 35

+#define PassAction 36

+#define WildCard 87

+#define LABEL 89

+#define Pragma 92

+#define FirstSetSymbol 93

+#define NonTerminal 100

+#define TokenTerm 101

+#define ID 148

+#define INT 150

+

+#ifdef __USE_PROTOS

+void grammar(void);

+#else

+extern void grammar();

+#endif

+

+#ifdef __USE_PROTOS

+void class_def(void);

+#else

+extern void class_def();

+#endif

+

+#ifdef __USE_PROTOS

+void rule(void);

+#else

+extern void rule();

+#endif

+

+#ifdef __USE_PROTOS

+void laction(void);

+#else

+extern void laction();

+#endif

+

+#ifdef __USE_PROTOS

+void lmember(void);

+#else

+extern void lmember();

+#endif

+

+#ifdef __USE_PROTOS

+void lprefix(void);

+#else

+extern void lprefix();

+#endif

+

+#ifdef __USE_PROTOS

+void aPred(void);

+#else

+extern void aPred();

+#endif

+

+#ifdef __USE_PROTOS

+extern Predicate * predOrExpr(void);

+#else

+extern Predicate * predOrExpr();

+#endif

+

+#ifdef __USE_PROTOS

+extern Predicate * predAndExpr(void);

+#else

+extern Predicate * predAndExpr();

+#endif

+

+#ifdef __USE_PROTOS

+extern Predicate * predPrimary(void);

+#else

+extern Predicate * predPrimary();

+#endif

+

+#ifdef __USE_PROTOS

+void aLexclass(void);

+#else

+extern void aLexclass();

+#endif

+

+#ifdef __USE_PROTOS

+void error(void);

+#else

+extern void error();

+#endif

+

+#ifdef __USE_PROTOS

+void tclass(void);

+#else

+extern void tclass();

+#endif

+

+#ifdef __USE_PROTOS

+void token(void);

+#else

+extern void token();

+#endif

+

+#ifdef __USE_PROTOS

+void block(set * toksrefd,set * rulesrefd);

+#else

+extern void block();

+#endif

+

+#ifdef __USE_PROTOS

+void alt(set * toksrefd,set * rulesrefd);

+#else

+extern void alt();

+#endif

+

+#ifdef __USE_PROTOS

+extern LabelEntry * element_label(void);

+#else

+extern LabelEntry * element_label();

+#endif

+

+#ifdef __USE_PROTOS

+extern Node * element(int old_not,int first_on_line,int use_def_MT_handler);

+#else

+extern Node * element();

+#endif

+

+#ifdef __USE_PROTOS

+void default_exception_handler(void);

+#else

+extern void default_exception_handler();

+#endif

+

+#ifdef __USE_PROTOS

+extern ExceptionGroup * exception_group(void);

+#else

+extern ExceptionGroup * exception_group();

+#endif

+

+#ifdef __USE_PROTOS

+extern ExceptionHandler * exception_handler(void);

+#else

+extern ExceptionHandler * exception_handler();

+#endif

+

+#ifdef __USE_PROTOS

+void enum_file(char * fname);

+#else

+extern void enum_file();

+#endif

+

+#ifdef __USE_PROTOS

+void defines(char * fname);

+#else

+extern void defines();

+#endif

+

+#ifdef __USE_PROTOS

+void enum_def(char * fname);

+#else

+extern void enum_def();

+#endif

+

+#endif

+extern SetWordType zzerr1[];

+extern SetWordType zzerr2[];

+extern SetWordType zzerr3[];

+extern SetWordType zzerr4[];

+extern SetWordType setwd1[];

+extern SetWordType zzerr5[];

+extern SetWordType zzerr6[];

+extern SetWordType zzerr7[];

+extern SetWordType zzerr8[];

+extern SetWordType zzerr9[];

+extern SetWordType setwd2[];

+extern SetWordType zzerr10[];

+extern SetWordType zzerr11[];

+extern SetWordType zzerr12[];

+extern SetWordType zzerr13[];

+extern SetWordType setwd3[];

+extern SetWordType zzerr14[];

+extern SetWordType zzerr15[];

+extern SetWordType zzerr16[];

+extern SetWordType zzerr17[];

+extern SetWordType zzerr18[];

+extern SetWordType zzerr19[];

+extern SetWordType zzerr20[];

+extern SetWordType zzerr21[];

+extern SetWordType setwd4[];

+extern SetWordType zzerr22[];

+extern SetWordType zzerr23[];

+extern SetWordType zzerr24[];

+extern SetWordType zzerr25[];

+extern SetWordType zzerr26[];

+extern SetWordType setwd5[];

+extern SetWordType zzerr27[];

+extern SetWordType zzerr28[];

+extern SetWordType zzerr29[];

+extern SetWordType zzerr30[];

+extern SetWordType zzerr31[];

+extern SetWordType zzerr32[];

+extern SetWordType zzerr33[];

+extern SetWordType setwd6[];

+extern SetWordType zzerr34[];

+extern SetWordType zzerr35[];

+extern SetWordType zzerr36[];

+extern SetWordType zzerr37[];

+extern SetWordType zzerr38[];

+extern SetWordType zzerr39[];

+extern SetWordType zzerr40[];

+extern SetWordType zzerr41[];

+extern SetWordType zzerr42[];

+extern SetWordType setwd7[];

+extern SetWordType zzerr43[];

+extern SetWordType zzerr44[];

+extern SetWordType zzerr45[];

+extern SetWordType zzerr46[];

+extern SetWordType zzerr47[];

+extern SetWordType zzerr48[];

+extern SetWordType zzerr49[];

+extern SetWordType zzerr50[];

+extern SetWordType zzerr51[];

+extern SetWordType zzerr52[];

+extern SetWordType zzerr53[];

+extern SetWordType setwd8[];

+extern SetWordType zzerr54[];

+extern SetWordType zzerr55[];

+extern SetWordType zzerr56[];

+extern SetWordType zzerr57[];

+extern SetWordType setwd9[];

+extern SetWordType zzerr58[];

+extern SetWordType zzerr59[];

+extern SetWordType zzerr60[];

+extern SetWordType zzerr61[];

+extern SetWordType zzerr62[];

+extern SetWordType zzerr63[];

+extern SetWordType zzerr64[];

+extern SetWordType zzerr65[];

+extern SetWordType setwd10[];

+extern SetWordType setwd11[];

diff --git a/Source/Pccts/build.xml b/Source/Pccts/build.xml
new file mode 100644
index 0000000..58a82f4
--- /dev/null
+++ b/Source/Pccts/build.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK Pccts Tool

+  Copyright (c) 2006, Intel Corporation

+  <property name="ToolName" value="Pccts"/>

+-->

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <target name="init">

+    <echo message="Building the EDK Pccts Tools"/>

+  </target>

+

+  <target name="GenTool" depends="init, Pccts">

+    <echo message="The EDK Pccts Tools build has completed!"/>

+  </target>

+

+  <target name="Pccts" depends="init">

+    <subant target="" inheritall="true">

+       <fileset dir="${PACKAGE_DIR}/Pccts/antlr" includes="build.xml"/>

+    </subant>

+    <subant target="" inheritall="true">

+      <fileset dir="${PACKAGE_DIR}/Pccts/dlg" includes="build.xml"/>

+    </subant>

+  </target>

+

+  <target name="clean">

+    <ant dir="${PACKAGE_DIR}/Pccts/antlr" target="clean" inheritAll="true"/>

+    <ant dir="${PACKAGE_DIR}/Pccts/dlg" target="clean" inheritAll="true"/>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executables from the package: Pccts"/>  

+    <ant dir="${PACKAGE_DIR}/Pccts/antlr" target="cleanall" inheritAll="true"/>

+    <ant dir="${PACKAGE_DIR}/Pccts/dlg" target="cleanall" inheritAll="true"/>

+  </target>

+

+</project>

diff --git a/Source/Pccts/dlg/DlgMS.mak b/Source/Pccts/dlg/DlgMS.mak
new file mode 100644
index 0000000..086af95
--- /dev/null
+++ b/Source/Pccts/dlg/DlgMS.mak
@@ -0,0 +1,121 @@
+# PCCTS directory

+

+# You will need to set the LIB variable similar to this.

+# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib"

+

+# PCCTS_HOME=<your PCCTS_HOME>

+PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts

+DLG_SRC=$(PCCTS_HOME)\dlg

+PCCTS_H=$(PCCTS_HOME)\h

+

+

+# Support directories

+SET=$(PCCTS_HOME)\support\set

+

+

+# Compiler stuff

+CC = cl

+CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \

+        -D "ZZLEXBUFSIZE=65536"  /D "LONGFILENAMES" /W3 /Zi

+

+DLG_OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \

+           output.obj relabel.obj automata.obj

+

+SUPPORT_OBJS = set.obj

+

+# Dependencies

+

+dlg.exe: $(DLG_OBJS) $(SUPPORT_OBJS)

+    $(CC) $(CFLAGS) -o dlg.exe $(DLG_OBJS) $(SUPPORT_OBJS)

+    del *.obj

+    del *.ilk

+    del *.pdb

+		move dlg.exe $(WORKSPACE)\Tools\bin\.

+

+dlg_p.obj: $(DLG_SRC)\dlg_p.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+                	$(DLG_SRC)\mode.h \

+                	$(DLG_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_p.c

+

+dlg_a.obj: $(DLG_SRC)\dlg_a.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgauto.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+                	$(DLG_SRC)\mode.h \

+                	$(DLG_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_a.c

+

+main.obj: $(DLG_SRC)\main.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+                	$(DLG_SRC)\mode.h \

+                	$(DLG_SRC)\stdpccts.h \

+                	$(DLG_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\main.c

+

+err.obj: $(DLG_SRC)\err.c \

+					$(PCCTS_H)\antlr.h \

+					$(PCCTS_H)\config.h \

+					$(PCCTS_H)\dlgdef.h \

+					$(PCCTS_H)\err.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+                	$(DLG_SRC)\tokens.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\err.c

+

+support.obj: $(DLG_SRC)\support.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\support.c

+

+output.obj: $(DLG_SRC)\output.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\output.c

+

+relabel.obj: $(DLG_SRC)\relabel.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\relabel.c

+

+automata.obj: $(DLG_SRC)\automata.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+                	$(DLG_SRC)\dlg.h \

+

+    $(CC) -c $(CFLAGS) $(DLG_SRC)\automata.c

+

+

+set.obj: $(SET)\set.c \

+					$(PCCTS_H)\config.h \

+					$(SET)\set.h \

+

+    $(CC) -c $(CFLAGS) $(SET)\set.c

+

+clean:	

+    del *.obj

+

+distclean:

+    del *.obj

+    del $(WORKSPACE)\Tools\bin\dlg.exe

diff --git a/Source/Pccts/dlg/DlgPPC.mak b/Source/Pccts/dlg/DlgPPC.mak
new file mode 100644
index 0000000..55b643a
--- /dev/null
+++ b/Source/Pccts/dlg/DlgPPC.mak
@@ -0,0 +1,84 @@
+#   File:       dlgPPC.make

+#   Target:     dlgPPC

+#   Sources:    automata.c

+#               dlg_a.c

+#               dlg_p.c

+#               err.c

+#               main.c

+#               output.c

+#               relabel.c

+#               support.c

+#               ::support:set:set.c

+#   Created:    Sunday, May 17, 1998 11:34:20 PM

+#	Author:		Kenji Tanaka

+

+

+MAKEFILE     = dlgPPC.make

+¥MondoBuild¥ = {MAKEFILE}  # Make blank to avoid rebuilds when makefile is modified

+Includes     = ¶

+		-i "::h:" ¶

+		-i "::support:set:"

+Sym¥PPC      = 

+ObjDir¥PPC   = ":Obj:"

+

+PPCCOptions  = {Includes} {Sym¥PPC}  -w off -d MPW -d __STDC__=1 -d USER_ZZSYN

+

+Objects¥PPC  = ¶

+		"{ObjDir¥PPC}automata.c.x" ¶

+		"{ObjDir¥PPC}dlg_a.c.x" ¶

+		"{ObjDir¥PPC}dlg_p.c.x" ¶

+		"{ObjDir¥PPC}err.c.x" ¶

+		"{ObjDir¥PPC}main.c.x" ¶

+		"{ObjDir¥PPC}output.c.x" ¶

+		"{ObjDir¥PPC}relabel.c.x" ¶

+		"{ObjDir¥PPC}support.c.x" ¶

+		"{ObjDir¥PPC}set.c.x"

+

+

+dlgPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC}

+	PPCLink ¶

+		-o {Targ} {Sym¥PPC} ¶

+		{Objects¥PPC} ¶

+		-t 'MPST' ¶

+		-c 'MPS ' ¶

+		"{SharedLibraries}InterfaceLib" ¶

+		"{SharedLibraries}StdCLib" ¶

+		"{SharedLibraries}MathLib" ¶

+		"{PPCLibraries}StdCRuntime.o" ¶

+		"{PPCLibraries}PPCCRuntime.o" ¶

+		"{PPCLibraries}PPCToolLibs.o"

+

+

+"{ObjDir¥PPC}automata.c.x" Ä {¥MondoBuild¥} automata.c

+	{PPCC} automata.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}dlg_a.c.x" Ä {¥MondoBuild¥} dlg_a.c

+	{PPCC} dlg_a.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}dlg_p.c.x" Ä {¥MondoBuild¥} dlg_p.c

+	{PPCC} dlg_p.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c

+	{PPCC} err.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c

+	{PPCC} main.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}output.c.x" Ä {¥MondoBuild¥} output.c

+	{PPCC} output.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}relabel.c.x" Ä {¥MondoBuild¥} relabel.c

+	{PPCC} relabel.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}support.c.x" Ä {¥MondoBuild¥} support.c

+	{PPCC} support.c -o {Targ} {PPCCOptions}

+

+"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c"

+	{PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions}

+

+

+dlgPPC ÄÄ dlg.r

+	Rez dlg.r -o dlgPPC -a

+

+Install  Ä dlgPPC

+	Duplicate -y dlgPPC "{MPW}"Tools:dlg

diff --git a/Source/Pccts/dlg/automata.c b/Source/Pccts/dlg/automata.c
new file mode 100644
index 0000000..d6d5d78
--- /dev/null
+++ b/Source/Pccts/dlg/automata.c
@@ -0,0 +1,353 @@
+/* Automata conversion functions for DLG

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#include "dlg.h"

+#ifdef MEMCHK

+#include "trax.h"

+#else

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif /* __STDC__ */

+#endif

+

+#define hash_list struct _hash_list_

+hash_list{

+	hash_list *next;	/* next thing in list */

+	dfa_node *node;

+ };

+

+int	dfa_allocated = 0;	/* keeps track of number of dfa nodes */

+dfa_node	**dfa_array;	/* root of binary tree that stores dfa array */

+dfa_node	*dfa_model_node;

+hash_list 	*dfa_hash[HASH_SIZE];	/* used to quickly find */

+					/* desired dfa node */

+

+void 

+#ifdef __USE_PROTOS

+make_dfa_model_node(int width)

+#else

+make_dfa_model_node(width)

+int width;

+#endif

+{

+	register int i;

+	dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node)

+			 + sizeof(int)*width);

+	dfa_model_node->node_no = -1; /* impossible value for real dfa node */

+	dfa_model_node->dfa_set = 0;

+	dfa_model_node->alternatives = FALSE;

+	dfa_model_node->done = FALSE;

+	dfa_model_node->nfa_states = empty;

+	for(i = 0; i<width; i++){

+		dfa_model_node->trans[i] = NIL_INDEX;

+	}

+}

+

+

+/* adds a new nfa to the binary tree and returns a pointer to it */

+dfa_node *

+#ifdef __USE_PROTOS

+new_dfa_node(set nfa_states)

+#else

+new_dfa_node(nfa_states)

+set nfa_states;

+#endif

+{

+	register int j;

+	register dfa_node *t;

+	static int dfa_size=0;	/* elements dfa_array[] can hold */

+

+	++dfa_allocated;

+	if (dfa_size<=dfa_allocated){

+		/* need to redo array */

+		if (!dfa_array){

+			/* need some to do inital allocation */

+			dfa_size=dfa_allocated+DFA_MIN;

+			dfa_array=(dfa_node **) malloc(sizeof(dfa_node*)*

+				dfa_size);

+		}else{

+			/* need more space */

+			dfa_size=2*(dfa_allocated+1);

+			dfa_array=(dfa_node **) realloc(dfa_array,

+				sizeof(dfa_node*)*dfa_size);

+		}

+	}

+	/* fill out entry in array */

+	t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no);

+	*t = *dfa_model_node;

+	for (j=0; j<class_no; ++j)

+		t->trans[j] = NIL_INDEX;

+	t->node_no = dfa_allocated;

+	t->nfa_states = set_dup(nfa_states);

+	dfa_array[dfa_allocated] = t;

+	return t;

+}

+

+

+/* past a pointer to the start start of the nfa graph

+ * nfa_to_dfa convers this graph to dfa.  The function returns

+ * a pointer to the first dfa state.

+ * NOTE:  The function that prints out the table will have to figure out how

+ * to find the other dfa states given the first dfa_state and the number of dfa

+ * nodes allocated

+ */

+dfa_node **

+#ifdef __USE_PROTOS

+nfa_to_dfa(nfa_node *start)

+#else

+nfa_to_dfa(start)

+nfa_node *start;

+#endif

+{

+	register dfa_node *d_state, *trans_d_state;

+	register int a;

+	set t;

+	int last_done;

+	unsigned *nfa_list;

+	unsigned *reach_list;

+

+	reach_list = (unsigned *) malloc((2+nfa_allocated)*sizeof(unsigned));

+	if (!start) return NULL;

+	t = set_of(NFA_NO(start));

+	_set_pdq(t,reach_list);

+	closure(&t,reach_list);

+	/* Make t a dfa state */

+	d_state = dfastate(t);

+	last_done = DFA_NO(d_state);

+	

+	do {

+		/* Mark dfa state x as "done" */

+		d_state->done = TRUE;

+		nfa_list = set_pdq(d_state->nfa_states);

+		for (a = 0; a<class_no; ++a) {

+			/* Add NFA states reached by a from d_state */

+			reach(nfa_list,a,reach_list);

+			/* Were any states found? */

+			if ((*reach_list)!=nil) {

+				/* was t=empty; */

+				set_free(t);

+				/* yes, compute closure */

+				closure(&t,reach_list);

+				/* Make DFA state of it ... */

+				trans_d_state = dfastate(t);

+				/* And make transition x->t, labeled with a */

+				d_state->trans[a] = DFA_NO(trans_d_state);

+				d_state->alternatives = TRUE;

+			}

+		}

+		free(nfa_list);

+		++last_done; /* move forward in queue */

+		/* And so forth until nothing isn't done */

+		d_state = DFA(last_done);

+	} while (last_done<=dfa_allocated);

+

+	free(reach_list);

+	set_free(t);

+

+	/* returns pointer to the array that holds the automaton */

+	return dfa_array;

+}

+

+void 

+#ifdef __USE_PROTOS

+clear_hash(void)

+#else

+clear_hash()

+#endif

+{

+	register int i;

+

+	for(i=0; i<HASH_SIZE; ++i)

+		dfa_hash[i] = 0;

+}

+

+#if HASH_STAT

+void

+#ifdef __USE_PROTOS

+fprint_hash_stats(FILE *f)

+#else

+fprint_hash_stats(f)

+FILE *f;

+#endif

+{

+	register hash_list *p;

+	register int i,j;

+	register total;

+

+	total=0;

+	for(i=0; i<HASH_SIZE; ++i){

+		j=0;

+		p = dfa_hash[i];

+		while(p){

+			++j;

+			p = p->next;

+		}

+		total+=j;

+		fprintf(f,"bin[%d] has %d\n",i,j);

+	}

+	fprintf(f,"total = %d\n",total);

+}

+#endif

+

+/* Returns a pointer to a dfa node that has the same nfa nodes in it.

+ * This may or maynot be a newly created node.

+ */

+dfa_node *

+#ifdef __USE_PROTOS

+dfastate(set nfa_states)

+#else

+dfastate(nfa_states)

+set nfa_states;

+#endif

+{

+	register hash_list *p;

+	int bin;

+

+	/* hash using set and see if it exists */

+	bin = set_hash(nfa_states,HASH_SIZE);

+	p = dfa_hash[bin];

+	while(p && !set_equ(nfa_states,(p->node)->nfa_states)){

+		p = p->next;

+	}

+	if(!p){

+		/* next state to add to hash table */

+		p = (hash_list*)malloc(sizeof(hash_list));

+		p->node = new_dfa_node(nfa_states);

+		p->next = dfa_hash[bin];

+		dfa_hash[bin] = p;

+	}

+	return (p->node);

+}

+

+

+/* this reach assumes the closure has been done already on set */

+int 

+#ifdef __USE_PROTOS

+reach(unsigned *nfa_list, register int a, unsigned *reach_list)

+#else

+reach(nfa_list, a, reach_list)

+unsigned *nfa_list;

+register int a;

+unsigned *reach_list;

+#endif

+{

+	register unsigned *e;

+	register nfa_node *node;

+	int t=0;

+

+	e = nfa_list;

+	if (e){

+		while (*e != nil){

+			node = NFA(*e);

+			if (set_el(a,node->label)){

+				t=1;

+				*reach_list=NFA_NO(node->trans[0]);

+				++reach_list;

+			}

+			++e;

+		}

+	}

+	*reach_list=nil;

+	return t;

+}

+

+/* finds all the nodes that can be reached by epsilon transitions

+   from the set of a nodes and returns puts them back in set b */

+set 

+#ifdef __USE_PROTOS

+closure(set *b, unsigned *reach_list)

+#else

+closure(b, reach_list)

+set *b;

+unsigned *reach_list;

+#endif

+{

+	register nfa_node *node,*n;	/* current node being examined */

+	register unsigned *e;

+

+	++operation_no;

+#if 0

+	t = e = set_pdq(*b);

+#else

+	e=reach_list;

+#endif

+	while (*e != nil){

+		node = NFA(*e);

+		set_orel(NFA_NO(node),b);

+		/* mark it done */

+		node->nfa_set = operation_no;

+		if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&

+		  (n->nfa_set != operation_no)){

+			/* put in b */

+			set_orel(NFA_NO(n),b);

+			close1(n,operation_no,b);

+		}

+		if ((n=node->trans[1]) != NIL_INDEX &&

+		  (n->nfa_set != operation_no)){

+			/* put in b */

+			set_orel(NFA_NO(node->trans[1]),b);

+			close1(n,operation_no,b);

+		}

+		++e;

+	}

+#if 0

+	free(t);

+#endif

+	return *b;

+}

+

+#ifdef __USE_PROTOS

+void close1(nfa_node *node, int o, set *b)

+#else

+void close1(node,o,b)

+nfa_node *node;

+int o;	/* marker to avoid cycles */

+set *b;

+#endif

+{

+	register nfa_node *n;	/* current node being examined */

+

+	/* mark it done */

+	node->nfa_set = o;

+	if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&

+	  (n->nfa_set != o)){

+		/* put in b */

+		set_orel(NFA_NO(n),b);

+		close1(n,o,b);

+	}

+	if ((n=node->trans[1]) != NIL_INDEX &&

+	  (n->nfa_set != o)){

+		/* put in b */

+		set_orel(NFA_NO(node->trans[1]),b);

+		close1(n,o,b);

+	}

+}

diff --git a/Source/Pccts/dlg/build.xml b/Source/Pccts/dlg/build.xml
new file mode 100644
index 0000000..da5dbd0
--- /dev/null
+++ b/Source/Pccts/dlg/build.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK Pccts Tool: dlg

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="dlg"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="PACKAGE_DIR" value="${WORKSPACE}/Tools"/>

+

+  <target name="init">

+		<condition property="CheckDepends">

+		  <uptodate targetfile="${WORKSPACE}/Tools/bin/dlg.exe">

+			  <srcfiles dir="." includes="*.c *.h *.g"/>

+			</uptodate>

+		</condition>

+		<if>

+		  <equals arg1="${CheckDepends}" arg2="true"/>

+			<then>

+				<echo message="Executable, dlg.exe, is up to date."/>

+			</then>

+      <else>

+        <echo message="Building the EDK Pccts Tool: ${ToolName}"/>

+      </else>

+		</if>

+  </target>

+

+  <target name="GenTool" depends="init" unless="CheckDepends">

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="TRUE">

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="-f DlgMS.mak"/>

+    		</exec>

+		  </then>

+		<elseif>

+      <istrue value="${cygwin}"/>

+      <then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">

+	    	  <arg line="-f makefile.cygwin"/>

+    		</exec>

+      </then>

+    </elseif>

+		<elseif>

+      <equals arg1="${ToolChain}" arg2="gcc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">

+	      	<arg line="-s"/>

+	    	  <arg line="-f makefile BIN_DIR=${BIN_DIR}"/>

+    		</exec>

+		  </then>

+		</elseif>

+		</if>

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+	</target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="TRUE">

+	    	  <arg line="/C"/>

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="-f DlgMS.mak clean"/>

+    		</exec>

+		  </then>

+    <elseif>

+      <istrue value="${cygwin}"/>

+      <then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">

+	    	  <arg line="-f makefile.cygwin clean"/>

+    		</exec>

+      </then>

+		</elseif>

+		<elseif>

+      <equals arg1="${ToolChain}" arg2="gcc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">

+	      	<arg line="-s"/>

+	    	  <arg line="-f makefile clean"/>

+    		</exec>

+		  </then>

+		</elseif>

+		</if>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <if>

+      <equals arg1="${ToolChain}" arg2="msvc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="FALSE">

+	    	  <arg line="/C"/>

+	    	  <arg line="/NOLOGO"/>

+	    	  <arg line="-f DlgMS.mak clean"/>

+    		</exec>

+		  </then>

+		<elseif>

+      <equals arg1="${ToolChain}" arg2="gcc"/>

+			<then>

+    	  <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="FALSE">

+	      	<arg line="-s"/>

+	    	  <arg line="-f makefile clean"/>

+    		</exec>

+		  </then>

+		</elseif>

+		</if>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/Pccts/dlg/dlg.1 b/Source/Pccts/dlg/dlg.1
new file mode 100644
index 0000000..f68e3ae
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.1
@@ -0,0 +1,79 @@
+.TH dlg 1 "April 1994" "DLG" "PCCTS Manual Pages"

+.SH NAME

+dlg \- DFA Lexical Analyzer Generator

+.SH SYNTAX

+.LP

+\fBdlg\fR [\fIoptions\fR] \fIlexical_spec\fR [\fIoutput_file\fR]

+.SH DESCRIPTION

+.B dlg

+is a tool that produces fast deterministic finite automata for recognizing

+regular expressions in input.

+.SH OPTIONS

+.IP "\fB-CC\fR"

+Generate C++ output.  The \fIoutput_file\fP is not specified in this

+case.

+.IP "\fB-C\fR[\fP level\fR]

+Where \fPlevel\fR is the compression level used.  0 indications no

+compression, 1 removes all unused characters from the transition from table,

+and 2 maps equivalent characters into the same character classes.  It is

+suggested that level -C2 is used, since it will significantly reduce the size

+of the dfa produced for lexical analyzer.

+.IP "\fB-m\fP

+Produces the header file for the lexical mode with a name other than

+the default name of "mode.h".

+.IP \fB-i\fP

+An interactive, or as interactive as possible, parser is produced.  A character

+is only obtained when required to decide which state to go to.  Some care

+must be taken to obtain accept states that do not require look ahead at the

+next character to determine if that is the stop state.  Any regular expression

+with a Kleene closure at the end is guaranteed to require another character

+of look ahead.

+.IP "\fB-cl\fP class

+Specify a class name for DLG to generate.  The default is DLGLexer.

+'class' will be a subclass of DLGLexerBase; only used for -CC.

+.IP \fB-ci\fP

+The automaton will treat upper and lower case characters identically.

+This is accomplished in the automaton; the characters in the lexical

+buffer are unmodified.

+.IP \fB-cs\fP

+Upper and lower case characters are treated as distinct.  This is the

+default.

+.IP "\fB-o\fP dir

+Directory where output files should go (default=".").  This is very

+nice for keeping the source directory clear of ANTLR and DLG spawn.

+.IP \fB-Wambiguity\fP

+Warns if more than one regular expression could match the same character

+sequence.  The warnings give the numbers of the expressions in the dlg

+lexical specification file.  The numbering of the expressions starts at one.

+Multiple warnings may be print for the same expressions.

+.IP \-

+Used in place of file names to get input from standard in or send output

+to standard out.

+.SH "SPECIAL CONSIDERATIONS"

+.PP

+\fIDlg\fP works...  we think.  There is no implicit guarantee of

+anything.  We reserve no \fBlegal\fP rights to the software known as

+the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the

+public domain.  An individual or company may do whatever they wish

+with source code distributed with PCCTS or the code generated by

+PCCTS, including the incorporation of PCCTS, or its output, into

+commercial software.  We encourage users to develop software with

+PCCTS.  However, we do ask that credit is given to us for developing

+PCCTS.  By "credit", we mean that if you incorporate our source code

+into one of your programs (commercial product, research project, or

+otherwise) that you acknowledge this fact somewhere in the

+documentation, research report, etc...  If you like PCCTS and have

+developed a nice tool with the output, please mention that you

+developed it using PCCTS.  As long as these guidelines are followed, we

+expect to continue enhancing this system and expect to make other

+tools available as they are completed.

+.SH FILES

+.B mode.h

+,

+.B dlgauto.h

+,

+.B dlgdef.h

+.SH SEE ALSO

+.BR antlr (1),

+.BR pccts (1)

+.SH BUGS

diff --git a/Source/Pccts/dlg/dlg.h b/Source/Pccts/dlg/dlg.h
new file mode 100644
index 0000000..9f387c0
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.h
@@ -0,0 +1,250 @@
+/* dlg header file

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+/* MR1 Move pcctscfg.h to top of file 					*/

+

+#include "pcctscfg.h"						

+

+/* turn off warnings for unreferenced labels */

+

+#ifdef _MSC_VER

+#pragma warning(disable:4102)

+#endif

+

+#include "set.h"

+

+#define TRUE	1

+#define FALSE	0

+

+/***** output related stuff *******************/

+#define IN	input_stream

+#define OUT	output_stream

+

+#define MAX_MODES	50	/* number of %%names allowed */

+#define MAX_ON_LINE	10

+

+#define NFA_MIN		64	/* minimum nfa_array size */

+#define DFA_MIN		64	/* minimum dfa_array size */

+

+#define DEFAULT_CLASSNAME "DLGLexer"

+

+/* these macros allow the size of the character set to be easily changed */

+/* NOTE: do NOT change MIN_CHAR since EOF is the lowest char, -1 */

+#define MIN_CHAR (-1)	/* lowest possible character possible on input */

+#define MAX_CHAR 255	/* highest possible character possible on input */

+#define CHAR_RANGE (1+(MAX_CHAR) - (MIN_CHAR))

+

+/* indicates that the not an "array" reference */

+#define NIL_INDEX 0

+

+/* size of hash table used to find dfa_states quickly */

+#define HASH_SIZE 211

+

+#define nfa_node struct _nfa_node

+nfa_node {

+	int		node_no;

+	int		nfa_set;

+	int		accept;	/* what case to use */

+	nfa_node	*trans[2];

+	set		label;	/* one arc always labelled with epsilon */

+};

+

+#define dfa_node struct _dfa_node

+dfa_node {

+	int		node_no;

+	int		dfa_set;

+	int		alternatives;	/* used for interactive mode */

+					/* are more characters needed */

+	int		done;

+	set		nfa_states;

+	int		trans[1];/* size of transition table depends on

+				  * number of classes required for automata.

+				  */

+

+

+};

+

+/******** macros for accessing the NFA and DFA nodes ****/

+#define NFA(x)	(nfa_array[x])

+#define DFA(x)	(dfa_array[x])

+#define DFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX)

+#define NFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX)

+

+/******** wrapper for memory checking ***/

+/*#define malloc(x)	dlg_malloc((x),__FILE__,__LINE__)*/

+

+/*#define calloc(x,y)	dlg_calloc((x),(y),__FILE__,__LINE__)*/

+

+/******** antlr attributes *************/

+typedef struct {

+	unsigned char letter;

+	nfa_node *l,*r;

+	set label;

+	} Attrib;

+

+#define zzcr_attr(attr, token, text) {					\

+	(attr)->letter = text[0]; (attr)->l = NULL;			\

+	(attr)->r = NULL; (attr)->label = empty;			\

+}

+#define zzd_attr(a)	set_free((a)->label);

+

+/******************** Variable ******************************/

+extern char	program[];	/* tells what program this is */

+extern char	version[];	/* tells what version this is */

+extern char	*file_str[];	/* file names being used */

+extern int	err_found;	/* flag to indicate error occured */

+extern int	action_no;	/* last action function printed */

+extern int	func_action;	/* should actions be turned into functions?*/

+extern set	used_chars;	/* used to label trans. arcs */

+extern set	used_classes;	/* classes or chars used to label trans. arcs */

+extern int	class_no;	/* number of classes used */

+extern set	class_sets[];	/* shows char. in each class */

+extern set	normal_chars;	/* mask off unused portion of set */

+extern int	comp_level;	/* what compression level to use */

+extern int	interactive;	/* interactive scanner (avoid lookahead)*/

+extern int	mode_counter;	/* keeps track of the number of %%name */

+extern int	dfa_basep[];	/* start of each group of dfa */

+extern int	dfa_class_nop[];/* number of transistion arcs in */

+				/* each dfa in each mode */

+extern int	nfa_allocated;

+extern int	dfa_allocated;

+extern nfa_node	**nfa_array;	/* start of nfa "array" */

+extern dfa_node	**dfa_array;	/* start of dfa "array" */

+extern int	operation_no;	/* unique number for each operation */

+extern FILE	*input_stream;	/* where description read from */

+extern FILE	*output_stream; /* where to put the output */

+extern FILE	*mode_stream;	/* where to put the mode output */

+extern FILE	*class_stream;

+extern char	*mode_file;	/* name of file for mode output */

+extern int	gen_ansi;	/* produce ansi compatible code */

+extern int	case_insensitive;/* ignore case of input spec. */

+extern int	warn_ambig;	/* show if regular expressions ambiguous */

+extern int	gen_cpp;

+extern char *cl_file_str;

+extern int	firstLexMember;	/* MR1 */

+extern char *OutputDirectory;

+extern char	*class_name;

+

+/******************** Functions ******************************/

+#ifdef __USE_PROTOS

+extern char 	*dlg_malloc(int, char *, int); /* wrapper malloc */

+extern char 	*dlg_calloc(int, int, char *, int); /* wrapper calloc */

+extern int	reach(unsigned *, register int, unsigned *);

+extern set	closure(set *, unsigned *);

+extern dfa_node *new_dfa_node(set);

+extern nfa_node *new_nfa_node(void);

+extern dfa_node *dfastate(set);

+extern dfa_node **nfa_to_dfa(nfa_node *);

+extern void	internal_error(char *, char *, int);    /* MR9 23-Sep-97 */

+extern FILE	*read_stream(char *);	/* opens file for reading */

+extern FILE	*write_stream(char *);	/* opens file for writing */

+extern void	make_nfa_model_node(void);

+extern void	make_dfa_model_node(int);

+extern char *ClassName(char *);

+extern char *OutMetaName(char *);

+extern void error(char*, int);

+extern void warning(char*, int);

+extern void p_head(void);

+extern void p_class_hdr(void);

+extern void p_includes(void);

+extern void p_tables(void);

+extern void p_tail(void);					/* MR1 */

+extern void p_class_def1(void);				/* MR1 */

+extern void new_automaton_mode(void);			/* MR1 */

+extern int  relabel(nfa_node *,int);			/* MR1 */

+extern void p_shift_table(int);				/* MR1 */

+extern void p_bshift_table(void);				/* MR1 */

+extern void p_class_table(void);				/* MR1 */

+extern void p_mode_def(char *,int);			/* MR1 */

+extern void init(void);					/* MR1 */

+extern void p_class_def2(void);				/* MR1 */

+extern void clear_hash(void);				/* MR1 */

+extern void p_alternative_table(void);			/* MR1 */

+extern void p_node_table(void);				/* MR1 */

+extern void p_dfa_table(void);				/* MR1 */

+extern void p_accept_table(void);				/* MR1 */

+extern void p_action_table(void);				/* MR1 */

+extern void p_base_table(void);				/* MR1 */

+extern void p_single_node(int,int);			/* MR1 */

+extern char * minsize(int);				/* MR1 */

+extern void close1(nfa_node *,int,set *);		/* MR1 */

+extern void partition(nfa_node *,int);			/* MR1 */

+extern void intersect_nfa_labels(nfa_node *,set *);	/* MR1 */

+extern void r_intersect(nfa_node *,set *);		/* MR1 */

+extern void label_node(nfa_node *);			/* MR1 */

+extern void label_with_classes(nfa_node *);		/* MR1 */

+

+#else

+extern char *dlg_malloc();	/* wrapper malloc */

+extern char *dlg_calloc();	/* wrapper calloc */

+extern int	reach();

+extern set	closure();

+extern dfa_node *new_dfa_node();

+extern nfa_node *new_nfa_node();

+extern dfa_node *dfastate();

+extern dfa_node **nfa_to_dfa();

+extern void	internal_error();   /* MR9 23-Sep-97 */

+extern FILE	*read_stream();		/* opens file for reading */

+extern FILE	*write_stream();	/* opens file for writing */

+extern void	make_nfa_model_node();

+extern void	make_dfa_model_node();

+extern char *ClassName();

+extern char *OutMetaName();

+extern void error();

+extern void warning();

+extern void p_head();                   /* MR9 */

+extern void p_class_hdr();              /* MR9 */

+extern void p_includes();               /* MR9 */

+extern void p_tables();                 /* MR9 */

+extern void p_tail();					/* MR1 */

+extern void p_class_def1();				/* MR1 */

+extern void new_automaton_mode();			/* MR1 */

+extern int  relabel();					/* MR1 */

+extern void p_shift_table();				/* MR1 */

+extern void p_bshift_table();				/* MR1 */

+extern void p_class_table();				/* MR1 */

+extern void p_mode_def();				/* MR1 */

+extern void init();					/* MR1 */

+extern void p_class_def2();				/* MR1 */

+extern void clear_hash();				/* MR1 */

+extern void p_alternative_table();			/* MR1 */

+extern void p_node_table();				/* MR1 */

+extern void p_dfa_table();				/* MR1 */

+extern void p_accept_table();				/* MR1 */

+extern void p_action_table();				/* MR1 */

+extern void p_base_table();				/* MR1 */

+extern void p_single_node();				/* MR1 */

+extern char * minsize();				/* MR1 */

+extern void close1();					/* MR1 */

+extern void partition();				/* MR1 */

+extern void intersect_nfa_labels();			/* MR1 */

+extern void r_intersect();				/* MR1 */

+extern void label_node();				/* MR1 */

+extern void label_with_classes();			/* MR1 */

+

+#endif

diff --git a/Source/Pccts/dlg/dlg.r b/Source/Pccts/dlg/dlg.r
new file mode 100644
index 0000000..c5311fa
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.r
@@ -0,0 +1,275 @@
+/*

+	File:		dlgMPW.r

+	Target:		dlg 133MR

+	Created:    Monday, June 15, 1998 4:44:11 AM

+	Author:		Kenji Tanaka (kentar@osa.att.ne.jp)

+*/

+

+#include "cmdo.r"

+

+resource 'cmdo' (128, "Dlg") {

+	{	/* array dialogs: 1 elements */

+		/* [1] */

+		295,

+		"DLG -- Purdue Compiler Construction Tool"

+		" Set (PCCTS) lexical analyzer generator.",

+		{	/* array itemArray: 18 elements */

+			/* [1] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{35, 175, 50, 225},

+				"On",

+				"-CC",

+				"When this control is checked, DLG genera"

+				"tes a scanner using C++ classes rather t"

+				"han C functions."

+			},

+			/* [2] */

+			Or {

+				{	/* array OrArray: 1 elements */

+					/* [1] */

+					1

+				}

+			},

+			RegularEntry {

+				"Lexer Class Name:",

+				{35, 225, 50, 355},

+				{35, 355, 51, 450},

+				"DLGLexer",

+				keepCase,

+				"-cl",

+				"This entry specifies the name DLG uses f"

+				"or the C++ lexer class."

+			},

+			/* [3] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{25, 165, 60, 460},

+				"C++ Code Generation"

+			},

+			/* [4] */

+			NotDependent {

+

+			},

+			Files {

+				InputFile,

+				RequiredFile {

+					{37, 25, 56, 135},

+					"Input File",

+					"",

+					"Choose the lexical description file for "

+					"DLG to process."

+				},

+				Additional {

+					"",

+					"",

+					"",

+					"",

+					{	/* array TypesArray: 1 elements */

+						/* [1] */

+						text

+					}

+				}

+			},

+			/* [5] */

+			Or {

+				{	/* array OrArray: 1 elements */

+					/* [1] */

+					-1

+				}

+			},

+			Files {

+				OutputFile,

+				RequiredFile {

+					{66, 25, 85, 135},

+					"Output File",

+					"",

+					"Choose the name of the file that will ho"

+					"ld the DLG-produced scanner."

+				},

+				NoMore {

+

+				}

+			},

+			/* [6] */

+			Or {

+				{	/* array OrArray: 2 elements */

+					/* [1] */

+					1,

+					/* [2] */

+					5

+				}

+			},

+			Dummy {

+

+			},

+			/* [7] */

+			NotDependent {

+

+			},

+			Redirection {

+				DiagnosticOutput,

+				{90, 25}

+			},

+			/* [8] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{25, 20, 132, 145},

+				"Files"

+			},

+			/* [9] */

+			NotDependent {

+

+			},

+			Files {

+				DirOnly,

+				OptionalFile {

+					{68, 175, 84, 305},

+					{88, 175, 107, 305},

+					"Output Directory",

+					":",

+					"-o",

+					"",

+					"Choose the directory where DLG will put "

+					"its output.",

+					dim,

+					"Output DirectoryI",

+					"",

+					""

+				},

+				NoMore {

+

+				}

+			},

+			/* [10] */

+			NotDependent {

+

+			},

+			RegularEntry {

+				"Mode File Name:",

+				{68, 315, 83, 450},

+				{88, 315, 104, 450},

+				"mode.h",

+				keepCase,

+				"-m",

+				"This entry specifies the name DLG uses f"

+				"or its lexical mode output file."

+			},

+			/* [11] */

+			NotDependent {

+

+			},

+			RadioButtons {

+				{	/* array radioArray: 3 elements */

+					/* [1] */

+					{134, 175, 149, 255}, "None", "", Set, "When this option is selected, DLG will n"

+					"ot compress its tables.",

+					/* [2] */

+					{134, 265, 149, 345}, "Level 1", "-C1", NotSet, "When this option is selected, DLG will r"

+					"emove all unused characters from the tra"

+					"nsition-from table.",

+					/* [3] */

+					{134, 360, 149, 450}, "Level 2", "-C2", NotSet, "When this option is selected, DLG will p"

+					"erform level 1 compression plus it will "

+					"map equivalent characters into the same "

+					"character classes."

+				}

+			},

+			/* [12] */

+			NotDependent {

+

+			},

+			TextBox {

+				gray,

+				{124, 165, 156, 460},

+				"Table Compression"

+			},

+			/* [13] */

+			NotDependent {

+

+			},

+			CheckOption {

+				Set,

+				{165, 20, 180, 145},

+				"Case Sensitive",

+				"-ci",

+				"When this control is checked, the DLG au"

+				"tomaton will treat upper and lower case "

+				"characters identically."

+			},

+			/* [14] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{165, 150, 180, 300},

+				"Interactive Scanner",

+				"-i",

+				"When this control is checked, DLG will g"

+				"enerate as interactive a scanner as poss"

+				"ible."

+			},

+			/* [15] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{165, 310, 180, 460},

+				"Ambiguity Warnings",

+				"-Wambiguity",

+				"When this control is checked, DLG warns "

+				"if more than one regular expression coul"

+				"d match the same character sequence."

+			},

+			/* [16] */

+			NotDependent {

+

+			},

+			VersionDialog {

+				VersionString {

+					"1.33MR"

+				},

+				"PCCTS was written by Terence Parr, Russe"

+				"ll Quong, Will Cohen, and Hank Dietz: 19"

+				"89-1998. MPW port by Scott Haney.",

+				noDialog

+			},

+			/* [17] */

+			And {

+				{	/* array AndArray: 2 elements */

+					/* [1] */

+					4,

+					/* [2] */

+					6

+				}

+			},

+			DoItButton {

+

+			},

+			/* [18] */

+			NotDependent {

+

+			},

+			CheckOption {

+				NotSet,

+				{142, 20, 157, 148},

+				"Generate ANSI C",

+				"-ga",

+				"When this control is checked, DLG genera"

+				"tes ANSI C compatible code."

+			}

+		}

+	}

+};

+

diff --git a/Source/Pccts/dlg/dlg1.txt b/Source/Pccts/dlg/dlg1.txt
new file mode 100644
index 0000000..06b320d
--- /dev/null
+++ b/Source/Pccts/dlg/dlg1.txt
@@ -0,0 +1,132 @@
+

+

+

+dlg(1)                 PCCTS Manual Pages                  dlg(1)

+

+

+

+NAME

+     dlg - DFA Lexical Analyzer Generator

+

+SYNTAX

+     dlg [_o_p_t_i_o_n_s] _l_e_x_i_c_a_l__s_p_e_c [_o_u_t_p_u_t__f_i_l_e]

+

+DESCRIPTION

+     dlg is a tool that produces fast deterministic finite auto-

+     mata for recognizing regular expressions in input.

+

+OPTIONS

+     -CC  Generate C++ output.  The _o_u_t_p_u_t__f_i_l_e is not specified

+          in this case.

+

+     -C[ level]

+          Where level is the compression level used.  0 indica-

+          tions no compression, 1 removes all unused characters

+          from the transition from table, and 2 maps equivalent

+          characters into the same character classes.  It is sug-

+          gested that level -C2 is used, since it will signifi-

+          cantly reduce the size of the dfa produced for lexical

+          analyzer.

+

+     -m   Produces the header file for the lexical mode with a

+          name other than the default name of "mode.h".

+

+     -i   An interactive, or as interactive as possible, parser

+          is produced.  A character is only obtained when

+          required to decide which state to go to.  Some care

+          must be taken to obtain accept states that do not

+          require look ahead at the next character to determine

+          if that is the stop state.  Any regular expression with

+          a Kleene closure at the end is guaranteed to require

+          another character of look ahead.

+

+     -cl class

+          Specify a class name for DLG to generate.  The default

+          is DLGLexer.

+

+     -ci  The automaton will treat upper and lower case charac-

+          ters identically.  This is accomplished in the automa-

+          ton; the characters in the lexical buffer are unmodi-

+          fied.

+

+     -cs  Upper and lower case characters are treated as dis-

+          tinct.  This is the default.

+

+     -o dir

+          Directory where output files should go (default=".").

+          This is very nice for keeping the source directory

+          clear of ANTLR and DLG spawn.

+

+     -Wambiguity

+          Warns if more than one regular expression could match

+          the same character sequence.  The warnings give the

+          numbers of the expressions in the dlg lexical specifi-

+          cation file.  The numbering of the expressions starts

+          at one.  Multiple warnings may be print for the same

+          expressions.

+

+     -    Used in place of file names to get input from standard

+          in or send output to standard out.

+

+SPECIAL CONSIDERATIONS

+     _D_l_g works...  we think.  There is no implicit guarantee of

+     anything.  We reserve no legal rights to the software known

+     as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS

+     is in the public domain.  An individual or company may do

+     whatever they wish with source code distributed with PCCTS

+     or the code generated by PCCTS, including the incorporation

+     of PCCTS, or its output, into commercial software.  We

+     encourage users to develop software with PCCTS.  However, we

+     do ask that credit is given to us for developing PCCTS.  By

+     "credit", we mean that if you incorporate our source code

+     into one of your programs (commercial product, research pro-

+     ject, or otherwise) that you acknowledge this fact somewhere

+     in the documentation, research report, etc...  If you like

+     PCCTS and have developed a nice tool with the output, please

+     mention that you developed it using PCCTS.  As long as these

+     guidelines are followed, we expect to continue enhancing

+     this system and expect to make other tools available as they

+     are completed.

+

+FILES

+     mode.h , dlgauto.h , dlgdef.h

+

+SEE ALSO

+     antlr(1), pccts(1)

+

+BUGS

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

diff --git a/Source/Pccts/dlg/dlg_a.c b/Source/Pccts/dlg/dlg_a.c
new file mode 100644
index 0000000..0b8982c
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_a.c
@@ -0,0 +1,1414 @@
+

+/* parser.dlg -- DLG Description of scanner

+ *

+ * Generated from: dlg_p.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include <ctype.h>

+#include "dlg.h"

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+LOOKAHEAD

+

+void

+#ifdef __USE_PROTOS

+zzerraction(void)

+#else

+zzerraction()

+#endif

+{

+	(*zzerr)("invalid token");

+	zzadvance();

+	zzskip();

+}

+/*

+ * D L G tables

+ *

+ * Generated from: parser.dlg

+ *

+ * 1989-2001 by  Will Cohen, Terence Parr, and Hank Dietz

+ * Purdue University Electrical Engineering

+ * DLG Version 1.33MR33

+ */

+

+#include "mode.h"

+

+

+

+

+int	func_action;		/* should actions be turned into functions?*/

+int	lex_mode_counter = 0;	/* keeps track of the number of %%names */

+/* MR1									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+/* MR1				via <<%%lexmember...>>			    */

+/* MR1									    */

+int	lexMember = 0;		/* <<%%lexmemeber ...>>	   		MR1 */

+int	lexAction = 0;		/* <<%%lexaction ...>>			MR1 */

+int	parserClass = 0;	/* <<%%parserclass ...>>        MR1 */

+int	lexPrefix = 0;		/* <<%%lexprefix ...>>			MR1 */

+char	theClassName[100];						     /* MR11 */

+char	*pClassName=theClassName;					 /* MR11 */

+int	firstLexMember=1;					             /* MR1 */

+

+#ifdef __USE_PROTOS

+void  xxputc(int c) {						/* MR1 */

+#else

+  void xxputc(c)							/* MR1 */

+  int	c;							/* MR1 */

+  {								/* MR1 */

+#endif

+    if (parserClass) {						/* MR1 */

+      *pClassName++=c;						/* MR1 */

+      *pClassName=0;						/* MR1 */

+    } else if (lexMember || lexPrefix) {				/* MR1 */

+      if (class_stream != NULL) fputc(c,class_stream);		/* MR1 */

+    } else {							/* MR1 */

+      fputc(c,OUT);						/* MR1 */

+    };								/* MR1 */

+  }  								/* MR1 */

+  

+#ifdef __USE_PROTOS

+  void xxprintf(char *format,char *string) {			/* MR1 */

+#else

+    void xxprintf(format,string) 					/* MR1 */

+    char *format;							/* MR1 */

+    char *string;							/* MR1 */

+    {								/* MR1 */

+#endif

+      if (lexMember || lexPrefix || parserClass) {			/* MR1 */

+        if (class_stream != NULL)					/* MR1 */

+        fprintf(class_stream,format,string);			/* MR1 */

+      } else {							/* MR1 */

+        fprintf(OUT,format,string);					/* MR1 */

+      };								/* MR1 */

+    }  								/* MR1 */

+

+static void act1()

+{ 

+		NLA = 1;

+	}

+

+

+static void act2()

+{ 

+		NLA = 2;

+    zzskip();   

+	}

+

+

+static void act3()

+{ 

+		NLA = 3;

+    zzline++; zzskip(); DAWDLE;   

+	}

+

+

+static void act4()

+{ 

+		NLA = L_EOF;

+	}

+

+

+static void act5()

+{ 

+		NLA = PER_PER;

+	}

+

+

+static void act6()

+{ 

+		NLA = NAME_PER_PER;

+    p_mode_def(&zzlextext[2],lex_mode_counter++);   

+	}

+

+

+static void act7()

+{ 

+		NLA = LEXMEMBER;

+    lexMember=1;					/* MR1 */

+    if (firstLexMember != 0) {			/* MR1 */

+      firstLexMember=0;				/* MR1 */

+      p_class_def1();				/* MR1 */

+    };						/* MR1 */

+    zzmode(ACT);					/* MR1 */

+	}

+

+

+static void act8()

+{ 

+		NLA = LEXACTION;

+    lexAction=1;zzmode(ACT);  

+	}

+

+

+static void act9()

+{ 

+		NLA = PARSERCLASS;

+    parserClass=1;				/* MR1 */

+    zzmode(ACT);					/* MR1 */

+	}

+

+

+static void act10()

+{ 

+		NLA = LEXPREFIX;

+    lexPrefix=1;zzmode(ACT);  

+	}

+

+

+static void act11()

+{ 

+		NLA = ACTION;

+    if (func_action)

+    fprintf(OUT,"\n%s %sact%d()\n{ ",

+    gen_cpp?"ANTLRTokenType":"static void",

+    gen_cpp?ClassName("::"):"", ++action_no);

+    zzmode(ACT); zzskip();

+	}

+

+

+static void act12()

+{ 

+		NLA = GREAT_GREAT;

+	}

+

+

+static void act13()

+{ 

+		NLA = L_BRACE;

+	}

+

+

+static void act14()

+{ 

+		NLA = R_BRACE;

+	}

+

+

+static void act15()

+{ 

+		NLA = L_PAR;

+	}

+

+

+static void act16()

+{ 

+		NLA = R_PAR;

+	}

+

+

+static void act17()

+{ 

+		NLA = L_BRACK;

+	}

+

+

+static void act18()

+{ 

+		NLA = R_BRACK;

+	}

+

+

+static void act19()

+{ 

+		NLA = ZERO_MORE;

+	}

+

+

+static void act20()

+{ 

+		NLA = ONE_MORE;

+	}

+

+

+static void act21()

+{ 

+		NLA = OR;

+	}

+

+

+static void act22()

+{ 

+		NLA = RANGE;

+	}

+

+

+static void act23()

+{ 

+		NLA = NOT;

+	}

+

+

+static void act24()

+{ 

+		NLA = OCTAL_VALUE;

+    {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}  

+	}

+

+

+static void act25()

+{ 

+		NLA = HEX_VALUE;

+    {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}  

+	}

+

+

+static void act26()

+{ 

+		NLA = DEC_VALUE;

+    {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}  

+	}

+

+

+static void act27()

+{ 

+		NLA = TAB;

+    zzlextext[0] = '\t';  

+	}

+

+

+static void act28()

+{ 

+		NLA = NL;

+    zzlextext[0] = '\n';  

+	}

+

+

+static void act29()

+{ 

+		NLA = CR;

+    zzlextext[0] = '\r';  

+	}

+

+

+static void act30()

+{ 

+		NLA = BS;

+    zzlextext[0] = '\b';  

+	}

+

+

+static void act31()

+{ 

+		NLA = CONTINUATION;

+    zzline++; zzskip();  

+	}

+

+

+static void act32()

+{ 

+		NLA = LIT;

+    zzlextext[0] = zzlextext[1];  

+	}

+

+

+static void act33()

+{ 

+		NLA = REGCHAR;

+	}

+

+static unsigned char shift0[257] = {

+  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  1, 2, 40, 40, 1, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 1, 40, 40, 40, 40, 4, 40, 

+  40, 30, 31, 34, 35, 40, 37, 40, 40, 23, 

+  24, 24, 24, 24, 24, 24, 24, 25, 25, 40, 

+  40, 26, 40, 27, 40, 3, 21, 21, 21, 21, 

+  21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 

+  22, 22, 22, 22, 22, 22, 22, 22, 22, 20, 

+  22, 22, 32, 39, 33, 40, 22, 40, 11, 9, 

+  12, 21, 6, 19, 22, 22, 14, 22, 22, 5, 

+  8, 16, 15, 17, 22, 10, 18, 13, 22, 22, 

+  22, 7, 22, 22, 28, 36, 29, 38, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 

+  40, 40, 40, 40, 40, 40, 40

+};

+

+

+static void act34()

+{ 

+		NLA = 1;

+    error("unterminated action", zzline); zzmode(START);   

+	}

+

+

+static void act35()

+{ 

+		NLA = ACTION;

+    if (func_action) fprintf(OUT,"}\n\n");

+    zzmode(START);

+    /* MR1									    */

+    /* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+    /* MR1				via <<%%lexmember ...>>			    */

+    /* MR1			This is a consequence of not saving actions         */

+    /* MR1									    */

+    /* MR1 */	   parserClass=0;		

+    /* MR1 */	   lexPrefix=0;

+    /* MR1 */	   lexAction=0;

+    /* MR1 */	   lexMember=0;

+	}

+

+

+static void act36()

+{ 

+		NLA = 34;

+    xxputc(zzlextext[0]); zzskip();   

+	}

+

+

+static void act37()

+{ 

+		NLA = 35;

+    xxputc('>'); zzskip();   

+	}

+

+

+static void act38()

+{ 

+		NLA = 36;

+    xxputc('\\'); zzskip();   

+	}

+

+

+static void act39()

+{ 

+		NLA = 37;

+    xxputc(zzlextext[0]); ++zzline; zzskip();   

+	}

+

+

+static void act40()

+{ 

+		NLA = 38;

+    zzmode(ACTION_COMMENTS);			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	}

+

+

+static void act41()

+{ 

+		NLA = 39;

+    zzmode(ACTION_CPP_COMMENTS);			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	}

+

+

+static void act42()

+{ 

+		NLA = 40;

+    xxputc(zzlextext[0]); zzskip();   

+	}

+

+static unsigned char shift1[257] = {

+  0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 3, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 5, 6, 6, 6, 6, 4, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 1, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6

+};

+

+

+static void act43()

+{ 

+		NLA = 1;

+	}

+

+

+static void act44()

+{ 

+		NLA = 41;

+    zzmode(ACT);					/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	}

+

+

+static void act45()

+{ 

+		NLA = 42;

+    zzline++; xxputc(zzlextext[0]); zzskip();  

+	}

+

+

+static void act46()

+{ 

+		NLA = 43;

+    xxputc(zzlextext[0]); zzskip();  

+	}

+

+static unsigned char shift2[257] = {

+  0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 1, 4, 4, 4, 4, 2, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 

+  4, 4, 4, 4, 4, 4, 4

+};

+

+

+static void act47()

+{ 

+		NLA = 1;

+	}

+

+

+static void act48()

+{ 

+		NLA = 44;

+    zzmode(ACT); zzline++;			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	}

+

+

+static void act49()

+{ 

+		NLA = 45;

+    xxputc(zzlextext[0]); zzskip();  

+	}

+

+static unsigned char shift3[257] = {

+  0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 

+  2, 2, 2, 2, 2, 2, 2

+};

+

+#define DfaStates	94

+typedef unsigned char DfaState;

+

+static DfaState st0[42] = {

+  1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 

+  6, 6, 6, 6, 6, 6, 7, 8, 9, 10, 

+  11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 

+  6, 94

+};

+

+static DfaState st1[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st2[42] = {

+  94, 21, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st3[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st4[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st5[42] = {

+  94, 94, 94, 94, 22, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st6[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st7[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 23, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st8[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 24, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st9[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st10[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st11[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st12[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st13[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st14[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st15[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st16[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st17[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st18[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st19[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st20[42] = {

+  94, 25, 26, 25, 25, 25, 25, 25, 25, 27, 

+  28, 25, 25, 29, 25, 25, 30, 25, 25, 25, 

+  25, 25, 25, 31, 32, 32, 25, 25, 25, 25, 

+  25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 

+  25, 94

+};

+

+static DfaState st21[42] = {

+  94, 21, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st22[42] = {

+  94, 94, 94, 94, 94, 33, 33, 33, 33, 33, 

+  33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 

+  33, 33, 33, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st23[42] = {

+  94, 94, 94, 94, 34, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st24[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st25[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st26[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st27[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st28[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st29[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st30[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st31[42] = {

+  94, 94, 94, 94, 94, 94, 94, 35, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  35, 94, 94, 36, 36, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st32[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 37, 37, 37, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st33[42] = {

+  94, 94, 94, 94, 94, 38, 38, 38, 38, 38, 

+  38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 

+  38, 38, 38, 38, 38, 38, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st34[42] = {

+  94, 94, 94, 94, 39, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st35[42] = {

+  94, 94, 94, 94, 94, 94, 40, 94, 94, 40, 

+  94, 40, 40, 94, 94, 94, 94, 94, 94, 40, 

+  94, 40, 94, 40, 40, 40, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st36[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 36, 36, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st37[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 37, 37, 37, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st38[42] = {

+  94, 94, 94, 94, 94, 38, 38, 38, 38, 38, 

+  38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 

+  38, 38, 38, 38, 38, 38, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st39[42] = {

+  94, 94, 94, 94, 94, 41, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 42, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st40[42] = {

+  94, 94, 94, 94, 94, 94, 40, 94, 94, 40, 

+  94, 40, 40, 94, 94, 94, 94, 94, 94, 40, 

+  94, 40, 94, 40, 40, 40, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st41[42] = {

+  94, 94, 94, 94, 94, 94, 43, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st42[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 44, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st43[42] = {

+  94, 94, 94, 94, 94, 94, 94, 45, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st44[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  46, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st45[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 47, 94, 

+  94, 48, 94, 94, 94, 94, 94, 49, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st46[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 50, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st47[42] = {

+  94, 94, 94, 94, 94, 94, 51, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st48[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 52, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st49[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  53, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st50[42] = {

+  94, 94, 94, 94, 94, 94, 54, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st51[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 55, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st52[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 56, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st53[42] = {

+  94, 94, 94, 94, 94, 94, 57, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st54[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  58, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st55[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 59, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st56[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 60, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st57[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 61, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st58[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 62, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st59[42] = {

+  94, 94, 94, 94, 94, 94, 63, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st60[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 64, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st61[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 65, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st62[42] = {

+  94, 94, 94, 94, 94, 66, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st63[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  67, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st64[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 68, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st65[42] = {

+  94, 94, 94, 94, 94, 94, 94, 69, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st66[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 70, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st67[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st68[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st69[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st70[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 71, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st71[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 72, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st72[42] = {

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 

+  94, 94

+};

+

+static DfaState st73[8] = {

+  74, 75, 76, 77, 78, 79, 79, 94

+};

+

+static DfaState st74[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st75[8] = {

+  94, 80, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st76[8] = {

+  94, 81, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st77[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st78[8] = {

+  94, 94, 94, 94, 82, 83, 94, 94

+};

+

+static DfaState st79[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st80[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st81[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st82[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st83[8] = {

+  94, 94, 94, 94, 94, 94, 94, 94

+};

+

+static DfaState st84[6] = {

+  85, 86, 87, 88, 87, 94

+};

+

+static DfaState st85[6] = {

+  94, 94, 94, 94, 94, 94

+};

+

+static DfaState st86[6] = {

+  94, 94, 89, 94, 94, 94

+};

+

+static DfaState st87[6] = {

+  94, 94, 94, 94, 94, 94

+};

+

+static DfaState st88[6] = {

+  94, 94, 94, 94, 94, 94

+};

+

+static DfaState st89[6] = {

+  94, 94, 94, 94, 94, 94

+};

+

+static DfaState st90[4] = {

+  91, 92, 93, 94

+};

+

+static DfaState st91[4] = {

+  94, 94, 94, 94

+};

+

+static DfaState st92[4] = {

+  94, 94, 94, 94

+};

+

+static DfaState st93[4] = {

+  94, 94, 94, 94

+};

+

+

+DfaState *dfa[94] = {

+	st0,

+	st1,

+	st2,

+	st3,

+	st4,

+	st5,

+	st6,

+	st7,

+	st8,

+	st9,

+	st10,

+	st11,

+	st12,

+	st13,

+	st14,

+	st15,

+	st16,

+	st17,

+	st18,

+	st19,

+	st20,

+	st21,

+	st22,

+	st23,

+	st24,

+	st25,

+	st26,

+	st27,

+	st28,

+	st29,

+	st30,

+	st31,

+	st32,

+	st33,

+	st34,

+	st35,

+	st36,

+	st37,

+	st38,

+	st39,

+	st40,

+	st41,

+	st42,

+	st43,

+	st44,

+	st45,

+	st46,

+	st47,

+	st48,

+	st49,

+	st50,

+	st51,

+	st52,

+	st53,

+	st54,

+	st55,

+	st56,

+	st57,

+	st58,

+	st59,

+	st60,

+	st61,

+	st62,

+	st63,

+	st64,

+	st65,

+	st66,

+	st67,

+	st68,

+	st69,

+	st70,

+	st71,

+	st72,

+	st73,

+	st74,

+	st75,

+	st76,

+	st77,

+	st78,

+	st79,

+	st80,

+	st81,

+	st82,

+	st83,

+	st84,

+	st85,

+	st86,

+	st87,

+	st88,

+	st89,

+	st90,

+	st91,

+	st92,

+	st93

+};

+

+

+DfaState accepts[95] = {

+  0, 1, 2, 3, 4, 33, 33, 33, 33, 13, 

+  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 

+  0, 2, 5, 11, 12, 32, 31, 30, 29, 27, 

+  28, 24, 26, 6, 0, 0, 24, 26, 6, 0, 

+  25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 

+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 

+  0, 0, 0, 0, 0, 0, 0, 7, 8, 10, 

+  0, 0, 9, 0, 34, 36, 38, 39, 42, 42, 

+  35, 37, 41, 40, 0, 43, 46, 46, 45, 44, 

+  0, 47, 48, 49, 0

+};

+

+void (*actions[50])() = {

+	zzerraction,

+	act1,

+	act2,

+	act3,

+	act4,

+	act5,

+	act6,

+	act7,

+	act8,

+	act9,

+	act10,

+	act11,

+	act12,

+	act13,

+	act14,

+	act15,

+	act16,

+	act17,

+	act18,

+	act19,

+	act20,

+	act21,

+	act22,

+	act23,

+	act24,

+	act25,

+	act26,

+	act27,

+	act28,

+	act29,

+	act30,

+	act31,

+	act32,

+	act33,

+	act34,

+	act35,

+	act36,

+	act37,

+	act38,

+	act39,

+	act40,

+	act41,

+	act42,

+	act43,

+	act44,

+	act45,

+	act46,

+	act47,

+	act48,

+	act49

+};

+

+static DfaState dfa_base[] = {

+	0,

+	73,

+	84,

+	90

+};

+

+static unsigned char *b_class_no[] = {

+	shift0,

+	shift1,

+	shift2,

+	shift3

+};

+

+

+

+#define ZZSHIFT(c) (b_class_no[zzauto][1+c])

+#define MAX_MODE 4

+#include "dlgauto.h"

diff --git a/Source/Pccts/dlg/dlg_p.c b/Source/Pccts/dlg/dlg_p.c
new file mode 100644
index 0000000..e726ae3
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_p.c
@@ -0,0 +1,959 @@
+/*

+ * A n t l r  T r a n s l a t i o n  H e a d e r

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ *

+ *   ..\bin\antlr dlg_p.g -gh

+ *

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include <ctype.h>

+#include "dlg.h"

+#define zzSET_SIZE 8

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "mode.h"

+

+/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */

+

+#ifndef PCCTS_PURIFY

+#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s));

+#endif

+

+ANTLR_INFO

+

+

+/* MR20 G. Hobbelt 

+Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled

+*/

+

+#ifdef __TURBOC__

+#pragma warn -aus  /* unused assignment of 'xxx' */

+#endif

+

+int	action_no = 0;	   /* keep track of actions outputed */

+int	nfa_allocated = 0; /* keeps track of number of nfa nodes */

+nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */

+nfa_node nfa_model_node;   /* model to initialize new nodes */

+set	used_chars;	   /* used to label trans. arcs */

+set	used_classes;	   /* classes or chars used to label trans. arcs */

+set	normal_chars;	   /* mask to get rid elements that aren't used

+in set */

+int	flag_paren = FALSE;

+int	flag_brace = FALSE;

+int	mode_counter = 0;  /* keep track of number of %%names */

+

+  

+

+void

+#ifdef __USE_PROTOS

+grammar(void)

+#else

+grammar()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  p_head(); p_class_hdr(); func_action = FALSE;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (setwd1[LA(1)]&0x1) ) {

+      {

+        zzBLOCK(zztasp3);

+        zzMake0;

+        {

+        if ( (LA(1)==LEXACTION) ) {

+          zzmatch(LEXACTION); zzCONSUME;

+        }

+        else {

+          if ( (LA(1)==LEXMEMBER) ) {

+            zzmatch(LEXMEMBER); zzCONSUME;

+          }

+          else {

+            if ( (LA(1)==LEXPREFIX) ) {

+              zzmatch(LEXPREFIX); zzCONSUME;

+            }

+            else {

+              if ( (LA(1)==PARSERCLASS) ) {

+                zzmatch(PARSERCLASS); zzCONSUME;

+              }

+              else {

+                if ( (LA(1)==ACTION) ) {

+                }

+                else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+              }

+            }

+          }

+        }

+        zzEXIT(zztasp3);

+        }

+      }

+      zzmatch(ACTION); zzCONSUME;

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  if ( gen_cpp ) p_includes();

+  start_states();

+  func_action = FALSE; p_tables(); p_tail();

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==ACTION) ) {

+      zzmatch(ACTION); zzCONSUME;

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(1);

+  if (firstLexMember != 0) p_class_def1();

+ zzCONSUME;

+

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x2);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+start_states(void)

+#else

+start_states()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==PER_PER) ) {

+      zzmatch(PER_PER); zzCONSUME;

+      do_conversion();

+    }

+    else {

+      if ( (LA(1)==NAME_PER_PER) ) {

+        zzmatch(NAME_PER_PER); zzCONSUME;

+        do_conversion();

+        {

+          zzBLOCK(zztasp3);

+          zzMake0;

+          {

+          while ( (LA(1)==NAME_PER_PER) ) {

+            zzmatch(NAME_PER_PER); zzCONSUME;

+            do_conversion();

+            zzLOOP(zztasp3);

+          }

+          zzEXIT(zztasp3);

+          }

+        }

+      }

+      else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzmatch(PER_PER); zzCONSUME;

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x4);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+do_conversion(void)

+#else

+do_conversion()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  new_automaton_mode(); func_action = TRUE;

+  rule_list();

+  

+  dfa_class_nop[mode_counter] =

+  relabel(zzaArg(zztasp1,1 ).l,comp_level);

+  if (comp_level)

+  p_shift_table(mode_counter);

+  dfa_basep[mode_counter] = dfa_allocated+1;

+  make_dfa_model_node(dfa_class_nop[mode_counter]);

+  nfa_to_dfa(zzaArg(zztasp1,1 ).l);

+  ++mode_counter;

+  func_action = FALSE;

+#ifdef HASH_STAT

+  fprint_hash_stats(stderr);

+#endif

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x8);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+rule_list(void)

+#else

+rule_list()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  if ( (setwd1[LA(1)]&0x10) ) {

+    rule();

+    zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      while ( (setwd1[LA(1)]&0x20) ) {

+        rule();

+        {nfa_node *t1;

+          t1 = new_nfa_node();

+          (t1)->trans[0]=zzaRet.l;

+          (t1)->trans[1]=zzaArg(zztasp2,1 ).l;

+          /* all accept nodes "dead ends" */

+          zzaRet.l=t1; zzaRet.r=NULL;

+        }

+        zzLOOP(zztasp2);

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+  }

+  else {

+    if ( (setwd1[LA(1)]&0x40) ) {

+      zzaRet.l = new_nfa_node(); zzaRet.r = NULL;

+      warning("no regular expressions", zzline);

+    }

+    else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd1, 0x80);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+rule(void)

+#else

+rule()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  if ( (setwd2[LA(1)]&0x1) ) {

+    reg_expr();

+    zzmatch(ACTION);

+    if (zzaArg(zztasp1,1 ).r != NULL) {

+      zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; (zzaArg(zztasp1,1 ).r)->accept=action_no;

+    }

+ zzCONSUME;

+

+  }

+  else {

+    if ( (LA(1)==ACTION) ) {

+      zzmatch(ACTION);

+      zzaRet.l = NULL; zzaRet.r = NULL;

+      error("no expression for action  ", zzline);

+ zzCONSUME;

+

+    }

+    else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x2);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+reg_expr(void)

+#else

+reg_expr()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  and_expr();

+  zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (LA(1)==OR) ) {

+      zzmatch(OR); zzCONSUME;

+      and_expr();

+      {nfa_node *t1, *t2;

+        t1 = new_nfa_node(); t2 = new_nfa_node();

+        (t1)->trans[0]=zzaRet.l;

+        (t1)->trans[1]=zzaArg(zztasp2,2 ).l;

+        /* MR23 */		   if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2;

+        if (zzaArg(zztasp2,2 ).r) {

+          (zzaArg(zztasp2,2 ).r)->trans[1]=t2;     /* MR20 */

+        }

+        zzaRet.l=t1; zzaRet.r=t2;

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x4);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+and_expr(void)

+#else

+and_expr()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  repeat_expr();

+  

+  zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (setwd2[LA(1)]&0x8) ) {

+      repeat_expr();

+      if (zzaRet.r != NULL) {

+        (zzaRet.r)->trans[1]=zzaArg(zztasp2,1 ).l;

+        zzaRet.r=zzaArg(zztasp2,1 ).r;

+      }

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x10);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+repeat_expr(void)

+#else

+repeat_expr()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  if ( (setwd2[LA(1)]&0x20) ) {

+    expr();

+    zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;

+    {

+      zzBLOCK(zztasp2);

+      zzMake0;

+      {

+      if ( (LA(1)==ZERO_MORE) ) {

+        zzmatch(ZERO_MORE);

+        {	nfa_node *t1,*t2;

+          /* MR23 */		if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l;

+          t1 = new_nfa_node(); t2 = new_nfa_node();

+          t1->trans[0]=zzaRet.l;

+          t1->trans[1]=t2;

+          /* MR23 */		if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2;

+          zzaRet.l=t1;zzaRet.r=t2;

+        }

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==ONE_MORE) ) {

+          zzmatch(ONE_MORE);

+          if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l;

+ zzCONSUME;

+

+        }

+        else {

+          if ( (setwd2[LA(1)]&0x40) ) {

+          }

+          else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+      }

+      zzEXIT(zztasp2);

+      }

+    }

+  }

+  else {

+    if ( (LA(1)==ZERO_MORE) ) {

+      zzmatch(ZERO_MORE);

+      error("no expression for *", zzline);

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==ONE_MORE) ) {

+        zzmatch(ONE_MORE);

+        error("no expression for +", zzline);

+ zzCONSUME;

+

+      }

+      else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd2, 0x80);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+expr(void)

+#else

+expr()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  zzaRet.l = new_nfa_node();

+  zzaRet.r = new_nfa_node();

+  if ( (LA(1)==L_BRACK) ) {

+    zzmatch(L_BRACK); zzCONSUME;

+    atom_list();

+    zzmatch(R_BRACK);

+    

+    /* MR23 */		if (zzaRet.l != NULL) {

+      (zzaRet.l)->trans[0] = zzaRet.r;

+      (zzaRet.l)->label = set_dup(zzaArg(zztasp1,2 ).label);

+      set_orin(&used_chars,(zzaRet.l)->label);

+    }

+ zzCONSUME;

+

+  }

+  else {

+    if ( (LA(1)==NOT) ) {

+      zzmatch(NOT); zzCONSUME;

+      zzmatch(L_BRACK); zzCONSUME;

+      atom_list();

+      zzmatch(R_BRACK);

+      

+      /* MR23 */		if (zzaRet.l != NULL) {

+        (zzaRet.l)->trans[0] = zzaRet.r;

+        (zzaRet.l)->label = set_dif(normal_chars,zzaArg(zztasp1,3 ).label);

+        set_orin(&used_chars,(zzaRet.l)->label);

+      }

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==L_PAR) ) {

+        zzmatch(L_PAR); zzCONSUME;

+        reg_expr();

+        zzmatch(R_PAR);

+        

+        /* MR23 */		if (zzaRet.l != NULL) {				

+          (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l;

+          if (zzaArg(zztasp1,2 ).r) {

+            (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r;    /* MR20 */

+          }

+        }

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==L_BRACE) ) {

+          zzmatch(L_BRACE); zzCONSUME;

+          reg_expr();

+          zzmatch(R_BRACE);

+          

+          /* MR23 */		if (zzaRet.l != NULL) {

+            (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l;

+            (zzaRet.l)->trans[1] = zzaRet.r;

+            if (zzaArg(zztasp1,2 ).r) {

+              (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r;    /* MR20 */

+            }

+          }

+ zzCONSUME;

+

+        }

+        else {

+          if ( (setwd3[LA(1)]&0x1) ) {

+            atom();

+            

+            /* MR23 */		if (zzaRet.l != NULL) {

+              (zzaRet.l)->trans[0] = zzaRet.r;

+              (zzaRet.l)->label = set_dup(zzaArg(zztasp1,1 ).label);

+              set_orin(&used_chars,(zzaRet.l)->label);

+            }

+          }

+          else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+        }

+      }

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x2);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+atom_list(void)

+#else

+atom_list()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  set_free(zzaRet.label);

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    while ( (setwd3[LA(1)]&0x4) ) {

+      near_atom();

+      set_orin(&(zzaRet.label),zzaArg(zztasp2,1 ).label);

+      zzLOOP(zztasp2);

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x8);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+near_atom(void)

+#else

+near_atom()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  register int i;

+  register int i_prime;

+  anychar();

+  zzaRet.letter=zzaArg(zztasp1,1 ).letter; zzaRet.label=set_of(zzaArg(zztasp1,1 ).letter);

+  i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR;

+  if (case_insensitive && islower(i_prime))

+  set_orel(toupper(i_prime)-MIN_CHAR,

+  &(zzaRet.label));

+  if (case_insensitive && isupper(i_prime))

+  set_orel(tolower(i_prime)-MIN_CHAR,

+  &(zzaRet.label));

+  {

+    zzBLOCK(zztasp2);

+    zzMake0;

+    {

+    if ( (LA(1)==RANGE) ) {

+      zzmatch(RANGE); zzCONSUME;

+      anychar();

+      if (case_insensitive){

+        i_prime = zzaRet.letter+MIN_CHAR;

+        zzaRet.letter = (islower(i_prime) ?

+        toupper(i_prime) : i_prime)-MIN_CHAR;

+        i_prime = zzaArg(zztasp2,2 ).letter+MIN_CHAR;

+        zzaArg(zztasp2,2 ).letter = (islower(i_prime) ?

+        toupper(i_prime) : i_prime)-MIN_CHAR;

+      }

+      /* check to see if range okay */

+      {

+        int debugLetter1 = zzaRet.letter;

+        int debugLetter2 = zzaArg(zztasp2,2 ).letter;

+      }

+      if (zzaRet.letter > zzaArg(zztasp2,2 ).letter 

+      && zzaArg(zztasp2,2 ).letter != 0xff){       /* MR16 */

+        error("invalid range  ", zzline);

+      }

+      for (i=zzaRet.letter; i<= (int)zzaArg(zztasp2,2 ).letter; ++i){

+        set_orel(i,&(zzaRet.label));

+        i_prime = i+MIN_CHAR;

+        if (case_insensitive && islower(i_prime))

+        set_orel(toupper(i_prime)-MIN_CHAR,

+        &(zzaRet.label));

+        if (case_insensitive && isupper(i_prime))

+        set_orel(tolower(i_prime)-MIN_CHAR,

+        &(zzaRet.label));

+      }

+    }

+    else {

+      if ( (setwd3[LA(1)]&0x10) ) {

+      }

+      else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+    }

+    zzEXIT(zztasp2);

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x20);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+atom(void)

+#else

+atom()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  register int i_prime;

+  anychar();

+  zzaRet.label = set_of(zzaArg(zztasp1,1 ).letter);

+  i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR;

+  if (case_insensitive && islower(i_prime))

+  set_orel(toupper(i_prime)-MIN_CHAR,

+  &(zzaRet.label));

+  if (case_insensitive && isupper(i_prime))

+  set_orel(tolower(i_prime)-MIN_CHAR,

+  &(zzaRet.label));

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x40);

+  }

+}

+

+void

+#ifdef __USE_PROTOS

+anychar(void)

+#else

+anychar()

+#endif

+{

+  zzRULE;

+  zzBLOCK(zztasp1);

+  zzMake0;

+  {

+  if ( (LA(1)==REGCHAR) ) {

+    zzmatch(REGCHAR);

+    zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+  }

+  else {

+    if ( (LA(1)==OCTAL_VALUE) ) {

+      zzmatch(OCTAL_VALUE);

+      zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+    }

+    else {

+      if ( (LA(1)==HEX_VALUE) ) {

+        zzmatch(HEX_VALUE);

+        zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+      }

+      else {

+        if ( (LA(1)==DEC_VALUE) ) {

+          zzmatch(DEC_VALUE);

+          zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+        }

+        else {

+          if ( (LA(1)==TAB) ) {

+            zzmatch(TAB);

+            zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+          }

+          else {

+            if ( (LA(1)==NL) ) {

+              zzmatch(NL);

+              zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+            }

+            else {

+              if ( (LA(1)==CR) ) {

+                zzmatch(CR);

+                zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+              }

+              else {

+                if ( (LA(1)==BS) ) {

+                  zzmatch(BS);

+                  zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+                }

+                else {

+                  if ( (LA(1)==LIT) ) {

+                    zzmatch(LIT);

+                    zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;

+ zzCONSUME;

+

+                  }

+                  else {

+                    if ( (LA(1)==L_EOF) ) {

+                      zzmatch(L_EOF);

+                      zzaRet.letter = 0;

+ zzCONSUME;

+

+                    }

+                    else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}

+                  }

+                }

+              }

+            }

+          }

+        }

+      }

+    }

+  }

+  zzEXIT(zztasp1);

+  return;

+fail:

+  zzEXIT(zztasp1);

+  /* empty action */  

+  zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);

+  zzresynch(setwd3, 0x80);

+  }

+}

+

+/* adds a new nfa to the binary tree and returns a pointer to it */

+nfa_node *

+#ifdef __USE_PROTOS

+new_nfa_node(void)

+#else

+new_nfa_node()

+#endif

+{

+  register nfa_node *t;

+  static int nfa_size=0;	/* elements nfa_array[] can hold */

+  

+	++nfa_allocated;

+  if (nfa_size<=nfa_allocated){

+    /* need to redo array */

+    if (!nfa_array){

+      /* need some to do inital allocation */

+      nfa_size=nfa_allocated+NFA_MIN;

+      nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)*

+      nfa_size);

+    }else{

+      /* need more space */

+      nfa_size=2*(nfa_allocated+1);

+      nfa_array=(nfa_node **) realloc(nfa_array,

+      sizeof(nfa_node*)*nfa_size);

+    }

+  }

+  /* fill out entry in array */

+  t = (nfa_node*) malloc(sizeof(nfa_node));

+  nfa_array[nfa_allocated] = t;

+  *t = nfa_model_node;

+  t->node_no = nfa_allocated;

+  return t;

+}

+

+

+/* initialize the model node used to fill in newly made nfa_nodes */

+void

+#ifdef __USE_PROTOS

+make_nfa_model_node(void)

+#else

+make_nfa_model_node()

+#endif

+{

+  nfa_model_node.node_no = -1; /* impossible value for real nfa node */

+  nfa_model_node.nfa_set = 0;

+  nfa_model_node.accept = 0;   /* error state default*/

+  nfa_model_node.trans[0] = NULL;

+  nfa_model_node.trans[1] = NULL;

+  nfa_model_node.label = empty;

+}

+

+#if defined(DEBUG) || defined(_DEBUG)

+

+/* print out the pointer value and the node_number */

+void

+#ifdef __USE_PROTOS

+fprint_dfa_pair(FILE *f, nfa_node *p)

+#else

+fprint_dfa_pair(f, p)

+FILE *f;

+nfa_node *p;

+#endif

+{

+  if (p){

+    fprintf(f, "%x (%d)", p, p->node_no);

+  }else{

+    fprintf(f, "(nil)");

+  }

+}

+

+/* print out interest information on a set */

+void

+#ifdef __USE_PROTOS

+fprint_set(FILE *f, set s)

+#else

+fprint_set(f,s)

+FILE *f;

+set s;

+#endif

+{

+  unsigned int *x;

+  

+	fprintf(f, "n = %d,", s.n);

+  if (s.setword){

+    fprintf(f, "setword = %x,   ", s.setword);

+    /* print out all the elements in the set */

+    x = set_pdq(s);

+    while (*x!=nil){

+      fprintf(f, "%d ", *x);

+      ++x;

+    }

+  }else{

+    fprintf(f, "setword = (nil)");

+  }

+}

+

+/* code to be able to dump out the nfas

+return 0 if okay dump

+return 1 if screwed up

+*/

+int

+#ifdef __USE_PROTOS

+dump_nfas(int first_node, int last_node)

+#else

+dump_nfas(first_node, last_node)

+int first_node;

+int last_node;

+#endif

+{

+  register int i;

+  nfa_node *t;

+  

+	for (i=first_node; i<=last_node; ++i){

+    t = NFA(i);

+    if (!t) break;

+    fprintf(stderr, "nfa_node %d {\n", t->node_no);

+    fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set);

+    fprintf(stderr, "\taccept\t=\t%d\n", t->accept);

+    fprintf(stderr, "\ttrans\t=\t(");

+    fprint_dfa_pair(stderr, t->trans[0]);

+    fprintf(stderr, ",");

+    fprint_dfa_pair(stderr, t->trans[1]);

+    fprintf(stderr, ")\n");

+    fprintf(stderr, "\tlabel\t=\t{ ");

+    fprint_set(stderr, t->label);

+    fprintf(stderr, "\t}\n");

+    fprintf(stderr, "}\n\n");

+  }

+  return 0;

+}

+#endif

+

+/* DLG-specific syntax error message generator

+* (define USER_ZZSYN when compiling so don't get 2 definitions)

+*/

+void

+#ifdef __USE_PROTOS

+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)

+#else

+zzsyn(text, tok, egroup, eset, etok, k, bad_text)

+char *text, *egroup, *bad_text;

+int tok;

+int etok;

+int k;

+SetWordType *eset;

+#endif

+{

+fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline);

+fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);

+if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}

+if ( k==1 ) fprintf(stderr, " missing");

+else

+{

+fprintf(stderr, "; \"%s\" not", bad_text);

+if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");

+}

+if ( zzset_deg(eset)>0 ) zzedecode(eset);

+else fprintf(stderr, " %s", zztokens[etok]);

+if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);

+fprintf(stderr, "\n");

+}

diff --git a/Source/Pccts/dlg/dlg_p.g b/Source/Pccts/dlg/dlg_p.g
new file mode 100644
index 0000000..58ca110
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_p.g
@@ -0,0 +1,614 @@
+/*  This is the parser for the dlg

+ *  This is a part of the Purdue Compiler Construction Tool Set

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-1995

+ */

+

+#header	<<

+#include <ctype.h>

+#include "dlg.h"

+>>

+

+<<

+

+/* MR20 G. Hobbelt 

+   Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled

+*/

+

+#ifdef __TURBOC__

+#pragma warn -aus  /* unused assignment of 'xxx' */

+#endif

+

+int	action_no = 0;	   /* keep track of actions outputed */

+int	nfa_allocated = 0; /* keeps track of number of nfa nodes */

+nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */

+nfa_node nfa_model_node;   /* model to initialize new nodes */

+set	used_chars;	   /* used to label trans. arcs */

+set	used_classes;	   /* classes or chars used to label trans. arcs */

+set	normal_chars;	   /* mask to get rid elements that aren't used

+			      in set */

+int	flag_paren = FALSE;

+int	flag_brace = FALSE;

+int	mode_counter = 0;  /* keep track of number of %%names */

+

+>>

+

+#lexaction <<

+int	func_action;		/* should actions be turned into functions?*/

+int	lex_mode_counter = 0;	/* keeps track of the number of %%names */

+/* MR1									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+/* MR1				via <<%%lexmember...>>			    */

+/* MR1									    */

+int	lexMember = 0;		/* <<%%lexmemeber ...>>	   		MR1 */

+int	lexAction = 0;		/* <<%%lexaction ...>>			MR1 */

+int	parserClass = 0;	/* <<%%parserclass ...>>        MR1 */

+int	lexPrefix = 0;		/* <<%%lexprefix ...>>			MR1 */

+char	theClassName[100];						     /* MR11 */

+char	*pClassName=theClassName;					 /* MR11 */

+int	firstLexMember=1;					             /* MR1 */

+

+#ifdef __USE_PROTOS

+void  xxputc(int c) {						/* MR1 */

+#else

+void xxputc(c)							/* MR1 */

+  int	c;							/* MR1 */

+{								/* MR1 */

+#endif

+  if (parserClass) {						/* MR1 */

+    *pClassName++=c;						/* MR1 */

+    *pClassName=0;						/* MR1 */

+  } else if (lexMember || lexPrefix) {				/* MR1 */

+    if (class_stream != NULL) fputc(c,class_stream);		/* MR1 */

+  } else {							/* MR1 */

+    fputc(c,OUT);						/* MR1 */

+  };								/* MR1 */

+}  								/* MR1 */

+

+#ifdef __USE_PROTOS

+void xxprintf(char *format,char *string) {			/* MR1 */

+#else

+void xxprintf(format,string) 					/* MR1 */

+  char *format;							/* MR1 */

+  char *string;							/* MR1 */

+{								/* MR1 */

+#endif

+  if (lexMember || lexPrefix || parserClass) {			/* MR1 */

+    if (class_stream != NULL)					/* MR1 */

+	 fprintf(class_stream,format,string);			/* MR1 */

+  } else {							/* MR1 */

+    fprintf(OUT,format,string);					/* MR1 */

+  };								/* MR1 */

+}  								/* MR1 */

+>>

+

+#token "[\r\t\ ]+"	<< zzskip(); >>						/* Ignore white */

+#token "\n"			<< zzline++; zzskip(); DAWDLE; >>	/* Track Line # */

+#token L_EOF		"\@"

+#token PER_PER		"\%\%"

+#token NAME_PER_PER	"\%\%[a-zA-Z_][a-zA-Z0-9_]*"

+		<< p_mode_def(&zzlextext[2],lex_mode_counter++); >>

+

+#token LEXMEMBER	"\<\<\%\%lexmember"			/* MR1 */

+		<<lexMember=1;					/* MR1 */

+	          if (firstLexMember != 0) {			/* MR1 */

+	            firstLexMember=0;				/* MR1 */

+	            p_class_def1();				/* MR1 */

+		  };						/* MR1 */

+	          zzmode(ACT);					/* MR1 */

+                >>						/* MR1 */

+#token LEXACTION	"\<\<\%\%lexaction"			/* MR1 */

+		<<lexAction=1;zzmode(ACT);>>			/* MR1 */

+#token PARSERCLASS	"\<\<\%\%parserclass"			/* MR1 */

+		<<parserClass=1;				/* MR1 */

+		  zzmode(ACT);					/* MR1 */

+		>>						/* MR1 */

+#token LEXPREFIX	"\<\<\%\%lexprefix"			/* MR1 */

+		<<lexPrefix=1;zzmode(ACT);>>			/* MR1 */

+

+#token ACTION		"\<\<"

+		<< if (func_action)

+			fprintf(OUT,"\n%s %sact%d()\n{ ",

+					gen_cpp?"ANTLRTokenType":"static void",

+					gen_cpp?ClassName("::"):"", ++action_no);

+		   zzmode(ACT); zzskip();

+		>>

+#token GREAT_GREAT	"\>\>"

+#token L_BRACE		"\{"

+#token R_BRACE		"\}"

+#token L_PAR		"\("

+#token R_PAR		"\)"

+#token L_BRACK		"\["

+#token R_BRACK		"\]"

+#token ZERO_MORE	"\*"

+#token ONE_MORE		"\+"

+#token OR		"\|"

+#token RANGE		"\-"

+#token NOT		"\~"

+#token OCTAL_VALUE "\\0[0-7]*"		

+	<< {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}>>

+#token HEX_VALUE   "\\0[Xx][0-9a-fA-F]+"

+	<< {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}>>

+#token DEC_VALUE   "\\[1-9][0-9]*"

+	<< {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}>>

+#token TAB		"\\t"		<< zzlextext[0] = '\t';>>

+#token NL		"\\n"		<< zzlextext[0] = '\n';>>

+#token CR		"\\r"		<< zzlextext[0] = '\r';>>

+#token BS		"\\b"		<< zzlextext[0] = '\b';>>

+

+/* MR1									*/

+/* MR1 10-Apr-97 MR1	Allow #token regular expressions to cross lines	*/

+/* MR1									*/

+#token CONTINUATION	"\\ \n"		<< zzline++; zzskip();>> /* MR1 */

+

+/* NOTE: this takes ANYTHING after the \ */

+#token LIT		"\\~[tnrb]"	<< zzlextext[0] = zzlextext[1];>>

+

+/* NOTE: this takes ANYTHING that doesn't match the other tokens */

+#token REGCHAR		"~[\\]"

+

+

+grammar		:   << p_head(); p_class_hdr(); func_action = FALSE;>>

+		 ( {LEXACTION | LEXMEMBER | LEXPREFIX | PARSERCLASS } ACTION)* /* MR1 */

+		    <<if ( gen_cpp ) p_includes();>>

+		    start_states

+		    << func_action = FALSE; p_tables(); p_tail(); >>

+		    (ACTION)* "@"

+			<< if (firstLexMember != 0) p_class_def1(); >> 		/* MR1 */

+		;

+

+start_states	: ( PER_PER do_conversion

+		  | NAME_PER_PER do_conversion (NAME_PER_PER do_conversion)*)

+		    PER_PER

+		;

+

+do_conversion	: <<new_automaton_mode(); func_action = TRUE;>>

+			rule_list

+			<<

+				dfa_class_nop[mode_counter] =

+					relabel($1.l,comp_level);

+				if (comp_level)

+					p_shift_table(mode_counter);

+				dfa_basep[mode_counter] = dfa_allocated+1;

+				make_dfa_model_node(dfa_class_nop[mode_counter]);

+				nfa_to_dfa($1.l);

+				++mode_counter;

+		    		func_action = FALSE;

+#ifdef HASH_STAT

+				fprint_hash_stats(stderr);

+#endif

+			>>

+		;

+

+rule_list	: rule <<$$.l=$1.l; $$.r=$1.r;>>

+			(rule

+				<<{nfa_node *t1;

+				   t1 = new_nfa_node();

+				   (t1)->trans[0]=$$.l;

+				   (t1)->trans[1]=$1.l;

+				   /* all accept nodes "dead ends" */

+				   $$.l=t1; $$.r=NULL;

+				   }

+				>>

+			)*

+		| /* empty */

+			<<$$.l = new_nfa_node(); $$.r = NULL;

+			   warning("no regular expressions", zzline);

+			>>

+		;

+

+rule	: reg_expr ACTION

+/* MR23 */		<< if ($1.r != NULL) {

+					$$.l=$1.l; $$.r=$1.r; ($1.r)->accept=action_no;

+				   }

+				>>

+		| ACTION

+			<<$$.l = NULL; $$.r = NULL;

+			  error("no expression for action  ", zzline);

+			>>

+		;

+

+reg_expr	: and_expr <<$$.l=$1.l; $$.r=$1.r;>>

+			(OR and_expr

+				<<{nfa_node *t1, *t2;

+				   t1 = new_nfa_node(); t2 = new_nfa_node();

+				   (t1)->trans[0]=$$.l;

+				   (t1)->trans[1]=$2.l;

+/* MR23 */		   if ($$.r != NULL) ($$.r)->trans[1]=t2;

+                   if ($2.r) {

+    				   ($2.r)->trans[1]=t2;     /* MR20 */

+                   }

+				   $$.l=t1; $$.r=t2;

+				  }

+				>>

+			)*

+		;

+

+and_expr	: repeat_expr

+					<<

+						$$.l=$1.l; $$.r=$1.r;

+				    >>

+			(repeat_expr 

+/* MR23 */				<< if ($$.r != NULL) {

+							($$.r)->trans[1]=$1.l;

+							$$.r=$1.r;

+						   }

+						>>

+			)*

+		;

+

+repeat_expr	: expr <<$$.l=$1.l; $$.r=$1.r;>>

+			{ ZERO_MORE

+			<<{	nfa_node *t1,*t2;

+/* MR23 */		if ($$.r != NULL) ($$.r)->trans[0] = $$.l;

+				t1 = new_nfa_node(); t2 = new_nfa_node();

+				t1->trans[0]=$$.l;

+				t1->trans[1]=t2;

+/* MR23 */		if ($$.r != NULL) ($$.r)->trans[1]=t2;

+				$$.l=t1;$$.r=t2;

+			  }

+			>>

+			| ONE_MORE

+/* MR23 */		<<if ($$.r != NULL) ($$.r)->trans[0] = $$.l;>>

+			}

+		| ZERO_MORE

+			<< error("no expression for *", zzline);>>

+		| ONE_MORE

+			<< error("no expression for +", zzline);>>

+		;

+

+expr	: << $$.l = new_nfa_node();

+			 $$.r = new_nfa_node();

+		  >>

+		  L_BRACK atom_list R_BRACK

+			<<

+/* MR23 */		if ($$.l != NULL) {

+					($$.l)->trans[0] = $$.r;

+					($$.l)->label = set_dup($2.label);

+					set_orin(&used_chars,($$.l)->label);

+				}

+			>>

+		| NOT L_BRACK atom_list R_BRACK

+			<<

+/* MR23 */		if ($$.l != NULL) {

+					($$.l)->trans[0] = $$.r;

+					($$.l)->label = set_dif(normal_chars,$3.label);

+					set_orin(&used_chars,($$.l)->label);

+				}

+			>>

+		| L_PAR reg_expr R_PAR

+			<<

+/* MR23 */		if ($$.l != NULL) {				

+					($$.l)->trans[0] = $2.l;

+					if ($2.r) {

+    					($2.r)->trans[1] = $$.r;    /* MR20 */

+					}

+				}

+			>>

+		| L_BRACE reg_expr R_BRACE

+			<<

+/* MR23 */		if ($$.l != NULL) {

+					($$.l)->trans[0] = $2.l;

+					($$.l)->trans[1] = $$.r;

+			        if ($2.r) {

+    					($2.r)->trans[1] = $$.r;    /* MR20 */

+					}

+				}

+			>>

+		| atom

+			<<

+/* MR23 */		if ($$.l != NULL) {

+					($$.l)->trans[0] = $$.r;

+					($$.l)->label = set_dup($1.label);

+					set_orin(&used_chars,($$.l)->label);

+				}

+			>>

+		;

+

+atom_list	: << set_free($$.label); >>

+				(near_atom <<set_orin(&($$.label),$1.label);>>)*

+		;

+

+near_atom	: << register int i;

+		     register int i_prime;

+		  >>

+		  anychar

+			<<$$.letter=$1.letter; $$.label=set_of($1.letter);

+			i_prime = $1.letter + MIN_CHAR;

+			if (case_insensitive && islower(i_prime))

+				set_orel(toupper(i_prime)-MIN_CHAR,

+					&($$.label));

+			if (case_insensitive && isupper(i_prime))

+	 			set_orel(tolower(i_prime)-MIN_CHAR,

+					&($$.label));

+			>>

+			{ RANGE anychar

+				<< if (case_insensitive){

+					i_prime = $$.letter+MIN_CHAR;

+					$$.letter = (islower(i_prime) ?

+						toupper(i_prime) : i_prime)-MIN_CHAR;

+					i_prime = $2.letter+MIN_CHAR;

+					$2.letter = (islower(i_prime) ?

+						toupper(i_prime) : i_prime)-MIN_CHAR;

+				   }

+				   /* check to see if range okay */

+					{

+					    int debugLetter1 = $$.letter;

+						int debugLetter2 = $2.letter;

+					}

+				   if ($$.letter > $2.letter 

+                                       && $2.letter != 0xff){       /* MR16 */

+					  error("invalid range  ", zzline);

+				   }

+				   for (i=$$.letter; i<= (int)$2.letter; ++i){

+					set_orel(i,&($$.label));

+					i_prime = i+MIN_CHAR;

+					if (case_insensitive && islower(i_prime))

+						set_orel(toupper(i_prime)-MIN_CHAR,

+							&($$.label));

+					if (case_insensitive && isupper(i_prime))

+		 				set_orel(tolower(i_prime)-MIN_CHAR,

+							&($$.label));

+					}

+				>>

+			}

+		;

+

+atom		: << register int i_prime;>>

+		  anychar

+		  <<$$.label = set_of($1.letter);

+		    i_prime = $1.letter + MIN_CHAR;

+		    if (case_insensitive && islower(i_prime))

+			set_orel(toupper(i_prime)-MIN_CHAR,

+				&($$.label));

+		    if (case_insensitive && isupper(i_prime))

+	 		set_orel(tolower(i_prime)-MIN_CHAR,

+				&($$.label));

+		  >>

+		;

+

+anychar		: REGCHAR	<<$$.letter = $1.letter - MIN_CHAR;>>

+		| OCTAL_VALUE	<<$$.letter = $1.letter - MIN_CHAR;>>

+		| HEX_VALUE	<<$$.letter = $1.letter - MIN_CHAR;>>

+		| DEC_VALUE	<<$$.letter = $1.letter - MIN_CHAR;>>

+		| TAB		<<$$.letter = $1.letter - MIN_CHAR;>>

+		| NL		<<$$.letter = $1.letter - MIN_CHAR;>>

+		| CR		<<$$.letter = $1.letter - MIN_CHAR;>>

+		| BS		<<$$.letter = $1.letter - MIN_CHAR;>>

+		| LIT		<<$$.letter = $1.letter - MIN_CHAR;>>

+		/* NOTE: LEX_EOF is ALWAYS shifted to 0 = MIN_CHAR - MIN_CHAR*/

+		| L_EOF		<<$$.letter = 0;>>

+		;

+

+<</* empty action */>>

+

+#lexclass ACT

+#token "@"	<< error("unterminated action", zzline); zzmode(START); >>

+#token ACTION "\>\>"

+		<< if (func_action) fprintf(OUT,"}\n\n");

+		   zzmode(START);

+/* MR1									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+/* MR1				via <<%%lexmember ...>>			    */

+/* MR1			This is a consequence of not saving actions         */

+/* MR1									    */

+/* MR1 */	   parserClass=0;		

+/* MR1 */	   lexPrefix=0;

+/* MR1 */	   lexAction=0;

+/* MR1 */	   lexMember=0;

+		>>

+#token "\>"		<< xxputc(zzlextext[0]); zzskip(); >>		/* MR1 */

+#token "\\\>"		<< xxputc('>'); zzskip(); >>			/* MR1 */

+#token "\\"		<< xxputc('\\'); zzskip(); >>			/* MR1 */

+#token "\n"		<< xxputc(zzlextext[0]); ++zzline; zzskip(); >>	/* MR1 */

+#token "/\*"		<< zzmode(ACTION_COMMENTS);			/* MR1 */

+			   xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+			>>						/* MR1 */

+#token "//"		<< zzmode(ACTION_CPP_COMMENTS);			/* MR1 */

+			   xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+			>>						/* MR1 */

+#token "~[]"		<< xxputc(zzlextext[0]); zzskip(); >>		/* MR1 */

+									/* MR1 */

+#lexclass ACTION_COMMENTS						/* MR1 */

+#token "\*/"		<< zzmode(ACT);					/* MR1 */

+			   xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+			>>						/* MR1 */

+#token "[\n\r]"		<< zzline++; xxputc(zzlextext[0]); zzskip();>>	/* MR1 */

+#token "~[]"		<< xxputc(zzlextext[0]); zzskip();>>		/* MR1 */

+									/* MR1 */

+#lexclass ACTION_CPP_COMMENTS						/* MR1 */

+#token "[\n\r]"		<< zzmode(ACT); zzline++;			/* MR1 */

+			   xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+			>>						/* MR1 */

+#token "~[]"		<< xxputc(zzlextext[0]); zzskip();>>		/* MR1 */

+

+<<

+/* adds a new nfa to the binary tree and returns a pointer to it */

+nfa_node *

+#ifdef __USE_PROTOS

+new_nfa_node(void)

+#else

+new_nfa_node()

+#endif

+{

+	register nfa_node *t;

+	static int nfa_size=0;	/* elements nfa_array[] can hold */

+

+	++nfa_allocated;

+	if (nfa_size<=nfa_allocated){

+		/* need to redo array */

+		if (!nfa_array){

+			/* need some to do inital allocation */

+			nfa_size=nfa_allocated+NFA_MIN;

+			nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)*

+				nfa_size);

+		}else{

+			/* need more space */

+			nfa_size=2*(nfa_allocated+1);

+			nfa_array=(nfa_node **) realloc(nfa_array,

+				sizeof(nfa_node*)*nfa_size);

+		}

+	}

+	/* fill out entry in array */

+	t = (nfa_node*) malloc(sizeof(nfa_node));

+	nfa_array[nfa_allocated] = t;

+	*t = nfa_model_node;

+	t->node_no = nfa_allocated;

+	return t;

+}

+

+

+/* initialize the model node used to fill in newly made nfa_nodes */

+void

+#ifdef __USE_PROTOS

+make_nfa_model_node(void)

+#else

+make_nfa_model_node()

+#endif

+{

+	nfa_model_node.node_no = -1; /* impossible value for real nfa node */

+	nfa_model_node.nfa_set = 0;

+	nfa_model_node.accept = 0;   /* error state default*/

+	nfa_model_node.trans[0] = NULL;

+	nfa_model_node.trans[1] = NULL;

+	nfa_model_node.label = empty;

+}

+>>

+

+<<

+#if defined(DEBUG) || defined(_DEBUG)

+

+/* print out the pointer value and the node_number */

+void

+#ifdef __USE_PROTOS

+fprint_dfa_pair(FILE *f, nfa_node *p)

+#else

+fprint_dfa_pair(f, p)

+FILE *f;

+nfa_node *p;

+#endif

+{

+	if (p){

+		fprintf(f, "%x (%d)", p, p->node_no);

+	}else{

+		fprintf(f, "(nil)");

+	}

+}

+

+/* print out interest information on a set */

+void

+#ifdef __USE_PROTOS

+fprint_set(FILE *f, set s)

+#else

+fprint_set(f,s)

+FILE *f;

+set s;

+#endif

+{

+	unsigned int *x;

+

+	fprintf(f, "n = %d,", s.n);

+	if (s.setword){

+		fprintf(f, "setword = %x,   ", s.setword);

+		/* print out all the elements in the set */

+		x = set_pdq(s);

+		while (*x!=nil){

+			fprintf(f, "%d ", *x);

+			++x;

+		}

+	}else{

+		fprintf(f, "setword = (nil)");

+	}

+}

+

+/* code to be able to dump out the nfas

+	return 0 if okay dump

+	return 1 if screwed up

+ */

+int

+#ifdef __USE_PROTOS

+dump_nfas(int first_node, int last_node)

+#else

+dump_nfas(first_node, last_node)

+int first_node;

+int last_node;

+#endif

+{

+	register int i;

+	nfa_node *t;

+

+	for (i=first_node; i<=last_node; ++i){

+		t = NFA(i);

+		if (!t) break;

+		fprintf(stderr, "nfa_node %d {\n", t->node_no);

+		fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set);

+		fprintf(stderr, "\taccept\t=\t%d\n", t->accept);

+		fprintf(stderr, "\ttrans\t=\t(");

+		fprint_dfa_pair(stderr, t->trans[0]);

+		fprintf(stderr, ",");

+		fprint_dfa_pair(stderr, t->trans[1]);

+		fprintf(stderr, ")\n");

+		fprintf(stderr, "\tlabel\t=\t{ ");

+		fprint_set(stderr, t->label);

+		fprintf(stderr, "\t}\n");

+		fprintf(stderr, "}\n\n");

+	}

+	return 0;

+}

+#endif

+>>

+

+<<

+/* DLG-specific syntax error message generator

+ * (define USER_ZZSYN when compiling so don't get 2 definitions)

+ */

+void

+#ifdef __USE_PROTOS

+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)

+#else

+zzsyn(text, tok, egroup, eset, etok, k, bad_text)

+char *text, *egroup, *bad_text;

+int tok;

+int etok;

+int k;

+SetWordType *eset;

+#endif

+{

+	fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline);

+	fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);

+	if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}

+	if ( k==1 ) fprintf(stderr, " missing");

+	else

+	{

+		fprintf(stderr, "; \"%s\" not", bad_text);

+		if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");

+	}

+	if ( zzset_deg(eset)>0 ) zzedecode(eset);

+	else fprintf(stderr, " %s", zztokens[etok]);

+	if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);

+	fprintf(stderr, "\n");

+}

+>>

diff --git a/Source/Pccts/dlg/err.c b/Source/Pccts/dlg/err.c
new file mode 100644
index 0000000..c3eaeae
--- /dev/null
+++ b/Source/Pccts/dlg/err.c
@@ -0,0 +1,99 @@
+/*

+ * A n t l r  S e t s / E r r o r  F i l e  H e a d e r

+ *

+ * Generated from: dlg_p.g

+ *

+ * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001

+ * Parr Research Corporation

+ * with Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include <ctype.h>

+#include "dlg.h"

+#define zzSET_SIZE 8

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "err.h"

+

+ANTLRChar *zztokens[46]={

+	/* 00 */	"Invalid",

+	/* 01 */	"@",

+	/* 02 */	"[\\r\\t\\ ]+",

+	/* 03 */	"\\n",

+	/* 04 */	"L_EOF",

+	/* 05 */	"PER_PER",

+	/* 06 */	"NAME_PER_PER",

+	/* 07 */	"LEXMEMBER",

+	/* 08 */	"LEXACTION",

+	/* 09 */	"PARSERCLASS",

+	/* 10 */	"LEXPREFIX",

+	/* 11 */	"ACTION",

+	/* 12 */	"GREAT_GREAT",

+	/* 13 */	"L_BRACE",

+	/* 14 */	"R_BRACE",

+	/* 15 */	"L_PAR",

+	/* 16 */	"R_PAR",

+	/* 17 */	"L_BRACK",

+	/* 18 */	"R_BRACK",

+	/* 19 */	"ZERO_MORE",

+	/* 20 */	"ONE_MORE",

+	/* 21 */	"OR",

+	/* 22 */	"RANGE",

+	/* 23 */	"NOT",

+	/* 24 */	"OCTAL_VALUE",

+	/* 25 */	"HEX_VALUE",

+	/* 26 */	"DEC_VALUE",

+	/* 27 */	"TAB",

+	/* 28 */	"NL",

+	/* 29 */	"CR",

+	/* 30 */	"BS",

+	/* 31 */	"CONTINUATION",

+	/* 32 */	"LIT",

+	/* 33 */	"REGCHAR",

+	/* 34 */	"\\>",

+	/* 35 */	"\\\\>",

+	/* 36 */	"\\",

+	/* 37 */	"\\n",

+	/* 38 */	"/\\*",

+	/* 39 */	"//",

+	/* 40 */	"~[]",

+	/* 41 */	"\\*/",

+	/* 42 */	"[\\n\\r]",

+	/* 43 */	"~[]",

+	/* 44 */	"[\\n\\r]",

+	/* 45 */	"~[]"

+};

+SetWordType zzerr1[8] = {0x80,0xf,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr2[8] = {0x60,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};

+SetWordType zzerr3[8] = {0x70,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType setwd1[46] = {0x0,0x6,0x0,0x0,0x30,0xc8,0xc8,

+	0x1,0x1,0x1,0x1,0x35,0x0,0x30,0x0,

+	0x30,0x0,0x30,0x0,0x30,0x30,0x0,0x0,

+	0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,

+	0x0,0x30,0x30,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr4[8] = {0x10,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType zzerr5[8] = {0x10,0xe8,0xbb,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType zzerr6[8] = {0x10,0xa0,0x9a,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType setwd2[46] = {0x0,0x0,0x0,0x0,0xeb,0x2,0x2,

+	0x0,0x0,0x0,0x0,0xd6,0x0,0xeb,0xd4,

+	0xeb,0xd4,0xeb,0x0,0xcb,0xcb,0xd0,0x0,

+	0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,

+	0x0,0xeb,0xeb,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0};

+SetWordType zzerr7[8] = {0x10,0xa0,0x82,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType zzerr8[8] = {0x10,0x0,0x44,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType zzerr9[8] = {0x10,0x0,0x0,0x7f, 0x3,0x0,0x0,0x0};

+SetWordType setwd3[46] = {0x0,0x0,0x0,0x0,0xf7,0x0,0x0,

+	0x0,0x0,0x0,0x0,0xc2,0x0,0xc2,0xc2,

+	0xc2,0xc2,0xc2,0xb8,0xc2,0xc2,0xc2,0x80,

+	0xc2,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,

+	0x0,0xf7,0xf7,0x0,0x0,0x0,0x0,0x0,

+	0x0,0x0,0x0,0x0,0x0,0x0,0x0};

diff --git a/Source/Pccts/dlg/main.c b/Source/Pccts/dlg/main.c
new file mode 100644
index 0000000..35bd827
--- /dev/null
+++ b/Source/Pccts/dlg/main.c
@@ -0,0 +1,281 @@
+/* Main function for dlg version

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "stdpccts.h"

+

+char	program[] = "dlg";

+char	version[] = "1.33MR33";					/* MRXXX */

+int	numfiles = 0;

+char	*file_str[2] = {NULL, NULL};

+char	*mode_file = "mode.h";

+char	*class_name = DEFAULT_CLASSNAME;

+char	*OutputDirectory = TopDirectory;

+

+/* Option variables */

+int comp_level = 0;

+int interactive = FALSE;

+int case_insensitive = FALSE;

+int warn_ambig = FALSE;

+int gen_cpp = FALSE;

+

+#ifdef __USE_PROTOS

+static int ci_strequ(char *a,char *b)

+#else

+static int ci_strequ(a,b)

+  char  *a;

+  char  *b;

+#endif

+{

+  for ( ;*a != 0 && *b != 0; a++, b++) {

+    if (toupper(*a) != toupper(*b)) return 0;

+  }

+  return (*a == *b);

+}

+

+/* Option List Stuff */

+#ifdef __USE_PROTOS

+void p_comp0(void)		{comp_level = 0;}

+void p_comp1(void)		{comp_level = 1;}

+void p_comp2(void)		{comp_level = 2;}

+void p_stdio(void)		{ file_str[numfiles++] = NULL;}

+void p_file(char *s) 	{ file_str[numfiles++] = s;}

+void p_cl_name(char *s, char *t)

+	{

+		if ( gen_cpp ) {

+			class_name = t;

+		}

+		else {

+			warning("-cl only valid in C++ mode; -cl ignored...",0);

+		}

+	}

+void p_mode_file(char *s, char *t){mode_file=t;}

+void p_outdir(char *s,char *t) {OutputDirectory=t;}

+void p_ansi(void)		{gen_ansi = TRUE;}

+void p_interactive(void)	{interactive = TRUE;}

+void p_case_s(void)		{ case_insensitive = FALSE; }

+void p_case_i(void)		{ case_insensitive = TRUE; }

+void p_warn_ambig(void)	{ warn_ambig = TRUE; }

+void p_cpp(void)		{ gen_cpp = TRUE; }

+#else

+void p_comp0()		{comp_level = 0;}

+void p_comp1()		{comp_level = 1;}

+void p_comp2()		{comp_level = 2;}

+void p_stdio()		{ file_str[numfiles++] = NULL;}

+void p_file(s) char *s;	{ file_str[numfiles++] = s;}

+void p_cl_name(s,t)

+	char *s, *t;

+	{

+		if ( gen_cpp ) {

+			class_name = t;

+		}

+		else {

+			warning("-cl only valid in C++ mode; -cl ignored...",0);

+		}

+	}

+void p_mode_file(s,t) char *s,*t;{mode_file=t;}

+void p_outdir(s,t) char *s,*t;{OutputDirectory=t;}

+void p_ansi()		{gen_ansi = TRUE;}

+void p_interactive()	{interactive = TRUE;}

+void p_case_s()		{ case_insensitive = FALSE; }

+void p_case_i()		{ case_insensitive = TRUE; }

+void p_warn_ambig()	{ warn_ambig = TRUE; }

+void p_cpp()		{ gen_cpp = TRUE; }

+#endif

+

+#ifdef __cplusplus

+typedef void (*WildFunc)(...);

+#else

+typedef void (*WildFunc)();

+#endif

+

+typedef struct {

+			char *option;

+			int  arg;

+			WildFunc process;

+			char *descr;

+		} Opt;

+

+Opt options[] = {

+	{ "-CC", 0, (WildFunc)p_cpp, "Generate C++ output" },

+	{ "-C0", 0, (WildFunc)p_comp0, "No compression (default)" },

+	{ "-C1", 0, (WildFunc)p_comp1, "Compression level 1" },

+	{ "-C2", 0, (WildFunc)p_comp2, "Compression level 2" },

+	{ "-ga", 0, (WildFunc)p_ansi, "Generate ansi C"},

+	{ "-Wambiguity", 0, (WildFunc)p_warn_ambig, "Warn if expressions ambiguous"},

+	{ "-m", 1, (WildFunc)p_mode_file, "Rename lexical mode output file"},

+	{ "-i", 0, (WildFunc)p_interactive, "Build interactive scanner (not valid for C++ mode)"},

+	{ "-ci", 0, (WildFunc)p_case_i, "Make lexical analyzer case insensitive"},

+	{ "-cl", 1, (WildFunc)p_cl_name, "Rename lexer class (DLGLexer); only used for -CC"},

+	{ "-cs", 0, (WildFunc)p_case_s, "Make lexical analyzer case sensitive (default)"},

+	{ "-o",  1, (WildFunc)p_outdir, OutputDirectoryOption},

+	{ "-", 0, (WildFunc)p_stdio, "Use standard i/o rather than file"},

+	{ "*", 0, (WildFunc)p_file, ""}, /* anything else is a file */

+	{ NULL, 0, NULL }	

+ };

+

+#ifdef __USE_PROTOS

+void ProcessArgs(int argc, char **argv, Opt *options)

+#else

+void ProcessArgs(argc, argv, options)

+int argc;

+char **argv;

+Opt *options;

+#endif

+{

+	Opt *p;

+	

+	while ( argc-- > 0 )

+	{

+		p = options;

+		while ( p->option != NULL )

+		{

+			if ( strcmp(p->option, "*") == 0 ||

+				 ci_strequ(p->option,*argv) )

+			{

+				if ( p->arg )

+				{

+					(*p->process)( *argv, *(argv+1) );

+					argv++;

+					argc--;

+				}

+				else

+					(*p->process)( *argv );

+				break;

+			}

+			p++;

+		}

+		argv++;

+	}

+}

+

+#ifdef __USE_PROTOS

+int main(int argc, char *argv[])

+#else

+int main(argc, argv)

+int argc;

+char *argv[];

+#endif

+{

+	init();

+	fprintf(stderr, "%s  Version %s   1989-2001\n", &(program[0]),

+		&(version[0]));

+	if ( argc == 1 )

+	{

+		Opt *p = options;

+		fprintf(stderr, "%s [options] f1 f2 ... fn\n",argv[0]);

+		while ( *(p->option) != '*' )

+		{

+			fprintf(stderr, "\t%s %s\t%s\n",

+							p->option,

+							(p->arg)?"___":"   ",

+							p->descr);

+			p++;

+		}

+	}else{

+		ProcessArgs(argc-1, &(argv[1]), options);

+		if (interactive && gen_cpp) {

+			fprintf(stderr,"\n");

+/***  MR21a This statement is wrong ! ***/

+#if 0

+***			fprintf(stderr,"Interactive lexer option (\"-i\") has no effect when in C++ mode\n");

+***			fprintf(stderr,"because of extra buffering provided by ANTLRTokenBuffer class.\n");

+***			fprintf(stderr,"\n");

+#endif

+		}

+		input_stream = read_stream(file_str[0]);

+		if (input_stream) {

+			/* don't overwrite unless input okay */

+			if ( gen_cpp ) {

+				output_stream = write_stream(ClassName(CPP_FILE_SUFFIX));

+				if ( file_str[1]!=NULL ) {

+					warning("output file implicit in C++ mode; ignored...",0);

+				}

+				class_stream = write_stream(ClassName(".h"));

+				mode_stream = class_stream;

+			}

+			else {

+				output_stream = write_stream(file_str[1]);

+				mode_stream = write_stream(mode_file);

+			}

+		}

+		/* make sure that error reporting routines in grammar

+		   know what the file really is */

+		/* make sure that reading and writing somewhere */

+		if (input_stream && output_stream && mode_stream){

+			ANTLR(grammar(), input_stream);

+		}

+		p_class_def2();			/* MR1 */

+	}

+	if ( output_stream!=NULL ) fclose(output_stream);

+	if ( !gen_cpp && mode_stream!=NULL ) fclose(mode_stream);

+	if ( class_stream!=NULL ) fclose(class_stream);

+	exit(PCCTS_EXIT_SUCCESS);

+	return 0;		/* get rid of warning message MR1 */

+}

+

+/* initialize all the variables */

+void 

+#ifdef __USE_PROTOS

+init(void)

+#else

+init()

+#endif

+{

+	register int i;

+

+#ifdef SPECIAL_INITS

+	special_inits();					/* MR1 */

+#endif

+	used_chars = empty;

+	used_classes = empty;

+	/* make the valid character set */

+	normal_chars = empty;

+	/* NOTE: MIN_CHAR is EOF */

+	/* NOTE: EOF is not quite a valid char, it is special. Skip it*/

+	for (i = 1; i<CHAR_RANGE; ++i){

+		set_orel(i,&normal_chars);

+	}

+	make_nfa_model_node();

+	clear_hash();

+	/* NOTE: need to set this flag before the lexer starts getting */

+	/* tokens */

+   	func_action = FALSE;	

+}

+

+/* stuff that needs to be reset when a new automaton is being built */

+void 

+#ifdef __USE_PROTOS

+new_automaton_mode(void)					/* MR1 */

+#else

+new_automaton_mode()					/* MR1 */

+#endif

+{

+	set_free(used_chars);

+	clear_hash();

+}

diff --git a/Source/Pccts/dlg/makefile b/Source/Pccts/dlg/makefile
new file mode 100644
index 0000000..d5cceb8
--- /dev/null
+++ b/Source/Pccts/dlg/makefile
@@ -0,0 +1,156 @@
+#

+# Makefile for DLG 1.33

+# Terence Parr

+# Purdue University, U of MN, Parr Research Corporation

+# 1989-1994

+#

+# Ported to IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+##

+## Uncomment the appropriate section to build

+##

+

+#

+#   OS/2 & DOS 16 bit using MSC 6.0

+#

+#CC=cl

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=/NOD:LLIBCE LLIBCEP

+#OBJ_EXT = obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        link @<<

+#$** /NOI

+#$@ /STACK:16384

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        bind $@ c:\os2\doscalls.lib

+#        copy *.exe ..\bin

+#

+

+#

+#   Borland C++ for DOS

+#

+#CC=bcc

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= emu mathl cl

+#OBJ_EXT = obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#       tlink @&&|

+#C0L $**

+#$@ /Tde /c

+#

+#$(LIBS)

+#$(DEF_FILE) $(LFLAGS) ;

+#|

+#        copy *.exe ..\bin

+#

+

+#

+# C-Set/2 for OS/2

+#

+#CC=icc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 /DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT=obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        link386 @<<

+#$** /NOI

+#$@ /STACK:32768

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        copy *.exe ..\bin

+#

+

+#

+# Borland C++ for OS/2

+#

+#CC=bcc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= c2 os2

+#

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        tlink @&&|

+#c02 $** -c

+#dlg.exe

+#

+#C2 os2

+#

+#|

+#        copy *.exe ..\bin

+#

+

+#

+#   UNIX

+#

+CC=cc

+COPT=-O

+ANTLR=${BIN_DIR}/antlr

+DLG=${BIN_DIR}/dlg

+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -DZZLEXBUFSIZE=65536

+OBJ_EXT=o

+OUT_OBJ = -o

+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \

+        relabel.o automata.o

+

+dlg : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o ${BIN_DIR}/dlg $(OBJ)

+

+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \

+        relabel.c automata.c

+

+#dlg_p.c parser.dlg err.c tokens.h : dlg_p.g

+#	$(ANTLR) dlg_p.g

+

+#dlg_a.c mode.h : parser.dlg

+#	$(DLG) -C2 parser.dlg dlg_a.c

+

+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_p.c

+

+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_a.c

+

+main.$(OBJ_EXT) : main.c dlg.h

+	$(CC) $(CFLAGS) -c main.c

+

+set.$(OBJ_EXT) : $(SET)/set.c

+	$(CC) -c $(CFLAGS) $(SET)/set.c

+

+lint:

+	lint *.c

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

diff --git a/Source/Pccts/dlg/makefile.cygwin b/Source/Pccts/dlg/makefile.cygwin
new file mode 100644
index 0000000..bbba820
--- /dev/null
+++ b/Source/Pccts/dlg/makefile.cygwin
@@ -0,0 +1,157 @@
+#

+# Makefile for DLG 1.33

+# Terence Parr

+# Purdue University, U of MN, Parr Research Corporation

+# 1989-1994

+#

+# Ported to IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+##

+## Uncomment the appropriate section to build

+##

+

+#

+#   OS/2 & DOS 16 bit using MSC 6.0

+#

+#CC=cl

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=/NOD:LLIBCE LLIBCEP

+#OBJ_EXT = obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        link @<<

+#$** /NOI

+#$@ /STACK:16384

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        bind $@ c:\os2\doscalls.lib

+#        copy *.exe ..\bin

+#

+

+#

+#   Borland C++ for DOS

+#

+#CC=bcc

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= emu mathl cl

+#OBJ_EXT = obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#       tlink @&&|

+#C0L $**

+#$@ /Tde /c

+#

+#$(LIBS)

+#$(DEF_FILE) $(LFLAGS) ;

+#|

+#        copy *.exe ..\bin

+#

+

+#

+# C-Set/2 for OS/2

+#

+#CC=icc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 /DUSER_ZZSYN

+#OUT_OBJ = -Fo

+#LIBS=

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT=obj

+#

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        link386 @<<

+#$** /NOI

+#$@ /STACK:32768

+#

+#$(LIBS: = +^

+#)

+#$(DEF_FILE) $(LFLAGS) ;

+#<<

+#        copy *.exe ..\bin

+#

+

+#

+# Borland C++ for OS/2

+#

+#CC=bcc

+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -DUSER_ZZSYN

+#OUT_OBJ = -o

+#LIBS= c2 os2

+#

+#ANTLR=..\bin\antlr

+#DLG=..\bin\dlg

+#OBJ_EXT = obj

+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \

+#        output.obj relabel.obj automata.obj

+#        tlink @&&|

+#c02 $** -c

+#dlg.exe

+#

+#C2 os2

+#

+#|

+#        copy *.exe ..\bin

+#

+

+#

+#   UNIX

+#

+BIN_DIR=../../../../bin

+CC=cc

+COPT=-O

+ANTLR=$(BIN_DIR)/antlr.exe

+DLG=${BIN_DIR}/dlg.exe

+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -DZZLEXBUFSIZE=65536

+OBJ_EXT=o

+OUT_OBJ = -o

+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \

+        relabel.o automata.o

+

+dlg : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o $(BIN_DIR)/dlg.exe $(OBJ)

+

+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \

+        relabel.c automata.c

+

+#dlg_p.c parser.dlg err.c tokens.h : dlg_p.g

+#	$(ANTLR) dlg_p.g

+

+#dlg_a.c mode.h : parser.dlg

+#	$(DLG) -C2 parser.dlg dlg_a.c

+

+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_p.c

+

+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_a.c

+

+main.$(OBJ_EXT) : main.c dlg.h

+	$(CC) $(CFLAGS) -c main.c

+

+set.$(OBJ_EXT) : $(SET)/set.c

+	$(CC) -c $(CFLAGS) $(SET)/set.c

+

+lint:

+	lint *.c

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

diff --git a/Source/Pccts/dlg/makefile1 b/Source/Pccts/dlg/makefile1
new file mode 100644
index 0000000..4d00f79
--- /dev/null
+++ b/Source/Pccts/dlg/makefile1
@@ -0,0 +1,63 @@
+#

+# Makefile for DLG 1.33

+# Terence Parr

+# Purdue University, U of MN, Parr Research Corporation

+# 1989-1994

+#

+# Ported to IBM C-Set/2 and Microsoft 6.0 by

+# Ed Harfmann

+# Micro Data Base Systems

+# Lafayette, Indiana

+#

+SET=../support/set

+PCCTS_H=../h

+

+##

+## Uncomment the appropriate section to build

+##

+

+

+#

+#   UNIX

+#

+CC=cc

+ANTLR=../bin/antlr

+DLG=../bin/dlg

+ANSI=-ansi

+CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000

+OBJ_EXT=o

+OUT_OBJ = -o

+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \

+        relabel.o automata.o

+

+dlg : $(OBJ) $(SRC)

+		$(CC) $(CFLAGS) -o dlg $(OBJ)

+		mv dlg ../bin

+

+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \

+        relabel.c automata.c

+

+dlg_p.c parser.dlg err.c tokens.h : dlg_p.g

+	$(ANTLR) dlg_p.g

+

+dlg_a.c mode.h : parser.dlg

+	$(DLG) -C2 parser.dlg dlg_a.c

+

+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_p.c

+

+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h

+	$(CC) $(CFLAGS) -c dlg_a.c

+

+main.$(OBJ_EXT) : main.c dlg.h

+	$(CC) $(CFLAGS) -c main.c

+

+set.$(OBJ_EXT) : $(SET)/set.c

+	$(CC) -c $(CFLAGS) $(SET)/set.c

+

+lint:

+	lint *.c

+

+#clean up all the intermediate files

+clean:

+	rm -f *.$(OBJ_EXT) core

diff --git a/Source/Pccts/dlg/mode.h b/Source/Pccts/dlg/mode.h
new file mode 100644
index 0000000..3f3279e
--- /dev/null
+++ b/Source/Pccts/dlg/mode.h
@@ -0,0 +1,4 @@
+#define START 0

+#define ACT 1

+#define ACTION_COMMENTS 2

+#define ACTION_CPP_COMMENTS 3

diff --git a/Source/Pccts/dlg/output.c b/Source/Pccts/dlg/output.c
new file mode 100644
index 0000000..2e56a6d
--- /dev/null
+++ b/Source/Pccts/dlg/output.c
@@ -0,0 +1,850 @@
+/* output.c, output generator for dlg

+ *

+ * Output Notes:

+ *

+ * DfaStates == number of dfa nodes in automaton (just a #define)

+ * DfaState == type large enough to index every node in automaton

+ *         <256 unsigned char, <65536 unsigned short, etc.

+ *

+ * Thus, the elements in each of the automaton states (st%d) are type DfaState

+ * and are size appropriately, since they must be able to index the next

+ * automaton state.

+ *

+ * dfa[] == a linear array that points to all the automaton states (st%d)

+ *         (dfa_base[] should be the same, but isn't right now)

+ *

+ * accepts[] == Taking a closer look at this one, it probably shouldn't be type

+ *         DfaState because there is no real requirement that the number of

+ *         accepts states is less than the number of dfa state.  However, if

+ *         the number of accept states was more than the number of DFA states

+ *         then the lexical specification would be really ambiguous.

+ *

+ *         Another note. Is that is should be possible to fold accepts[] and

+ *         actions[] together.  If this is done, I would suggest get rid of

+ *         accept[] and make actions[] have an entry for each state (st%d) in

+ *         the automaton.

+ *

+ * dfa_base[] == starting location for each lexical mode.  This should be

+ *         Dfastate type (but isn't right now), since it points to the states

+ *         in the automaton.

+ *

+ * dfa_class_no[] == indicates the number of columns each lexical mode has.

+ *

+ * b_class_no[] == pointer to the start of the translation array used to

+ *         convert from input character to character class.  This could cause

+ *         problems if there are more than 256 classes

+ *

+ * shift%d[] == the actual translation arrays that convert the input character

+ *         into the character class.  These will have to change if there are

+ *         more than 256 character classes.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <string.h>

+#include "dlg.h"

+#ifdef MEMCHK

+#include "trax.h"

+#else

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif /* __STDC__ */

+#endif

+

+static char *mode_name[MAX_MODES];

+static int mode_number[MAX_MODES];

+static int cur_mode=0;

+

+int operation_no = 0; /* used to mark nodes so that infinite loops avoided */

+int dfa_basep[MAX_MODES]; 	/* start of each group of states */

+int dfa_class_nop[MAX_MODES];	/* number of elements in each group of states*/

+

+int gen_ansi = FALSE;		/* allows ansi code to be generated */

+

+FILE *input_stream;	/* where to read description from */

+FILE *output_stream;	/* where to put the output	  */

+FILE *mode_stream;	/* where to put the mode.h stuff */

+FILE *class_stream;	/* where to put the scan.h stuff (if gen_cpp) */

+

+/* NOTE: This section is MACHINE DEPENDENT */

+#define DIF_SIZE 4

+#if defined(PC) && !defined(PC32)

+unsigned long typesize[DIF_SIZE]  = { 0x7f, 0x7fff, 0x7ffful, 0x7ffffffful }; /* MR20 */

+char t0[] = "unsigned char";

+char t1[] = "unsigned short";

+char t2[] = "unsigned int";

+char t3[] = "unsigned long";

+char *typevar[DIF_SIZE] = { t0, t1, t2, t3};

+#else

+unsigned long typesize[DIF_SIZE]  = { 0x7f, 0x7fff, 0x7ffffffful, 0x7ffffffful }; /* MR20 */

+char t0[] = "unsigned char";

+char t1[] = "unsigned short";

+char t2[] = "unsigned int";

+char t3[] = "unsigned long";

+char *typevar[DIF_SIZE] = { t0, t1, t2, t3};

+#endif

+

+/* Added by TJP August 1994 */

+/* Take in MyLexer and return MyLexer_h */

+

+static char *

+#ifdef __USE_PROTOS

+gate_symbol(char *name)

+#else

+gate_symbol(name)

+char *name;

+#endif

+{

+	static char buf[100];

+	sprintf(buf, "%s_h", name);

+	return buf;

+}

+

+/* Added by TJP August 1994 */

+static char *

+#ifdef __USE_PROTOS

+mystrdup(char *s)

+#else

+mystrdup(s)

+char *s;

+#endif

+{

+	char *p = (char *)malloc(strlen(s)+1);

+	strcpy(p, s);

+	return p;

+}

+

+#ifdef __USE_PROTOS

+void p_class_hdr(void)

+#else

+void p_class_hdr()						

+#endif

+{

+	if ( class_stream == NULL ) return;

+	fprintf(class_stream, "#ifndef %s\n", gate_symbol(ClassName("")));

+	fprintf(class_stream, "#define %s\n", gate_symbol(ClassName("")));

+	fprintf(class_stream, "/*\n");

+	fprintf(class_stream, " * D L G L e x e r  C l a s s  D e f i n i t i o n\n");

+	fprintf(class_stream, " *\n");

+	fprintf(class_stream, " * Generated from:");

+	fprintf(class_stream, " %s", file_str[0]);

+	fprintf(class_stream, "\n");

+	fprintf(class_stream, " *\n");

+	fprintf(class_stream, " * 1989-2001 by  Will Cohen, Terence Parr, and Hank Dietz\n");

+	fprintf(class_stream, " * Purdue University Electrical Engineering\n");

+	fprintf(class_stream, " * DLG Version %s\n", version);

+	fprintf(class_stream, " */\n\n");

+	fprintf(class_stream, "\n");

+	fprintf(class_stream, "#include \"%s\"\n", DLEXERBASE_H);

+}

+

+/* MR1									*/

+/* MR1 16-Apr-97  Split printing of class header up into several parts  */

+/* MR1		    so that #lexprefix <<...>>and #lexmember <<...>>	*/

+/* MR1		    can be inserted in the appropriate spots		*/

+/* MR1									*/

+

+#ifdef __USE_PROTOS

+void p_class_def1(void)

+#else

+void p_class_def1()

+#endif

+{

+	if ( class_stream == NULL ) return;

+	fprintf(class_stream, "\nclass %s : public DLGLexerBase {\n", ClassName(""));

+	fprintf(class_stream, "public:\n");

+}

+

+#ifdef __USE_PROTOS

+void p_class_def2(void)

+#else

+void p_class_def2()

+#endif

+{

+	int i, m;

+	if ( class_stream == NULL ) return;

+	fprintf(class_stream, "public:\n");

+	fprintf(class_stream, "\tstatic const int MAX_MODE;\n");

+	fprintf(class_stream, "\tstatic const int DfaStates;\n");

+	for (i=0; i<cur_mode; i++) {

+		fprintf(class_stream, "\tstatic const int %s;\n", mode_name[i]);

+	}

+

+	fprintf(class_stream, "\ttypedef %s DfaState;\n\n", minsize(dfa_allocated));

+	fprintf(class_stream, "\t%s(DLGInputStream *in,\n",ClassName(""));

+	fprintf(class_stream, "\t\tunsigned bufsize=2000)\n");

+	fprintf(class_stream, "\t\t: DLGLexerBase(in, bufsize, %d)\n", interactive);

+	fprintf(class_stream, "\t{\n");

+	fprintf(class_stream, "\t;\n");

+	fprintf(class_stream, "\t}\n");

+	fprintf(class_stream, "\tvoid	  mode(int);\n");

+	fprintf(class_stream, "\tANTLRTokenType nextTokenType(void);\n");

+	fprintf(class_stream, "\tvoid     advance(void);\n");

+	fprintf(class_stream, "protected:\n");

+	for (i=1; i<=action_no; ++i) {

+		fprintf(class_stream, "\tANTLRTokenType act%d();\n", i);

+	}

+

+	for(m=0; m<(mode_counter-1); ++m){

+		for(i=dfa_basep[m]; i<dfa_basep[m+1]; ++i)

+			fprintf(class_stream, "\tstatic DfaState st%d[%d];\n", i-1, dfa_class_nop[m]+1);

+	}

+	for(i=dfa_basep[m]; i<=dfa_allocated; ++i)

+		fprintf(class_stream, "\tstatic DfaState st%d[%d];\n", i-1, dfa_class_nop[m]+1);

+

+	fprintf(class_stream, "\tstatic DfaState *dfa[%d];\n", dfa_allocated);

+	fprintf(class_stream, "\tstatic DfaState dfa_base[];\n");

+/*	fprintf(class_stream, "\tstatic int dfa_base_no[];\n"); */

+	fprintf(class_stream, "\tstatic unsigned char *b_class_no[];\n");

+	fprintf(class_stream, "\tstatic DfaState accepts[%d];\n",dfa_allocated+1);

+	fprintf(class_stream, "\tstatic DLGChar alternatives[%d];\n",dfa_allocated+1);

+	/* WARNING: should be ANTLRTokenType for action table, but g++ 2.5.6 is hosed */

+	fprintf(class_stream, "\tstatic ANTLRTokenType (%s::*actions[%d])();\n", ClassName(""), action_no+1);

+	for(m=0; m<mode_counter; ++m) {

+		fprintf(class_stream, "\tstatic unsigned char shift%d[%d];\n",

+			m, CHAR_RANGE);

+	}

+	if (comp_level)

+		fprintf(class_stream, "\tint ZZSHIFT(int c) { return b_class_no[automaton][1+c]; }\n");

+	else

+		fprintf(class_stream, "\tint ZZSHIFT(int c) { return 1+c; }\n");

+

+/* MR1									  */

+/* MR1 11-APr-97   Kludge to allow inclusion of user-defined code in	  */

+/* MR1			 DLGLexer class header				  */

+/* MR1		   Deprecated in favor of 133MR1 addition #lexmember <<>> */

+/* MR1									  */

+/* MR1 */	fprintf(class_stream,"//\n");

+/* MR1 */	fprintf(class_stream,

+/* MR1 */	   "// 133MR1 Deprecated feature to allow inclusion of ");

+/* MR1 */	fprintf(class_stream,

+/* MR1 */	   "user-defined code in DLG class header\n");

+/* MR1 */	fprintf(class_stream,"//\n");

+/* MR1 */

+/* MR1 */	fprintf(class_stream,"#ifdef DLGLexerIncludeFile\n");

+/* MR1 */	fprintf(class_stream,"#include DLGLexerIncludeFile\n");

+/* MR1 */	fprintf(class_stream,"#endif\n");

+

+	fprintf(class_stream, "};\n");

+

+	fprintf(class_stream, "typedef ANTLRTokenType (%s::*Ptr%sMemberFunc)();\n",

+			ClassName(""), ClassName(""));

+

+	fprintf(class_stream, "#endif\n");

+}

+

+/* generate required header on output */

+

+#ifdef __USE_PROTOS

+void p_head(void)

+#else

+void p_head()

+#endif

+{

+	fprintf(OUT, "/*\n");

+	fprintf(OUT, " * D L G tables\n");

+	fprintf(OUT, " *\n");

+	fprintf(OUT, " * Generated from:");

+	fprintf(OUT, " %s", file_str[0]);

+	fprintf(OUT, "\n");

+	fprintf(OUT, " *\n");

+	fprintf(OUT, " * 1989-2001 by  Will Cohen, Terence Parr, and Hank Dietz\n");

+	fprintf(OUT, " * Purdue University Electrical Engineering\n");

+	fprintf(OUT, " * DLG Version %s\n", version);

+	fprintf(OUT, " */\n\n");

+	if ( gen_cpp)  fprintf(OUT, "#include \"pcctscfg.h\"\n");

+	if ( gen_cpp ) fprintf(OUT, "#include \"pccts_stdio.h\"\n");

+	if ( !gen_cpp ) fprintf(OUT, "#include \"%s\"\n\n", mode_file);

+	fprintf(OUT,"\n");

+}

+

+#ifdef __USE_PROTOS

+void p_includes(void)

+#else

+void p_includes()

+#endif

+{

+	fprintf(OUT, "#include \"%s\"\n", APARSER_H);

+	fprintf(OUT, "#include \"%s\"\n", DLEXERBASE_H);

+	fprintf(OUT, "#include \"%s\"\n", ClassName(".h"));

+}

+

+/* generate code to tie up any loose ends */

+

+#ifdef __USE_PROTOS

+void p_tail(void)   				/* MR1 */

+#else

+void p_tail()						/* MR1 */

+#endif

+{

+	if ( gen_cpp ) {

+		if ( strcmp(ClassName(""), DEFAULT_CLASSNAME)!=0 )

+			fprintf(OUT, "#define DLGLexer %s\n", ClassName(""));

+		fprintf(OUT, "#include \"%s\"\n", DLEXER_H);  /* MR23 Rename DLexer.cpp to DLexer.h */

+		return;

+	}

+	fprintf(OUT, "\n");

+	fprintf(OUT, "\n");

+	if (comp_level)

+		fprintf(OUT, "#define ZZSHIFT(c) (b_class_no[zzauto][1+c])\n");

+	else

+		fprintf(OUT, "#define ZZSHIFT(c) (1+c)\n");

+	if ( !gen_cpp ) fprintf(OUT, "#define MAX_MODE %d\n",mode_counter);

+	fprintf(OUT, "#include \"dlgauto.h\"\n");

+}

+

+

+/* output the table of DFA for general use */

+

+#ifdef __USE_PROTOS

+void p_tables()

+#else

+void p_tables()

+#endif

+{

+	if ( !gen_cpp ) {

+		fprintf(OUT, "#define DfaStates\t%d\n", dfa_allocated);

+		fprintf(OUT, "typedef %s DfaState;\n\n", minsize(dfa_allocated));

+	}

+

+	if ( gen_cpp ) {

+		int i;

+		fprintf(OUT, "\n");

+		fprintf(OUT, "const int %s::MAX_MODE=%d;\n",

+				ClassName(""),

+				mode_counter);

+		fprintf(OUT, "const int %s::DfaStates=%d;\n",

+				ClassName(""),

+				dfa_allocated);

+		for (i=0; i<cur_mode; i++) {

+			fprintf(OUT, "const int %s::%s=%d;\n",

+					ClassName(""), mode_name[i], mode_number[i]);

+		}

+		fprintf(OUT, "\n");

+	}

+

+	p_node_table();

+	p_dfa_table();

+	p_accept_table();

+	p_action_table();

+	p_base_table();

+	p_class_table();

+	if (comp_level)

+		p_bshift_table();

+	if (interactive || gen_cpp )

+		p_alternative_table();

+}

+

+

+/* figures out the smallest variable type that will hold the transitions

+ */

+

+#ifdef __USE_PROTOS

+char *minsize(int elements)

+#else

+char *minsize(elements)

+int elements;

+#endif

+{

+	int i = 0;

+

+	while ((unsigned long) elements > typesize[i]) /* MR20 */

+		++i;

+	return typevar[i];

+}

+

+

+#ifdef __USE_PROTOS

+void p_node_table(void)

+#else

+void p_node_table()

+#endif

+{

+	register int	i;

+	register int	m = 0;

+

+	for(m=0; m<(mode_counter-1); ++m){

+		for(i=dfa_basep[m]; i<dfa_basep[m+1]; ++i)

+			p_single_node(i,dfa_class_nop[m]);

+	}

+	for(i=dfa_basep[m]; i<=dfa_allocated; ++i)

+		p_single_node(i,dfa_class_nop[m]);

+}

+

+

+#ifdef __USE_PROTOS

+void p_single_node(int i,int classes)

+#else

+void p_single_node(i,classes)

+int i,classes;

+#endif

+{

+	register int	j;

+	register int	trans, items_on_line;

+

+#if 1

+	/* extra state (classes+1) for invalid characters */

+	fprintf(OUT, "%sDfaState %sst%d[%d] = {\n  ",

+		gen_cpp?ClassName("::"):"static ",

+		gen_cpp?ClassName("::"):"",(i-1), (classes+1));

+#else

+	fprintf(OUT, "static DfaState st%d[%d] = {\n  ", (i-1), classes);

+#endif

+	items_on_line = MAX_ON_LINE;

+	for(j=0; j<classes; ++j){

+		DAWDLE;

+		trans = DFA(i)->trans[j];

+		if (trans == NIL_INDEX)

+			trans = dfa_allocated+1;

+		/* all of DFA moved down one in array */

+		fprintf(OUT, "%d", trans-1);

+		fprintf(OUT, ", ");

+		if (!(--items_on_line)){

+			fprintf(OUT, "\n  ");

+			items_on_line = MAX_ON_LINE;

+		}

+	}

+#if 1

+	/* put in jump to error state */

+	fprintf(OUT, "%d\n};\n\n", dfa_allocated);

+#else

+	fprintf(OUT, "\n};\n\n");

+#endif

+}

+

+

+#ifdef __USE_PROTOS

+void p_dfa_table(void)

+#else

+void p_dfa_table()

+#endif

+{

+	register int	i;

+

+	fprintf(OUT, "\n%sDfaState *%sdfa[%d] = {\n",

+		gen_cpp?ClassName("::"):"",gen_cpp?ClassName("::"):"", dfa_allocated);

+	for (i=0; i<(dfa_allocated-1); ++i){

+		fprintf(OUT, "\tst%d,\n", i);

+	}

+	fprintf(OUT, "\tst%d\n", i);

+	fprintf(OUT, "};\n\n");

+}

+

+

+#ifdef __USE_PROTOS

+void p_accept_table(void)

+#else

+void p_accept_table()

+#endif

+{

+	register int	i = 1;

+	register int	items_on_line = 0;

+	int		true_interactive = TRUE;

+

+	/* make sure element for one past (zzerraction) -WEC 12/16/92 */

+	fprintf(OUT,"\n%sDfaState %saccepts[%d] = {\n  ",

+			gen_cpp?ClassName("::"):"",

+			gen_cpp?ClassName("::"):"",

+			dfa_allocated+1);

+	/* don't do anything if no dfa nodes */

+	if (i>dfa_allocated) goto skip_accepts;

+	for (;;) {

+		int accept=0;   /* MR14a - Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) */

+		set accept_set;

+		set nfa_states;

+		unsigned int *t, *nfa_i;

+		unsigned int *q, *regular_expr;

+

+		accept_set = empty;

+		nfa_states = DFA(i)->nfa_states;

+		t = nfa_i = set_pdq(nfa_states);

+		/* NOTE: picks lowest accept because accepts monotonic	*/

+		/*	with respect to nfa node numbers and set_pdq	*/

+		/*	returns in that order				*/

+		while((*nfa_i != nil) && (!(accept = NFA(*nfa_i)->accept))){

+			nfa_i++;

+		}

+

+		/* figure out if more than one accept state there */

+		if (warn_ambig ){

+			set_orel(accept, &accept_set);

+			while(*nfa_i != nil){

+				set_orel(NFA(*nfa_i)->accept, &accept_set);

+				nfa_i++;

+			}

+			/* remove error action from consideration */

+			set_rm(0, accept_set);

+

+			if( set_deg(accept_set)>1){

+				fprintf(stderr, "dlg warning: ambiguous regular expression ");

+				q = regular_expr = set_pdq(accept_set);

+				while(*regular_expr != nil){

+					fprintf(stderr," %d ", *regular_expr);

+					++regular_expr;

+				}

+				fprintf(stderr, "\n");

+				free(q);

+			}

+		}

+

+		if ((DFA(i)->alternatives) && (accept != 0)){

+			true_interactive = FALSE;

+		}

+		fprintf(OUT, "%d, ", accept);

+

+		/* free up memory before we "break" below -ATG 4/6/95 */

+		free(t);

+		set_free(accept_set);

+

+		if ((++i)>dfa_allocated)

+			break;

+		if ((++items_on_line)>=MAX_ON_LINE){

+			fprintf(OUT,"\n  ");

+			items_on_line = 0;

+		}

+/*

+		free(t);

+		set_free(accept_set);

+*/

+	}

+	/* make sure element for one past (zzerraction) -WEC 12/16/92 */

+skip_accepts:

+	fprintf(OUT, "0\n};\n\n");

+}

+

+

+#ifdef __USE_PROTOS

+void p_action_table(void)

+#else

+void p_action_table()

+#endif

+{

+	register int	i;

+	char* theClassName = ClassName("");

+

+	if ( gen_cpp )

+		fprintf(OUT, "Ptr%sMemberFunc %s::actions[%d] = {\n", theClassName,

+					theClassName, action_no+1);

+	else

+		fprintf(OUT, "void (*actions[%d])() = {\n", action_no+1);

+	if ( gen_cpp )

+/*		fprintf(OUT, "\t(Ptr%sMemberFunc)&%s::erraction,\n", theClassName, theClassName);*/

+		fprintf(OUT, "\t&%s::erraction,\n", theClassName);

+	else

+		fprintf(OUT, "\tzzerraction,\n");

+	for (i=1; i<action_no; ++i) {

+		if ( gen_cpp )

+/*			fprintf(OUT,"\t(Ptr%sMemberFunc)&%s::act%d,\n", theClassName, theClassName, i);*/

+			fprintf(OUT,"\t&%s::act%d,\n", theClassName, i);

+		else

+			fprintf(OUT,"\tact%d,\n", i);

+		DAWDLE;

+	}

+	if ( gen_cpp )

+/*		fprintf(OUT,"\t(Ptr%sMemberFunc)&%s::act%d\n", theClassName, theClassName, i);*/

+		fprintf(OUT,"\t&%s::act%d\n", theClassName, i);

+	else

+		fprintf(OUT,"\tact%d\n", i);

+	fprintf(OUT, "};\n\n");

+}

+

+

+#ifdef __USE_PROTOS

+void p_shift_table(int m)  				    /* MR1 */

+#else

+void p_shift_table(m)						/* MR1 */

+int m;

+#endif

+{

+	register int	i = 0, j;

+	register int	items_on_line = 0;

+

+	fprintf(OUT, "%s unsigned char %sshift%d[%d] = {\n  ",

+		gen_cpp?"":"static",

+		gen_cpp?ClassName("::"):"", m, CHAR_RANGE);

+	for (;;) {

+		/* find which partition character i is in */

+		for (j=0; j<dfa_class_nop[mode_counter]; ++j){

+			if (set_el(i,class_sets[j]))

+				break;

+			}

+		fprintf(OUT,"%d",j);

+		if ((++i)>=CHAR_RANGE)

+			break;

+		fprintf(OUT,", ");

+		if ((++items_on_line)>=MAX_ON_LINE){

+			fprintf(OUT,"\n  ");

+			items_on_line = 0;

+			}

+		}

+	fprintf(OUT, "\n};\n\n");

+}

+

+

+#ifdef __USE_PROTOS

+void p_base_table(void)

+#else

+void p_base_table()

+#endif

+{

+	register int m;

+

+	fprintf(OUT, "%sDfaState %sdfa_base[] = {\n",

+			gen_cpp?ClassName("::"):"static ",

+			gen_cpp?ClassName("::"):"");

+	for(m=0; m<(mode_counter-1); ++m)

+		fprintf(OUT, "\t%d,\n", dfa_basep[m]-1);

+	fprintf(OUT, "\t%d\n};\n\n", dfa_basep[m]-1);

+}

+

+

+#ifdef __USE_PROTOS

+void p_class_table(void)    				/* MR1 */

+#else

+void p_class_table()						/* MR1 */

+#endif

+{

+#if 0

+	register int m;

+

+	fprintf(OUT,"%s int %sdfa_class_no[] = {\n",

+			gen_cpp?"":"static",

+			gen_cpp?ClassName("::"):"");

+	for(m=0; m<(mode_counter-1); ++m)

+		fprintf(OUT,"\t%d,\n", dfa_class_nop[m]);

+	fprintf(OUT,"\t%d\n};\n\n", dfa_class_nop[m]);

+#endif

+}

+

+

+#ifdef __USE_PROTOS

+void p_bshift_table(void)					/* MR1 */

+#else

+void p_bshift_table()						/* MR1 */

+#endif

+{

+	register int m;

+

+	fprintf(OUT,"%s unsigned char *%sb_class_no[] = {\n",

+		gen_cpp?"":"static",

+		gen_cpp?ClassName("::"):"");

+	for(m=0; m<(mode_counter-1); ++m)

+		fprintf(OUT, "\tshift%d,\n", m);

+	fprintf(OUT, "\tshift%d\n};\n\n", m);

+}

+

+

+#ifdef __USE_PROTOS

+void p_alternative_table(void)				/* MR1 */

+#else

+void p_alternative_table()					/* MR1 */

+#endif

+{

+	register int i;

+

+	if ( !gen_cpp ) fprintf(OUT, "#define ZZINTERACTIVE\n\n");

+	if ( gen_cpp )

+		fprintf(OUT, "DLGChar %salternatives[%d] = {\n",  /* mr23 vhs %sDfaStates+1 */

+				ClassName("::"),

+				dfa_allocated+1); /* vhs ClassName("::")); */

+	else

+		fprintf(OUT, "static %s zzalternatives[DfaStates+1] = {\n",

+				minsize(dfa_allocated));

+

+	for(i=1; i<=dfa_allocated; ++i)

+		fprintf(OUT, "\t%d,\n", DFA(i)->alternatives);

+	fprintf(OUT, "/* must have 0 for zzalternatives[DfaStates] */\n");

+	fprintf(OUT, "\t0\n};\n\n");

+}

+

+

+#ifdef __USE_PROTOS

+void p_mode_def(char *s,int m)			/* MR1 */

+#else

+void p_mode_def(s,m)					/* MR1 */

+char *s;

+int m;

+#endif

+{

+	if ( gen_cpp )

+	{

+		mode_name[cur_mode] = mystrdup(s);

+		mode_number[cur_mode] = m;

+		cur_mode++;

+	}

+	else

+		fprintf(mode_stream, "#define %s %d\n", s, m);

+}

+

+#ifdef __USE_PROTOS

+char * ClassName(char *suffix)

+#else

+char * ClassName(suffix)

+char *suffix;

+#endif

+{

+	static char buf[200];

+	extern char *class_name;

+

+	sprintf(buf, "%s%s", class_name, suffix);

+	return buf;

+}

+

+#ifdef DEBUG

+

+/* print out a particular nfa node that is pointed to by p */

+

+#ifdef __USE_PROTOS

+void p_nfa_node(nfa_node *p)

+#else

+void p_nfa_node(p)

+nfa_node *p;

+#endif

+{

+	 register nfa_node *t;

+

+	if (p != NIL_INDEX){

+		printf("NFA state : %d\naccept state : %d\n",

+			NFA_NO(p),p->accept);

+		if (p->trans[0] != NIL_INDEX){

+			printf("trans[0] => %d on ", NFA_NO(p->trans[0]));

+			p_set(p->label);

+			printf("\n");

+			}

+		else

+			printf("trans[0] => nil\n");

+		if (p->trans[1] != NIL_INDEX)

+			printf("trans[1] => %d on epsilon\n",

+				NFA_NO(p->trans[1]));

+		else

+			printf("trans[1] => nil\n");

+		printf("\n");

+		}

+}

+#endif

+

+#ifdef  DEBUG

+

+/* code to print out special structures when using a debugger */

+

+#ifdef __USE_PROTOS

+void p_nfa(p)

+#else

+void p_nfa(nfa_node *p)

+nfa_node *p;	/* state number also index into array */

+#endif

+{

+/* each node has a marker on it so it only gets printed once */

+

+	operation_no++; /* get new number */

+	s_p_nfa(p);

+}

+

+#ifdef __USE_PROTOS

+void s_p_nfa(nfa_node *p)

+#else

+void s_p_nfa(p)

+nfa_node *p;	/* state number also index into array */

+#endif

+{

+	if ((p != NIL_INDEX) && (p->nfa_set != operation_no)){

+		/* so it is only printed once */

+		p->nfa_set = operation_no;

+		p_nfa_node(p);

+		s_p_nfa(p->trans[0]);

+		s_p_nfa(p->trans[1]);

+		}

+}

+

+#ifdef __USE_PROTOS

+void p_dfa_node(dfa_node *p)

+#else

+void p_dfa_node(p)

+dfa_node *p;

+#endif

+{

+	int i;

+

+	if (p != NIL_INDEX){

+		printf("DFA state :%d\n",NFA_NO(p));

+		if (p->done)

+			printf("done\n");

+		else

+			printf("undone\n");

+		printf("from nfa states : ");

+		p_set(p->nfa_states);

+		printf("\n");

+		/* NOTE: trans arcs stored as ints rather than pointer*/

+		for (i=0; i<class_no; i++){

+			printf("%d ",p->trans[i]);

+			}

+		printf("\n\n");

+		}

+}

+

+#ifdef __USE_PROTOS

+void p_dfa(void)

+#else

+void p_dfa()

+#endif

+{

+/* prints out all the dfa nodes actually allocated */

+

+	int i;

+

+	for (i = 1; i<=dfa_allocated; i++)

+		p_dfa_node(NFA(i));

+}

+

+

+/* print out numbers in the set label */

+

+#ifdef __USE_PROTOS

+void p_set(set label)

+#else

+void p_set(label)

+set label;

+#endif

+{

+	unsigned *t, *e;

+

+	if (set_nil(label)){

+		printf("epsilon\n");

+	}else{

+		t = e = set_pdq(label);

+		while(*e != nil){

+			printf("%d ", (*e+MIN_CHAR));

+			e++;

+		}

+		printf("\n");

+		free(t);

+	}

+	

+}

+#endif

diff --git a/Source/Pccts/dlg/parser.dlg b/Source/Pccts/dlg/parser.dlg
new file mode 100644
index 0000000..df9a637
--- /dev/null
+++ b/Source/Pccts/dlg/parser.dlg
@@ -0,0 +1,398 @@
+<<

+/* parser.dlg -- DLG Description of scanner

+ *

+ * Generated from: dlg_p.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#define ANTLR_VERSION	13333

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include <ctype.h>

+#include "dlg.h"

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+LOOKAHEAD

+

+void

+#ifdef __USE_PROTOS

+zzerraction(void)

+#else

+zzerraction()

+#endif

+{

+	(*zzerr)("invalid token");

+	zzadvance();

+	zzskip();

+}

+>>

+

+<<%%lexaction

+

+int	func_action;		/* should actions be turned into functions?*/

+int	lex_mode_counter = 0;	/* keeps track of the number of %%names */

+/* MR1									    */

+/* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+/* MR1				via <<%%lexmember...>>			    */

+/* MR1									    */

+int	lexMember = 0;		/* <<%%lexmemeber ...>>	   		MR1 */

+int	lexAction = 0;		/* <<%%lexaction ...>>			MR1 */

+int	parserClass = 0;	/* <<%%parserclass ...>>        MR1 */

+int	lexPrefix = 0;		/* <<%%lexprefix ...>>			MR1 */

+char	theClassName[100];						     /* MR11 */

+char	*pClassName=theClassName;					 /* MR11 */

+int	firstLexMember=1;					             /* MR1 */

+

+#ifdef __USE_PROTOS

+void  xxputc(int c) {						/* MR1 */

+#else

+  void xxputc(c)							/* MR1 */

+  int	c;							/* MR1 */

+  {								/* MR1 */

+#endif

+    if (parserClass) {						/* MR1 */

+      *pClassName++=c;						/* MR1 */

+      *pClassName=0;						/* MR1 */

+    } else if (lexMember || lexPrefix) {				/* MR1 */

+      if (class_stream != NULL) fputc(c,class_stream);		/* MR1 */

+    } else {							/* MR1 */

+      fputc(c,OUT);						/* MR1 */

+    };								/* MR1 */

+  }  								/* MR1 */

+  

+#ifdef __USE_PROTOS

+  void xxprintf(char *format,char *string) {			/* MR1 */

+#else

+    void xxprintf(format,string) 					/* MR1 */

+    char *format;							/* MR1 */

+    char *string;							/* MR1 */

+    {								/* MR1 */

+#endif

+      if (lexMember || lexPrefix || parserClass) {			/* MR1 */

+        if (class_stream != NULL)					/* MR1 */

+        fprintf(class_stream,format,string);			/* MR1 */

+      } else {							/* MR1 */

+        fprintf(OUT,format,string);					/* MR1 */

+      };								/* MR1 */

+    }  								/* MR1 */

+>>

+

+

+%%START

+

+@

+	<<

+		NLA = 1;

+	>>

+

+[\r\t\ ]+

+	<<

+		NLA = 2;

+    zzskip();   

+	>>

+

+\n

+	<<

+		NLA = 3;

+    zzline++; zzskip(); DAWDLE;   

+	>>

+

+\@

+	<<

+		NLA = L_EOF;

+	>>

+

+\%\%

+	<<

+		NLA = PER_PER;

+	>>

+

+\%\%[a-zA-Z_][a-zA-Z0-9_]*

+	<<

+		NLA = NAME_PER_PER;

+    p_mode_def(&zzlextext[2],lex_mode_counter++);   

+	>>

+

+\<\<\%\%lexmember

+	<<

+		NLA = LEXMEMBER;

+    lexMember=1;					/* MR1 */

+    if (firstLexMember != 0) {			/* MR1 */

+      firstLexMember=0;				/* MR1 */

+      p_class_def1();				/* MR1 */

+    };						/* MR1 */

+    zzmode(ACT);					/* MR1 */

+	>>

+

+\<\<\%\%lexaction

+	<<

+		NLA = LEXACTION;

+    lexAction=1;zzmode(ACT);  

+	>>

+

+\<\<\%\%parserclass

+	<<

+		NLA = PARSERCLASS;

+    parserClass=1;				/* MR1 */

+    zzmode(ACT);					/* MR1 */

+	>>

+

+\<\<\%\%lexprefix

+	<<

+		NLA = LEXPREFIX;

+    lexPrefix=1;zzmode(ACT);  

+	>>

+

+\<\<

+	<<

+		NLA = ACTION;

+    if (func_action)

+    fprintf(OUT,"\n%s %sact%d()\n{ ",

+    gen_cpp?"ANTLRTokenType":"static void",

+    gen_cpp?ClassName("::"):"", ++action_no);

+    zzmode(ACT); zzskip();

+	>>

+

+\>\>

+	<<

+		NLA = GREAT_GREAT;

+	>>

+

+\{

+	<<

+		NLA = L_BRACE;

+	>>

+

+\}

+	<<

+		NLA = R_BRACE;

+	>>

+

+\(

+	<<

+		NLA = L_PAR;

+	>>

+

+\)

+	<<

+		NLA = R_PAR;

+	>>

+

+\[

+	<<

+		NLA = L_BRACK;

+	>>

+

+\]

+	<<

+		NLA = R_BRACK;

+	>>

+

+\*

+	<<

+		NLA = ZERO_MORE;

+	>>

+

+\+

+	<<

+		NLA = ONE_MORE;

+	>>

+

+\|

+	<<

+		NLA = OR;

+	>>

+

+\-

+	<<

+		NLA = RANGE;

+	>>

+

+\~

+	<<

+		NLA = NOT;

+	>>

+

+\\0[0-7]*

+	<<

+		NLA = OCTAL_VALUE;

+    {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}  

+	>>

+

+\\0[Xx][0-9a-fA-F]+

+	<<

+		NLA = HEX_VALUE;

+    {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}  

+	>>

+

+\\[1-9][0-9]*

+	<<

+		NLA = DEC_VALUE;

+    {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}  

+	>>

+

+\\t

+	<<

+		NLA = TAB;

+    zzlextext[0] = '\t';  

+	>>

+

+\\n

+	<<

+		NLA = NL;

+    zzlextext[0] = '\n';  

+	>>

+

+\\r

+	<<

+		NLA = CR;

+    zzlextext[0] = '\r';  

+	>>

+

+\\b

+	<<

+		NLA = BS;

+    zzlextext[0] = '\b';  

+	>>

+

+\\ \n

+	<<

+		NLA = CONTINUATION;

+    zzline++; zzskip();  

+	>>

+

+\\~[tnrb]

+	<<

+		NLA = LIT;

+    zzlextext[0] = zzlextext[1];  

+	>>

+

+~[\\]

+	<<

+		NLA = REGCHAR;

+	>>

+

+

+%%ACT

+

+@

+	<<

+		NLA = 1;

+    error("unterminated action", zzline); zzmode(START);   

+	>>

+

+\>\>

+	<<

+		NLA = ACTION;

+    if (func_action) fprintf(OUT,"}\n\n");

+    zzmode(START);

+    /* MR1									    */

+    /* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */

+    /* MR1				via <<%%lexmember ...>>			    */

+    /* MR1			This is a consequence of not saving actions         */

+    /* MR1									    */

+    /* MR1 */	   parserClass=0;		

+    /* MR1 */	   lexPrefix=0;

+    /* MR1 */	   lexAction=0;

+    /* MR1 */	   lexMember=0;

+	>>

+

+\>

+	<<

+		NLA = 34;

+    xxputc(zzlextext[0]); zzskip();   

+	>>

+

+\\\>

+	<<

+		NLA = 35;

+    xxputc('>'); zzskip();   

+	>>

+

+\\

+	<<

+		NLA = 36;

+    xxputc('\\'); zzskip();   

+	>>

+

+\n

+	<<

+		NLA = 37;

+    xxputc(zzlextext[0]); ++zzline; zzskip();   

+	>>

+

+/\*

+	<<

+		NLA = 38;

+    zzmode(ACTION_COMMENTS);			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	>>

+

+//

+	<<

+		NLA = 39;

+    zzmode(ACTION_CPP_COMMENTS);			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	>>

+

+~[]

+	<<

+		NLA = 40;

+    xxputc(zzlextext[0]); zzskip();   

+	>>

+

+

+%%ACTION_COMMENTS

+

+@

+	<<

+		NLA = 1;

+	>>

+

+\*/

+	<<

+		NLA = 41;

+    zzmode(ACT);					/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	>>

+

+[\n\r]

+	<<

+		NLA = 42;

+    zzline++; xxputc(zzlextext[0]); zzskip();  

+	>>

+

+~[]

+	<<

+		NLA = 43;

+    xxputc(zzlextext[0]); zzskip();  

+	>>

+

+

+%%ACTION_CPP_COMMENTS

+

+@

+	<<

+		NLA = 1;

+	>>

+

+[\n\r]

+	<<

+		NLA = 44;

+    zzmode(ACT); zzline++;			/* MR1 */

+    xxprintf("%s", &(zzlextext[0])); zzskip();	/* MR1 */

+	>>

+

+~[]

+	<<

+		NLA = 45;

+    xxputc(zzlextext[0]); zzskip();  

+	>>

+

+%%

diff --git a/Source/Pccts/dlg/relabel.c b/Source/Pccts/dlg/relabel.c
new file mode 100644
index 0000000..0b8bc16
--- /dev/null
+++ b/Source/Pccts/dlg/relabel.c
@@ -0,0 +1,217 @@
+/* This group of functions does the character class compression.

+   It goes over the dfa and relabels the arcs with the partitions

+   of characters in the NFA.  The partitions are stored in the

+   array class.

+

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include "dlg.h"

+#ifdef MEMCHK

+#include "trax.h"

+#else

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif /* __STDC__ */

+#endif

+

+int	class_no = CHAR_RANGE;	/* number of classes for labels */

+int	first_el[CHAR_RANGE];	/* first element in each class partition */

+set	class_sets[CHAR_RANGE];	/* array holds partitions from class */

+				/* compression */

+

+/* goes through labels on NFA graph and partitions the characters into

+ * character classes.  This reduces the amount of space required for each

+ * dfa node, since only one arc is required each class instead of one arc

+ * for each character

+ * level:

+ * 0 no compression done

+ * 1 remove unused characters from classes

+ * 2 compress equivalent characters into same class

+ *

+ * returns the number of character classes required

+ */

+#ifdef __USE_PROTOS

+int relabel(nfa_node* start,int level)

+#else

+int relabel(start,level)

+int level;

+nfa_node *start;

+#endif

+{

+	if (level){

+		set_free(used_classes);	

+		partition(start,level);

+		label_with_classes(start);

+	}else{

+		/* classes equivalent to all characters in alphabet */

+		class_no = CHAR_RANGE;

+	}

+	return class_no;

+}

+

+/* makes character class sets for new labels */

+#ifdef __USE_PROTOS

+void partition(nfa_node* start,int level)

+#else

+void partition(start,level)

+nfa_node	*start;	/* beginning of nfa graph */

+int		level;	/* compression level to uses */

+#endif

+{

+	set current_class;

+	set unpart_chars;

+	set temp;

+

+	unpart_chars = set_dup(used_chars);

+#if 0

+	/* EOF (-1+1) alway in class 0 */

+	class_sets[0] = set_of(0);

+	first_el[0] = 0;

+	used_classes = set_of(0);

+	temp = set_dif(unpart_chars, class_sets[0]);

+	set_free(unpart_chars);

+	unpart_chars = temp;

+	class_no = 1;

+#else

+	class_no = 0;

+#endif

+	while (!set_nil(unpart_chars)){

+		/* don't look for equivalent labels if c <= 1 */

+		if (level <= 1){

+			current_class = set_of(set_int(unpart_chars));

+		}else{

+			current_class = set_dup(unpart_chars);

+			intersect_nfa_labels(start,&current_class);

+		}

+		set_orel(class_no,&used_classes);

+		first_el[class_no] = set_int(current_class);

+		class_sets[class_no] = current_class;

+		temp = set_dif(unpart_chars,current_class);

+		set_free(unpart_chars);

+		unpart_chars = temp;

+		++class_no;

+	}

+

+	/* free unpart_chars -ATG 5/6/95 */

+	set_free(unpart_chars);

+

+#if 0

+	/* group all the other unused characters into a class */

+	set_orel(class_no,&used_classes);

+	first_el[class_no] = set_int(current_class);

+	class_sets[class_no] = set_dif(normal_chars,used_chars);

+	++class_no;

+#endif

+}

+

+

+/* given pointer to beginning of graph and recursively walks it trying

+ * to find a maximal partition.  This partion in returned in maximal_class

+ */

+#ifdef __USE_PROTOS

+void intersect_nfa_labels(nfa_node* start,set* maximal_class)

+#else

+void intersect_nfa_labels(start,maximal_class)

+nfa_node *start;

+set *maximal_class;

+#endif

+{

+	/* pick a new operation number */

+	++operation_no;

+	r_intersect(start,maximal_class);	

+}

+

+#ifdef __USE_PROTOS

+void r_intersect(nfa_node* start,set* maximal_class)

+#else

+void r_intersect(start,maximal_class)

+nfa_node *start;

+set * maximal_class;

+#endif

+{

+	set temp;

+

+	if(start && start->nfa_set != operation_no)

+	{

+		start->nfa_set = operation_no;

+		temp = set_and(*maximal_class,start->label);

+		if (!set_nil(temp))

+		{

+			set_free(*maximal_class);

+			*maximal_class = temp;

+		}else{

+			set_free(temp);

+		}

+		r_intersect(start->trans[0],maximal_class);

+		r_intersect(start->trans[1],maximal_class);

+	}

+}

+

+

+/* puts class labels in place of old character labels */

+#ifdef __USE_PROTOS

+void label_with_classes(nfa_node* start)

+#else

+void label_with_classes(start)

+nfa_node *start;

+#endif

+{

+	++operation_no;

+	label_node(start);

+}

+

+#ifdef __USE_PROTOS

+void label_node(nfa_node *start)

+#else

+void label_node(start)

+nfa_node *start;

+#endif

+{

+	set new_label;

+	register int i;

+

+	/* only do node if it hasn't been done before */

+	if (start && start->nfa_set != operation_no){

+		start->nfa_set = operation_no;

+		new_label = empty;

+		for (i = 0; i<class_no; ++i){

+			/* if one element of class in old_label,

+			   all elements are. */

+			if (set_el(first_el[i],start->label))

+				set_orel(i,&new_label);

+		}

+		set_free(start->label);

+		start->label = new_label;

+		/* do any nodes that can be reached from this one */

+		label_node(start->trans[0]);

+		label_node(start->trans[1]);

+	}

+}

diff --git a/Source/Pccts/dlg/stdpccts.h b/Source/Pccts/dlg/stdpccts.h
new file mode 100644
index 0000000..06ec67e
--- /dev/null
+++ b/Source/Pccts/dlg/stdpccts.h
@@ -0,0 +1,26 @@
+#ifndef STDPCCTS_H

+#define STDPCCTS_H

+/*

+ * stdpccts.h -- P C C T S  I n c l u d e

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * With AHPCRC, University of Minnesota

+ * ANTLR Version 1.33MR33

+ */

+

+#ifndef ANTLR_VERSION

+#define ANTLR_VERSION	13333

+#endif

+

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+#include <ctype.h>

+#include "dlg.h"

+#define zzSET_SIZE 8

+#include "antlr.h"

+#include "tokens.h"

+#include "dlgdef.h"

+#include "mode.h"

+#endif

diff --git a/Source/Pccts/dlg/support.c b/Source/Pccts/dlg/support.c
new file mode 100644
index 0000000..84fe99d
--- /dev/null
+++ b/Source/Pccts/dlg/support.c
@@ -0,0 +1,240 @@
+/*

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * DLG 1.33

+ * Will Cohen

+ * With mods by Terence Parr; AHPCRC, University of Minnesota

+ * 1989-2001

+ */

+

+#include <stdio.h>

+#include <string.h>

+#include "dlg.h"

+#ifdef MEMCHK

+#include "trax.h"

+#else

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif /* __STDC__ */

+#endif

+

+int	err_found = 0;			/* indicates whether problem found */

+

+#ifdef __USE_PROTOS

+void internal_error(char *s, char *file,int line)    /* MR9 23-Sep-97 */

+#else

+void internal_error(s,file,line)    /* MR9 23-Sep-97 */

+char *s,*file;

+int line;

+#endif

+{

+	fprintf(stderr,s,file,line);

+	exit(PCCTS_EXIT_FAILURE);

+}

+

+#ifdef __USE_PROTOS

+char *dlg_malloc(int bytes,char *file,int line)

+#else

+char *dlg_malloc(bytes,file,line)

+int bytes;

+char *file;

+int line;

+#endif

+{

+	char *t;

+

+	t = (char *) malloc(bytes);

+	if (!t){

+		/* error */

+		internal_error("%s(%d): unable to allocate memory\n",

+			file,line);

+	}

+	return t;

+}

+

+

+#ifdef __USE_PROTOS

+char *dlg_calloc(int n,int bytes,char *file,int line)

+#else

+char *dlg_calloc(n,bytes,file,line)

+int n,bytes;

+char *file;

+int line;

+#endif

+{

+	char *t;

+

+	t = (char *) calloc(n,bytes);

+	if (!t){

+		/* error */

+		internal_error("%s(%d): unable to allocate memory\n",

+			file,line);

+	}

+	return t;

+}

+

+

+#ifdef __USE_PROTOS

+FILE *read_stream(char *name)

+#else

+FILE *read_stream(name)

+char *name;

+#endif

+{

+	FILE *f;

+

+	if (name){

+		if (name[0] == '-') {

+			fprintf(stderr, "dlg: invalid option: '%s'\n", name);

+			f = NULL;

+		}else{

+			f = fopen(name, "r");

+			if (f == NULL){

+				/* couldn't open file */

+				fprintf(stderr,

+					"dlg: Warning: Can't read file %s.\n",

+					name);

+			}

+		}

+	}else{

+		/* open stdin if nothing there */

+		f = stdin;

+	}

+	return f;

+}

+

+#ifdef __USE_PROTOS

+FILE *write_stream(char *name)

+#else

+FILE *write_stream(name)

+char *name;

+#endif

+{

+	FILE *f;

+

+	if (name){

+		if (name[0] == '-') {

+			fprintf(stderr, "dlg: invalid option: '%s'\n", name);

+			f = NULL;

+		}else{

+			f = fopen(OutMetaName(name), "w");

+			if (f == NULL){

+				/* couldn't open file */

+				fprintf(stderr,

+					"dlg: Warning: Can't write to file %s.\n",

+					name);

+			}

+			else

+#ifdef SPECIAL_FOPEN

+                special_fopen_actions(OutMetaName(name));	/* MR1 */

+#else

+		;						/* MR1 */

+#endif

+		}

+	}else{

+		/* open stdout if nothing there */

+		f = stdout;

+	}

+	return f;

+}

+

+

+#ifdef __USE_PROTOS

+void fatal(char *message,int line_no)

+#else

+void fatal(message,line_no)

+char *message;

+int line_no;

+#endif

+{

+	fprintf(stderr,ErrHdr,

+		(file_str[0] ? file_str[0] : "stdin"), line_no);

+	fprintf(stderr, " Fatal: %s\n", message);

+	exit(PCCTS_EXIT_FAILURE);

+}

+

+#ifdef __USE_PROTOS

+void error(char *message,int line_no)

+#else

+void error(message,line_no)

+char *message;

+int line_no;

+#endif

+{

+	fprintf(stderr,ErrHdr,

+		(file_str[0] ? file_str[0] : "stdin"), line_no);

+	fprintf(stderr, " Error: %s\n", message);

+	err_found = 1;

+}

+

+#ifdef __USE_PROTOS

+void warning(char *message,int line_no)

+#else

+void warning(message,line_no)

+char *message;

+int line_no;

+#endif

+{

+	fprintf(stderr,ErrHdr,

+		(file_str[0] ? file_str[0] : "stdin"), line_no);

+	fprintf(stderr, " Warning: %s\n", message);

+}

+

+/* MR10: Jeff Vincent

+   MR10: Changed to remove directory information from n only if

+   MR10: if OutputDirectory was changed by user (-o option)

+*/

+

+#ifdef __USE_PROTOS

+char *OutMetaName(char *n)

+#else

+char *OutMetaName(n)

+char *n;

+#endif

+{	

+    static char *dir_sym = DirectorySymbol;

+    static char newname[MaxFileName+1];

+    char *p;

+

+	/* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */

+    if (strcmp(OutputDirectory, TopDirectory) == 0)

+		return n;

+

+	/* p will point to filename without path information */

+	if ((p = strrchr(n, *dir_sym)) != NULL)

+		p++;

+	else

+		p = n;

+

+	/* Copy new output directory into newname[] */

+	strcpy(newname, OutputDirectory);

+

+	/* if new output directory does not have trailing dir_sym, add it! */

+	if (newname[strlen(newname)-1] != *dir_sym)

+		strcat(newname, dir_sym);

+

+	/* contatenate FILE NAME ONLY to new output directory */

+	strcat(newname, p);

+

+	return newname;

+}

diff --git a/Source/Pccts/dlg/tokens.h b/Source/Pccts/dlg/tokens.h
new file mode 100644
index 0000000..73e502b
--- /dev/null
+++ b/Source/Pccts/dlg/tokens.h
@@ -0,0 +1,133 @@
+#ifndef tokens_h

+#define tokens_h

+/* tokens.h -- List of labelled tokens and stuff

+ *

+ * Generated from: dlg_p.g

+ *

+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001

+ * Purdue University Electrical Engineering

+ * ANTLR Version 1.33MR33

+ */

+#define zzEOF_TOKEN 1

+#define L_EOF 4

+#define PER_PER 5

+#define NAME_PER_PER 6

+#define LEXMEMBER 7

+#define LEXACTION 8

+#define PARSERCLASS 9

+#define LEXPREFIX 10

+#define ACTION 11

+#define GREAT_GREAT 12

+#define L_BRACE 13

+#define R_BRACE 14

+#define L_PAR 15

+#define R_PAR 16

+#define L_BRACK 17

+#define R_BRACK 18

+#define ZERO_MORE 19

+#define ONE_MORE 20

+#define OR 21

+#define RANGE 22

+#define NOT 23

+#define OCTAL_VALUE 24

+#define HEX_VALUE 25

+#define DEC_VALUE 26

+#define TAB 27

+#define NL 28

+#define CR 29

+#define BS 30

+#define CONTINUATION 31

+#define LIT 32

+#define REGCHAR 33

+

+#ifdef __USE_PROTOS

+void grammar(void);

+#else

+extern void grammar();

+#endif

+

+#ifdef __USE_PROTOS

+void start_states(void);

+#else

+extern void start_states();

+#endif

+

+#ifdef __USE_PROTOS

+void do_conversion(void);

+#else

+extern void do_conversion();

+#endif

+

+#ifdef __USE_PROTOS

+void rule_list(void);

+#else

+extern void rule_list();

+#endif

+

+#ifdef __USE_PROTOS

+void rule(void);

+#else

+extern void rule();

+#endif

+

+#ifdef __USE_PROTOS

+void reg_expr(void);

+#else

+extern void reg_expr();

+#endif

+

+#ifdef __USE_PROTOS

+void and_expr(void);

+#else

+extern void and_expr();

+#endif

+

+#ifdef __USE_PROTOS

+void repeat_expr(void);

+#else

+extern void repeat_expr();

+#endif

+

+#ifdef __USE_PROTOS

+void expr(void);

+#else

+extern void expr();

+#endif

+

+#ifdef __USE_PROTOS

+void atom_list(void);

+#else

+extern void atom_list();

+#endif

+

+#ifdef __USE_PROTOS

+void near_atom(void);

+#else

+extern void near_atom();

+#endif

+

+#ifdef __USE_PROTOS

+void atom(void);

+#else

+extern void atom();

+#endif

+

+#ifdef __USE_PROTOS

+void anychar(void);

+#else

+extern void anychar();

+#endif

+

+#endif

+extern SetWordType zzerr1[];

+extern SetWordType zzerr2[];

+extern SetWordType zzerr3[];

+extern SetWordType setwd1[];

+extern SetWordType zzerr4[];

+extern SetWordType zzerr5[];

+extern SetWordType zzerr6[];

+extern SetWordType setwd2[];

+extern SetWordType zzerr7[];

+extern SetWordType zzerr8[];

+extern SetWordType zzerr9[];

+extern SetWordType setwd3[];

diff --git a/Source/Pccts/h/AParser.cpp b/Source/Pccts/h/AParser.cpp
new file mode 100644
index 0000000..720fe75
--- /dev/null
+++ b/Source/Pccts/h/AParser.cpp
@@ -0,0 +1,871 @@
+/* ANTLRParser.C

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+#include "pccts_stdlib.h"

+#include "pccts_stdarg.h"

+#include "pccts_string.h"

+#include "pccts_stdio.h"

+

+PCCTS_NAMESPACE_STD

+

+/* I have to put this here due to C++ limitation

+ * that you can't have a 'forward' decl for enums.

+ * I hate C++!!!!!!!!!!!!!!!

+ * Of course, if I could use real templates, this would go away.

+ */

+// MR1

+// MR1  10-Apr-97  133MR1  Prevent use of varying sizes for the

+// MR1  			ANTLRTokenType enum

+// MR1

+

+enum ANTLRTokenType { TER_HATES_CPP=0, ITS_TOO_COMPLICATED=9999};	    // MR1

+

+#define ANTLR_SUPPORT_CODE

+

+#include ATOKEN_H

+#include ATOKENBUFFER_H

+#include APARSER_H

+

+static const int zzINF_DEF_TOKEN_BUFFER_SIZE = 2000;    /* MR14 */

+static const int zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000;  /* MR14 */

+

+                 /* L o o k a h e a d  M a c r o s */

+

+/* maximum of 32 bits/unsigned int and must be 8 bits/byte;

+ * we only use 8 bits of it.

+ */

+SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = {

+	0x00000001, 0x00000002, 0x00000004, 0x00000008,

+	0x00000010, 0x00000020, 0x00000040, 0x00000080

+};

+

+char ANTLRParser::eMsgBuffer[500] = "";

+

+ANTLRParser::

+~ANTLRParser()

+{

+	delete [] token_type;

+    delete [] zzFAILtext;       // MR16 Manfred Kogler

+}

+

+ANTLRParser::

+ANTLRParser(ANTLRTokenBuffer *_inputTokens,

+			int k,

+			int use_inf_look,

+			int dlook,

+			int ssize)

+{

+	LLk = k;

+	can_use_inf_look = use_inf_look;

+/* MR14 */    if (dlook != 0) {

+/* MR14 */      panic("ANTLRParser::ANTLRParser - Demand lookahead not supported in C++ mode");

+/* MR14 */

+/* MR14 */    };

+    demand_look = 0;    /* demand_look = dlook; */

+    bsetsize = ssize;

+	guessing = 0;

+	token_tbl = NULL;

+	eofToken = (ANTLRTokenType)1;

+

+	// allocate lookahead buffer

+	token_type = new ANTLRTokenType[LLk];

+	lap = 0;

+	labase = 0;

+#ifdef ZZDEFER_FETCH

+	stillToFetch = 0;                                                   // MR19

+#endif

+	dirty = 0;

+    inf_labase = 0;                                                     // MR7

+    inf_last = 0;                                                       // MR7

+	/* prime lookahead buffer, point to inputTokens */

+	this->inputTokens = _inputTokens;

+	this->inputTokens->setMinTokens(k);

+	_inputTokens->setParser(this);					                    // MR1

+    resynchConsumed=1;                                                  // MR8

+    zzFAILtext=NULL;                                                    // MR9

+    traceOptionValueDefault=0;                                          // MR10

+    traceReset();                                                       // MR10

+    zzGuessSeq=0;                                                       // MR10

+    syntaxErrCount=0;                                                   // MR11

+}

+

+void ANTLRParser::init()

+{

+   prime_lookahead();

+   resynchConsumed=1;                                                   // MR8

+   traceReset();                                                        // MR10

+}

+

+void ANTLRParser::traceReset()

+{

+   traceOptionValue=traceOptionValueDefault;

+   traceGuessOptionValue=1;

+   traceCurrentRuleName=NULL;

+   traceDepth=0;

+}

+

+

+#ifdef _MSC_VER  // MR23

+//Turn off warning:

+//interaction between '_setjmp' and C++ object destruction is non-portable

+#pragma warning(disable : 4611)

+#endif

+int ANTLRParser::

+guess(ANTLRParserState *st)

+{

+	saveState(st);

+	guessing = 1;

+	return setjmp(guess_start.state);

+}

+#ifdef _MSC_VER  // MR23

+#pragma warning(default: 4611)

+#endif

+

+void ANTLRParser::

+saveState(ANTLRParserState *buf)

+{

+	buf->guess_start = guess_start;

+	buf->guessing = guessing;

+	buf->inf_labase = inf_labase;

+	buf->inf_last = inf_last;

+	buf->dirty = dirty;

+    buf->traceOptionValue=traceOptionValue;            /* MR10 */

+    buf->traceGuessOptionValue=traceGuessOptionValue;  /* MR10 */

+    buf->traceCurrentRuleName=traceCurrentRuleName;    /* MR10 */

+    buf->traceDepth=traceDepth;                        /* MR10 */

+}

+

+void ANTLRParser::

+restoreState(ANTLRParserState *buf)

+{

+	int     i;

+    int     prevTraceOptionValue;

+

+	guess_start = buf->guess_start;

+	guessing = buf->guessing;

+	inf_labase = buf->inf_labase;

+	inf_last = buf->inf_last;

+	dirty = buf->dirty;

+

+	// restore lookahead buffer from k tokens before restored TokenBuffer position

+	// if demand_look, then I guess we don't look backwards for these tokens.

+	for (i=1; i<=LLk; i++) token_type[i-1] =

+		inputTokens->bufferedToken(i-LLk)->getType();

+	lap = 0;

+	labase = 0;

+

+    /* MR10 */

+

+    prevTraceOptionValue=traceOptionValue;

+    traceOptionValue=buf->traceOptionValue;

+    if ( (prevTraceOptionValue > 0) !=

+             (traceOptionValue > 0)) {

+      if (traceCurrentRuleName != NULL) {  /* MR21 */

+          if (traceOptionValue > 0) {

+            /* MR23 */ printMessage(stderr,

+                   "trace enable restored in rule %s depth %d\n",

+                   traceCurrentRuleName,

+                   traceDepth);

+          };

+          if (traceOptionValue <= 0) {

+            /* MR23 */ printMessage(stderr,

+            "trace disable restored in rule %s depth %d\n",

+            traceCurrentRuleName, /* MR21 */

+            traceDepth);

+          };

+       }

+    };

+    traceGuessOptionValue=buf->traceGuessOptionValue;

+    traceCurrentRuleName=buf->traceCurrentRuleName;

+    traceDepth=buf->traceDepth;

+    traceGuessDone(buf);

+}

+

+/* Get the next symbol from the input stream; put it into lookahead buffer;

+ * fill token_type[] fast reference cache also.  NLA is the next place where

+ * a lookahead ANTLRAbstractToken should go.

+ */

+void ANTLRParser::

+consume()

+{

+

+#ifdef ZZDEBUG_CONSUME_ACTION

+    zzdebug_consume_action();

+#endif

+

+// MR19 V.H. Simonis

+//      Defer Fetch feature

+//      Moves action of consume() into LA() function

+

+#ifdef ZZDEFER_FETCH

+      stillToFetch++;

+#else

+      NLA = inputTokens->getToken()->getType();

+      dirty--;

+      lap = (lap+1)&(LLk-1);

+#endif

+

+}

+

+_ANTLRTokenPtr ANTLRParser::

+LT(int i)

+{

+

+// MR19 V.H. Simonis

+//      Defer Fetch feature

+//      Moves action of consume() into LA() function

+

+#ifdef ZZDEFER_FETCH

+    undeferFetch();

+#endif

+

+#ifdef DEBUG_TOKENBUFFER

+	if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() < LLk )     /* MR20 Was "<=" */

+	{

+		char buf[2000];                 /* MR20 Was "static" */

+        sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i);

+		panic(buf);

+	}

+#endif

+	return inputTokens->bufferedToken(i-LLk);

+}

+

+void

+ANTLRParser::

+look(int k)

+{

+	int i, c = k - (LLk-dirty);

+	for (i=1; i<=c; i++) consume();

+}

+

+/* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK);

+ */

+void

+ANTLRParser::

+prime_lookahead()

+{

+	int i;

+	for(i=1;i<=LLk; i++) consume();

+	dirty=0;

+	// lap = 0;     // MR14 Sinan Karasu (sinan.karasu@boeing.com)

+	// labase = 0;  // MR14

+    labase=lap;     // MR14

+}

+

+/* check to see if the current input symbol matches '_t'.

+ * During NON demand lookahead mode, dirty will always be 0 and

+ * hence the extra code for consuming tokens in _match is never

+ * executed; the same routine can be used for both modes.

+ */

+int ANTLRParser::

+_match(ANTLRTokenType _t, ANTLRChar **MissText,

+	   ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok,

+	   SetWordType **MissSet)

+{

+	if ( dirty==LLk ) {

+		consume();

+	}

+	if ( LA(1)!=_t ) {

+		*MissText=NULL;

+		*MissTok= _t;

+		*BadTok = LT(1);

+		*MissSet=NULL;

+		return 0;

+	}

+	dirty++;

+	labase = (labase+1)&(LLk-1);	// labase maintained even if !demand look

+	return 1;

+}

+

+/* check to see if the current input symbol matches '_t'.

+ * Used during exception handling.

+ */

+int ANTLRParser::

+_match_wsig(ANTLRTokenType _t)

+{

+	if ( dirty==LLk ) {

+		consume();

+	}

+	if ( LA(1)!=_t ) return 0;

+	dirty++;

+	labase = (labase+1)&(LLk-1);	// labase maintained even if !demand look

+	return 1;

+}

+

+/* check to see if the current input symbol matches any token in a set.

+ * During NON demand lookahead mode, dirty will always be 0 and

+ * hence the extra code for consuming tokens in _match is never

+ * executed; the same routine can be used for both modes.

+ */

+int ANTLRParser::

+_setmatch(SetWordType *tset, ANTLRChar **MissText,

+	   ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok,

+	   SetWordType **MissSet, SetWordType *tokclassErrset)

+{

+	if ( dirty==LLk ) {

+		consume();

+	}

+	if ( !set_el(LA(1), tset) ) {

+		*MissText=NULL;										/* MR23 */

+		*MissTok=(ANTLRTokenType) 0;						/* MR23 */

+		*BadTok=LT(1);										/* MR23 */

+		*MissSet=tokclassErrset;							/* MR23 */

+		return 0;

+	}

+	dirty++;

+	labase = (labase+1)&(LLk-1);	// labase maintained even if !demand look

+	return 1;

+}

+

+int ANTLRParser::

+_setmatch_wsig(SetWordType *tset)

+{

+	if ( dirty==LLk ) {

+		consume();

+	}

+	if ( !set_el(LA(1), tset) ) return 0;

+	dirty++;

+	labase = (labase+1)&(LLk-1);	// labase maintained even if !demand look

+	return 1;

+}

+

+                   /* Exception handling routines */

+//

+//  7-Apr-97 133MR1

+//   	     Change suggested by Eli Sternheim (eli@interhdl.com)

+//

+void ANTLRParser::

+consumeUntil(SetWordType *st)

+{

+	ANTLRTokenType		tmp;	                        				// MR1

+	const			int Eof=1;                                          // MR1

+	while ( !set_el( (tmp=LA(1)), st) && tmp!=Eof) { consume(); }       // MR1

+}

+

+//

+//  7-Apr-97 133MR1

+//   	     Change suggested by Eli Sternheim (eli@interhdl.com)

+//

+void ANTLRParser::

+consumeUntilToken(int t)

+{

+	int	tmp;                                                            // MR1

+	const	int Eof=1;                                                  // MR1

+	while ( (tmp=LA(1)) !=t && tmp!=Eof) { consume(); }                 // MR1

+}

+

+

+                        /* Old error stuff */

+

+void ANTLRParser::

+resynch(SetWordType *wd,SetWordType mask)

+{

+

+/* MR8              S.Bochnak@microtool.com.pl                          */

+/* MR8              Change file scope static "consumed" to instance var */

+

+	/* if you enter here without having consumed a token from last resynch

+	 * force a token consumption.

+	 */

+/* MR8 */  	if ( !resynchConsumed ) {consume(); resynchConsumed=1; return;}

+

+   	/* if current token is in resynch set, we've got what we wanted */

+

+/* MR8 */  	if ( wd[LA(1)]&mask || LA(1) == eofToken ) {resynchConsumed=0; return;}

+	

+   	/* scan until we find something in the resynch set */

+

+        	while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();}

+

+/* MR8 */	resynchConsumed=1;

+}

+

+/* standard error reporting function that assumes DLG-based scanners;

+ * you should redefine in subclass to change it or if you use your

+ * own scanner.

+ */

+

+/* MR23 THM There appears to be a parameter "badText" passed to syn()

+            which is not present in the parameter list.  This may be

+            because in C mode there is no attribute function which

+            returns the text, so the text representation of the token

+            must be passed explicitly.  I think.

+*/

+           

+void ANTLRParser::

+syn(_ANTLRTokenPtr /*tok MR23*/, ANTLRChar *egroup, SetWordType *eset,

+	ANTLRTokenType etok, int k)

+{

+	int line;

+

+	line = LT(1)->getLine();

+

+    syntaxErrCount++;                                   /* MR11 */

+

+    /* MR23  If the token is not an EOF token, then use the ->getText() value.

+

+             If the token is the EOF token the text returned by ->getText() 

+             may be garbage.  If the text from the token table is "@" use

+             "<eof>" instead, because end-users don't know what "@" means.

+             If the text is not "@" then use that text, which must have been

+             supplied by the grammar writer.

+     */

+	const char * errorAt = LT(1)->getText();

+	if (LA(1) == eofToken) {

+  	  errorAt = parserTokenName(LA(1));

+  	  if (errorAt[0] == '@') errorAt = "<eof>";

+	}

+	/* MR23 */ printMessage(stderr, "line %d: syntax error at \"%s\"",

+					line, errorAt);

+	if ( !etok && !eset ) {/* MR23 */ printMessage(stderr, "\n"); return;}

+	if ( k==1 ) /* MR23 */ printMessage(stderr, " missing");

+	else

+	{

+		/* MR23 */ printMessage(stderr, "; \"%s\" not", LT(k)->getText()); // MR23 use LT(k) since k>1

+		if ( set_deg(eset)>1 ) /* MR23 */ printMessage(stderr, " in");

+	}

+	if ( set_deg(eset)>0 ) edecode(eset);

+	else /* MR23 */ printMessage(stderr, " %s", token_tbl[etok]);

+	if ( strlen(egroup) > 0 ) /* MR23 */ printMessage(stderr, " in %s", egroup);

+	/* MR23 */ printMessage(stderr, "\n");

+}

+

+/* is b an element of set p? */

+int ANTLRParser::

+set_el(ANTLRTokenType b, SetWordType *p)

+{

+	return( p[DIVWORD(b)] & bitmask[MODWORD(b)] );

+}

+

+int ANTLRParser::

+set_deg(SetWordType *a)

+{

+	/* Fast compute degree of a set... the number

+	   of elements present in the set.  Assumes

+	   that all word bits are used in the set

+	*/

+	register SetWordType *p = a;

+	register SetWordType *endp = &(a[bsetsize]);

+	register int degree = 0;

+

+	if ( a == NULL ) return 0;

+	while ( p < endp )

+	{

+		register SetWordType t = *p;

+		register SetWordType *b = &(bitmask[0]);

+		do {

+			if (t & *b) ++degree;

+		} while (++b < &(bitmask[sizeof(SetWordType)*8]));

+		p++;

+	}

+

+	return(degree);

+}

+

+void ANTLRParser::

+edecode(SetWordType *a)

+{

+	register SetWordType *p = a;

+	register SetWordType *endp = &(p[bsetsize]);

+	register unsigned e = 0;

+

+	if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " {");

+	do {

+		register SetWordType t = *p;

+		register SetWordType *b = &(bitmask[0]);

+		do {

+			if ( t & *b ) /* MR23 */ printMessage(stderr, " %s", token_tbl[e]);

+			e++;

+		} while (++b < &(bitmask[sizeof(SetWordType)*8]));

+	} while (++p < endp);

+	if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " }");

+}

+

+/* input looks like:

+ *      zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk)

+ * where the zzMiss stuff is set here to the token that did not match

+ * (and which set wasn't it a member of).

+ */

+

+// MR9 29-Sep-97    Stan Bochnak (S.Bochnak@microTool.com.pl)

+// MR9              Original fix to static allocated text didn't

+// MR9                work because a pointer to it was passed back

+// MR9                to caller.  Replace with instance variable.

+

+const int   SETWORDCOUNT=20;

+

+void

+ANTLRParser::FAIL(int k, ...)

+{

+//

+//  MR1 10-Apr-97	

+//

+

+    if (zzFAILtext == NULL) zzFAILtext=new char [1000];          // MR9

+    SetWordType **f=new SetWordType *[SETWORDCOUNT];             // MR1 // MR9

+    SetWordType **miss_set;

+    ANTLRChar **miss_text;

+    _ANTLRTokenPtr *bad_tok;

+    ANTLRChar **bad_text;

+//

+//  7-Apr-97 133MR1

+//  		err_k is passed as a "int *", not "unsigned *"

+//

+    int	*err_k;                                                         // MR1

+    int i;

+    va_list ap;

+

+    va_start(ap, k);

+

+    zzFAILtext[0] = '\0';

+	if ( k > SETWORDCOUNT ) panic("FAIL: overflowed buffer");

+    for (i=1; i<=k; i++)    /* collect all lookahead sets */

+    {

+        f[i-1] = va_arg(ap, SetWordType *);

+    }

+    for (i=1; i<=k; i++)    /* look for offending token */

+    {

+        if ( i>1 ) strcat(zzFAILtext, " ");

+        strcat(zzFAILtext, LT(i)->getText());

+        if ( !set_el(LA(i), f[i-1]) ) break;

+    }

+    miss_set = va_arg(ap, SetWordType **);

+    miss_text = va_arg(ap, ANTLRChar **);

+    bad_tok = va_arg(ap, _ANTLRTokenPtr *);

+    bad_text = va_arg(ap, ANTLRChar **);

+    err_k = va_arg(ap, int *);                      					// MR1

+    if ( i>k )

+    {

+        /* bad; lookahead is permutation that cannot be matched,

+         * but, the ith token of lookahead is valid at the ith position

+         * (The old LL sub 1 (k) versus LL(k) parsing technique)

+         */

+        *miss_set = NULL;

+        *miss_text = LT(1)->getText();

+        *bad_tok = LT(1);

+        *bad_text = (*bad_tok)->getText();

+        *err_k = k;

+//

+//  MR4 20-May-97	erroneously deleted contents of f[]

+//  MR4			        reported by Bruce Guenter (bruceg@qcc.sk.ca)

+//  MR1 10-Apr-97	release temporary storage

+//

+      delete [] f;                                                      // MR1

+      return;                                                           // MR1

+    }

+/*  MR23 printMessage(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/

+    *miss_set = f[i-1];

+    *miss_text = zzFAILtext;

+    *bad_tok = LT(i);

+    *bad_text = (*bad_tok)->getText();

+    if ( i==1 ) *err_k = 1;

+    else *err_k = k;

+//

+//  MR4 20-May-97	erroneously deleted contents of f[]

+//  MR4			      reported by Bruce Guenter (bruceg@qcc.sk.ca)

+//  MR1 10-Apr-97	release temporary storage

+//

+    delete [] f;                                                        // MR1

+    return;                                                             // MR1

+}

+

+int ANTLRParser::

+_match_wdfltsig(ANTLRTokenType tokenWanted, SetWordType *whatFollows)

+{

+	if ( dirty==LLk ) consume();

+

+	if ( LA(1)!=tokenWanted )

+	{

+        syntaxErrCount++;                                   /* MR11 */

+		/* MR23 */ printMessage(stderr,

+				"line %d: syntax error at \"%s\" missing %s\n",

+				LT(1)->getLine(),

+				(LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */

+				token_tbl[tokenWanted]);

+		consumeUntil( whatFollows );

+		return 0;

+	}

+	else {

+		dirty++;

+		labase = (labase+1)&(LLk-1); // labase maintained even if !demand look

+/*		if ( !demand_look ) consume(); */

+		return 1;

+	}

+}

+

+

+int ANTLRParser::

+_setmatch_wdfltsig(SetWordType *tokensWanted,

+					ANTLRTokenType tokenTypeOfSet,

+					SetWordType *whatFollows)

+{

+	if ( dirty==LLk ) consume();

+	if ( !set_el(LA(1), tokensWanted) )

+	{

+        syntaxErrCount++;                                   /* MR11 */

+		/* MR23 */ printMessage(stderr,

+				"line %d: syntax error at \"%s\" missing %s\n",

+				LT(1)->getLine(),

+				(LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */

+				token_tbl[tokenTypeOfSet]);

+		consumeUntil( whatFollows );

+		return 0;

+	}

+	else {

+		dirty++;

+		labase = (labase+1)&(LLk-1); // labase maintained even if !demand look

+/*		if ( !demand_look ) consume(); */

+		return 1;

+	}

+}

+

+char *ANTLRParser::

+eMsgd(char *err,int d)

+{

+	sprintf(eMsgBuffer, err, d);	// dangerous, but I don't care

+	return eMsgBuffer;

+}

+

+char *ANTLRParser::

+eMsg(char *err, char *s)

+{

+	sprintf(eMsgBuffer, err, s);

+	return eMsgBuffer;

+}

+

+char *ANTLRParser::

+eMsg2(char *err,char *s, char *t)

+{

+	sprintf(eMsgBuffer, err, s, t);

+	return eMsgBuffer;

+}

+

+void ANTLRParser::

+panic(const char *msg)  // MR20 const

+{

+	/* MR23 */ printMessage(stderr, "ANTLR panic: %s\n", msg);

+	exit(PCCTS_EXIT_FAILURE);           // MR1

+}

+

+const ANTLRChar *ANTLRParser::          // MR1

+parserTokenName(int tok) {              // MR1

+	return token_tbl[tok];              // MR1

+}                                       // MR1

+

+void ANTLRParser::traceGuessDone(const ANTLRParserState *state) {

+

+  int   doIt=0;

+

+  if (traceCurrentRuleName == NULL) return;

+

+  if (traceOptionValue <= 0) {

+    doIt=0;

+  } else if (traceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    /* MR23 */ printMessage(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d",

+        state->traceCurrentRuleName,

+        LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),

+        state->traceDepth);

+    if (state->guessing != 0) {

+      /* MR23 */ printMessage(stderr," (guess mode continues - an enclosing guess is still active)");

+    } else {

+      /* MR23 */ printMessage(stderr," (guess mode ends)");

+    };

+    /* MR23 */ printMessage(stderr,"\n");

+  };

+}

+

+void ANTLRParser::traceGuessFail() {

+

+  int   doIt=0;

+

+  if (traceCurrentRuleName == NULL) return;     /* MR21 */

+

+  if (traceOptionValue <= 0) {

+    doIt=0;

+  } else if (guessing && traceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    /* MR23 */ printMessage(stderr,"guess failed in %s\n",traceCurrentRuleName);

+  };

+}

+

+/* traceOption:

+     zero value turns off trace

+*/

+

+void ANTLRParser::tracein(const ANTLRChar * rule) {

+

+  int       doIt=0;

+

+  traceDepth++;

+  traceCurrentRuleName=rule;

+

+  if (traceOptionValue <= 0) {

+    doIt=0;

+  } else if (guessing && traceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    /* MR23 */ printMessage(stderr,"enter rule %s {\"%s\"} depth %d",

+            rule,

+            LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),

+            traceDepth);

+    if (guessing) /* MR23 */ printMessage(stderr," guessing");

+    /* MR23 */ printMessage(stderr,"\n");

+  };

+  return;

+}

+

+void ANTLRParser::traceout(const ANTLRChar * rule) {

+

+  int       doIt=0;

+

+  traceDepth--;

+

+  if (traceOptionValue <= 0) {

+    doIt=0;

+  } else if (guessing && traceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    /* MR23 */ printMessage(stderr,"exit rule %s {\"%s\"} depth %d",

+            rule,

+            LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),

+            traceDepth+1);

+    if (guessing) /* MR23 */ printMessage(stderr," guessing");

+    /* MR23 */ printMessage(stderr,"\n");

+  };

+}

+

+int ANTLRParser::traceOption(int delta) {

+

+    int     prevValue=traceOptionValue;

+

+    traceOptionValue=traceOptionValue+delta;

+

+    if (traceCurrentRuleName != NULL) {

+      if (prevValue <= 0 && traceOptionValue > 0) {

+        /* MR23 */ printMessage(stderr,"trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);

+      };

+      if (prevValue > 0 && traceOptionValue <= 0) {

+        /* MR23 */ printMessage(stderr,"trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);

+      };

+    };

+

+    return  prevValue;

+}

+

+int ANTLRParser::traceGuessOption(int delta) {

+

+    int     prevValue=traceGuessOptionValue;

+

+    traceGuessOptionValue=traceGuessOptionValue+delta;

+

+    if (traceCurrentRuleName != NULL) {

+      if (prevValue <= 0 && traceGuessOptionValue > 0) {

+        /* MR23 */ printMessage(stderr,"guess trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);

+      };

+      if (prevValue > 0 && traceGuessOptionValue <= 0) {

+        /* MR23 */ printMessage(stderr,"guess trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);

+      };

+    };

+    return prevValue;

+}

+

+// MR19 V.H. Simonis Defer Fetch feature

+

+void ANTLRParser::undeferFetch()

+{

+

+#ifdef ZZDEFER_FETCH

+    if (stillToFetch) {

+        for (int stillToFetch_x = 0; stillToFetch_x < stillToFetch; ++stillToFetch_x) {

+    		NLA = inputTokens->getToken()->getType();

+    		dirty--;

+    		lap = (lap+1)&(LLk-1);

+        }

+        stillToFetch = 0;

+    }

+#else

+    return;

+#endif

+

+}

+

+int ANTLRParser::isDeferFetchEnabled()

+{

+#ifdef ZZDEFER_FETCH

+    return 1;

+#else

+    return 0;

+#endif

+}

+

+//MR23

+int ANTLRParser::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+  	int iRet = printMessageV(pFile, pFormat, marker);

+	va_end( marker );

+	return iRet;

+}

+

+int ANTLRParser::printMessageV(FILE* pFile, const char* pFormat, va_list arglist) // MR23

+{

+  	return vfprintf(pFile, pFormat, arglist);

+}

+

+// MR23 Move semantic predicate error handling from macro to virtual function

+//

+// Called by the zzfailed_pred

+

+void ANTLRParser::failedSemanticPredicate(const char* predicate)

+{

+    printMessage(stdout,"line %d: semantic error; failed predicate: '%s'\n",

+    	LT(1)->getLine(), predicate);

+}

diff --git a/Source/Pccts/h/AParser.h b/Source/Pccts/h/AParser.h
new file mode 100644
index 0000000..fe405f4
--- /dev/null
+++ b/Source/Pccts/h/AParser.h
@@ -0,0 +1,376 @@
+/* ANTLRParser.h

+ *

+ * Define the generic ANTLRParser superclass, which is subclassed to

+ * define an actual parser.

+ *

+ * Before entry into this file: ANTLRTokenType must be set.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef APARSER_H_GATE

+#define APARSER_H_GATE

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_setjmp.h"

+

+PCCTS_NAMESPACE_STD

+

+#include ATOKEN_H

+#include ATOKENBUFFER_H

+

+#ifdef ZZCAN_GUESS

+#ifndef ZZINF_LOOK

+#define ZZINF_LOOK

+#endif

+#endif

+

+

+#define NLA			(token_type[lap&(LLk-1)])/* --> next LA */

+

+typedef unsigned char SetWordType;

+

+/* Define external bit set stuff (for SetWordType) */

+#define EXT_WORDSIZE	(sizeof(char)*8)

+#define EXT_LOGWORDSIZE	3

+

+           /* s y n t a c t i c  p r e d i c a t e  s t u f f */

+

+#ifndef zzUSER_GUESS_HOOK

+#define zzUSER_GUESS_HOOK(seqFrozen,zzrv)

+#endif

+

+#ifndef zzUSER_GUESS_DONE_HOOK

+#define zzUSER_GUESS_DONE_HOOK(seqFrozen)

+#endif

+

+/* MR14 Add zzUSER_GUESS_FAIL_HOOK and related code */

+

+#define zzUSER_GUESS_FAIL_HOOK_INTERNAL zzUSER_GUESS_FAIL_HOOK(SeqFrozen)

+#ifndef zzUSER_GUESS_FAIL_HOOK

+#define zzUSER_GUESS_FAIL_HOOK(zzGuessSeq)

+#endif

+

+

+typedef struct _zzjmp_buf {

+			jmp_buf state;

+		} zzjmp_buf;

+

+/* these need to be macros not member functions */

+#define zzGUESS_BLOCK		ANTLRParserState zzst; int zzrv; int _marker; int zzGuessSeqFrozen;

+#define zzNON_GUESS_MODE	if ( !guessing )

+#define zzGUESS_FAIL		guess_fail();

+

+/*  Note:  zzGUESS_DONE does not execute longjmp() */

+

+#define zzGUESS_DONE		{zzrv=1; inputTokens->rewind(_marker); guess_done(&zzst);zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) }

+#define zzGUESS				saveState(&zzst); \

+							guessing = 1; \

+                            zzGuessSeqFrozen = ++zzGuessSeq; \

+							_marker = inputTokens->mark(); \

+							zzrv = setjmp(guess_start.state); \

+                            zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \

+						    if ( zzrv ) zzGUESS_DONE

+

+#define zzTRACEdata     const ANTLRChar *zzTracePrevRuleName = NULL;

+

+#ifndef zzTRACEIN

+#define zzTRACEIN(r)	zzTracePrevRuleName=traceCurrentRuleName;tracein(r);

+#endif

+#ifndef zzTRACEOUT

+#define zzTRACEOUT(r)	traceout(r);traceCurrentRuleName=zzTracePrevRuleName;

+#endif

+

+                  /* a n t l r  p a r s e r  d e f */

+

+struct ANTLRParserState {

+	/* class variables */

+	zzjmp_buf guess_start;

+	int guessing;

+

+	int inf_labase;

+	int inf_last;

+

+	int dirty;

+

+    int             traceOptionValue;       // MR10

+    int             traceGuessOptionValue;  // MR10

+    const ANTLRChar *traceCurrentRuleName;  // MR10

+    int             traceDepth;             // MR10

+

+};

+

+/* notes:

+ *

+ * multiple inheritance is a cool way to include what stuff is needed

+ * in this structure (like guess stuff).  however, i'm not convinced that

+ * multiple inheritance works correctly on all platforms.  not that

+ * much space is used--just include all possibly useful members.

+ *

+ * the class should also be a template with arguments for the lookahead

+ * depth and so on.  that way, more than one parser can be defined (as

+ * each will probably have different lookahead requirements).  however,

+ * am i sure that templates work?  no, i'm not sure.

+ *

+ * no attributes are maintained and, hence, the 'asp' variable is not

+ * needed.  $i can still be referenced, but it refers to the token

+ * associated with that rule element.  question: where are the token's

+ * stored if not on the software stack?  in local variables created

+ * and assigned to by antlr.

+ */

+class ANTLRParser {

+protected:

+	/* class variables */

+	static SetWordType bitmask[sizeof(SetWordType)*8];

+	static char eMsgBuffer[500];

+

+protected:

+	int LLk;					// number of lookahead symbols (old LL_K)

+	int demand_look;

+	ANTLRTokenType eofToken;			// when do I stop during resynch()s

+	int bsetsize;           			// size of bitsets created by ANTLR in

+        								// units of SetWordType

+

+	ANTLRTokenBuffer *inputTokens;	//place to get input tokens

+

+	zzjmp_buf guess_start;		// where to jump back to upon failure

+	int guessing;				// if guessing (using (...)? predicate)

+

+	// infinite lookahead stuff

+	int can_use_inf_look;		// set by subclass (generated by ANTLR)

+	int inf_lap;

+	int inf_labase;

+	int inf_last;

+	int *_inf_line;

+

+	const ANTLRChar **token_tbl; // pointer to table of token type strings MR20 const

+

+	int dirty;					// used during demand lookahead

+

+	ANTLRTokenType *token_type;		// fast reference cache of token.getType()

+//	ANTLRLightweightToken **token;	// the token with all its attributes

+	int lap;

+	int labase;

+#ifdef ZZDEFER_FETCH

+	int stillToFetch;                               // MR19 V.H. Simonis

+#endif

+

+private:

+	void fill_inf_look();

+

+protected:

+	virtual void guess_fail() {                         // MR9 27-Sep-97 make virtual

+        traceGuessFail();                               // MR10

+        longjmp(guess_start.state, 1); }                // MR9

+	virtual void guess_done(ANTLRParserState *st) {     // MR9 27-Sep-97 make virtual

+         restoreState(st); }                            // MR9

+	virtual int guess(ANTLRParserState *);              // MR9 27-Sep-97 make virtual

+	void look(int);

+    int _match(ANTLRTokenType, ANTLRChar **, ANTLRTokenType *,

+			   _ANTLRTokenPtr *, SetWordType **);

+    int _setmatch(SetWordType *, ANTLRChar **, ANTLRTokenType *,

+			   _ANTLRTokenPtr *, SetWordType **,

+			   SetWordType * tokclassErrset /* MR23 */);

+    int _match_wsig(ANTLRTokenType);

+    int _setmatch_wsig(SetWordType *);

+    virtual void consume();

+    virtual void resynch(SetWordType *wd,SetWordType mask); // MR21

+	void prime_lookahead();

+	virtual void tracein(const ANTLRChar *r);              // MR10

+	virtual void traceout(const ANTLRChar *r);             // MR10

+	static unsigned MODWORD(unsigned x) {return x & (EXT_WORDSIZE-1);}	// x % EXT_WORDSIZE // MR9

+	static unsigned DIVWORD(unsigned x) {return x >> EXT_LOGWORDSIZE;}	// x / EXT_WORDSIZE // MR9

+	int set_deg(SetWordType *);

+	int set_el(ANTLRTokenType, SetWordType *);

+	virtual void edecode(SetWordType *);				// MR1

+	virtual void FAIL(int k, ...);					    // MR1

+    int                 traceOptionValue;                           // MR10

+    int                 traceGuessOptionValue;                      // MR10

+    const ANTLRChar     *traceCurrentRuleName;                      // MR10

+    int                 traceDepth;                                 // MR10

+    void                traceReset();                               // MR10

+    virtual void        traceGuessFail();                           // MR10

+    virtual void        traceGuessDone(const ANTLRParserState *);   // MR10

+    int                 zzGuessSeq;                                 // MR10

+

+public:

+	ANTLRParser(ANTLRTokenBuffer *,

+				int k=1,

+				int use_inf_look=0,

+				int demand_look=0,

+				int bsetsize=1);

+	virtual ~ANTLRParser();

+

+	virtual void init();

+	

+	ANTLRTokenType LA(int i)

+	{

+//

+//  MR14 demand look will always be 0 for C++ mode

+//

+////	return demand_look ? token_type[(labase+(i)-1)&(LLk-1)] :

+////						token_type[(lap+(i)-1)&(LLk-1)];

+

+// MR19 V.H. Simonis Defer fetch feature

+

+#ifdef ZZDEFER_FETCH

+      undeferFetch();

+#endif

+	  return token_type[(lap+(i)-1)&(LLk-1)];

+	}

+	_ANTLRTokenPtr LT(int i);

+

+	void setEofToken(ANTLRTokenType t)	{ eofToken = t; }

+	ANTLRTokenType getEofToken() const  { return eofToken; }    // MR14

+

+	void noGarbageCollectTokens()	{ inputTokens->noGarbageCollectTokens(); }

+	void garbageCollectTokens()		{ inputTokens->garbageCollectTokens(); }

+

+    virtual void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup,

+					 SetWordType *eset, ANTLRTokenType etok, int k);

+	virtual void saveState(ANTLRParserState *);     // MR9 27-Sep-97 make virtual

+	virtual void restoreState(ANTLRParserState *);  // MR9 27-Sep-97 make virtual

+

+	virtual void panic(const char *msg); // MR20 const

+

+	static char *eMsgd(char *,int);

+	static char *eMsg(char *,char *);

+	static char *eMsg2(char *,char *,char *);

+

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+	virtual int printMessageV(FILE* pFile, const char* pFormat, va_list arglist); // MR23

+

+	void consumeUntil(SetWordType *st);

+	void consumeUntilToken(int t);

+

+	virtual int _setmatch_wdfltsig(SetWordType *tokensWanted,

+					 ANTLRTokenType tokenTypeOfSet,

+					 SetWordType *whatFollows);

+	virtual int _match_wdfltsig(ANTLRTokenType tokenWanted,

+					 SetWordType *whatFollows);

+	

+	const ANTLRChar * parserTokenName(int tok);			// MR1

+

+    int                 traceOptionValueDefault;        // MR11

+    int                 traceOption(int delta);         // MR11

+    int                 traceGuessOption(int delta);    // MR11

+

+//  MR8  5-Aug-97   S.Bochnak@microtool.com.pl

+//  MR8             Move resynch static local variable

+//  MR8               to class instance

+

+    int                 syntaxErrCount;                      // MR12

+    ANTLRTokenStream   *getLexer() const {                   // MR12

+      return inputTokens ? inputTokens->getLexer() : 0; }    // MR12

+protected:                                              // MR8

+    int     resynchConsumed;                            // MR8

+    char    *zzFAILtext; // workarea required by zzFAIL // MR9

+    void    undeferFetch();                             // MR19 V.H. Simonis

+    int     isDeferFetchEnabled();                      // MR19 V.H. Simonis

+    virtual void failedSemanticPredicate(const char* predicate); /* MR23 */

+};

+

+#define zzmatch(_t)							\

+	if ( !_match((ANTLRTokenType)_t, &zzMissText, &zzMissTok, \

+				 (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail;

+

+#define zzmatch_wsig(_t,handler)						\

+	if ( !_match_wsig((ANTLRTokenType)_t) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}

+

+#define zzsetmatch(_ts,_tokclassErrset)							\

+	if ( !_setmatch(_ts, &zzMissText, &zzMissTok, \

+				 (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail;

+

+#define zzsetmatch_wsig(_ts, handler)				\

+	if ( !_setmatch_wsig(_ts) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}

+

+/* For the dflt signal matchers, a FALSE indicates that an error occurred

+ * just like the other matchers, but in this case, the routine has already

+ * recovered--we do NOT want to consume another token.  However, when

+ * the match was successful, we do want to consume hence _signal=0 so that

+ * a token is consumed by the "if (!_signal) consume(); _signal=NoSignal;"

+ * preamble.

+ */

+#define zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) \

+	if ( !_setmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) ) \

+		_signal = MismatchedToken;

+

+#define zzmatch_wdfltsig(tokenWanted, whatFollows) \

+	if ( !_match_wdfltsig(tokenWanted, whatFollows) ) _signal = MismatchedToken;

+

+

+//  MR1  10-Apr-97 	zzfailed_pred() macro does not backtrack in guess mode.

+//  MR1	   		    Identification and correction due to J. Lilley

+//

+//  MR23            Call virtual method to report error.

+//  MR23            Provide more control over failed predicate action

+//                  without any need for user to worry about guessing internals.

+

+#ifndef zzfailed_pred

+#define zzfailed_pred(_p,_hasuseraction,_useraction) \

+  if (guessing) { \

+    zzGUESS_FAIL; \

+  } else { \

+    zzfailed_pred_action(_p,_hasuseraction,_useraction) \

+  }

+#endif

+

+//  MR23            Provide more control over failed predicate action

+//                  without any need for user to worry about guessing internals.

+//                  _hasuseraction == 0 => no user specified error action

+//                  _hasuseraction == 1 => user specified error action

+

+#ifndef zzfailed_pred_action

+#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \

+    if (_hasuseraction) { _useraction } else { failedSemanticPredicate(_p); }

+#endif

+

+#define zzRULE \

+		SetWordType *zzMissSet=NULL; ANTLRTokenType zzMissTok=(ANTLRTokenType)0;	\

+		_ANTLRTokenPtr zzBadTok=NULL; ANTLRChar *zzBadText=(ANTLRChar *)"";	\

+		int zzErrk=1,zzpf=0; \

+        zzTRACEdata \

+		ANTLRChar *zzMissText=(ANTLRChar *)"";

+

+#endif

+

+        /* S t a n d a r d  E x c e p t i o n  S i g n a l s */

+

+#define NoSignal			0

+#define MismatchedToken		1

+#define NoViableAlt			2

+#define NoSemViableAlt		3

+

+/* MR7  Allow more control over signalling                                  */

+/*        by adding "Unwind" and "SetSignal"                                */

+

+#define Unwind              4

+#define setSignal(newValue) *_retsignal=_signal=(newValue)

+#define suppressSignal       *_retsignal=_signal=0

+#define exportSignal        *_retsignal=_signal

diff --git a/Source/Pccts/h/ASTBase.cpp b/Source/Pccts/h/ASTBase.cpp
new file mode 100644
index 0000000..a94f080
--- /dev/null
+++ b/Source/Pccts/h/ASTBase.cpp
@@ -0,0 +1,256 @@
+/* Abstract syntax tree manipulation functions

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_stdarg.h"

+

+PCCTS_NAMESPACE_STD

+

+#define ANTLR_SUPPORT_CODE

+

+#include "ASTBase.h"

+

+/* ensure that tree manipulation variables are current after a rule

+ * reference

+ */

+void

+ASTBase::link(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)

+{

+	if ( *_sibling == NULL ) return;

+	if ( *_root == NULL ) *_root = *_sibling;

+	else if ( *_root != *_sibling ) (*_root)->_down = *_sibling;

+	if ( *_tail==NULL ) *_tail = *_sibling;

+	while ( (*_tail)->_right != NULL ) *_tail = (*_tail)->_right;

+}

+

+/* add a child node to the current sibling list */

+void

+ASTBase::subchild(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)

+{

+	if ( *_tail != NULL ) (*_tail)->_right = this;

+	else {

+		*_sibling = this;

+		if ( *_root != NULL ) (*_root)->_down = *_sibling;

+	}

+	*_tail = this;

+	if ( *_root == NULL ) *_root = *_sibling;

+}

+

+/* make a new AST node.  Make the newly-created

+ * node the root for the current sibling list.  If a root node already

+ * exists, make the newly-created node the root of the current root.

+ */

+void

+ASTBase::subroot(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)

+{

+	if ( *_root != NULL )

+		if ( (*_root)->_down == *_sibling ) *_sibling = *_tail = *_root;

+	*_root = this;

+	(*_root)->_down = *_sibling;

+}

+

+/* Apply preorder_action(), etc.. to root then each sibling */

+//

+//  7-Apr-97 133MR1

+//	Fix suggested by Ron House (house@helios.usq.edu.au)

+//

+void

+ASTBase::preorder(void* pData /*= NULL*/ /* MR23 */)

+{

+	ASTBase *tree = this;

+

+	while ( tree!= NULL )

+	{

+		if ( tree->_down != NULL ) {

+			tree->preorder_before_action(pData); 		// MR1	

+		};

+		tree->preorder_action(pData);

+		if ( tree->_down!=NULL )

+		{

+			tree->_down->preorder(pData);

+			tree->preorder_after_action(pData);			// MR1

+		}

+		tree = tree->_right;

+	}

+}

+

+/* free all AST nodes in tree; apply func to each before freeing */

+void

+ASTBase::destroy()

+{

+   ASTBase* tree = this;

+   while (tree) {

+      if (tree->_down) tree->_down->destroy();

+

+      ASTBase* cur = tree;

+      tree = tree->_right;

+      delete cur;

+   }

+}

+

+/* build a tree (root child1 child2 ... NULL)

+ * If root is NULL, simply make the children siblings and return ptr

+ * to 1st sibling (child1).  If root is not single node, return NULL.

+ *

+ * Siblings that are actually siblins lists themselves are handled

+ * correctly.  For example #( NULL, #( NULL, A, B, C), D) results

+ * in the tree ( NULL A B C D ).

+ *

+ * Requires at least two parameters with the last one being NULL.  If

+ * both are NULL, return NULL.

+ */

+ASTBase *

+ASTBase::tmake(ASTBase *root, ...)

+{

+	va_list ap;

+	register ASTBase *child, *sibling=NULL, *tail=NULL /*MR23*/, *w;

+

+	va_start(ap, root);

+

+	if ( root != NULL )

+		if ( root->_down != NULL ) {  

+            root->reportOverwriteOfDownPointer();  /* MR21 Report problem which almost always an error */

+            return NULL;

+        }

+	child = va_arg(ap, ASTBase *);

+	while ( child != NULL )

+	{

+		for (w=child; w->_right!=NULL; w=w->_right) {;} /* find end of child */

+		if ( sibling == NULL ) {sibling = child; tail = w;}

+		else {tail->_right = child; tail = w;}

+		child = va_arg(ap, ASTBase *);

+	}

+	if ( root==NULL ) root = sibling;

+	else root->_down = sibling;

+	va_end(ap);

+	return root;

+}

+

+#ifndef PCCTS_NOT_USING_SOR

+

+/* tree duplicate */

+// forgot to check for NULL this (TJP July 23,1995)

+ASTBase *

+ASTBase::dup()

+{

+	ASTBase *u, *t=this;

+	

+	if ( t == NULL ) return NULL;

+/*

+	u = new ASTBase;

+	*u = *t;

+*/

+	u = (ASTBase *)this->shallowCopy();

+	if ( t->_right!=NULL ) u->_right = t->_right->dup();

+	else u->_right = NULL;

+	if ( t->_down!=NULL ) u->_down = t->_down->dup();

+	else u->_down = NULL;

+	return u;

+}

+#endif

+

+//

+//  7-Apr-97 133MR1

+//  	     Fix suggested by Asgeir Olafsson (olafsson@cstar.ac.com)

+//

+/* tree duplicate */

+

+#ifndef PCCTS_NOT_USING_SOR

+

+ASTBase *

+ASTDoublyLinkedBase::dup()

+{

+	ASTDoublyLinkedBase *u, *t=this;

+	

+	if ( t == NULL ) return NULL;

+	u = (ASTDoublyLinkedBase *)this->shallowCopy();

+	u->_up = NULL;		/* set by calling invocation */

+	u->_left = NULL;

+	if (t->_right!=NULL) {						// MR1

+          u->_right=t->_right->dup();					// MR1

+	  ((ASTDoublyLinkedBase *)u->_right)->_left = u;		// MR1

+        } else {							// MR1

+	  u->_right = NULL;						// MR1

+        };								// MR1

+	if (t->_down!=NULL) {						// MR1

+  	  u->_down = t->_down->dup();					// MR1

+          ((ASTDoublyLinkedBase *)u->_down)->_up = u;			// MR1

+        } else {							// MR1

+	  u->_down = NULL;						// MR1

+        };								// MR1

+	return u;

+}

+

+#endif

+

+/*

+ * Set the 'up', and 'left' pointers of all nodes in 't'.

+ * Initial call is double_link(your_tree, NULL, NULL).

+ */

+void

+ASTDoublyLinkedBase::double_link(ASTBase *left, ASTBase *up)

+{

+    ASTDoublyLinkedBase *t = this;

+

+    t->_left = (ASTDoublyLinkedBase *) left;

+    t->_up = (ASTDoublyLinkedBase *) up;

+    if (t->_down != NULL)

+		((ASTDoublyLinkedBase *)t->_down)->double_link(NULL, t);

+    if (t->_right != NULL)

+		((ASTDoublyLinkedBase *)t->_right)->double_link(t, up);

+}

+

+// MR21 ASTBase::reportOverwriteOfDownPointer

+

+void ASTBase::reportOverwriteOfDownPointer()

+{

+    panic("Attempt to overwrite down pointer in ASTBase::tmake");

+}

+

+// MR21 ASTBase::panic

+

+void ASTBase::panic(const char *msg)

+{

+	/* MR23 */ printMessage(stderr,"ASTBase panic: %s\n", msg);

+	exit(PCCTS_EXIT_FAILURE);

+}

+

+#ifdef PCCTS_NOT_USING_SOR

+//MR23

+int ASTBase::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+  	int iRet = vfprintf(pFile, pFormat, marker);

+	va_end( marker );

+	return iRet;

+}

+#endif

diff --git a/Source/Pccts/h/ASTBase.h b/Source/Pccts/h/ASTBase.h
new file mode 100644
index 0000000..912f4b8
--- /dev/null
+++ b/Source/Pccts/h/ASTBase.h
@@ -0,0 +1,122 @@
+/* Abstract syntax tree

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ASTBase_H

+#define ASTBase_H

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+

+PCCTS_NAMESPACE_STD

+

+#ifndef PCCTS_NOT_USING_SOR

+#include "PCCTSAST.h"

+#endif

+

+/*

+ * Notes:

+ *

+ * To specify a copy constructor, subclass one of these classes and

+ * give the copy constructor.  To use dup(), you must define shallowCopy().

+ * shallowCopy() can use either a copy constructor or just copy the node

+ * itself.

+ */

+

+#ifdef PCCTS_NOT_USING_SOR

+class DllExportPCCTS ASTBase {

+#else

+class DllExportPCCTS ASTBase : public PCCTS_AST {

+#endif

+

+protected:

+	ASTBase *_right, *_down;

+

+public:

+

+#ifdef PCCTS_NOT_USING_SOR

+	ASTBase *right()	{ return _right; }

+	ASTBase *down()	    { return _down; }

+	void setRight(ASTBase *t)	{ _right = (ASTBase *)t; }

+	void setDown(ASTBase *t)	{ _down = (ASTBase *)t; }

+#else

+	PCCTS_AST *right()	{ return _right; }	// define the SORCERER interface

+	PCCTS_AST *down()	{ return _down; }

+	void setRight(PCCTS_AST *t)	{ _right = (ASTBase *)t; }

+	void setDown(PCCTS_AST *t)	{ _down = (ASTBase *)t; }

+#endif

+	ASTBase() { _right = _down = NULL; }

+	virtual ~ASTBase() { ; }

+#ifndef PCCTS_NOT_USING_SOR

+	virtual ASTBase *dup();

+#endif

+	void destroy();

+	void preorder(void* pData = NULL /* MR23 */);

+	static ASTBase *tmake(ASTBase *, ...);

+	static void link(ASTBase **, ASTBase **, ASTBase **);

+	void subchild(ASTBase **, ASTBase **, ASTBase **);

+	void subroot(ASTBase **, ASTBase **, ASTBase **);

+	virtual void preorder_action(void* /*pData*/ = NULL /* MR23 */) { ; }

+	virtual void preorder_before_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " ("); }

+	virtual void preorder_after_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " )"); }

+    virtual void panic(const char *msg);         /* MR21 */

+    virtual void reportOverwriteOfDownPointer(); /* MR21 */

+#ifdef PCCTS_NOT_USING_SOR

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+#endif

+};

+

+class DllExportPCCTS ASTDoublyLinkedBase : public ASTBase {

+protected:

+    ASTDoublyLinkedBase *_left, *_up;

+

+public:

+  void double_link(ASTBase *left, ASTBase *up);

+

+#ifndef PCCTS_NOT_USING_SOR

+  virtual ASTBase *dup();

+#endif

+

+#ifdef PCCTS_NOT_USING_SOR

+  ASTBase *left() { return _left; }

+  ASTBase *up() { return _up; }

+  void setLeft(ASTBase *t) { _left = (ASTDoublyLinkedBase *)t; }    // MR6

+  void setUp(ASTBase *t)   { _up = (ASTDoublyLinkedBase *)t; }	    // MR6

+#else

+  PCCTS_AST *left() { return _left; }

+  PCCTS_AST *up() { return _up; }

+  void setLeft(PCCTS_AST *t) { _left = (ASTDoublyLinkedBase *)t; }  // MR6

+  void setUp(PCCTS_AST *t)   { _up = (ASTDoublyLinkedBase *)t; }	// MR6

+#endif

+

+};

+

+class AST;	// announce that this class will be coming along shortly

+#endif

diff --git a/Source/Pccts/h/ATokPtr.h b/Source/Pccts/h/ATokPtr.h
new file mode 100644
index 0000000..75b4c86
--- /dev/null
+++ b/Source/Pccts/h/ATokPtr.h
@@ -0,0 +1,88 @@
+/* ATokPtr.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Written by Russell Quong June 30, 1995

+ * Adapted by Terence Parr to ANTLR stuff

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ATokPtr_h

+#define ATokPtr_h

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+

+PCCTS_NAMESPACE_STD

+

+// pointer to a reference counted object

+// robust in that an unused ANTLRTokenPtr can point to NULL.

+

+class ANTLRAbstractToken;

+

+class DllExportPCCTS ANTLRTokenPtr {

+public:

+    ANTLRTokenPtr(ANTLRAbstractToken *addr=NULL){ptr_ = addr; ref();}

+    ANTLRTokenPtr(const ANTLRTokenPtr &lhs)	{ptr_ = lhs.ptr_; lhs.ref();}

+    ~ANTLRTokenPtr();

+

+    // use ANTLRTokenPtr as a pointer to ANTLRToken

+//

+//  8-Apr-97	MR1	Make operator -> a const member function

+//			  as well as some other member functions

+//

+    ANTLRAbstractToken *operator-> () const { return ptr_; }		// MR1

+//

+//  7-Apr-97 133MR1

+//	     Fix suggested by Andreas Magnusson

+//			(Andreas.Magnusson@mailbox.swipnet.se)

+    void operator = (const ANTLRTokenPtr & lhs);		    	// MR1

+    void operator = (ANTLRAbstractToken *addr);

+    int operator != (const ANTLRTokenPtr &q) const	    		// MR1 // MR11 unsigned -> int

+	{ return this->ptr_ != q.ptr_; }

+    int operator == (const ANTLRTokenPtr &q) const  			// MR1 // MR11 unsigned -> int

+	{ return this->ptr_ == q.ptr_; }

+    int operator == (const ANTLRAbstractToken *addr) const      // MR11

+    { return this->ptr_ == addr; }

+    int operator != (const ANTLRAbstractToken *addr) const      // MR11

+    { return this->ptr_ != addr; }

+

+    void ref() const;

+    void deref();

+

+protected:

+    ANTLRAbstractToken *ptr_;

+};

+

+//typedef ANTLRTokenPtr _ANTLRTokenPtr;

+

+/*

+ * Since you cannot redefine operator->() to return one of the user's

+ * token object types, we must down cast.  This is a drag.  Here's

+ * a macro that helps.  template: "mytoken(a-smart-ptr)->myfield".

+ */

+#define mytoken(tk) ((ANTLRToken *)(tk.operator->()))

+

+#endif

diff --git a/Source/Pccts/h/ATokPtrImpl.h b/Source/Pccts/h/ATokPtrImpl.h
new file mode 100644
index 0000000..9c07cf5
--- /dev/null
+++ b/Source/Pccts/h/ATokPtrImpl.h
@@ -0,0 +1,88 @@
+/*

+ * ATokPtrImpl.h (formerly ATokPtr.cpp)

+ *

+ * This is #included in ATokBuffer.cpp for historical reasons.

+ * It has been renamed because of problems with the .cpp extension

+ * when used with IDE.

+ *

+ *

+ * ANTLRToken MUST be defined before entry to this file.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Written by Russell Quong June 30, 1995

+ * Adapted by Terence Parr to ANTLR stuff

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+PCCTS_NAMESPACE_STD

+

+#include "ATokPtr.h"

+

+void ANTLRTokenPtr::ref() const

+{

+    if (ptr_ != NULL) {

+		ptr_->ref();

+	}

+}

+

+void ANTLRTokenPtr::deref()

+{

+    if (ptr_ != NULL)

+    {

+		ptr_->deref();

+		if ( ptr_->nref()==0 )

+		{

+		    delete ptr_;

+			ptr_ = NULL;

+		}

+    }

+}

+

+ANTLRTokenPtr::~ANTLRTokenPtr()

+{

+    deref();

+}

+

+//

+//  8-Apr-97	MR1	Make operator -> a const member function

+//			  as weall as some other member functions

+//

+void ANTLRTokenPtr::operator = (const ANTLRTokenPtr & lhs)	// MR1

+{

+    lhs.ref();	// protect against "xp = xp"; ie same underlying object

+    deref();

+    ptr_ = lhs.ptr_;

+}

+

+void ANTLRTokenPtr::operator = (ANTLRAbstractToken *addr)

+{

+    if (addr != NULL) {

+	addr->ref();

+    }

+    deref();

+    ptr_ = addr;

+}

diff --git a/Source/Pccts/h/AToken.h b/Source/Pccts/h/AToken.h
new file mode 100644
index 0000000..6167c21
--- /dev/null
+++ b/Source/Pccts/h/AToken.h
@@ -0,0 +1,325 @@
+/* ANTLRToken.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ATOKEN_H_GATE

+#define ATOKEN_H_GATE

+

+#include "pcctscfg.h"

+

+#include "pccts_string.h"

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+#include "pccts_stdarg.h" // MR23

+

+PCCTS_NAMESPACE_STD

+

+// MR9      RJV (JVincent@novell.com) Not needed for variable length strings

+

+//// MR9 #ifndef ANTLRCommonTokenTEXTSIZE

+//// MR9 #define ANTLRCommonTokenTEXTSIZE        	100

+//// MR9 #endif

+

+

+/* must define what a char looks like; can make this a class too */

+typedef char ANTLRChar;

+

+/* D E F I N E  S M A R T  P O I N T E R S */

+

+//#include ATOKPTR_H   not tested yet, leave out

+class ANTLRAbstractToken;

+typedef ANTLRAbstractToken *_ANTLRTokenPtr;

+

+class ANTLRAbstractToken {

+public:

+    virtual ~ANTLRAbstractToken() {;}

+    virtual ANTLRTokenType getType() const = 0;

+    virtual void setType(ANTLRTokenType t) = 0;

+    virtual int getLine() const = 0;

+    virtual void setLine(int line) = 0;

+    virtual ANTLRChar *getText() const = 0;

+    virtual void setText(const ANTLRChar *) = 0;

+

+    /* This function will disappear when I can use templates */

+	virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,

+										  ANTLRChar *text,

+										  int line) = 0;

+

+	/* define to satisfy ANTLRTokenBuffer's need to determine whether or

+	   not a token object can be destroyed.  If nref()==0, no one has

+	   a reference, and the object may be destroyed.  This function defaults

+	   to 1, hence, if you use deleteTokens() message with a token object

+	   not derived from ANTLRCommonRefCountToken, the parser will compile

+	   but will not delete objects after they leave the token buffer.

+    */

+

+	virtual unsigned nref() const { return 1; }     // MR11

+	virtual void ref() {;}

+	virtual void deref() {;}

+

+	virtual void panic(const char *msg)             // MR20 const

+		{

+			/* MR23 */ printMessage(stderr, "ANTLRAbstractToken panic: %s\n", msg);

+			exit(PCCTS_EXIT_FAILURE);

+		}

+

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...) // MR23

+		{

+			va_list marker;

+			va_start( marker, pFormat );

+  			int iRet = vfprintf(pFile, pFormat, marker);

+			va_end( marker );

+			return iRet;

+		}

+};

+

+/* This class should be subclassed.  It cannot store token type or text */

+

+class ANTLRRefCountToken : public ANTLRAbstractToken {

+public:

+#ifdef DBG_REFCOUNTTOKEN

+	static int ctor;

+	static int dtor;

+#endif

+protected:

+    unsigned refcnt_;

+#ifdef DBG_REFCOUNTTOKEN

+	char object[200];

+#endif

+

+public:

+

+	// MR23 - No matter what you do, you're hammered.

+	//        Don't give names to formals something breaks.

+	//		  Give names to formals and don't use them it breaks.

+

+#ifndef DBG_REFCOUNTTOKEN

+	ANTLRRefCountToken(ANTLRTokenType /* t MR23 */, const ANTLRChar * /* s MR23 */)

+#else

+	ANTLRRefCountToken(ANTLRTokenType t, const ANTLRChar * s)

+#endif

+

+#ifndef DBG_REFCOUNTTOKEN

+		{

+			refcnt_ = 0;

+		}

+#else

+	{

+		ctor++;

+		refcnt_ = 0;

+		if ( t==1 ) sprintf(object,"tok_EOF");

+		else sprintf(object,"tok_%s",s);

+		/* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor);

+	}

+#endif

+	ANTLRRefCountToken()

+#ifndef DBG_REFCOUNTTOKEN

+		{ refcnt_ = 0; }

+#else

+		{

+			ctor++;

+			refcnt_ = 0;

+			sprintf(object,"tok_blank");

+			/* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor);

+		}

+	virtual ~ANTLRRefCountToken()

+		{

+			dtor++;

+			if ( dtor>ctor ) /* MR23 */ printMessage(stderr, "WARNING: dtor>ctor\n");

+			/* MR23 */ printMessage(stderr, "dtor %s #%d\n", object, dtor);

+			object[0]='\0';

+		}

+#endif

+

+	// reference counting stuff needed by ANTLRTokenPtr.

+	// User should not access these; for C++ language reasons, we had

+	// to make these public.  Yuck.

+

+	void ref()		      { refcnt_++; }

+	void deref()	      { refcnt_--; }

+	unsigned nref()	const { return refcnt_; }   // MR11

+

+	virtual ANTLRAbstractToken *makeToken(ANTLRTokenType /*tt MR23*/,

+										  ANTLRChar * /*txt MR23*/,

+										  int /*line MR23*/)

+	{

+		panic("call to ANTLRRefCountToken::makeToken()\n");

+		return NULL;

+	}

+};

+

+class ANTLRCommonNoRefCountToken : public ANTLRAbstractToken {

+protected:

+	ANTLRTokenType _type;

+	int _line;

+	ANTLRChar *_text;               // MR9 RJV

+

+public:

+	ANTLRCommonNoRefCountToken(ANTLRTokenType t, const ANTLRChar *s)

+	{ setType(t); _line = 0; _text = NULL; setText(s); }

+	ANTLRCommonNoRefCountToken()

+	{ setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); }

+

+	~ANTLRCommonNoRefCountToken() { if (_text) delete [] _text; }  // MR9 RJV: Added Destructor to remove string

+

+	ANTLRTokenType getType() const 	{ return _type; }

+	void setType(ANTLRTokenType t)	{ _type = t; }

+	virtual int getLine() const		{ return _line; }

+	void setLine(int line)	    	{ _line = line; }

+	ANTLRChar *getText() const   	{ return _text; }

+    int getLength() const           { return strlen(getText()); }       // MR11

+

+// MR9 RJV: Added code for variable length strings to setText()

+

+	void setText(const ANTLRChar *s)

+	{	if (s != _text) {

+          if (_text) delete [] _text;

+          if (s != NULL) {

+         	_text = new ANTLRChar[strlen(s)+1];

+            if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed");

+            strcpy(_text,s);

+    	  } else {

+            _text = new ANTLRChar[1];

+            if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed");

+            strcpy(_text,"");

+          };

+        };

+	}

+

+	virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,

+										  ANTLRChar *txt,

+										  int line)

+		{

+			ANTLRAbstractToken *t = new ANTLRCommonNoRefCountToken;

+			t->setType(tt); t->setText(txt); t->setLine(line);

+			return t;

+		}

+

+// MR9 THM Copy constructor required when heap allocated string is used with copy semantics

+

+   ANTLRCommonNoRefCountToken (const ANTLRCommonNoRefCountToken& from) :

+         ANTLRAbstractToken(from) {

+ 	 setType(from._type);

+	 setLine(from._line);

+     _text=NULL;

+     setText(from._text);

+  };

+

+// MR9 THM operator =() required when heap allocated string is used with copy semantics

+

+   virtual ANTLRCommonNoRefCountToken& operator =(const ANTLRCommonNoRefCountToken& rhs) {

+

+//////  MR15 WatCom can't hack use of operator =()

+//////  Use this:  *( (ANTRLAbstractToken *) this)=rhs;

+

+     *( (ANTLRAbstractToken *) this ) = rhs;

+

+  	 setType(rhs._type);

+ 	 setLine(rhs._line);

+     setText(rhs._text);

+     return *this;

+   };

+};

+

+class ANTLRCommonToken : public ANTLRRefCountToken {

+protected:

+	ANTLRTokenType       _type;

+	int                  _line;

+	ANTLRChar           *_text;               // MR9 RJV:Added

+

+public:

+	ANTLRCommonToken(ANTLRTokenType t, const ANTLRChar *s) : ANTLRRefCountToken(t,s)

+		{ setType(t); _line = 0; _text = NULL; setText(s); }                    // MR9

+	ANTLRCommonToken()

+		{ setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); }   // MR9

+

+	virtual ~ANTLRCommonToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string

+

+	ANTLRTokenType getType() const 	{ return _type; }

+	void setType(ANTLRTokenType t)	{ _type = t; }

+	virtual int getLine() const		{ return _line; }

+	void setLine(int line)	    	{ _line = line; }

+	ANTLRChar *getText() const		{ return _text; }

+    int getLength() const           { return strlen(getText()); }       // MR11

+

+// MR9 RJV: Added code for variable length strings to setText()

+

+	void setText(const ANTLRChar *s)

+	{	if (s != _text) {

+          if (_text) delete [] _text;

+          if (s != NULL) {

+         	_text = new ANTLRChar[strlen(s)+1];

+            if (_text == NULL) panic("ANTLRCommonToken::setText new failed");

+            strcpy(_text,s);

+    	  } else {

+            _text = new ANTLRChar[1];

+            if (_text == NULL) panic("ANTLRCommonToken::setText new failed");

+            strcpy(_text,"");

+          };

+        };

+	}

+

+	virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,

+										  ANTLRChar *txt,

+										  int line)

+	{

+		ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt);

+		t->setLine(line);

+		return t;

+	}

+

+// MR9 THM Copy constructor required when heap allocated string is used with copy semantics

+

+   ANTLRCommonToken (const ANTLRCommonToken& from) :

+         ANTLRRefCountToken(from) {

+ 	 setType(from._type);

+	 setLine(from._line);

+     _text=NULL;

+     setText(from._text);

+  };

+

+// MR9 THM operator =() required when heap allocated string is used with copy semantics

+

+   virtual ANTLRCommonToken& operator =(const ANTLRCommonToken& rhs) {

+

+//////  MR15 WatCom can't hack use of operator =()

+//////  Use this instead:   *( (ANTRLRRefCountToken *) this)=rhs;

+

+     *( (ANTLRRefCountToken *) this) = rhs;

+

+  	 setType(rhs._type);

+ 	 setLine(rhs._line);

+     setText(rhs._text);

+     return *this;

+   };

+};

+

+// used for backward compatibility

+typedef ANTLRCommonToken ANTLRCommonBacktrackingToken;

+

+#endif

diff --git a/Source/Pccts/h/ATokenBuffer.cpp b/Source/Pccts/h/ATokenBuffer.cpp
new file mode 100644
index 0000000..9a2f2fc
--- /dev/null
+++ b/Source/Pccts/h/ATokenBuffer.cpp
@@ -0,0 +1,374 @@
+/* ANTLRTokenBuffer.cpp

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+typedef int ANTLRTokenType;	// fool AToken.h into compiling

+

+class ANTLRParser;					/* MR1 */

+

+#define ANTLR_SUPPORT_CODE

+

+#include "pcctscfg.h"

+

+#include ATOKENBUFFER_H

+#include APARSER_H		// MR23

+

+typedef ANTLRAbstractToken *_ANTLRTokenPtr;

+

+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)

+static unsigned char test[1000];

+#endif

+

+#ifdef DBG_REFCOUNTTOKEN

+int ANTLRRefCountToken::ctor = 0; /* MR23 */

+int ANTLRRefCountToken::dtor = 0; /* MR23 */

+#endif

+

+ANTLRTokenBuffer::

+ANTLRTokenBuffer(ANTLRTokenStream *_input, int _k, int _chunk_size_formal) /* MR14 */

+{

+	this->input = _input;

+	this->k = _k;

+	buffer_size = chunk_size = _chunk_size_formal;

+	buffer = (_ANTLRTokenPtr *)

+			 calloc(chunk_size+1,sizeof(_ANTLRTokenPtr ));

+	if ( buffer == NULL ) {

+		panic("cannot alloc token buffer");

+	}

+	buffer++;				// leave the first elem empty so tp-1 is valid ptr

+

+	tp = &buffer[0];

+	last = tp-1;

+	next = &buffer[0];

+	num_markers = 0;

+	end_of_buffer = &buffer[buffer_size-1];

+	threshold = &buffer[(int)(buffer_size/2)];	// MR23 - Used to be 1.0/2.0 !

+	_deleteTokens = 1; 	// assume we delete tokens

+	parser=NULL;				// MR5 - uninitialized reference

+}

+

+static void f() {;}

+ANTLRTokenBuffer::

+~ANTLRTokenBuffer()

+{

+	f();

+	// Delete all remaining tokens (from 0..last inclusive)

+	if ( _deleteTokens )

+	{

+		_ANTLRTokenPtr *z;

+		for (z=buffer; z<=last; z++)

+		{

+			(*z)->deref();

+//			z->deref();

+#ifdef DBG_REFCOUNTTOKEN

+					/* MR23 */ printMessage(stderr, "##########dtor: deleting token '%s' (ref %d)\n",

+							((ANTLRCommonToken *)*z)->getText(), (*z)->nref());

+#endif

+			if ( (*z)->nref()==0 )

+			{

+				delete (*z);

+			}

+		}

+	}

+

+	if ( buffer!=NULL ) free((char *)(buffer-1));

+}

+

+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)

+#include "pccts_stdio.h"

+PCCTS_NAMESPACE_STD

+#endif

+

+_ANTLRTokenPtr ANTLRTokenBuffer::

+getToken()

+{

+	if ( tp <= last )	// is there any buffered lookahead still to be read?

+	{

+		return *tp++;	// read buffered lookahead

+	}

+	// out of buffered lookahead, get some more "real"

+	// input from getANTLRToken()

+	if ( num_markers==0 )

+	{

+		if( next > threshold )

+		{

+#ifdef DBG_TBUF

+/* MR23 */ printMessage(stderr,"getToken: next > threshold (high water is %d)\n", threshold-buffer);

+#endif

+			makeRoom();

+		}

+	}

+	else {

+		if ( next > end_of_buffer )

+		{

+#ifdef DBG_TBUF

+/* MR23 */ printMessage(stderr,"getToken: next > end_of_buffer (size is %d)\n", buffer_size);

+#endif

+			extendBuffer();

+		}

+	}

+	*next = getANTLRToken();

+	(*next)->ref();				// say we have a copy of this pointer in buffer

+	last = next;

+	next++;

+	tp = last;

+	return *tp++;

+}

+

+void ANTLRTokenBuffer::

+rewind(int pos)

+{

+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)

+	/* MR23 */ printMessage(stderr, "rewind(%d)[nm=%d,from=%d,%d.n=%d]\n", pos, num_markers, tp-buffer,pos,test[pos]);

+	test[pos]--;

+#endif

+	tp = &buffer[pos];

+	num_markers--;

+}

+

+/*

+ * This function is used to specify that the token pointers read

+ * by the ANTLRTokenBuffer should be buffered up (to be reused later).

+ */

+int ANTLRTokenBuffer::

+mark()

+{

+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)

+	test[tp-buffer]++;

+	/* MR23 */ printMessage(stderr,"mark(%d)[nm=%d,%d.n=%d]\n",tp-buffer,num_markers+1,tp-buffer,test[tp-buffer]);

+#endif

+	num_markers++;

+	return tp - buffer;

+}

+

+/*

+ * returns the token pointer n positions ahead.

+ * This implies that bufferedToken(1) gets the NEXT symbol of lookahead.

+ * This is used in conjunction with the ANTLRParser lookahead buffer.

+ *

+ * No markers are set or anything.  A bunch of input is buffered--that's all.

+ * The tp pointer is left alone as the lookahead has not been advanced

+ * with getToken().  The next call to getToken() will find a token

+ * in the buffer and won't have to call getANTLRToken().

+ *

+ * If this is called before a consume() is done, how_many_more_i_need is

+ * set to 'n'.

+ */

+_ANTLRTokenPtr ANTLRTokenBuffer::

+bufferedToken(int n)

+{

+//	int how_many_more_i_need = (last-tp < 0) ? n : n-(last-tp)-1;

+	int how_many_more_i_need = (tp > last) ? n : n-(last-tp)-1;

+	// Make sure that at least n tokens are available in the buffer

+#ifdef DBG_TBUF

+	/* MR23 */ printMessage(stderr, "bufferedToken(%d)\n", n);

+#endif

+	for (int i=1; i<=how_many_more_i_need; i++)

+	{

+		if ( next > end_of_buffer )	// buffer overflow?

+		{

+			extendBuffer();

+		}

+		*next = getANTLRToken();

+		(*next)->ref();		// say we have a copy of this pointer in buffer

+		last = next;

+		next++;

+	}

+	return tp[n - 1];

+}

+

+/* If no markers are set, the none of the input needs to be saved (except

+ * for the lookahead Token pointers).  We save only k-1 token pointers as

+ * we are guaranteed to do a getANTLRToken() right after this because otherwise

+ * we wouldn't have needed to extend the buffer.

+ *

+ * If there are markers in the buffer, we need to save things and so

+ * extendBuffer() is called.

+ */

+void ANTLRTokenBuffer::

+makeRoom()

+{

+#ifdef DBG_TBUF

+	/* MR23 */ printMessage(stderr, "in makeRoom.................\n");

+	/* MR23 */ printMessage(stderr, "num_markers==%d\n", num_markers);

+#endif

+/*

+	if ( num_markers == 0 )

+	{

+*/

+#ifdef DBG_TBUF

+		/* MR23 */ printMessage(stderr, "moving lookahead and resetting next\n");

+

+		_ANTLRTokenPtr *r;

+		/* MR23 */ printMessage(stderr, "tbuf = [");

+		for (r=buffer; r<=last; r++)

+		{

+			if ( *r==NULL ) /* MR23 */ printMessage(stderr, " xxx");

+			else /* MR23 */ printMessage(stderr, " '%s'", ((ANTLRCommonToken *)*r)->getText());

+		}

+		/* MR23 */ printMessage(stderr, " ]\n");

+

+		/* MR23 */ printMessage(stderr,

+		"before: tp=%d, last=%d, next=%d, threshold=%d\n",tp-buffer,last-buffer,next-buffer,threshold-buffer);

+#endif

+

+		// Delete all tokens from 0..last-(k-1) inclusive

+		if ( _deleteTokens )

+		{

+			_ANTLRTokenPtr *z;

+			for (z=buffer; z<=last-(k-1); z++)

+			{

+				(*z)->deref();

+//				z->deref();

+#ifdef DBG_REFCOUNTTOKEN

+					/* MR23 */ printMessage(stderr, "##########makeRoom: deleting token '%s' (ref %d)\n",

+							((ANTLRCommonToken *)*z)->getText(), (*z)->nref());

+#endif

+				if ( (*z)->nref()==0 )

+				{

+					delete (*z);

+				}

+			}

+		}

+

+		// reset the buffer to initial conditions, but move k-1 symbols

+		// to the beginning of buffer and put new input symbol at k

+		_ANTLRTokenPtr *p = buffer, *q = last-(k-1)+1;

+//		ANTLRAbstractToken **p = buffer, **q = end_of_buffer-(k-1)+1;

+#ifdef DBG_TBUF

+		/* MR23 */ printMessage(stderr, "lookahead buffer = [");

+#endif

+		for (int i=1; i<=(k-1); i++)

+		{

+			*p++ = *q++;

+#ifdef DBG_TBUF

+			/* MR23 */ printMessage(stderr,

+			" '%s'", ((ANTLRCommonToken *)buffer[i-1])->getText());

+#endif

+		}

+#ifdef DBG_TBUF

+		/* MR23 */ printMessage(stderr, " ]\n");

+#endif

+		next = &buffer[k-1];

+		tp = &buffer[k-1];	// tp points to what will be filled in next

+		last = tp-1;

+#ifdef DBG_TBUF

+		/* MR23 */ printMessage(stderr,

+		"after: tp=%d, last=%d, next=%d\n",

+		tp-buffer, last-buffer, next-buffer);

+#endif

+/*

+	}

+	else {

+		extendBuffer();

+	}

+*/

+}

+

+/* This function extends 'buffer' by chunk_size and returns with all

+ * pointers at the same relative positions in the buffer (the buffer base

+ * address could have changed in realloc()) except that 'next' comes

+ * back set to where the next token should be stored.  All other pointers

+ * are untouched.

+ */

+void

+ANTLRTokenBuffer::

+extendBuffer()

+{

+	int save_last = last-buffer, save_tp = tp-buffer, save_next = next-buffer;

+#ifdef DBG_TBUF

+	/* MR23 */ printMessage(stderr, "extending physical buffer\n");

+#endif

+	buffer_size += chunk_size;

+	buffer = (_ANTLRTokenPtr *)

+		realloc((char *)(buffer-1),

+				(buffer_size+1)*sizeof(_ANTLRTokenPtr ));

+	if ( buffer == NULL ) {

+		panic("cannot alloc token buffer");

+	}

+	buffer++;				// leave the first elem empty so tp-1 is valid ptr

+

+	tp = buffer + save_tp;	// put the pointers back to same relative position

+	last = buffer + save_last;

+	next = buffer + save_next;

+	end_of_buffer = &buffer[buffer_size-1];

+	threshold = &buffer[(int)(buffer_size*(1.0/2.0))];

+

+/*

+	// zero out new token ptrs so we'll know if something to delete in buffer

+	ANTLRAbstractToken **p = end_of_buffer-chunk_size+1;

+	for (; p<=end_of_buffer; p++) *p = NULL;

+*/

+}

+

+ANTLRParser * ANTLRTokenBuffer::				// MR1

+setParser(ANTLRParser *p) {					// MR1

+  ANTLRParser	*old=parser;					// MR1

+  parser=p;							// MR1

+  input->setParser(p);						// MR1

+  return old;							// MR1

+}								// MR1

+								// MR1

+ANTLRParser * ANTLRTokenBuffer::				// MR1

+getParser() {							// MR1

+  return parser;						// MR1

+}								// MR1

+

+void ANTLRTokenBuffer::panic(const char *msg) // MR23

+{ 

+	if (parser)				//MR23

+		parser->panic(msg);	//MR23

+	else					//MR23

+		exit(PCCTS_EXIT_FAILURE); 

+} 

+

+//MR23

+int ANTLRTokenBuffer::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+

+	int iRet = 0;

+	if (parser)

+		parser->printMessageV(pFile, pFormat, marker);

+	else

+  		iRet = vfprintf(pFile, pFormat, marker);

+

+	va_end( marker );

+	return iRet;

+}

+

+/* to avoid having to link in another file just for the smart token ptr

+ * stuff, we include it here.  Ugh.

+ *

+ * MR23 This causes nothing but problems for IDEs.

+ *      Change from .cpp to .h

+ *

+ */

+

+#include ATOKPTR_IMPL_H

diff --git a/Source/Pccts/h/ATokenBuffer.h b/Source/Pccts/h/ATokenBuffer.h
new file mode 100644
index 0000000..1c008fd
--- /dev/null
+++ b/Source/Pccts/h/ATokenBuffer.h
@@ -0,0 +1,109 @@
+/* ANTLRTokenBuffer.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ATOKENBUFFER_H_GATE

+#define ATOKENBUFFER_H_GATE

+

+#include "pcctscfg.h"

+

+#include "pccts_stdlib.h"

+

+PCCTS_NAMESPACE_STD

+

+#include ATOKEN_H

+#include ATOKENSTREAM_H

+

+/*

+ * The parser is "attached" to an ANTLRTokenBuffer via interface

+ * functions: getToken() and bufferedToken().  The object that actually

+ * consumes characters and constructs tokens is connected to the

+ * ANTLRTokenBuffer via interface function ANTLRTokenStream::getToken();

+ * where ANTLRTokenStream is really just a behavior (class with no data).

+ * C++ does not have this abstraction and hence we simply have come up

+ * with a fancy name for "void *".  See the note in ANTLRTokenStream.h on

+ * the "behavior" of ANTLRTokenStream.

+ */

+

+class ANTLRParser;					// MR1

+

+class DllExportPCCTS ANTLRTokenBuffer {

+protected:

+	ANTLRTokenStream *input;        // where do I get tokens

+	int buffer_size;

+	int chunk_size;

+	int num_markers;

+	int k;                          // Need at least this many tokens in buffer

+	_ANTLRTokenPtr *buffer;	// buffer used for arbitrary lookahead

+	_ANTLRTokenPtr *tp;        // pts into buffer; current token ptr

+	_ANTLRTokenPtr *last;      // pts to last valid token in buffer

+	_ANTLRTokenPtr *next;      // place to put token from getANTLRToken()

+	_ANTLRTokenPtr *end_of_buffer;

+	/* when you try to write a token past this and there are no markers

+	   set, then move k-1 tokens back to the beginning of the buffer.

+	   We want to stay away from the end of the buffer because we have

+	   to extend it if a marker is set and we reach the end (we cannot

+	   move tokens to the beginning of the buffer in this case).

+	 */

+	_ANTLRTokenPtr *threshold;

+	unsigned char _deleteTokens;

+

+	// This function is filled in by the subclass; it initiates fetch of input

+	virtual _ANTLRTokenPtr getANTLRToken() { return input->getToken(); }

+	void makeRoom();

+	void extendBuffer();

+

+public:

+	ANTLRTokenBuffer(ANTLRTokenStream *in, int k=1, int chksz=50);

+	virtual ~ANTLRTokenBuffer();

+	virtual _ANTLRTokenPtr getToken();

+	virtual void rewind(int pos);

+	virtual int mark();

+	virtual _ANTLRTokenPtr bufferedToken(int i);

+

+	void noGarbageCollectTokens()	{ _deleteTokens=0; }

+	void garbageCollectTokens()		{ _deleteTokens=1; }

+

+	virtual int bufferSize() { return buffer_size; }

+	virtual int minTokens() { return k; }

+	virtual void setMinTokens(int k_new) { k = k_new; }

+

+	virtual void panic(const char *msg); /* MR20 const */

+

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+

+protected:						// MR1

+	ANTLRParser	*parser;			// MR1

+public:							// MR1

+	ANTLRParser	*setParser(ANTLRParser *p);	// MR1

+	ANTLRParser	*getParser();			    // MR1

+    ANTLRTokenStream *getLexer() const {    // MR12

+      return input;}                        // MR12

+};

+

+#endif

diff --git a/Source/Pccts/h/ATokenStream.h b/Source/Pccts/h/ATokenStream.h
new file mode 100644
index 0000000..3dfea6e
--- /dev/null
+++ b/Source/Pccts/h/ATokenStream.h
@@ -0,0 +1,51 @@
+/* ANTLRTokenStream.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ATOKENSTREAM_H_GATE

+#define ATOKENSTREAM_H_GATE

+

+#include "pcctscfg.h"

+

+/* This is really a behavior or protocol; it merely indicates the behavior

+ * required of the input and output of an ANTLRTokenBuffer.  You could

+ * subclass it, but you can also just pass any old pointer to ANTLRTokenBuffer

+ * with a type cast (in which case, your getANTLRToken() would have to

+ * explicitly cast the input pointer to your REAL type (typically your lexer)).

+ */

+

+class ANTLRParser;							// MR1

+

+class DllExportPCCTS ANTLRTokenStream {

+public:

+    virtual _ANTLRTokenPtr getToken() = 0;

+	virtual ANTLRParser * setParser(ANTLRParser * /*p MR23*/) {return 0; };   // MR12

+	virtual ANTLRParser * getParser() { return 0; };		        // MR12

+};

+

+#endif

diff --git a/Source/Pccts/h/BufFileInput.cpp b/Source/Pccts/h/BufFileInput.cpp
new file mode 100644
index 0000000..99d08a4
--- /dev/null
+++ b/Source/Pccts/h/BufFileInput.cpp
@@ -0,0 +1,100 @@
+// FILE:        BufFileInput.cpp

+// AUTHOR:      Alexey Demakov (AVD) demakov@kazbek.ispras.ru

+// CREATION:    26-JAN-1998

+// DESCRIPTION: File Input Stream with lookahead for Scanner.

+//   See file BufFileInput.h for details

+

+// Change History:

+//

+//   22-Jun-1998    assert.h -> PCCTS_ASSERT_H

+//                  string.h -> PCCTS_STRING_H

+//

+//   28-May-1998    Add virtual destructor to release buffer.

+//

+//                  Add dummy definition for ANTLRTokenType

+//                  to allow compilation without knowing

+//                  token type codes.

+//

+//                  Manfred Kogler (km@cast.uni-linz.ac.at)

+//                  (1.33MR14)

+//

+//   20-Jul-1998    MR14a - Reorder initialization list for ctor.

+//

+

+enum ANTLRTokenType {TER_HATES_CPP=0, SO_DO_OTHERS=9999 };

+

+#include "pcctscfg.h"

+#include "pccts_assert.h"

+#include "pccts_string.h"

+

+PCCTS_NAMESPACE_STD

+

+#include "BufFileInput.h"

+

+BufFileInput::BufFileInput( FILE *f, int buf_size )

+: input( f ),

+  buf( new int[buf_size] ),

+  size( buf_size ),

+  start( 0 ),

+  len( 0 )

+{

+}

+

+BufFileInput::~BufFileInput()

+{

+  delete [] buf;

+}

+

+int BufFileInput::nextChar( void )

+{

+    if( len > 0 )

+    {

+        // get char from buffer

+        int c = buf[start];

+

+        if( c != EOF )

+        {

+            start++; start %= size;

+            len--;

+        }

+        return c;

+    } else {

+        // get char from file

+        int c = getc( input );

+

+        if( c == EOF )

+        {

+            // if EOF - put it in the buffer as indicator

+            buf[start] = EOF;

+            len++;

+        }

+        return c;

+    }

+}

+

+int BufFileInput::lookahead( char* s )

+{

+    int l = strlen( s );

+

+    assert( 0 < l && l <= size );

+

+    while( len < l )

+    {

+        int c = getc( input );

+

+        buf[ (start+len) % size ] = c;

+

+        len++;

+

+        if( c == EOF ) return 0;

+    }

+

+    for( int i = 0; i < l; i++ )

+    {

+        if( s[i] != buf[ (start+i) % size ] ) return 0;

+    }

+    return 1;

+}

+

+// End of file BufFileInput.cpp

+

diff --git a/Source/Pccts/h/BufFileInput.h b/Source/Pccts/h/BufFileInput.h
new file mode 100644
index 0000000..ea54c0e
--- /dev/null
+++ b/Source/Pccts/h/BufFileInput.h
@@ -0,0 +1,53 @@
+// FILE:        BufFileInput.h

+// AUTHOR:      Alexey Demakov (AVD) demakov@kazbek.ispras.ru

+// CREATION:    26-JAN-1998

+// DESCRIPTION: File Input Stream with lookahead for Scanner

+// Tested under Win32 with ANTLR 1.33 MR10 and MSVC 5.0

+

+// Change History:

+//

+//   28-May-1998    Add virtual destructor to release buffer

+//                  Manfred Kogler (km@cast.uni-linz.ac.at)

+//                  (1.33MR14)

+

+#ifndef BufFileInput_h

+#define BufFileInput_h

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+

+PCCTS_NAMESPACE_STD

+

+#include "DLexerBase.h"

+

+class DllExportPCCTS BufFileInput : public DLGInputStream

+{

+public:

+    // constructor

+    // f - input stream

+    // buf_size - size of buffer (maximal length for string in is_in)

+

+    BufFileInput(FILE *f, int buf_size = 8 );

+

+    virtual ~BufFileInput();

+

+    // gets next char from stream

+

+    virtual int nextChar( void );

+

+    // looks in stream and compares next l characters with s

+    // returns the result of comparision

+

+    int lookahead( char* s );

+

+private:

+    FILE *input; // input stream;

+    int* buf;    // buffer

+    int  size;   // size of buffer

+    int  start;  // position of the first symbol in buffer

+    int  len;    // count of characters in buffers

+};

+

+#endif

+// end of file BufFileInput.h

diff --git a/Source/Pccts/h/DLG_stream_input.h b/Source/Pccts/h/DLG_stream_input.h
new file mode 100644
index 0000000..d2147f5
--- /dev/null
+++ b/Source/Pccts/h/DLG_stream_input.h
@@ -0,0 +1,98 @@
+

+/************************************************************/

+/*															*/

+/*		Predefined char stream: Input from (c++) stream.	*/

+/*															*/

+/* By Hubert Holin (Hubert.Holin@Bigfoot.com), 1998.		*/

+/*															*/

+/* This is completely free stuff, do whatever you want with	*/

+/* it (but then, I will take no responsability for whatever	*/

+/* may happen if you do either... caveat emptor!).			*/

+/*															*/

+/************************************************************/

+

+#ifndef _DLG_STREAM_INPUT_H

+#define _DLG_STREAM_INPUT_H

+

+#include "pccts_istream.h"

+

+PCCTS_NAMESPACE_STD

+

+#ifndef DLGX_H

+#include "DLexerBase.h"

+#endif

+

+

+// NOTES:	The semantics of the copy constructor

+//			and the affectation operator may be unwaranted...

+//			and the stream may not be reset.

+//

+//			It would have been so much nicer for nextChar()

+//			to throw (of for the DLGInputStream to change status)

+//			upon hiting EOF than to return an "int"...

+

+template	<

+				class E,

+				class T = ::std::char_traits<E>

+			>

+class DLG_stream_input : public DLGInputStream

+{

+public:

+	

+						DLG_stream_input(::std::basic_istream<E,T> * p_input_stream)

+	:	input(p_input_stream)

+	{

+		// nothing to do!

+	};

+	

+						DLG_stream_input(const DLG_stream_input & a_recopier)

+	:	input(a_recopier.input)

+	{

+		// nothing to do!

+	};

+	

+	virtual				~DLG_stream_input()

+	{

+		this->purge();	// bloody templarized lookup...

+	};

+	

+	DLG_stream_input	operator = (const DLG_stream_input & a_affecter)

+	{

+		if (this != &a_affecter)

+		{

+			input = a_affecter.input;

+		}

+

+		return(*this);

+	};

+	

+	virtual int			nextChar()

+	{

+		E	extracted_stuff;

+		

+		input->get(extracted_stuff);

+		

+		if	(*input)

+		{

+			return(int(extracted_stuff));

+		}

+		else

+		{

+			return(EOF);

+		}

+	};

+	

+protected:

+	

+	::std::basic_istream<E,T> *	input;

+	

+private:

+	

+	void	purge()

+	{

+		// nothing to do!

+	};

+};

+

+#endif /* _DLG_STREAM_INPUT_H */

+

diff --git a/Source/Pccts/h/DLexer.h b/Source/Pccts/h/DLexer.h
new file mode 100644
index 0000000..37cac24
--- /dev/null
+++ b/Source/Pccts/h/DLexer.h
@@ -0,0 +1,191 @@
+/* DLexer.h (formerly DLexer.cpp)

+ *

+ * This was renamed because the use of the .cpp extension caused problems

+ * with IDEs.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#define ZZINC {if ( track_columns ) (++_endcol);}

+

+#define ZZGETC {ch = input->nextChar(); cl = ZZSHIFT(ch);}

+

+#define ZZNEWSTATE	(newstate = dfa[state][cl])

+

+#ifndef ZZCOPY

+#define ZZCOPY	\

+	/* Truncate matching buffer to size (not an error) */	\

+	if (nextpos < lastpos){				\

+		*(nextpos++) = ch;			\

+	}else{							\

+		bufovf = 1;					\

+	}

+#endif

+

+void DLGLexer::

+mode( int m )

+{

+	/* points to base of dfa table */

+	if (m<MAX_MODE){

+		automaton = m;

+		/* have to redo class since using different compression */

+		cl = ZZSHIFT(ch);

+	}else{

+		sprintf((char *)ebuf,"Invalid automaton mode = %d ",m);

+		errstd(ebuf);

+	}

+}

+

+ANTLRTokenType DLGLexer::

+nextTokenType(void)

+{

+	register int state, newstate;

+	/* last space reserved for the null char */

+	register DLGChar *lastpos;

+	ANTLRTokenType tk;

+

+skip:

+	bufovf = 0;

+	lastpos = &_lextext[_bufsize-1];

+	nextpos = _lextext;

+	_begcol = _endcol+1;

+more:

+	_begexpr = nextpos;

+	if ( interactive ) {

+		/* interactive version of automaton */

+		/* if there is something in ch, process it */

+		state = newstate = dfa_base[automaton];

+		if (charfull){

+			ZZINC;

+			ZZCOPY;

+			ZZNEWSTATE;

+		}

+		while (alternatives[newstate]){

+			state = newstate;

+			ZZGETC;

+			ZZINC;

+			ZZCOPY;

+			ZZNEWSTATE;

+		}

+		/* figure out if last character really part of token */

+		if ((state != dfa_base[automaton]) && (newstate == DfaStates)){

+			charfull = 1;

+			--nextpos;

+		}else{

+			charfull = 0;

+			state = newstate;

+		}

+		*(nextpos) = '\0';

+		/* Able to transition out of start state to some non err state?*/

+		if ( state == dfa_base[automaton] ){

+			/* make sure doesn't get stuck */

+			advance();

+		}

+	}

+	else { /* non-interactive version of automaton */

+		if (!charfull)

+			advance();

+		else

+			ZZINC;

+		state = dfa_base[automaton];

+		while (ZZNEWSTATE != DfaStates) {

+			state = newstate;

+			ZZCOPY;

+			ZZGETC;

+			ZZINC;

+		}

+		charfull = 1;

+		if ( state == dfa_base[automaton] ){

+			if (nextpos < lastpos){

+				*(nextpos++) = ch;

+			}else{

+				bufovf = 1;

+			}

+			*nextpos = '\0';

+			/* make sure doesn't get stuck */

+			advance();

+		}else{

+			*nextpos = '\0';

+		}

+	}

+	if ( track_columns ) _endcol -= charfull;

+	_endexpr = nextpos -1;

+	add_erase = 0;

+#ifdef OLD

+	tk = (ANTLRTokenType)

+		 (*actions[accepts[state]])(this);	// must pass this manually

+											// actions is not a [] of pointers

+											// to member functions.

+#endif

+	tk = (this->*actions[accepts[state]])();

+

+// MR1

+// MR1 11-Apr-97  Help for tracking DLG results

+// MR1

+

+#ifdef DEBUG_LEXER

+

+/* MR1 */        if (debugLexerFlag) {

+/* MR1 */	   if (parser != NULL) {

+/* MR1 */	     /* MR23 */ printMessage(stdout, "\ntoken name=%s",parser->parserTokenName(tk));

+/* MR1 */	   } else {

+/* MR1 */	     /* MR23 */ printMessage(stdout, "\ntoken nnumber=%d",tk);

+/* MR1 */	   };

+/* MR1 */	   /* MR23 */ printMessage(stdout, " lextext=(%s) mode=%d",

+/* MR1 */		 (_lextext[0]=='\n' && _lextext[1]==0) ?

+/* MR1 */			"newline" : _lextext,

+/* MR1 */				automaton);

+/* MR1 */          if (interactive && !charfull) {

+/* MR1 */	     /* MR23 */ printMessage(stdout, " char=empty");

+/* MR1 */          } else {

+/* MR1 */	     if (ch=='\n') {

+/* MR1 */	       /* MR23 */ printMessage(stdout, " char=newline");

+/* MR1 */	     } else {

+/* MR1 */	       /* MR23 */ printMessage(stdout, " char=(%c)",ch);

+/* MR1 */	     };

+/* MR1 */	   };

+/* MR1 */	   /* MR23 */ printMessage(stdout, " %s\n",

+/* MR1 */		 (add_erase==1 ? "skip()" :

+/* MR1 */		  add_erase==2 ? "more()" :

+/* MR1 */		  ""));

+/* MR1 */        };

+

+#endif

+

+	switch (add_erase) {

+		case 1: goto skip;

+		case 2: goto more;

+	}

+	return tk;

+}

+

+void DLGLexer::

+advance()

+{

+	if ( input==NULL ) err_in();

+	ZZGETC; charfull = 1; ZZINC;

+}

diff --git a/Source/Pccts/h/DLexerBase.cpp b/Source/Pccts/h/DLexerBase.cpp
new file mode 100644
index 0000000..b218afc
--- /dev/null
+++ b/Source/Pccts/h/DLexerBase.cpp
@@ -0,0 +1,302 @@
+/* DLGLexerBase.c

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+

+PCCTS_NAMESPACE_STD

+

+/* I have to put this here due to C++ limitation

+ * that you can't have a 'forward' decl for enums.

+ * I hate C++!!!!!!!!!!!!!!!

+ */

+

+// MR1

+// MR1  10-Apr-97  133MR1  Prevent use of varying sizes for the

+// MR1  			ANTLRTokenType enum

+// MR1

+

+enum ANTLRTokenType { TER_HATES_CPP=0, ITS_UTTER_GARBAGE,		// MR1

+					 WITH_SOME_GOOD_IDEAS=9999};	// MR1

+

+#define ANTLR_SUPPORT_CODE

+

+#include "pcctscfg.h"

+#include DLEXERBASE_H

+#include APARSER_H		// MR23

+

+DLGLexerBase::

+DLGLexerBase(DLGInputStream *in,

+	     unsigned bufsize,

+	     int _interactive,

+	     int _track_columns)

+{

+	this->_bufsize = bufsize;

+	this->_lextext = new DLGChar[_bufsize];

+	if ( this->_lextext==NULL ) {

+	    panic("text buffer is NULL");

+	}

+	this->_begexpr = this->_endexpr = NULL;

+	this->ch = this->bufovf = 0;

+	this->nextpos = NULL;

+	this->cl = 0;

+	this->add_erase = 0;

+	this->input = in;

+	this->_begcol = 0;

+	this->_endcol = 0;

+	this->_line = 1;

+	this->charfull = 0;

+	this->automaton = 0;

+	this->token_to_fill = NULL;

+	this->interactive = _interactive;

+	this->track_columns = _track_columns;

+	this->debugLexerFlag = 0;					// MR1

+	this->parser = NULL;						// MR1

+    this->lexErrCount=0;                        // MR11

+}

+

+// MR19  THM 

+

+void DLGLexerBase::reset()

+{

+	this->charfull = 0;

+	this->_begcol = 0;

+	this->_endcol = 0;

+	this->automaton = 0;

+	this->_line=1;

+	this->lexErrCount=0;

+}

+

+void DLGLexerBase::

+setInputStream( DLGInputStream *in )

+{

+	this->input = in;

+	_line = 1;

+	charfull = 0;

+}

+

+/* saves dlg state, but not what feeds dlg (such as file position) */

+void DLGLexerBase::

+saveState(DLGState *state)

+{

+	state->input = input;

+	state->interactive = interactive;

+	state->track_columns = track_columns;

+	state->auto_num = automaton;

+	state->add_erase = add_erase;

+	state->lookc = ch;

+	state->char_full = charfull;

+	state->begcol = _begcol;

+	state->endcol = _endcol;

+	state->line = _line;

+	state->lextext = _lextext;

+	state->begexpr = _begexpr;

+	state->endexpr = _endexpr;

+	state->bufsize = _bufsize;

+	state->bufovf = bufovf;

+	state->nextpos = nextpos;

+	state->class_num = cl;

+	state->debugLexerFlag = debugLexerFlag;				// MR1

+	state->parser = parser;						// MR1

+}

+

+void DLGLexerBase::

+restoreState(DLGState *state)

+{

+	input = state->input;

+	interactive = state->interactive;

+	track_columns = state->track_columns;

+	automaton = state->auto_num;

+	add_erase = state->add_erase;

+	ch = state->lookc;

+	charfull = state->char_full;

+	_begcol = state->begcol;

+	_endcol = state->endcol;

+	_line = state->line;

+	_lextext = state->lextext;

+	_begexpr = state->begexpr;

+	_endexpr = state->endexpr;

+	_bufsize = state->bufsize;

+	bufovf = state->bufovf;

+	nextpos = state->nextpos;

+	cl = state->class_num;

+	debugLexerFlag = state->debugLexerFlag;				// MR1

+	parser = state->parser;						// MR1

+}

+

+/* erase what is currently in the buffer, and get a new reg. expr */

+void DLGLexerBase::

+skip()

+{

+	add_erase = 1;

+}

+

+/* don't erase what is in the lextext buffer, add on to it */

+void DLGLexerBase::

+more()

+{

+	add_erase = 2;

+}

+

+/* substitute c for the reg. expr last matched and is in the buffer */

+void DLGLexerBase::

+replchar(DLGChar c)

+{

+	/* can't allow overwriting null at end of string */

+	if (_begexpr < &_lextext[_bufsize-1]){

+		*_begexpr = c;

+		*(_begexpr+1) = '\0';

+	}

+	_endexpr = _begexpr;

+	if (c != '\0') {

+		nextpos = _begexpr + 1;

+	}

+	else {

+		nextpos = _begexpr;	/* MR30 Zero terminates string. */

+	}

+}

+

+/* replace the string s for the reg. expr last matched and in the buffer */

+

+#ifdef _MSC_VER  // MR23

+//Turn off "assignment within conditional expression" warning

+#pragma warning(disable : 4706)

+#endif

+void DLGLexerBase::

+replstr(const DLGChar *s) /* MR20 const */

+{

+	register DLGChar *l= &_lextext[_bufsize -1];

+

+	nextpos = _begexpr;

+	if (s){

+		while ((nextpos <= l) && (*(nextpos++) = *(s++))){

+			/* empty */

+		}

+		/* correct for NULL at end of string */

+		nextpos--;

+	}

+	if ((nextpos <= l) && (*(--s) == 0)){

+		bufovf = 0;

+	}else{

+		bufovf = 1;

+	}

+	*(nextpos) = '\0';

+	_endexpr = nextpos - 1;

+}

+#ifdef _MSC_VER  // MR23

+#pragma warning(default: 4706)

+#endif

+

+void DLGLexerBase::

+errstd(const char *s)                               /* MR20 const */

+{

+        lexErrCount++;                              /* MR11 */

+        /* MR23 */ printMessage(stderr,

+                "%s near line %d (text was '%s')\n",

+                ((s == NULL) ? "Lexical error" : s),

+                _line,_lextext);

+}

+

+int DLGLexerBase::

+err_in()

+{

+	/* MR23 */ printMessage(stderr,"No input stream, function, or string\n");

+	/* return eof to get out gracefully */

+	return EOF;

+}

+

+ANTLRTokenType DLGLexerBase::

+erraction()

+{

+	errstd("invalid token");

+	advance();

+	skip();

+	return (ANTLRTokenType) 0;	// bogus, but satisfies compiler

+}

+

+_ANTLRTokenPtr DLGLexerBase::

+getToken()

+{

+	if ( token_to_fill==NULL ) panic("NULL token_to_fill");

+	ANTLRTokenType tt = nextTokenType();

+	_ANTLRTokenPtr tk = token_to_fill->makeToken(tt, _lextext,_line);

+	return tk;

+}

+

+void DLGLexerBase::

+panic(const char *msg)      /* MR20 const */

+{

+	if (parser)				//MR23

+		parser->panic(msg);	//MR23

+	else					//MR23

+	{

+		/* MR23 */ printMessage(stderr, "DLG panic: %s\n", msg);

+	//

+	//  7-Apr-97 133MR1

+	//

+		exit(PCCTS_EXIT_FAILURE);					// MR1

+	}

+}

+

+ANTLRParser * DLGLexerBase::						// MR1

+setParser(ANTLRParser *p) {						// MR1

+  ANTLRParser	*oldValue=parser;					// MR1

+  parser=p;								// MR1

+  return oldValue;							// MR1

+}									// MR1

+									// MR1

+ANTLRParser * DLGLexerBase::						// MR1

+getParser() {								// MR1

+  return parser;							// MR1

+}									// MR1

+									// MR1

+int DLGLexerBase::							// MR1

+debugLexer(int newValue) {						// MR1

+  int	oldValue=debugLexerFlag;					// MR1

+  debugLexerFlag=newValue;						// MR1

+  return oldValue;							// MR1

+}									// MR1

+

+//MR23

+int DLGLexerBase::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+

+	int iRet = 0;

+	if (parser)

+		parser->printMessageV(pFile, pFormat, marker);

+	else

+  		iRet = vfprintf(pFile, pFormat, marker);

+

+	va_end( marker );

+	return iRet;

+}

diff --git a/Source/Pccts/h/DLexerBase.h b/Source/Pccts/h/DLexerBase.h
new file mode 100644
index 0000000..db6cc18
--- /dev/null
+++ b/Source/Pccts/h/DLexerBase.h
@@ -0,0 +1,198 @@
+/* DLGLexerBase.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef DLGX_H

+#define DLGX_H

+

+#include "pcctscfg.h"

+#include "pccts_stdio.h"

+

+PCCTS_NAMESPACE_STD

+

+#include ATOKEN_H

+#include ATOKENSTREAM_H

+

+class ANTLRParser;							// MR1

+

+/* must define what a char looks like; can make this a class too */

+typedef char DLGChar;

+

+/*  Can have it as a class too: (ack this looks weird; is it right?)

+class DllExportPCCTS DLGChar {

+private:

+	int c;

+public:

+	DLGChar(int ch) { c = ch; }

+	int atom() { return c; }

+};

+*/

+

+/* user must subclass this */

+class DllExportPCCTS DLGInputStream {

+public:

+	virtual int nextChar() = 0;

+};

+

+/* Predefined char stream: Input from FILE */

+class DllExportPCCTS DLGFileInput : public DLGInputStream {

+private:

+	int found_eof;

+	FILE *input;

+public:

+	DLGFileInput(FILE *f) { input = f; found_eof = 0; }

+	int nextChar() {

+			int c;

+			if ( found_eof ) return EOF;

+			else {

+				c=getc(input);

+				if ( c==EOF ) found_eof = 1;

+				return c;

+			}

+	}

+    void DLGFileReset(FILE *f) {input=f; found_eof = 0; };              // MR11

+};

+

+// MR9  Suggested by Bruce Guenter (bruceg@qcc.sk.ca)

+// MR9  Make DLGStringInput const correct

+

+/* Predefined char stream: Input from string */

+class DllExportPCCTS DLGStringInput : public DLGInputStream {

+private:

+	const DLGChar *input;                                           // MR9

+	const DLGChar *p;                                               // MR9

+public:

+	DLGStringInput(const DLGChar *s) { input = s; p = &input[0];}   // MR9

+	int nextChar()

+		{

+			if (*p) return (int) (unsigned char) *p++;              // MR14

+			else return EOF;

+		}

+

+    void DLGStringReset(const DLGChar *s) {input=s; p= &input[0]; }; // MR11 // MR16

+};

+

+class DllExportPCCTS DLGState {

+public:

+	DLGInputStream *input;

+	int interactive;

+	int track_columns;

+	int auto_num;

+	int add_erase;

+	int lookc;

+	int char_full;

+	int begcol, endcol;

+	int line;

+	DLGChar *lextext, *begexpr, *endexpr;

+	int bufsize;

+	int bufovf;

+	DLGChar *nextpos;

+	int	class_num;

+	int	debugLexerFlag;						// MR1

+	ANTLRParser *parser;						// MR1

+};

+

+/* user must subclass this */

+class DllExportPCCTS DLGLexerBase : public ANTLRTokenStream {

+public:

+	virtual ANTLRTokenType erraction();

+

+protected:

+	DLGInputStream *input;

+	int interactive;

+	int track_columns;

+	DLGChar	*_lextext;	/* text of most recently matched token */

+	DLGChar	*_begexpr;	/* beginning of last reg expr recogn. */

+	DLGChar	*_endexpr;	/* beginning of last reg expr recogn. */

+	int	_bufsize;		/* number of characters in lextext */

+	int	_begcol;		/* column that first character of token is in*/

+	int	_endcol;		/* column that last character of token is in */

+	int	_line;			/* line current token is on */

+	int	ch;				/* character to determine next state */

+	int	bufovf;			/* indicates that buffer too small for text */

+	int	charfull;

+	DLGChar	*nextpos;	/* points to next available position in lextext*/

+	int	cl;

+	int automaton;

+	int	add_erase;

+	DLGChar ebuf[70];

+	_ANTLRTokenPtr token_to_fill;

+

+	int	debugLexerFlag;						// MR1

+	ANTLRParser	*parser;					// MR1

+public:

+	virtual _ANTLRTokenPtr getToken();      // MR12 public

+	virtual void advance(void) = 0;

+	void	skip(void);		/* erase lextext, look for antoher token */

+	void	more(void);		/* keep lextext, look for another token */

+	void	mode(int k);	/* switch to automaton 'k' */

+	void	saveState(DLGState *);

+	void	restoreState(DLGState *);

+	virtual ANTLRTokenType nextTokenType(void)=0;/* get next token */

+	void	replchar(DLGChar c);	/* replace last recognized reg. expr. with

+									 a character */

+	void	replstr(const DLGChar *s);	/* replace last recognized reg. expr. with

+    									 a string */ /* MR20 const */

+        virtual int err_in();						// MR1

+	virtual void errstd(const char *);				// MR1  MR20 const

+	int		line()		{ return _line; }

+	void	set_line(int newValue)	{ _line=newValue; };		// MR1

+	virtual void newline()	{ _line++; }

+	DLGChar	*lextext()	{ return _lextext; }

+

+	int		begcol()	{ return _begcol; }

+	int		endcol()	{ return _endcol; }

+	void	set_begcol(int a)	{ _begcol=a; }

+	void	set_endcol(int a)	{ _endcol=a; }

+	DLGChar	*begexpr()	{ return _begexpr; }

+	DLGChar	*endexpr()	{ return _endexpr; }

+	int		bufsize()	{ return _bufsize; }

+

+	void	setToken(ANTLRAbstractToken *t)	{ token_to_fill = t; }

+

+	void	setInputStream(DLGInputStream *);

+	DLGLexerBase(DLGInputStream *in,

+				 unsigned bufsize=2000,

+				 int interactive=0,

+				 int track_columns=0);

+	void reset();									// MR19

+	virtual ~DLGLexerBase() { delete [] _lextext; }

+	virtual void panic(const char *msg);			// MR1  MR20 const

+	void	trackColumns() {

+				track_columns = 1;

+				this->_begcol = 0;

+				this->_endcol = 0;

+			};

+	virtual ANTLRParser *setParser(ANTLRParser *p);			// MR1

+	virtual ANTLRParser *getParser();				// MR1

+	virtual int debugLexer(int value);				// MR1

+    int     lexErrCount;                            // MR12

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+};

+

+#endif

diff --git a/Source/Pccts/h/PBlackBox.h b/Source/Pccts/h/PBlackBox.h
new file mode 100644
index 0000000..d25b8d6
--- /dev/null
+++ b/Source/Pccts/h/PBlackBox.h
@@ -0,0 +1,134 @@
+#ifndef PBLACKBOX_H

+#define PBLACKBOX_H

+

+/*

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+/* Completely rewritten by Chris Uzdavinis (chris@atdesk.com) for MR23 */

+

+#include "pcctscfg.h"

+

+#include "pccts_iostream.h"

+

+PCCTS_NAMESPACE_STD

+

+//  MR20 Added #include for "DLexerBase.h"

+

+#include "DLexerBase.h"

+

+//

+//  The default buffer size of the lexer is given by the

+//   second argument of the lexer's ctor.  It is optional

+//   and defaults to 2000

+//

+

+template<class Lexer, class Parser, class Token>

+class DllExportPCCTS ParserBlackBox {

+private:

+  // no copy construction allowed

+  ParserBlackBox(ParserBlackBox const &);

+

+  // no copy assignment allowed

+  ParserBlackBox & operator=(ParserBlackBox const &);

+  

+protected:

+  DLGFileInput *in;

+  Lexer *scan;

+  _ANTLRTokenPtr tok;

+  ANTLRTokenBuffer *pipe;

+  Parser *_parser;

+  FILE *file;

+  int openByBlackBox;    /* MR21 Don't close what we haven't opened */

+public:

+	

+  ParserBlackBox(FILE *f)

+    : in(0)

+    , scan(0)

+    , tok(0)

+    , pipe(0)

+    , _parser(0)

+    , file(0)

+    , openByBlackBox(0)

+  {

+    if (f == NULL)

+    {

+      cerr << "invalid file pointer\n"; 

+    }

+    else

+    {

+      openByBlackBox = 0;     /* MR21a */

+      file = f;

+      in = new DLGFileInput(f);

+      scan = new Lexer(in);

+      pipe = new ANTLRTokenBuffer(scan);

+      tok = new Token;

+      scan->setToken(tok);

+      _parser = new Parser(pipe);

+      _parser->init();

+    }

+  }

+  ParserBlackBox(char *fname)

+    : in(0)

+    , scan(0)

+    , tok(0)

+    , pipe(0)

+    , _parser(0)

+    , file(0)

+    , openByBlackBox(0)

+  {

+    FILE *f = fopen(fname, "r");

+    if ( f==NULL ) {

+      openByBlackBox = 0;

+      cerr << "cannot open " << fname << "\n"; return;

+    }

+    else {

+      openByBlackBox = 1;

+      file = f;

+      in = new DLGFileInput(f);

+      scan = new Lexer(in);

+      pipe = new ANTLRTokenBuffer(scan);

+      tok = new Token;

+      scan->setToken(tok);

+      _parser = new Parser(pipe);

+      _parser->init();

+    }

+  }

+	

+  ~ParserBlackBox()

+  {

+    delete in; delete scan; delete pipe; delete _parser; delete tok;

+    if (1 == openByBlackBox) {

+      fclose(file);

+    }

+  }

+

+  Parser *parser()	   { return _parser; }

+  Lexer  *getLexer()     { return scan; }

+};

+

+#endif

diff --git a/Source/Pccts/h/PCCTSAST.cpp b/Source/Pccts/h/PCCTSAST.cpp
new file mode 100644
index 0000000..a8249cd
--- /dev/null
+++ b/Source/Pccts/h/PCCTSAST.cpp
@@ -0,0 +1,684 @@
+/*

+ * PCCTSAST.C

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public

+ * domain.  An individual or company may do whatever they wish with

+ * source code distributed with SORCERER or the code generated by

+ * SORCERER, including the incorporation of SORCERER, or its output, into

+ * commerical software.

+ *

+ * We encourage users to develop software with SORCERER.  However, we do

+ * ask that credit is given to us for developing SORCERER.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like SORCERER and have developed a nice tool with the

+ * output, please mention that you developed it using SORCERER.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * SORCERER 1.00B14 and ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * AHPCRC, University of Minnesota

+ * 1992-2000

+ */

+

+#define ANTLR_SUPPORT_CODE

+

+#include "pcctscfg.h"

+

+#include "PCCTSAST.h"

+#include "pccts_stdarg.h"

+

+PCCTS_NAMESPACE_STD

+

+#include <ctype.h>

+

+//#include "SList.h"

+

+               /* String Scanning/Parsing Stuff */

+

+const char *PCCTS_AST::scan_token_tbl[] = {     /* MR20 const */

+	"invalid",	/*	0 */

+	"LPAREN",	/*	1 */

+	"RPAREN",	/*	2 */

+	"PERCENT",	/*	3 */

+	"INT",		/*	4 */

+	"COLON",	/*	5 */

+	"POUND",	/*	6 */

+	"PERIOD",	/*	7 */

+};

+

+void PCCTS_AST::

+addChild(PCCTS_AST *t)

+{

+	if ( t==NULL ) return;

+	PCCTS_AST *s = down();

+	if ( s!=NULL )

+	{

+		while ( s->right()!=NULL ) s = s->right();

+		s->setRight(t);

+	}

+	else

+		this->setDown(t);

+}

+

+void PCCTS_AST::

+lisp(FILE *f)

+{

+	if ( down() != NULL ) /* MR23 */ printMessage(f," (");

+	lisp_action(f);

+	if ( down()!=NULL ) down()->lisp(f);

+	if ( down() != NULL ) /* MR23 */ printMessage(f," )");

+	if ( right()!=NULL ) right()->lisp(f);

+}

+

+/* build a tree (root child1 child2 ... NULL)

+ * If root is NULL, simply make the children siblings and return ptr

+ * to 1st sibling (child1).  If root is not single node, return NULL.

+ *

+ * Siblings that are actually sibling lists themselves are handled

+ * correctly.  For example #( NULL, #( NULL, A, B, C), D) results

+ * in the tree ( NULL A B C D ).

+ *

+ * Requires at least two parameters with the last one being NULL.  If

+ * both are NULL, return NULL.

+ *

+ * The down() and right() down/right pointers are used to make the tree.

+ */

+PCCTS_AST *PCCTS_AST::

+make(PCCTS_AST *rt, ...)

+{

+	va_list ap;

+	register PCCTS_AST *child, *sibling=NULL, *tail=NULL /*MR23*/, *w;

+	PCCTS_AST *root;

+

+	va_start(ap, rt);

+	root = rt;

+

+	if ( root != NULL )

+		if ( root->down() != NULL ) return NULL;

+	child = va_arg(ap, PCCTS_AST *);

+	while ( child != NULL )

+	{

+		/* find end of child */

+		for (w=child; w->right()!=NULL; w=w->right()) {;}

+		if ( sibling == NULL ) {sibling = child; tail = w;}

+		else {tail->setRight(child); tail = w;}

+		child = va_arg(ap, PCCTS_AST *);

+	}

+	if ( root==NULL ) root = sibling;

+	else root->setDown(sibling);

+	va_end(ap);

+	return root;

+}

+

+/* The following push and pop routines are only used by ast_find_all() */

+

+void PCCTS_AST::

+_push(PCCTS_AST **st, int *sp, PCCTS_AST *e)

+{

+	(*sp)--;

+	require((*sp)>=0, "stack overflow");

+	st[(*sp)] = e;

+}

+

+PCCTS_AST *PCCTS_AST::

+_pop(PCCTS_AST **st, int *sp)

+{

+	PCCTS_AST *e = st[*sp];

+	(*sp)++;

+	require((*sp)<=MaxTreeStackDepth, "stack underflow");

+	return e;

+}

+

+/* Find all occurrences of u in t.

+ * 'cursor' must be initialized to 't'.  It eventually

+ * returns NULL when no more occurrences of 'u' are found.

+ */

+PCCTS_AST *PCCTS_AST::

+ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor)

+{

+	PCCTS_AST *sib;

+	/*** static ***/ PCCTS_AST *template_stack[MaxTreeStackDepth];  /* MR23 Remove "static" */

+	/*** static ***/ int tsp = MaxTreeStackDepth;                   /* MR23 Remove "static" */

+

+////static int nesting = 0;                                         /* MR23 Not referenced */

+

+	if ( *cursor == NULL ) return NULL;

+	if ( *cursor!=this ) sib = *cursor;

+	else {

+		/* else, first time--start at top of template 't' */

+		tsp = MaxTreeStackDepth;

+		sib = this;

+		/* bottom of stack is always a NULL--"cookie" indicates "done" */

+		_push(template_stack, &tsp, NULL);

+	}

+

+keep_looking:

+	if ( sib==NULL )	/* hit end of sibling list */

+	{

+		sib = _pop(template_stack, &tsp);

+		if ( sib == NULL ) { *cursor = NULL; return NULL; }

+	}

+

+	if ( sib->type() != u->type() )

+	{

+		/* look for another match */

+		if ( sib->down()!=NULL )

+		{

+			if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());

+			sib=sib->down();

+			goto keep_looking;

+		}

+		/* nothing below to try, try next sibling */

+		sib=sib->right();

+		goto keep_looking;

+	}

+

+	/* found a matching root node, try to match what's below */

+	if ( match_partial(sib, u) )

+	{

+		/* record sibling cursor so we can pick up next from there */

+		if ( sib->down()!=NULL )

+		{

+			if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());

+			*cursor = sib->down();

+		}

+		else if ( sib->right()!=NULL ) *cursor = sib->right();

+		else *cursor = _pop(template_stack, &tsp);

+		return sib;

+	}

+

+	/* no match, keep searching */

+	if ( sib->down()!=NULL )

+	{

+		if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());

+		sib=sib->down();

+	}

+	else sib = sib->right();	/* else, try to right if zip below */

+	goto keep_looking;

+}

+

+/* are two trees exactly alike? */

+int PCCTS_AST::

+match(PCCTS_AST *u)

+{

+	PCCTS_AST *t = this;

+	PCCTS_AST *sib;

+

+	if ( u==NULL ) return 0;

+

+	for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())

+	{

+		if ( sib->type() != u->type() ) return 0;

+		if ( sib->down()!=NULL )

+			if ( !sib->down()->match(u->down()) ) return 0;

+	}

+	return 1;

+}

+

+/* Is 'u' a subtree of 't' beginning at the root? */

+int PCCTS_AST::

+match_partial(PCCTS_AST *t, PCCTS_AST *u)

+{

+	PCCTS_AST *sib;

+

+	if ( u==NULL ) return 1;

+	if ( t==NULL ) return 0; /* MR23 removed unreachable code */

+

+	for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())

+	{

+		if ( sib->type() != u->type() ) return 0;

+		if ( sib->down()!=NULL )

+			if ( !match_partial(sib->down(), u->down()) ) return 0;

+	}

+	return 1;

+}

+

+#ifdef _MSC_VER  // MR23

+//Turn off "unreachable code" warning

+#pragma warning(disable : 4702)

+#endif

+/* Walk the template tree 't' (matching against 'this'), filling in the

+ * 'labels' array, and setting 'n' according to how many labels were matched.

+ */

+int PCCTS_AST::

+scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n)

+{

+	ScanAST *sib;

+	PCCTS_AST *u = this;

+

+	if ( u==NULL ) return 0;

+

+	for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())

+	{

+		/* make sure tokens match; token of '0' means wildcard match */

+		if ( sib->type() != u->type() && sib->type()!=0 ) return 0;

+		/* we have a matched token here; set label pointers if exists */

+		if ( sib->label_num>0 )

+		{

+			require(labels!=NULL, "label found in template, but no array of labels");

+			(*n)++;

+			*(labels[sib->label_num-1]) = u;

+		}

+		/* match what's below if something there and current node is not wildcard */

+		if ( sib->down()!=NULL && sib->type()!=0 )

+		{

+			if ( sib->down()==NULL ) 

+			{

+				if ( u->down()!=NULL ) 

+					return 0; 

+				else 

+					return 1;

+			}

+			if ( !u->down()->scanmatch(sib->down(), labels, n) ) return 0;

+		}

+	}

+	return 1;

+}

+#ifdef _MSC_VER  // MR23

+#pragma warning(default : 4702)

+#endif

+

+void PCCTS_AST::

+insert_after(PCCTS_AST *b)

+{

+	PCCTS_AST *end;

+	if ( b==NULL ) return;

+	/* find end of b's child list */

+	for (end=b; end->right()!=NULL; end=end->right()) {;}

+	end->setRight(this->right());

+	this->setRight(b);

+}

+

+void PCCTS_AST::

+append(PCCTS_AST *b)

+{

+	PCCTS_AST *end;

+	require(b!=NULL, "append: NULL input tree");

+	/* find end of child list */

+	for (end=this; end->right()!=NULL; end=end->right()) {;}

+	end->setRight(b);

+}

+

+PCCTS_AST *PCCTS_AST::

+tail()

+{

+	PCCTS_AST *end;

+	/* find end of child list */

+	for (end=this; end->right()!=NULL; end=end->right()) {;}

+	return end;

+}

+

+PCCTS_AST *PCCTS_AST::

+bottom()

+{

+	PCCTS_AST *end;

+	/* find end of child list */

+	for (end=this; end->down()!=NULL; end=end->down()) {;}

+	return end;

+}

+

+PCCTS_AST *PCCTS_AST::

+cut_between(PCCTS_AST *a, PCCTS_AST *b)

+{

+	PCCTS_AST *end, *ret;

+	if (a==NULL||b==NULL) return NULL;

+	/* find node pointing to b */

+	for (end=a; end->right()!=NULL&&end->right()!=b; end=end->right())

+		{;}

+	if (end->right()==NULL) return NULL; //ast_cut_between: a,b not connected

+	end->setRight(NULL);	/* don't want it point to 'b' anymore */

+	ret = a->right();

+	a->setRight(b);

+	return ret;

+}

+

+#ifdef NOT_YET

+SList *PCCTS_AST::

+to_slist()

+{

+	SList *list = new SList;

+	PCCTS_AST *p;

+

+	for (p=this; p!=NULL; p=p->right())

+	{

+		list->add(p);

+	}

+	return list;

+}

+#endif

+

+void PCCTS_AST::

+tfree()

+{

+	PCCTS_AST *t = this;

+    if ( t->down()!=NULL ) t->down()->tfree();

+    if ( t->right()!=NULL ) t->right()->tfree();

+    delete t;

+}

+

+int PCCTS_AST::

+nsiblings()

+{

+	PCCTS_AST *t = this;

+	int n=0;

+

+	while ( t!=NULL )

+	{

+		n++;

+		t = t->right();

+	}

+	return n;

+}

+

+PCCTS_AST *PCCTS_AST::

+sibling_index(int i)

+{

+	PCCTS_AST *t = this;

+	int j=1;

+	require(i>0, "sibling_index: i<=0");

+

+	while ( t!=NULL )

+	{

+		if ( j==i ) return t;

+		j++;

+		t = t->right();

+	}

+	return NULL;

+}

+

+/* Assume this is a root node of a tree--

+ * duplicate that node and what's below; ignore siblings of root node.

+ */

+

+// MR9 23-Sep-97 RJV

+// MR9

+// MR9 RJV: Original version only duplicated the node and down elements.

+// MR9      Made copies of the pointers to sibling.

+// MR9      Changed call "down()->deepCopy()" to "down()->deepCopyBushy()"

+// MR9

+

+PCCTS_AST *PCCTS_AST::

+deepCopy()

+{

+	PCCTS_AST *u = this->shallowCopy();

+	if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());

+    u->setRight(NULL);

+	return u;

+}

+

+/* Copy all nodes including siblings of root. */

+PCCTS_AST *PCCTS_AST::

+deepCopyBushy()

+{

+	PCCTS_AST *u = this->shallowCopy();

+	/* copy the rest of the tree */

+	if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());

+	if ( right()!=NULL ) u->setRight(right()->deepCopyBushy());

+	return u;

+}

+

+void PCCTS_AST::

+scanast_free(ScanAST *t)

+{

+    if ( t == NULL ) return;

+    scanast_free( t->down() );

+    scanast_free( t->right() );

+    free( (char *) t );							// MR1

+}

+

+/*

+ * scan

+ *

+ * This function is like scanf(): it attempts to match a template

+ * against an input tree.  A variable number of tree pointers

+ * may be set according to the '%i' labels in the template string.

+ * For example:

+ *

+ *   t->ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )",

+ *            &w, &x, &y, &z);

+ *

+ * Naturally, you'd want this converted from

+ *

+ *	 t->ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )",

+ *			  &w, &x, &y, &z);

+ *

+ * by SORCERER.

+ *

+ * This function call must be done withing a SORCERER file because SORCERER

+ * must convert the token references to the associated token number.

+ *

+ * This functions parses the template and creates trees which are then

+ * matched against the input tree.  The labels are set as they are

+ * encountered; hence, partial matches may leave some pointers set

+ * and some NULL.  This routines initializes all argument pointers to NULL

+ * at the beginning.

+ *

+ * This function returns the number of labels matched.

+ */

+int PCCTS_AST::

+ast_scan(char *templ, ...)

+{

+	va_list ap;

+	ScanAST *tmpl;

+	int n, i, found=0;

+	PCCTS_AST ***label_ptrs=NULL;

+

+	va_start(ap, templ);

+

+	/* make a ScanAST tree out of the template */

+	tmpl = stringparser_parse_scanast(templ, &n);

+

+	/* make an array out of the labels */

+	if ( n>0 )

+	{

+		label_ptrs = (PCCTS_AST ***) calloc(n, sizeof(PCCTS_AST **));

+		require(label_ptrs!=NULL, "scan: out of memory");

+		for (i=1; i<=n; i++)

+		{

+			label_ptrs[i-1] = va_arg(ap, PCCTS_AST **);

+			*(label_ptrs[i-1]) = NULL;

+		}

+	}

+

+	/* match the input tree against the template */

+	scanmatch(tmpl, label_ptrs, &found);

+

+	scanast_free(tmpl);

+	free( (char *) label_ptrs);					// MR1

+

+	return found;

+}

+

+ScanAST *PCCTS_AST::

+new_scanast(int tok)

+{

+    ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST));

+//

+//  7-Apr-97 133MR1

+//

+    if ( p == NULL )

+        panic("out of memory\n");			// MR23

+	p->_token = tok;

+	return p;

+}

+

+ScanAST *PCCTS_AST::

+stringparser_parse_scanast(char *templ, int *num_labels)

+{

+	StringLexer lex;

+	StringParser parser;

+	ScanAST *t;

+

+	stringlexer_init(&lex, templ);

+	stringparser_init(&parser, &lex);

+	t = stringparser_parse_tree(&parser);

+	*num_labels = parser.num_labels;

+	return t;

+}

+

+void PCCTS_AST::

+stringparser_match(StringParser *parser, int token)

+{

+	if ( parser->token != token ) panic("bad tree in scan()");

+}

+

+/*

+ * Match a tree of the form:

+ *		(root child1 child2 ... childn)

+ * or,

+ *		node

+ *

+ * where the elements are integers or labeled integers.

+ */

+ScanAST *PCCTS_AST::

+stringparser_parse_tree(StringParser *parser)

+{

+	ScanAST *t=NULL, *root, *child, *last=NULL /*MR23*/;

+

+	if ( parser->token != __POUND )

+	{

+		return stringparser_parse_element(parser);

+	}

+	stringparser_match(parser,__POUND);

+	parser->token = stringscan_gettok(parser->lexer);

+	stringparser_match(parser,__LPAREN);

+	parser->token = stringscan_gettok(parser->lexer);

+	root = stringparser_parse_element(parser);

+	while ( parser->token != __RPAREN )

+	{

+		child = stringparser_parse_element(parser);

+		if ( t==NULL ) { t = child; last = t; }

+		else { last->_right = child; last = child; }

+	}

+	stringparser_match(parser,__RPAREN);

+	parser->token = stringscan_gettok(parser->lexer);

+	root->_down = t;

+	return root;

+}

+

+ScanAST *PCCTS_AST::

+stringparser_parse_element(StringParser *parser)

+{

+	char ebuf[100];

+	int label = 0;

+

+	if ( parser->token == __POUND )

+	{

+		return stringparser_parse_tree(parser);

+	}

+	if ( parser->token == __PERCENT )

+	{

+		parser->token = stringscan_gettok(parser->lexer);

+		stringparser_match(parser,__INT);

+		label = atoi(parser->lexer->text);

+		parser->num_labels++;

+		if ( label==0 ) panic("%%0 is an invalid label");

+		parser->token = stringscan_gettok(parser->lexer);

+		stringparser_match(parser,__COLON);

+		parser->token = stringscan_gettok(parser->lexer);

+		/* can label tokens and wildcards */

+		if ( parser->token != __INT && parser->token != __PERIOD )

+			panic("can only label tokens");

+	}

+	if ( parser->token == __INT )

+	{

+		ScanAST *p = new_scanast(atoi(parser->lexer->text));

+		parser->token = stringscan_gettok(parser->lexer);

+		p->label_num = label;

+		return p;

+	}

+	if ( parser->token == __PERIOD )

+	{

+		ScanAST *p = new_scanast(0);	/* token of 0 is wildcard */

+		parser->token = stringscan_gettok(parser->lexer);

+		p->label_num = label;

+		return p;

+	}

+	sprintf(ebuf, "mismatch token in scan(): %s", scan_token_str(parser->token));

+	panic(ebuf);

+	return NULL;

+}

+

+void PCCTS_AST::

+stringparser_init(StringParser *parser, StringLexer *input)

+{

+	parser->lexer = input;

+	parser->token = stringscan_gettok(parser->lexer);

+	parser->num_labels = 0;

+}

+

+void PCCTS_AST::

+stringlexer_init(StringLexer *scanner, char *input)

+{

+	scanner->text[0]='\0';

+	scanner->input = input;

+	scanner->p = input;

+	stringscan_advance(scanner);

+}

+

+void PCCTS_AST::

+stringscan_advance(StringLexer *scanner)

+{

+	if ( *(scanner->p) == '\0' ) scanner->c = __StringScanEOF;

+	scanner->c = *(scanner->p)++;

+}

+

+int PCCTS_AST::

+stringscan_gettok(StringLexer *scanner)

+{

+	char *index = &scanner->text[0];

+	char ebuf[100]; /* MR23 Remove static */

+

+	while ( isspace(scanner->c) ) { stringscan_advance(scanner); }

+	if ( isdigit(scanner->c) )

+	{

+		int tok = __INT;

+		while ( isdigit(scanner->c) ) {

+			*index++ = (char) /* static_cast<char> */ (scanner->c);     // MR23

+			stringscan_advance(scanner);

+		}

+		*index = '\0';

+		return tok;

+	}

+	switch ( scanner->c )

+	{

+		case '#' : stringscan_advance(scanner); return __POUND;

+		case '(' : stringscan_advance(scanner); return __LPAREN;

+		case ')' : stringscan_advance(scanner); return __RPAREN;

+		case '%' : stringscan_advance(scanner); return __PERCENT;

+		case ':' : stringscan_advance(scanner); return __COLON;

+		case '.' : stringscan_advance(scanner); return __PERIOD;

+		case '\0' : return __StringScanEOF;

+		case __StringScanEOF : return __StringScanEOF;

+		default  :

+			sprintf(ebuf, "invalid char in scan: '%c'", scanner->c);

+			panic(ebuf);

+	}

+	return __StringScanEOF;	// never reached

+}

+

+const char *PCCTS_AST:: /* MR20 const */

+scan_token_str(int t)

+{

+	if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t];

+	else if ( t==__StringScanEOF ) return "<end-of-string>";

+	else return "<invalid-token>";

+}

+

+//MR23

+int PCCTS_AST::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+  	int iRet = vfprintf(pFile, pFormat, marker);

+	va_end( marker );

+	return iRet;

+}

diff --git a/Source/Pccts/h/PCCTSAST.h b/Source/Pccts/h/PCCTSAST.h
new file mode 100644
index 0000000..3485da7
--- /dev/null
+++ b/Source/Pccts/h/PCCTSAST.h
@@ -0,0 +1,143 @@
+/* Abstract syntax tree

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef PCCTSAST_H

+#define PCCTSAST_H

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+

+PCCTS_NAMESPACE_STD

+

+//class SList;

+

+#define StringScanMaxText	50

+#define MaxTreeStackDepth	400

+

+//

+//  7-Apr-97 133MR1	signed int not accepted by AT&T cfront

+//

+typedef struct stringlexer {

+			int c;						// MR1

+			char *input;

+			char *p;

+			char text[StringScanMaxText];

+		} StringLexer;

+

+/* Define the structures needed for ast_scan() */

+typedef struct stringparser {

+			int token;

+			StringLexer *lexer;

+			int num_labels;

+		} StringParser;

+

+typedef struct _scanast {

+            struct _scanast *_right, *_down;

+            int _token;

+			int label_num;

+			int type() { return _token; }

+			struct _scanast *right() { return _right; }

+			struct _scanast *down() { return _down; }

+        } ScanAST;

+

+#define VALID_SCAN_TOKEN(t)		(t>=__LPAREN && t<=__PERIOD)

+

+class DllExportPCCTS PCCTS_AST {

+protected:

+	static const char *scan_token_tbl[];    /* MR20 const */

+	enum {

+	__LPAREN=1,

+	__RPAREN=2,

+	__PERCENT=3,

+	__INT=4,

+	__COLON=5,

+	__POUND=6,

+	__PERIOD=7,

+	__StringScanEOF=-1};

+

+protected:

+	const char *scan_token_str(int t);  /* MR20 const */

+	void stringlexer_init(StringLexer *scanner, char *input);

+	void stringparser_init(StringParser *, StringLexer *);

+	ScanAST *stringparser_parse_scanast(char *templ, int *n);

+	ScanAST *stringparser_parse_tree(StringParser *parser);

+	ScanAST *stringparser_parse_element(StringParser *parser);

+	void stringscan_advance(StringLexer *scanner);

+	int stringscan_gettok(StringLexer *scanner);

+	void _push(PCCTS_AST **st, int *sp, PCCTS_AST *e);

+	PCCTS_AST *_pop(PCCTS_AST **st, int *sp);

+	int match_partial(PCCTS_AST *t, PCCTS_AST *u);

+	int scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n);

+	void scanast_free(ScanAST *t);

+	ScanAST *new_scanast(int tok);

+	void stringparser_match(StringParser *parser, int type);

+	virtual PCCTS_AST *deepCopyBushy();

+

+public:

+	PCCTS_AST()	{;}

+	virtual ~PCCTS_AST() {;}

+

+	/* This group must be defined for SORCERER to work correctly */

+	virtual PCCTS_AST *right() = 0;

+	virtual PCCTS_AST *down() = 0;

+	virtual void setRight(PCCTS_AST *t) = 0;

+	virtual void setDown(PCCTS_AST *t) = 0;

+// we define these so ANTLR doesn't have to

+	virtual int type() { return 0; }

+	virtual void setType(int /*t MR23 */) {;}

+	virtual PCCTS_AST *shallowCopy() {panic("no shallowCopy() defined"); return NULL;}

+

+	/* These are not needed by ANTLR, but are support functions */

+	virtual PCCTS_AST *deepCopy();	// used by SORCERER in transform mode

+	virtual void addChild(PCCTS_AST *t);

+	virtual void lisp_action(FILE * /*f MR23 */) {;}

+	virtual void lisp(FILE *f);

+	static PCCTS_AST *make(PCCTS_AST *rt, ...);

+	virtual PCCTS_AST *ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor);

+	virtual int match(PCCTS_AST *u);

+	virtual void insert_after(PCCTS_AST *b);

+	virtual void append(PCCTS_AST *b);

+	virtual PCCTS_AST *tail();

+	virtual PCCTS_AST *bottom();

+	static  PCCTS_AST *cut_between(PCCTS_AST *a, PCCTS_AST *b);

+//	virtual SList *to_slist();

+	virtual void tfree();

+	int ast_scan(char *templ, ...);

+	virtual int nsiblings();

+	virtual PCCTS_AST *sibling_index(int i);

+

+	void require(int e,const char *err){ if ( !e ) panic(err); } /* MR20 const */

+	virtual void panic(const char *err)     // MR20 const

+		{ /* MR23 */ printMessage(stderr, "PCCTS_AST: %s\n", err); exit(PCCTS_EXIT_FAILURE); }

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+};

+

+#endif /* PCCTSAST_H */

diff --git a/Source/Pccts/h/SList.h b/Source/Pccts/h/SList.h
new file mode 100644
index 0000000..5b8bf97
--- /dev/null
+++ b/Source/Pccts/h/SList.h
@@ -0,0 +1,72 @@
+#ifndef SList_h

+#define SList_h

+

+/*

+ * SList.h

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public

+ * domain.  An individual or company may do whatever they wish with

+ * source code distributed with SORCERER or the code generated by

+ * SORCERER, including the incorporation of SORCERER, or its output, into

+ * commerical software.

+ *

+ * We encourage users to develop software with SORCERER.  However, we do

+ * ask that credit is given to us for developing SORCERER.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like SORCERER and have developed a nice tool with the

+ * output, please mention that you developed it using SORCERER.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * PCCTS 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1992-2000

+ */

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+

+PCCTS_NAMESPACE_STD

+

+#include "PCCTSAST.h"

+

+class PCCTS_AST;

+

+class SListNode {

+protected:

+	void *_elem;			/* pointer to any kind of element */

+	SListNode *_next;

+public:

+	SListNode()				{_elem=_next=NULL;}

+	virtual ~SListNode()	{_elem=_next=NULL;}

+	void *elem()			{ return _elem; }

+	void setElem(void *e)	{ _elem = e; }

+	void setNext(SListNode *t)	{ _next = t; }

+	SListNode *next()		{ return _next; }

+};

+

+class SList {

+	SListNode *head, *tail;

+public:

+	SList() {head=tail=NULL;}

+	virtual ~SList() {head=tail=NULL;}

+	virtual void *iterate(SListNode **);

+	virtual void add(void *e);

+	virtual void lfree();

+	virtual PCCTS_AST *to_ast(SList list);

+	virtual void require(int e,char *err){ if ( !e ) panic(err); }

+	virtual void panic(char *err){ /* MR23 */ printMessage(stderr, "SList panic: %s\n", err); exit(PCCTS_EXIT_FAILURE); }

+	virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23

+};

+

+#endif

diff --git a/Source/Pccts/h/antlr.h b/Source/Pccts/h/antlr.h
new file mode 100644
index 0000000..8066453
--- /dev/null
+++ b/Source/Pccts/h/antlr.h
@@ -0,0 +1,807 @@
+/* antlr.h 

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ANTLR_H

+#define ANTLR_H

+

+#include "pcctscfg.h"

+

+#include "pccts_stdio.h"

+

+/* turn off warnings for unreferenced labels */

+

+#ifdef _MSC_VER

+#pragma warning(disable:4102)

+#endif

+

+/*

+ * Define all of the stack setup and manipulation of $i, #i variables.

+ *

+ *	Notes:

+ *		The type 'Attrib' must be defined before entry into this .h file.

+ */

+

+

+#ifdef __USE_PROTOS

+#include "pccts_stdlib.h"

+#else

+#ifdef VAXC

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif

+#endif

+#include "pccts_string.h"

+

+#if 0

+#include "set.h"

+#endif

+

+

+typedef int ANTLRTokenType;

+typedef unsigned char SetWordType;

+

+typedef char ANTLRChar;

+

+						/* G u e s s  S t u f f */

+

+#ifdef ZZCAN_GUESS

+#ifndef ZZINF_LOOK

+#define ZZINF_LOOK

+#endif

+#endif

+

+#ifdef ZZCAN_GUESS

+typedef struct _zzjmp_buf {

+			jmp_buf state;

+		} zzjmp_buf;

+#endif

+

+

+/* can make this a power of 2 for more efficient lookup */

+

+#ifndef ZZLEXBUFSIZE

+#define ZZLEXBUFSIZE	8000 /* MR22 raise from 2k to 8k */

+#endif

+

+#define zzOvfChk														\

+            if ( zzasp <= 0 )                                           \

+            {                                                           \

+                fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__);		\

+                exit(PCCTS_EXIT_FAILURE);                                               \

+            }

+

+#ifndef ZZA_STACKSIZE

+#define ZZA_STACKSIZE	400

+#endif

+#ifndef ZZAST_STACKSIZE

+#define ZZAST_STACKSIZE	400

+#endif

+

+#ifndef zzfailed_pred

+#ifdef ZZCAN_GUESS

+#define zzfailed_pred(_p,_hasuseraction,_useraction) \

+  if (zzguessing) { \

+    zzGUESS_FAIL; \

+  } else { \

+    zzfailed_pred_action(_p,_hasuseraction,_useraction); \

+  }

+#else

+#define zzfailed_pred(_p,_hasuseraction,_useraction) \

+    zzfailed_pred_action(_p,_hasuseraction,_useraction);

+#endif

+#endif

+

+/*  MR23            Provide more control over failed predicate action

+                    without any need for user to worry about guessing internals.

+                    _hasuseraction == 0 => no user specified error action

+                    _hasuseraction == 1 => user specified error action

+*/

+

+#ifndef zzfailed_pred_action

+#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \

+    if (_hasuseraction) { _useraction } \

+    else { fprintf(stderr, "semantic error; failed predicate: '%s'\n",_p); }

+#endif

+

+/* MR19 zzchar_t additions */

+

+#ifdef LL_K

+#define LOOKAHEAD \

+	int zztokenLA[LL_K]; \

+	zzchar_t zztextLA[LL_K][ZZLEXBUFSIZE]; \

+	int zzlap = 0, zzlabase=0; /* labase only used for DEMAND_LOOK */

+#else

+#define LOOKAHEAD												\

+	int zztoken;

+#endif

+

+#ifndef zzcr_ast

+#define zzcr_ast(ast,attr,tok,text)

+#endif

+

+#ifdef DEMAND_LOOK

+#define DemandLookData  int zzdirty=1;

+#else

+#define DemandLookData

+#endif

+

+#ifndef zzUSER_GUESS_HOOK

+#define zzUSER_GUESS_HOOK(seqFrozen,zzrv)

+#endif

+

+#ifndef zzUSER_GUESS_DONE_HOOK

+#define zzUSER_GUESS_DONE_HOOK(seqFrozen)

+#endif

+

+						/* S t a t e  S t u f f */

+

+#ifdef ZZCAN_GUESS

+#define zzGUESS_BLOCK		zzantlr_state zzst; int zzrv; int zzGuessSeqFrozen;

+

+/* MR10 change zzGUESS: do zzGUESS_DONE when zzrv==1 after longjmp as in C++ mode */

+

+#define zzGUESS				zzsave_antlr_state(&zzst); \

+							zzguessing = 1; \

+                            zzGuessSeqFrozen=++zzGuessSeq; \

+							zzrv = setjmp(zzguess_start.state); \

+                            zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \

+                            if (zzrv) zzGUESS_DONE;

+#ifdef zzTRACE_RULES

+#define zzGUESS_FAIL		{ zzTraceGuessFail(); longjmp(zzguess_start.state, 1); }

+#else

+#define zzGUESS_FAIL		longjmp(zzguess_start.state, 1)

+#endif

+

+/* MR10 change zzGUESS_DONE: zzrv=1 to simulate longjmp() return value as in C++ mode */

+

+#define zzGUESS_DONE		{ zzrestore_antlr_state(&zzst); zzrv=1; zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) }

+#define zzNON_GUESS_MODE	if ( !zzguessing )

+#define zzGuessData                                     \

+            zzjmp_buf zzguess_start;                    \

+            int zzguessing;

+#else

+#define zzGUESS_BLOCK

+#define zzGUESS

+#define zzGUESS_FAIL

+#define zzGUESS_DONE

+#define zzNON_GUESS_MODE

+#define zzGuessData

+#endif

+

+typedef struct _zzantlr_state {

+#ifdef ZZCAN_GUESS

+			zzjmp_buf guess_start;

+			int guessing;

+#endif

+			int asp;

+			int ast_sp;

+#ifdef ZZINF_LOOK

+			int inf_lap;	/* not sure we need to save this one */

+			int inf_labase;

+			int inf_last;

+

+/* MR6 	Gunnar Rxnning (gunnar@candleweb.no)                                */

+/* MR6	  Additional state needs to be saved/restored                       */

+/* MR6    Matching changes in err.h                                         */

+

+			int *inf_tokens;	                                     /* MR6 */

+			char **inf_text;	                                     /* MR6 */

+			char *inf_text_buffer;		                             /* MR6 */

+			int *inf_line;		                                     /* MR6 */

+#endif

+#ifdef DEMAND_LOOK

+			int dirty;

+#endif

+

+#ifdef LL_K

+			int tokenLA[LL_K];

+			char textLA[LL_K][ZZLEXBUFSIZE];

+			int lap;

+			int labase;

+#else

+			int token;

+			char text[ZZLEXBUFSIZE];

+#endif

+#ifdef zzTRACE_RULES

+            int     traceOptionValue;       /* MR10 */

+            int     traceGuessOptionValue;  /* MR10 */

+            char    *traceCurrentRuleName;  /* MR10 */

+            int     traceDepth;             /* MR10 */

+#endif

+

+		} zzantlr_state;

+

+#ifdef zzTRACE_RULES

+extern int  zzTraceOptionValueDefault;

+extern int  zzTraceOptionValue;

+extern int  zzTraceGuessOptionValue;

+extern char *zzTraceCurrentRuleName;

+extern int  zzTraceDepth;

+#endif

+

+extern int zzGuessSeq;                      /* MR10 */

+extern int zzSyntaxErrCount;                /* MR11 */

+extern int zzLexErrCount;                   /* MR11 */

+

+                 /* I n f i n i t e  L o o k a h e a d */

+

+

+#ifdef ZZINF_LOOK

+#define InfLookData	\

+	int *zzinf_tokens;	\

+	char **zzinf_text;	\

+	char *zzinf_text_buffer;	\

+	int *zzinf_line;        \

+	int zzinf_labase;	\

+	int zzinf_last;

+#else

+#define InfLookData

+#endif

+

+#ifdef ZZINF_LOOK

+

+#ifndef ZZINF_DEF_TEXT_BUFFER_SIZE

+#define ZZINF_DEF_TEXT_BUFFER_SIZE	    20000

+#endif

+#ifndef ZZINF_DEF_TOKEN_BUFFER_SIZE

+#define ZZINF_DEF_TOKEN_BUFFER_SIZE	    2000

+#endif

+/* WARNING!!!!!!

+ * ZZINF_BUFFER_TEXT_CHUNK_SIZE must be > sizeof(text) largest possible token.

+ */

+#ifndef ZZINF_BUFFER_TEXT_CHUNK_SIZE

+#define ZZINF_BUFFER_TEXT_CHUNK_SIZE	5000

+#endif

+#ifndef ZZINF_BUFFER_TOKEN_CHUNK_SIZE

+#define ZZINF_BUFFER_TOKEN_CHUNK_SIZE	1000

+#endif

+

+#if ZZLEXBUFSIZE > ZZINF_BUFFER_TEXT_CHUNK_SIZE

+#define ZZINF_BUFFER_TEXT_CHUNK_SIZE	ZZLEXBUFSIZE+5

+#endif

+

+/* make inf_look user-access macros */

+#ifdef LL_K

+#define ZZINF_LA_VALID(i)	(((zzinf_labase+i-1)-LL_K+1) <= zzinf_last)

+#define ZZINF_LA(i)			zzinf_tokens[(zzinf_labase+i-1)-LL_K+1]

+#define ZZINF_LATEXT(i)		zzinf_text[(zzinf_labase+i-1)-LL_K+1]

+/* MR6	In 1.33 vanilla the #define ZZINF_LINE(i) is was commented out	*/

+#define ZZINF_LINE(i)       zzinf_line[(zzinf_labase+i-1)-LL_K+1]

+#else

+#define ZZINF_LA_VALID(i)	(((zzinf_labase+i-1)) <= zzinf_last)

+#define ZZINF_LA(i)			zzinf_tokens[(zzinf_labase+i-1)]

+#define ZZINF_LATEXT(i)		zzinf_text[(zzinf_labase+i-1)]

+#endif

+

+#define inf_zzgettok _inf_zzgettok()

+extern void _inf_zzgettok();

+

+#endif	/* ZZINF_LOOK */

+

+

+#ifdef LL_K

+

+#ifdef __USE_PROTOS

+#define ANTLR_INFO	\

+	Attrib zzempty_attr(void) {static Attrib a; return a;} \

+	Attrib zzconstr_attr(int _tok, char *_text) \

+		{Attrib a; zzcr_attr((&a),_tok,_text); return a;} \

+	int zzasp=ZZA_STACKSIZE; \

+	char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \

+	Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \

+	InfLookData \

+    zzGuessData

+#else

+#define ANTLR_INFO												\

+	Attrib zzempty_attr() {static Attrib a; return a;}		    \

+	Attrib zzconstr_attr(_tok, _text) int _tok; char *_text;    \

+		{Attrib a; zzcr_attr((&a),_tok,_text); return a;}	    \

+	int zzasp=ZZA_STACKSIZE;					    \

+	char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n";  \

+	Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData			    \

+	InfLookData                                                 \

+    zzGuessData

+#endif

+

+#else

+

+#ifdef __USE_PROTOS

+#define ANTLR_INFO												\

+	Attrib zzempty_attr(void) {static Attrib a; return a;}			\

+	Attrib zzconstr_attr(int _tok, char *_text)				\

+		{Attrib a; zzcr_attr((&a),_tok,_text); return a;}		\

+	int zzasp=ZZA_STACKSIZE;						\

+	char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n";      \

+	Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData				\

+	InfLookData                                                             \

+    zzGuessData

+#else

+#define ANTLR_INFO												\

+	Attrib zzempty_attr() {static Attrib a; return a;}			\

+	Attrib zzconstr_attr(_tok, _text) int _tok; char *_text;                \

+		{Attrib a; zzcr_attr((&a),_tok,_text); return a;}		\

+	int zzasp=ZZA_STACKSIZE;						\

+	char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n";      \

+	Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData				\

+	InfLookData                                                             \

+    zzGuessData

+#endif

+	

+#endif /* LL_k */

+

+

+#ifdef ZZINF_LOOK

+

+#ifdef LL_K

+#ifdef DEMAND_LOOK

+#define zzPrimeLookAhead  {zzdirty=LL_K; zzlap = zzlabase = 0;}

+#else

+#define zzPrimeLookAhead  {zzlap = zzlabase = 0; zzfill_inf_look();\

+						  {int _i;  for(_i=1;_i<=LL_K; _i++)		\

+										{zzCONSUME;} zzlap = zzlabase = 0;}}

+#endif

+

+#else /* LL_K */

+

+#ifdef DEMAND_LOOK

+#define zzPrimeLookAhead  zzfill_inf_look(); zzdirty=1

+#else

+#define zzPrimeLookAhead  zzfill_inf_look(); inf_zzgettok

+

+#endif

+#endif	/* LL_K */

+

+#else	/* ZZINF_LOOK */

+

+#ifdef LL_K

+#ifdef DEMAND_LOOK

+#define zzPrimeLookAhead  {zzdirty=LL_K; zzlap = zzlabase = 0;}

+#else

+#define zzPrimeLookAhead  {int _i; zzlap = 0; for(_i=1;_i<=LL_K; _i++)		\

+										{zzCONSUME;} zzlap = 0;}

+#endif

+

+#else

+

+#ifdef DEMAND_LOOK

+#define zzPrimeLookAhead  zzdirty=1

+#else

+#define zzPrimeLookAhead  zzgettok()

+#endif

+#endif	/* LL_K */

+

+#endif	/* ZZINF_LOOK */

+

+

+#ifdef LL_K

+#define zzenterANTLRs(s)                            \

+        zzlextext = &(zztextLA[0][0]); zzrdstr( s ); zzPrimeLookAhead;

+#define zzenterANTLRf(f)							\

+		zzlextext = &(zztextLA[0][0]); zzrdfunc( f ); zzPrimeLookAhead;

+#define zzenterANTLR(f)							\

+		zzlextext = &(zztextLA[0][0]); zzrdstream( f ); zzPrimeLookAhead;

+#ifdef ZZINF_LOOK

+#define zzleaveANTLR(f)			free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#define zzleaveANTLRf(f)	   	free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#define zzleaveANTLRs(f)		free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#else

+#define zzleaveANTLR(f)

+#define zzleaveANTLRf(f)

+#define zzleaveANTLRs(f)

+#endif

+

+#else

+

+#define zzenterANTLRs(s)                            \

+        {static char zztoktext[ZZLEXBUFSIZE];   \

+        zzlextext = zztoktext; zzrdstr( s ); zzPrimeLookAhead;}

+#define zzenterANTLRf(f)							\

+		{static char zztoktext[ZZLEXBUFSIZE];	\

+		zzlextext = zztoktext; zzrdfunc( f ); zzPrimeLookAhead;}

+#define zzenterANTLR(f)							\

+		{static char zztoktext[ZZLEXBUFSIZE];	\

+		zzlextext = zztoktext; zzrdstream( f ); zzPrimeLookAhead;}

+#ifdef ZZINF_LOOK

+#define zzleaveANTLR(f)			free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#define zzleaveANTLRf(f)	   	free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#define zzleaveANTLRs(f)		free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);

+#else

+#define zzleaveANTLR(f)

+#define zzleaveANTLRf(f)

+#define zzleaveANTLRs(f)

+#endif

+

+#endif

+

+/* MR19 Paul D. Smith (psmith@baynetworks.com)

+   Need to adjust AST stack pointer at exit.

+   Referenced in ANTLRx macros.

+*/

+

+#ifdef GENAST

+#define ZZAST_ADJUST ++zzast_sp;

+#else

+#define ZZAST_ADJUST

+#endif

+

+#define ANTLR(st, f)	zzbufsize = ZZLEXBUFSIZE;	\

+						zzenterANTLR(f);			\

+            {                                            \

+              zzBLOCK(zztasp1);                          \

+						  st; /* ++zzasp; Removed MR20 G. Hobbelt */     \

+						      /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \

+              /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */  \

+              zzEXIT_ANTLR(zztasp1 + 1);                 \

+            }                                            \

+						zzleaveANTLR(f);

+						

+#define ANTLRm(st, f, _m)	zzbufsize = ZZLEXBUFSIZE;	\

+						zzmode(_m);				\

+						zzenterANTLR(f);			\

+            {                                            \

+              zzBLOCK(zztasp1);                          \

+						  st; /* ++zzasp; Removed MR20 G. Hobbelt */     \

+						      /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \

+              /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */  \

+              zzEXIT_ANTLR(zztasp1 + 1);                 \

+            }                                            \

+						zzleaveANTLR(f);

+						

+#define ANTLRf(st, f)	zzbufsize = ZZLEXBUFSIZE;	\

+						zzenterANTLRf(f);			\

+            {                                            \

+              zzBLOCK(zztasp1);                          \

+						  st; /* ++zzasp; Removed MR20 G. Hobbelt */     \

+						      /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \

+              /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */  \

+              zzEXIT_ANTLR(zztasp1 + 1);                 \

+            }                                            \

+						zzleaveANTLRf(f);

+

+#define ANTLRs(st, s)   zzbufsize = ZZLEXBUFSIZE;	\

+                        zzenterANTLRs(s);           \

+            {                                            \

+              zzBLOCK(zztasp1);                          \

+						  st; /* ++zzasp; Removed MR20 G. Hobbelt */     \

+						      /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \

+              /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */  \

+              zzEXIT_ANTLR(zztasp1 + 1);                 \

+            }                                            \

+                        zzleaveANTLRs(s);

+

+#ifdef LL_K

+#define zztext		(&(zztextLA[zzlap][0]))

+#else

+#define zztext		zzlextext

+#endif

+

+

+					/* A r g u m e n t  A c c e s s */

+

+#define zzaCur			(zzaStack[zzasp])

+#define zzaRet			(*zzaRetPtr)

+#define zzaArg(v,n)		zzaStack[v-n]

+#define zzMakeAttr		{ zzNON_GUESS_MODE {zzOvfChk; --zzasp; zzcr_attr(&(zzaStack[zzasp]),LA(1),LATEXT(1));}}

+#ifdef zzdef0

+#define zzMake0			{ zzOvfChk; --zzasp; zzdef0(&(zzaStack[zzasp]));}

+#else

+#define zzMake0			{ zzOvfChk; --zzasp;}

+#endif

+#define zzaPush(_v)		{ zzOvfChk; zzaStack[--zzasp] = _v;}

+#ifndef zzd_attr

+#define zzREL(t)		zzasp=(t);		/* Restore state of stack */

+#else

+#define zzREL(t)		for (; zzasp<(t); zzasp++)				\

+						{ zzd_attr(&(zzaStack[zzasp])); }

+#endif

+

+

+#define zzsetmatch(_es,_tokclassErrset)						\

+	if ( !_zzsetmatch(_es, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; /* MR23 */

+

+#ifdef ZZCAN_GUESS

+#define zzsetmatch_wsig(_es, handler)		\

+	if ( !_zzsetmatch_wsig(_es) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;}

+#else

+#define zzsetmatch_wsig(_es, handler)		\

+	if ( !_zzsetmatch_wsig(_es) ) {_signal=MismatchedToken; goto handler;}

+#endif

+

+#ifdef __USE_PROTOS

+extern int _zzsetmatch(SetWordType *, char **, char **, int *, int *, SetWordType **, SetWordType * /* MR23 */); 

+extern int _zzsetmatch_wsig(SetWordType *);

+#else

+extern int _zzsetmatch();

+extern int _zzsetmatch_wsig();

+#endif

+

+#define zzmatch(_t)							\

+	if ( !_zzmatch(_t, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet) ) goto fail;

+

+#ifdef ZZCAN_GUESS

+#define zzmatch_wsig(_t,handler)			\

+	if ( !_zzmatch_wsig(_t) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;}

+#else

+#define zzmatch_wsig(_t,handler)			\

+	if ( !_zzmatch_wsig(_t) ) {_signal=MismatchedToken; goto handler;}

+#endif

+

+#ifdef __USE_PROTOS

+extern int _zzmatch(int, char **, char **, int *, int *, SetWordType **);

+extern int _zzmatch_wsig(int);

+#else

+extern int _zzmatch();

+extern int _zzmatch_wsig();

+#endif

+

+#define zzmatch_wdfltsig(_t,_f)			\

+	if ( !_zzmatch_wdfltsig(_t,_f) ) _signal=MismatchedToken;

+#define zzsetmatch_wdfltsig(tw,tt,wf)		\

+	if ( !_zzsetmatch_wdfltsig(tw,tt,wf) ) _signal=MismatchedToken;

+

+#ifdef __USE_PROTOS

+extern int _zzmatch_wdfltsig(int, SetWordType *);

+extern int _zzsetmatch_wdfltsig(SetWordType *tokensWanted,

+								int tokenTypeOfSet,

+								SetWordType *whatFollows);

+#else

+extern int _zzmatch_wdfltsig();

+extern int _zzsetmatch_wdfltsig();

+#endif

+

+#ifdef GENAST

+#define zzRULE		Attrib *zzaRetPtr = &(zzaStack[zzasp-1]);	\

+					SetWordType *zzMissSet=NULL; int zzMissTok=0;		\

+					int zzBadTok=0; char *zzBadText="";		\

+					int zzErrk=1,zzpf=0;					\

+                    zzTRACEdata \

+					char *zzMissText=""; zzASTVars

+#else

+#define zzRULE		Attrib *zzaRetPtr = &(zzaStack[zzasp-1]);	\

+					int zzBadTok=0; char *zzBadText="";		\

+					int zzErrk=1,zzpf=0;								\

+                    zzTRACEdata \

+					SetWordType *zzMissSet=NULL; int zzMissTok=0; char *zzMissText=""

+#endif

+

+#ifdef GENAST

+#define zzBLOCK(i)	int i = zzasp - 1; int zztsp = zzast_sp

+#define zzEXIT(i)	zzREL(i); zzastREL; zzNON_GUESS_MODE { zzastPush(*_root); }

+#define zzEXIT_ANTLR(i)	zzREL(i); zzastREL /* [i_a] added as we want this for the ANTLRx() macros */

+#define zzLOOP(i)	zzREL(i); zzastREL

+#else

+#define zzBLOCK(i)	int i = zzasp - 1

+#define zzEXIT(i)	zzREL(i)

+#define zzEXIT_ANTLR(i)	zzREL(i)           /* [i_a] added as we want this for the ANTLRx() macros */

+#define zzLOOP(i)	zzREL(i)

+#endif

+

+#ifdef LL_K

+

+#ifdef DEMAND_LOOK

+#define LOOK(_k)	{int i,stop=_k-(LL_K-zzdirty); for (i=1; i<=stop; i++)	\

+					zzCONSUME;}

+#define zzCONSUME	{zzgettok(); zzdirty--;							\

+					zzlap = (zzlap+1)&(LL_K-1);						\

+					zzlextext = &(zztextLA[zzlap][0]);}

+#else

+#ifdef ZZINF_LOOK

+#define zzCONSUME	{inf_zzgettok; 									\

+					zzlap = (zzlap+1)&(LL_K-1);						\

+					zzlextext = &(zztextLA[zzlap][0]);				\

+					}

+#else

+#define zzCONSUME	{zzgettok(); 									\

+					zzlap = (zzlap+1)&(LL_K-1);						\

+					zzlextext = &(zztextLA[zzlap][0]);}

+#endif /* ZZINF_LOOK */

+#endif /* DEMAND_LOOK */

+

+#else /* LL_K */

+

+#ifdef DEMAND_LOOK

+#define LOOK(_k)	if ( zzdirty) zzCONSUME;

+#ifdef ZZINF_LOOK

+#define zzCONSUME	inf_zzgettok; zzdirty=0;

+#else

+#define zzCONSUME	zzgettok(); zzdirty=0;

+#endif /* ZZINF_LOOK */

+

+#else  /* DEMAND_LOOK */

+

+#ifdef ZZINF_LOOK

+#define zzCONSUME	inf_zzgettok

+#else

+#define zzCONSUME	zzgettok();

+#endif

+

+#endif /* DEMAND_LOOK */

+

+#endif /* LL_K */

+

+#ifdef LL_K

+#define NLA			zztokenLA[zzlap&(LL_K-1)]	/* --> next LA */

+#define NLATEXT		zztextLA[zzlap&(LL_K-1)]	/* --> next text of LA */

+#ifdef DEMAND_LOOK

+#define LA(i)       zztokenLA[(zzlabase+(i)-1)&(LL_K-1)]

+#define LATEXT(i)   (&(zztextLA[(zzlabase+(i)-1)&(LL_K-1)][0]))

+#else

+#define LA(i)       zztokenLA[(zzlap+(i)-1)&(LL_K-1)]

+#define LATEXT(i)   (&(zztextLA[(zzlap+(i)-1)&(LL_K-1)][0]))

+#endif

+#else

+#define NLA			zztoken

+#define NLATEXT		zztext

+#define LA(i)       zztoken

+#define LATEXT(i)   zztext

+#endif

+

+

+           /* S t a n d a r d  S i g n a l s */

+

+#define NoSignal			0

+#define MismatchedToken		1

+#define NoViableAlt			2

+#define NoSemViableAlt		3

+

+/* MR7  Allow more control over signalling                                  */

+/*        by adding "Unwind" and "zzsetSignal"                              */

+

+#define Unwind              4

+#define zzsetSignal(newValue) *_retsignal=_signal=(newValue)

+#define zzsuppressSignal *_retsignal=_signal=0

+#define zzexportSignal    *_retsignal=_signal

+

+           /* F u n c t i o n  T r a c i n g */

+

+#ifndef zzTRACE_RULES

+#define zzTRACEdata

+#else

+#ifndef zzTRACEdata

+#define zzTRACEdata     ANTLRChar *zzTracePrevRuleName = NULL;

+#endif

+#endif

+

+#ifndef zzTRACEIN

+#define zzTRACEIN(r)	zzTracePrevRuleName=zzTraceCurrentRuleName;zzTraceIn(r);

+#endif

+#ifndef zzTRACEOUT

+#define zzTRACEOUT(r)	zzTraceOut(r);zzTraceCurrentRuleName=zzTracePrevRuleName;

+#endif

+

+/* MR19 zzchar_t additions */

+

+#ifndef zzchar_t

+#ifdef ZZWCHAR_T

+#define zzchar_t wchar_t

+#else

+#define zzchar_t char

+#endif

+#endif

+

+

+/* MR26 */

+

+#ifdef PCCTS_USE_STDARG

+extern void zzFAIL(int k, ...);

+#else

+extern void zzFAIL();

+#endif

+				/* E x t e r n  D e f s */

+

+#ifdef __USE_PROTOS

+extern Attrib zzempty_attr(void);

+extern Attrib zzconstr_attr(int, char *);

+extern void zzsyn(char *, int, char *, SetWordType *, int, int, char *);

+extern int zzset_el(unsigned, SetWordType *);

+extern int zzset_deg(SetWordType *);

+extern void zzedecode(SetWordType *);

+

+extern void zzresynch(SetWordType *, SetWordType);

+extern void zzsave_antlr_state(zzantlr_state *);

+extern void zzrestore_antlr_state(zzantlr_state *);

+extern void zzfill_inf_look(void);

+extern void zzconsumeUntil(SetWordType *st);                         /* MR7 */

+extern void zzconsumeUntilToken(int t);                              /* MR7 */

+extern void zzTraceIn(char * ruleName);                              /* MR10 */

+extern void zzTraceOut(char * ruleName);                             /* MR10 */

+extern int  zzTraceOption(int delta);                                /* MR10 */

+extern int  zzTraceGuessOption(int delta);                           /* MR10 */

+extern void zzTraceReset(void);                                      /* MR10 */

+extern void zzTraceGuessFail(void);                                  /* MR10 */

+#ifdef EXCEPTION_HANDLING

+extern void zzdflthandlers(int, int *);

+#endif

+#else

+extern Attrib zzempty_attr();

+extern Attrib zzconstr_attr();

+extern void zzsyn();

+extern int zzset_el();

+extern int zzset_deg();

+extern void zzedecode();

+extern void zzresynch();

+extern void zzsave_antlr_state();

+extern void zzrestore_antlr_state();

+extern void zzfill_inf_look();

+extern void zzconsumeUntil();                                        /* MR7 */

+extern void zzconsumeUntilToken();                                   /* MR7 */

+extern void zzTraceIn();                                             /* MR10 */

+extern void zzTraceOut();                                            /* MR10 */

+extern int  zzTraceOption();                                         /* MR10 */

+extern int  zzTraceGuessOption();                                    /* MR10 */

+extern void zzTraceReset();                                          /* MR10 */

+extern void zzTraceGuessFail();                                      /* MR10 */

+#ifdef EXCEPTION_HANDLING

+extern void zzdflthandlers();

+#endif

+#endif

+

+				/* G l o b a l  V a r i a b l e s */

+

+/* Define a parser; user should do a "#parser myname" in their grammar file */

+/*extern struct pccts_parser zzparser;*/

+

+extern char *zztokens[];

+#ifdef LL_K

+extern int zztokenLA[];

+extern zzchar_t zztextLA[][ZZLEXBUFSIZE];

+extern int zzlap;

+extern int zzlabase;

+#else

+extern int zztoken;

+#endif

+

+extern char zzStackOvfMsg[];

+extern int zzasp;

+extern Attrib zzaStack[];

+#ifdef ZZINF_LOOK

+extern int *zzinf_tokens;

+extern char **zzinf_text;

+extern char *zzinf_text_buffer;

+extern int *zzinf_line;

+extern int zzinf_labase;

+extern int zzinf_last;

+#endif

+#ifdef DEMAND_LOOK

+extern int zzdirty;

+#endif

+#ifdef ZZCAN_GUESS

+extern int zzguessing;

+extern zzjmp_buf zzguess_start;

+#endif

+

+/* Define global veriables that refer to values exported by the scanner.

+ * These declarations duplicate those in dlgdef.h, but are needed

+ * if ANTLR is not to generate a .dlg file (-gx); PS, this is a hack.

+ */

+extern zzchar_t *zzlextext;     /* text of most recently matched token */

+extern int      zzbufsize;      /* how long zzlextext is */

+

+#endif

diff --git a/Source/Pccts/h/ast.c b/Source/Pccts/h/ast.c
new file mode 100644
index 0000000..9326ae1
--- /dev/null
+++ b/Source/Pccts/h/ast.c
@@ -0,0 +1,345 @@
+/* Abstract syntax tree manipulation functions

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed. 

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+#ifdef PCCTS_USE_STDARG

+#include "pccts_stdarg.h"

+#else

+#include <varargs.h>

+#endif

+

+/* ensure that tree manipulation variables are current after a rule

+ * reference

+ */

+

+void

+#ifdef __USE_PROTOS

+zzlink(AST **_root, AST **_sibling, AST **_tail)

+#else

+zzlink(_root, _sibling, _tail)

+AST **_root, **_sibling, **_tail;

+#endif

+{

+	if ( *_sibling == NULL ) return;

+	if ( *_root == NULL ) *_root = *_sibling;

+	else if ( *_root != *_sibling ) (*_root)->down = *_sibling;

+	if ( *_tail==NULL ) *_tail = *_sibling;

+	while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right;

+}

+

+AST *

+#ifdef __USE_PROTOS

+zzastnew(void)

+#else

+zzastnew()

+#endif

+{

+	AST *p = (AST *) calloc(1, sizeof(AST));

+	if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__);

+	return p;

+}

+

+/* add a child node to the current sibling list */

+void

+#ifdef __USE_PROTOS

+zzsubchild(AST **_root, AST **_sibling, AST **_tail)

+#else

+zzsubchild(_root, _sibling, _tail)

+AST **_root, **_sibling, **_tail;

+#endif

+{

+	AST *n;

+	zzNON_GUESS_MODE {

+	n = zzastnew();

+#ifdef DEMAND_LOOK

+	zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));

+#else

+	zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));

+#endif

+	zzastPush( n );

+	if ( *_tail != NULL ) (*_tail)->right = n;

+	else {

+		*_sibling = n;

+		if ( *_root != NULL ) (*_root)->down = *_sibling;

+	}

+	*_tail = n;

+	if ( *_root == NULL ) *_root = *_sibling;

+	}

+}

+

+/* make a new AST node.  Make the newly-created

+ * node the root for the current sibling list.  If a root node already

+ * exists, make the newly-created node the root of the current root.

+ */

+void

+#ifdef __USE_PROTOS

+zzsubroot(AST **_root, AST **_sibling, AST **_tail)

+#else

+zzsubroot(_root, _sibling, _tail)

+AST **_root, **_sibling, **_tail;

+#endif

+{

+	AST *n;

+	zzNON_GUESS_MODE {

+	n = zzastnew();

+#ifdef DEMAND_LOOK

+	zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));

+#else

+	zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));

+#endif

+	zzastPush( n );

+	if ( *_root != NULL )

+		if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root;

+	*_root = n;

+	(*_root)->down = *_sibling;

+	}

+}

+

+/* Apply function to root then each sibling

+ * example: print tree in child-sibling LISP-format (AST has token field)

+ *

+ *	void show(tree)

+ *	AST *tree;

+ *	{

+ *		if ( tree == NULL ) return;

+ *		printf(" %s", zztokens[tree->token]);

+ *	}

+ *

+ *	void before() { printf(" ("); }

+ *	void after()  { printf(" )"); }

+ *

+ *	LISPdump() { zzpre_ast(tree, show, before, after); }

+ *

+ */

+void

+#ifdef __USE_PROTOS

+zzpre_ast(

+	  AST *tree,

+	  void (*func)(AST *),   /* apply this to each tree node */

+	  void (*before)(AST *), /* apply this to root of subtree before preordering it */

+	  void (*after)(AST *))  /* apply this to root of subtree after preordering it */

+#else

+zzpre_ast(tree, func, before, after)

+AST *tree;

+void (*func)(),   /* apply this to each tree node */

+	 (*before)(), /* apply this to root of subtree before preordering it */

+	 (*after)();  /* apply this to root of subtree after preordering it */

+#endif

+{

+	while ( tree!= NULL )

+	{

+		if ( tree->down != NULL ) (*before)(tree);

+		(*func)(tree);

+		zzpre_ast(tree->down, func, before, after);

+		if ( tree->down != NULL ) (*after)(tree);

+		tree = tree->right;

+	}

+}

+

+/* free all AST nodes in tree; apply func to each before freeing */

+

+#if 0

+////void

+////#ifdef __USE_PROTOS

+////zzfree_ast(AST *tree)

+////#else

+////zzfree_ast(tree)

+////AST *tree;

+////#endif

+////{

+////	if ( tree == NULL ) return;

+////	zzfree_ast( tree->down );

+////	zzfree_ast( tree->right );

+////	zztfree( tree );

+////}

+#endif

+

+/*

+   MR19 Optimize freeing of the following structure to limit recursion

+   SAKAI Kiyotaka (ksakai@isr.co.jp)

+*/

+

+/*

+         NULL o

+             / \

+           NULL o

+               / \

+            NULL NULL

+*/

+

+/*

+   MR21 Another refinement to replace recursion with iteration

+   NAKAJIMA Mutsuki (muc@isr.co.jp).

+*/

+

+void

+#ifdef __USE_PROTOS

+zzfree_ast(AST *tree)

+#else

+zzfree_ast(tree)

+AST *tree;

+#endif

+{

+

+    AST *otree;

+

+    if (tree == NULL) return;

+

+    while (tree->down == NULL || tree->right == NULL) {

+

+        if (tree->down == NULL && tree->right == NULL) {

+            zztfree(tree);

+            return;

+        }

+

+        otree = tree;

+        if (tree->down == NULL) {

+            tree = tree->right;

+        } else {

+            tree = tree->down;

+        }

+        zztfree( otree );

+    }

+

+    while (tree != NULL) {

+        zzfree_ast(tree->down);

+        otree = tree;

+        tree = otree->right;

+        zztfree(otree);

+    }

+}

+

+/* build a tree (root child1 child2 ... NULL)

+ * If root is NULL, simply make the children siblings and return ptr

+ * to 1st sibling (child1).  If root is not single node, return NULL.

+ *

+ * Siblings that are actually siblins lists themselves are handled

+ * correctly.  For example #( NULL, #( NULL, A, B, C), D) results

+ * in the tree ( NULL A B C D ).

+ *

+ * Requires at least two parameters with the last one being NULL.  If

+ * both are NULL, return NULL.

+ */

+#ifdef PCCTS_USE_STDARG

+AST *zztmake(AST *rt, ...)

+#else

+AST *zztmake(va_alist)

+va_dcl

+#endif

+{

+	va_list ap;

+	register AST *child, *sibling=NULL, *tail=NULL /* MR20 */, *w;

+	AST *root;

+

+#ifdef PCCTS_USE_STDARG

+	va_start(ap, rt);

+	root = rt;

+#else

+	va_start(ap);

+	root = va_arg(ap, AST *);

+#endif

+

+	if ( root != NULL )

+		if ( root->down != NULL ) return NULL;

+	child = va_arg(ap, AST *);

+	while ( child != NULL )

+	{

+		for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */

+		if ( sibling == NULL ) {sibling = child; tail = w;}

+		else {tail->right = child; tail = w;}

+		child = va_arg(ap, AST *);

+	}

+	if ( root==NULL ) root = sibling;

+	else root->down = sibling;

+	va_end(ap);

+	return root;

+}

+

+/* tree duplicate */

+AST *

+#ifdef __USE_PROTOS

+zzdup_ast(AST *t)

+#else

+zzdup_ast(t)

+AST *t;

+#endif

+{

+	AST *u;

+	

+	if ( t == NULL ) return NULL;

+	u = zzastnew();

+	*u = *t;

+#ifdef zzAST_DOUBLE

+	u->up = NULL;		/* set by calling invocation */

+	u->left = NULL;

+#endif

+	u->right = zzdup_ast(t->right);

+	u->down = zzdup_ast(t->down);

+#ifdef zzAST_DOUBLE

+	if ( u->right!=NULL ) u->right->left = u;

+	if ( u->down!=NULL ) u->down->up = u;

+#endif

+	return u;

+}

+

+void

+#ifdef __USE_PROTOS

+zztfree(AST *t)

+#else

+zztfree(t)

+AST *t;

+#endif

+{

+#ifdef zzd_ast

+	zzd_ast( t );

+#endif

+	free( t );

+}

+

+#ifdef zzAST_DOUBLE

+/*

+ * Set the 'up', and 'left' pointers of all nodes in 't'.

+ * Initial call is double_link(your_tree, NULL, NULL).

+ */

+void

+#ifdef __USE_PROTOS

+zzdouble_link(AST *t, AST *left, AST *up)

+#else

+zzdouble_link(t, left, up)

+AST *t, *left, *up;

+#endif

+{

+	if ( t==NULL ) return;

+	t->left = left;

+	t->up = up;

+	zzdouble_link(t->down, NULL, t);

+	zzdouble_link(t->right, t, up);

+}

+#endif

diff --git a/Source/Pccts/h/ast.h b/Source/Pccts/h/ast.h
new file mode 100644
index 0000000..5ff84bd
--- /dev/null
+++ b/Source/Pccts/h/ast.h
@@ -0,0 +1,121 @@
+/* Abstract syntax tree

+ *

+ * Macros, definitions

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ZZAST_H

+#define ZZAST_H

+

+#define zzastOvfChk														\

+			if ( zzast_sp <= 0 )                                        \

+            {                                                           \

+                fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__);    	\

+                exit(PCCTS_EXIT_FAILURE);                                               \

+            }

+

+#ifndef USER_DEFINED_AST

+#ifndef AST_FIELDS

+#define AST_FIELDS

+#endif

+

+typedef struct _ast {

+            struct _ast *right, *down;

+#ifdef zzAST_DOUBLE

+            struct _ast *left, *up;

+#endif

+            AST_FIELDS

+} AST;

+

+#else

+

+#ifdef zzAST_DOUBLE

+#define AST_REQUIRED_FIELDS   struct _ast *right, *down, *left, *up;

+#else

+#define AST_REQUIRED_FIELDS   struct _ast *right, *down;

+#endif

+

+#endif

+

+

+/* N o d e  a c c e s s  m a c r o s */

+#define zzchild(t)		(((t)==NULL)? (AST *) NULL:(t->down))   /* MR19 */

+#define zzsibling(t)	(((t)==NULL)? (AST *) NULL:(t->right))  /* MR19 */

+

+

+/* define global variables needed by #i stack */

+#define zzASTgvars												\

+	AST *zzastStack[ZZAST_STACKSIZE];							\

+	int zzast_sp = ZZAST_STACKSIZE;

+

+#define zzASTVars	AST *_ast = NULL, *_sibling = NULL, *_tail = NULL

+#define zzSTR		( (_tail==NULL)?(&_sibling):(&(_tail->right)) )

+#define zzastCur	(zzastStack[zzast_sp])

+#define zzastArg(i)	(zzastStack[zztsp-i])

+#define zzastPush(p) zzastOvfChk; zzastStack[--zzast_sp] = p;

+#define zzastDPush	--zzast_sp

+#define zzastMARK	zztsp=zzast_sp;		/* Save state of stack */

+#define zzastREL	zzast_sp=zztsp;		/* Return state of stack */

+#define zzrm_ast	{zzfree_ast(*_root); _tail = _sibling = (*_root)=NULL;}

+

+extern int zzast_sp;

+extern AST *zzastStack[];

+

+/* MR26 */

+

+#ifdef PCCTS_USE_STDARG

+AST *zztmake(AST *, ...);

+#else

+AST *zztmake();

+#endif

+

+#ifdef __USE_PROTOS

+void zzlink(AST **, AST **, AST **);

+void zzsubchild(AST **, AST **, AST **);

+void zzsubroot(AST **, AST **, AST **);

+void zzpre_ast(AST *, void (*)(AST *), void (*)(AST *), void (*)(AST *));

+void zzfree_ast(AST *);

+AST *zzdup_ast(AST *);

+void zztfree(AST *);

+void zzdouble_link(AST *, AST *, AST *);

+AST *zzastnew(void);

+

+#else

+

+void zzlink();

+AST *zzastnew();

+void zzsubchild();

+void zzsubroot();

+void zzpre_ast();

+void zzfree_ast();

+AST *zzdup_ast();

+void zztfree();

+void zzdouble_link();

+#endif

+

+#endif

diff --git a/Source/Pccts/h/charbuf.h b/Source/Pccts/h/charbuf.h
new file mode 100644
index 0000000..5f01c8b
--- /dev/null
+++ b/Source/Pccts/h/charbuf.h
@@ -0,0 +1,46 @@
+/* ANTLR attribute definition -- constant width text

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ZZCHARBUF_H

+#define ZZCHARBUF_H

+

+#include "pcctscfg.h"

+

+#include "pccts_string.h"

+

+#ifndef D_TextSize

+#define D_TextSize	30

+#endif

+

+typedef struct { char text[D_TextSize]; } Attrib;

+

+#define zzcr_attr(a,tok,t)	strncpy((a)->text, t, D_TextSize-1); \

+							(a)->text[D_TextSize-1] = '\0';

+

+#endif

diff --git a/Source/Pccts/h/charptr.c b/Source/Pccts/h/charptr.c
new file mode 100644
index 0000000..d3f80e6
--- /dev/null
+++ b/Source/Pccts/h/charptr.c
@@ -0,0 +1,58 @@
+/*

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#include "pcctscfg.h"

+

+#ifdef __STDC__

+#include "pccts_stdlib.h"

+#else

+#include <malloc.h>

+#endif

+#include "pccts_string.h"

+

+/* 133MR1 include stdio.h for fprintf in charptr.c */

+

+#include "pccts_stdio.h"

+

+/* 133MR1 include charptr.h for Attrib in charptr.c */

+

+#include "charptr.h"

+

+#ifdef __USE_PROTOS

+zzcr_attr(Attrib *a,int token,char *text)

+#else

+zzcr_attr(a,token,text)

+Attrib *a;

+int token;

+char *text;

+#endif

+{

+	*a = (char *) malloc(strlen(text)+1);			/* MR6 */

+	if ( *a == NULL ) {fprintf(stderr, "zzcr_attr: out of memory!\n"); exit(-1);}

+	strcpy(*a, text);

+}

diff --git a/Source/Pccts/h/charptr.h b/Source/Pccts/h/charptr.h
new file mode 100644
index 0000000..e73da68
--- /dev/null
+++ b/Source/Pccts/h/charptr.h
@@ -0,0 +1,48 @@
+/*

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+/*

+ * WARNING!!!!: charptr.h does NOT make copies and the

+ * memory is freed after the attribute scope exits.

+ */

+

+#ifndef ZZCHARPTR_H

+#define ZZCHARPTR_H

+

+typedef char *Attrib;

+#define zzdef0(a)		{*(a)=NULL;}

+/* MR8  Jens Tingleff (jensting@imaginet.fr)                                */

+/*          Set memory pointer to null after free()                         */

+#define zzd_attr(a)		{if ( *(a)!=NULL ) {free(*(a)); *(a)=NULL; }; }

+

+#ifdef __STDC__

+extern zzcr_attr(Attrib *,int,char *);

+#endif

+

+#endif

diff --git a/Source/Pccts/h/config.h b/Source/Pccts/h/config.h
new file mode 100644
index 0000000..8aa50ad
--- /dev/null
+++ b/Source/Pccts/h/config.h
@@ -0,0 +1 @@
+#include "pcctscfg.h"

diff --git a/Source/Pccts/h/dlgauto.h b/Source/Pccts/h/dlgauto.h
new file mode 100644
index 0000000..db94cef
--- /dev/null
+++ b/Source/Pccts/h/dlgauto.h
@@ -0,0 +1,504 @@
+/* dlgauto.h automaton

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Will Cohen and Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ZZDEFAUTO_H

+#define ZZDEFAUTO_H

+

+/*  10-Apr-97 133MR1	Uses __USE_PROTOS show should #include pcctscfg.h */

+

+#include "pcctscfg.h"

+

+zzchar_t	*zzlextext;	/* text of most recently matched token */

+zzchar_t	*zzbegexpr;	/* beginning of last reg expr recogn. */

+zzchar_t	*zzendexpr;	/* beginning of last reg expr recogn. */

+int	zzbufsize = 0;	/* number of characters in zzlextext */          /* MR7 */

+int	zzbegcol = 0;	/* column that first character of token is in*/

+int	zzendcol = 0;	/* column that last character of token is in */

+int	zzline = 1;	/* line current token is on */

+int	zzreal_line=1;	/* line of 1st portion of token that is not skipped */

+int	zzchar;		/* character to determine next state */

+int	zzbufovf;	/* indicates that buffer too small for text */

+int	zzcharfull = 0;

+static zzchar_t	*zznextpos;/* points to next available position in zzlextext*/

+static int 	zzclass;

+

+#ifdef __USE_PROTOS

+void	zzerrstd(const char *);

+void	(*zzerr)(const char *)=zzerrstd;/* pointer to error reporting function */

+extern int	zzerr_in(void);

+static int	(*zzfunc_in)(void) = zzerr_in;  /* MR20 */

+#else

+void	zzerrstd();

+void	(*zzerr)()=zzerrstd;	/* pointer to error reporting function */

+extern int	zzerr_in();

+static int	(*zzfunc_in)() = zzerr_in;      /* MR20 */

+#endif

+

+static FILE	*zzstream_in=0;

+static zzchar_t	*zzstr_in=0;

+

+#ifdef USER_ZZMODE_STACK

+int 	          zzauto = 0;

+#else

+static int     zzauto = 0;

+#endif

+static int	zzadd_erase;

+static char 	zzebuf[70];

+

+#ifdef ZZCOL

+#define ZZINC (++zzendcol)

+#else

+#define ZZINC

+#endif

+

+

+#define ZZGETC_STREAM {zzchar = getc(zzstream_in); zzclass = ZZSHIFT(zzchar);}

+#define ZZGETC_FUNC {zzchar = (*zzfunc_in)(); zzclass = ZZSHIFT(zzchar);}

+#define ZZGETC_STR { 			\

+	if (*zzstr_in){				\

+		zzchar = *zzstr_in;		\

+		++zzstr_in;				\

+	}else{						\

+		zzchar = EOF;			\

+	}							\

+	zzclass = ZZSHIFT(zzchar);	\

+}

+

+#define ZZNEWSTATE	(newstate = dfa[state][zzclass])

+

+#ifndef ZZCOPY

+#define ZZCOPY	\

+	/* Truncate matching buffer to size (not an error) */	\

+	if (zznextpos < lastpos){				\

+		*(zznextpos++) = zzchar;			\

+	}else{							\

+		zzbufovf = 1;					\

+	}

+#endif

+

+void

+#ifdef __USE_PROTOS

+zzrdstream( FILE *f )

+#else

+zzrdstream( f )

+FILE *f;

+#endif

+{

+	/* make sure that it is really set to something, otherwise just

+	   leave it be.

+	*/

+	if (f){

+		/* make sure that there is always someplace to get input

+		   before closing zzstream_in

+		*/

+#if 0

+		if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );

+#endif

+		zzline = 1;

+		zzstream_in = f;

+		zzfunc_in = NULL;

+		zzstr_in = 0;

+		zzcharfull = 0;

+	}

+}

+

+void

+#ifdef __USE_PROTOS

+zzrdfunc( int (*f)(void) )

+#else

+zzrdfunc( f )

+int (*f)();

+#endif

+{

+	/* make sure that it is really set to something, otherwise just

+	   leave it be.

+	*/

+	if (f){

+		/* make sure that there is always someplace to get input

+		   before closing zzstream_in

+		*/

+#if 0

+		if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );

+#endif

+		zzline = 1;

+		zzstream_in = NULL;

+		zzfunc_in = f;

+		zzstr_in = 0;

+		zzcharfull = 0;

+	}

+}

+

+

+void

+#ifdef __USE_PROTOS

+zzrdstr( zzchar_t *s )

+#else

+zzrdstr( s )

+zzchar_t *s;

+#endif

+{

+	/* make sure that it is really set to something, otherwise just

+	   leave it be.

+	*/

+	if (s){

+		/* make sure that there is always someplace to get input

+		   before closing zzstream_in

+		*/

+#if 0

+		if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );

+#endif

+		zzline = 1;

+		zzstream_in = NULL;

+		zzfunc_in = 0;

+		zzstr_in = s;

+		zzcharfull = 0;

+	}

+}

+

+

+#ifdef __USE_PROTOS

+void zzclose_stream(void)

+#else

+void zzclose_stream()

+#endif

+{

+#if 0

+	fclose( zzstream_in );

+	zzstream_in = NULL;

+	zzfunc_in = NULL;

+#endif

+}

+

+/* saves dlg state, but not what feeds dlg (such as file position) */

+void

+#ifdef __USE_PROTOS

+zzsave_dlg_state(struct zzdlg_state *state)

+#else

+zzsave_dlg_state(state)

+struct zzdlg_state *state;

+#endif

+{

+	state->stream = zzstream_in;

+	state->func_ptr = zzfunc_in;

+	state->str = zzstr_in;

+	state->auto_num = zzauto;

+	state->add_erase = zzadd_erase;

+	state->lookc = zzchar;

+	state->char_full = zzcharfull;

+	state->begcol = zzbegcol;

+	state->endcol = zzendcol;

+	state->line = zzline;

+	state->lextext = zzlextext;

+	state->begexpr = zzbegexpr;

+	state->endexpr = zzendexpr;

+	state->bufsize = zzbufsize;

+	state->bufovf = zzbufovf;

+	state->nextpos = zznextpos;

+	state->class_num = zzclass;

+}

+

+void

+#ifdef __USE_PROTOS

+zzrestore_dlg_state(struct zzdlg_state *state)

+#else

+zzrestore_dlg_state(state)

+struct zzdlg_state *state;

+#endif

+{

+	zzstream_in = state->stream;

+	zzfunc_in = state->func_ptr;

+	zzstr_in = state->str;

+	zzauto = state->auto_num;

+	zzadd_erase = state->add_erase;

+	zzchar = state->lookc;

+	zzcharfull = state->char_full;

+	zzbegcol = state->begcol;

+	zzendcol = state->endcol;

+	zzline = state->line;

+	zzlextext = state->lextext;

+	zzbegexpr = state->begexpr;

+	zzendexpr = state->endexpr;

+	zzbufsize = state->bufsize;

+	zzbufovf = state->bufovf;

+	zznextpos = state->nextpos;

+	zzclass = state->class_num;

+}

+

+void

+#ifdef __USE_PROTOS

+zzmode( int m )

+#else

+zzmode( m )

+int m;

+#endif

+{

+	/* points to base of dfa table */

+	if (m<MAX_MODE){

+		zzauto = m;

+		/* have to redo class since using different compression */

+		zzclass = ZZSHIFT(zzchar);

+	}else{

+		sprintf(zzebuf,"Invalid automaton mode = %d ",m);

+		zzerr(zzebuf);

+	}

+}

+

+/* erase what is currently in the buffer, and get a new reg. expr */

+

+#ifdef __USE_PROTOS

+void zzskip(void)

+#else

+void zzskip()

+#endif

+{

+	zzadd_erase = 1;

+}

+

+/* don't erase what is in the zzlextext buffer, add on to it */

+#ifdef __USE_PROTOS

+void zzmore()

+#else

+void zzmore()

+#endif

+{

+	zzadd_erase = 2;

+}

+

+/* substitute c for the reg. expr last matched and is in the buffer */

+#ifdef __USE_PROTOS

+void

+zzreplchar(zzchar_t c)

+#else

+void

+zzreplchar(c)

+zzchar_t c;

+#endif

+{

+	/* can't allow overwriting null at end of string */

+	if (zzbegexpr < &zzlextext[zzbufsize-1]){

+		*zzbegexpr = c;

+		*(zzbegexpr+1) = '\0';

+	}

+	zzendexpr = zzbegexpr;

+	if (c != '\0') {

+		zznextpos = zzbegexpr + 1;

+	}

+	else {

+		zznextpos = zzbegexpr;	/* MR30 Zero terminates string. */

+	}

+}

+

+/* replace the string s for the reg. expr last matched and in the buffer */

+void

+#ifdef __USE_PROTOS

+zzreplstr(register zzchar_t *s)

+#else

+zzreplstr(s)

+register zzchar_t *s;

+#endif

+{

+	register zzchar_t *l= &zzlextext[zzbufsize -1];

+

+	zznextpos = zzbegexpr;

+	if (s){

+	 	while ((zznextpos <= l) && (*(zznextpos++) = *(s++))!=0){

+			/* empty */

+		}

+		/* correct for NULL at end of string */

+		zznextpos--;

+	}

+	if ((zznextpos <= l) && (*(--s) == 0)){

+		zzbufovf = 0;

+	}else{

+		zzbufovf = 1;

+	}

+	*(zznextpos) = '\0';

+	zzendexpr = zznextpos - 1;

+}

+

+#ifdef __USE_PROTOS

+void zzgettok(void)

+#else

+void zzgettok()

+#endif

+{

+	register int state, newstate;

+	/* last space reserved for the null char */

+	zzchar_t *lastpos;  /* MR27 Remove register since address operator used. */

+

+skip:

+	zzreal_line = zzline;

+	zzbufovf = 0;

+	lastpos = &zzlextext[zzbufsize-1];

+	zznextpos = zzlextext;

+	zzbegcol = zzendcol+1;

+more:

+	zzbegexpr = zznextpos;

+#ifdef ZZINTERACTIVE

+	/* interactive version of automaton */

+	/* if there is something in zzchar, process it */

+	state = newstate = dfa_base[zzauto];

+	if (zzcharfull){

+		ZZINC;

+		ZZCOPY;

+		ZZNEWSTATE;

+	}

+	if (zzstr_in)

+		while (zzalternatives[newstate]){

+			state = newstate;

+			ZZGETC_STR;

+			ZZINC;

+			ZZCOPY;

+			ZZNEWSTATE;

+		}

+	else if (zzstream_in)

+		while (zzalternatives[newstate]){

+			state = newstate;

+			ZZGETC_STREAM;

+			ZZINC;

+			ZZCOPY;

+			ZZNEWSTATE;

+		}

+	else if (zzfunc_in)

+		while (zzalternatives[newstate]){

+			state = newstate;

+			ZZGETC_FUNC;

+			ZZINC;

+			ZZCOPY;

+			ZZNEWSTATE;

+		}

+	/* figure out if last character really part of token */

+	if ((state != dfa_base[zzauto]) && (newstate == DfaStates)){

+		zzcharfull = 1;

+		--zznextpos;

+	}else{

+		zzcharfull = 0;

+		state = newstate;

+	}

+	*(zznextpos) = '\0';

+	/* Able to transition out of start state to some non err state?*/

+	if ( state == dfa_base[zzauto] ){

+		/* make sure doesn't get stuck */

+		zzadvance();

+	}

+#else

+	/* non-interactive version of automaton */

+	if (!zzcharfull)

+		zzadvance();

+	else

+		ZZINC;

+	state = dfa_base[zzauto];

+	if (zzstr_in)

+		while (ZZNEWSTATE != DfaStates){

+			state = newstate;

+			ZZCOPY;

+			ZZGETC_STR;

+			ZZINC;

+		}

+	else if (zzstream_in)

+		while (ZZNEWSTATE != DfaStates){

+			state = newstate;

+			ZZCOPY;

+			ZZGETC_STREAM;

+			ZZINC;

+		}

+	else if (zzfunc_in)

+		while (ZZNEWSTATE != DfaStates){

+			state = newstate;

+			ZZCOPY;

+			ZZGETC_FUNC;

+			ZZINC;

+		}

+	zzcharfull = 1;

+	if ( state == dfa_base[zzauto] ){

+		if (zznextpos < lastpos){

+			*(zznextpos++) = zzchar;

+		}else{

+			zzbufovf = 1;

+		}

+		*zznextpos = '\0';

+		/* make sure doesn't get stuck */

+		zzadvance();

+	}else{

+		*zznextpos = '\0';

+	}

+#endif

+#ifdef ZZCOL

+	zzendcol -= zzcharfull;

+#endif

+	zzendexpr = zznextpos -1;

+	zzadd_erase = 0;

+	(*actions[accepts[state]])();

+	switch (zzadd_erase) {

+		case 1: goto skip;

+		case 2: goto more;

+	}

+}

+

+#ifdef __USE_PROTOS

+void zzadvance(void)

+#else

+void zzadvance()

+#endif

+{

+	if (zzstream_in) { ZZGETC_STREAM; zzcharfull = 1; ZZINC;}

+	if (zzfunc_in) { ZZGETC_FUNC; zzcharfull = 1; ZZINC;}

+	if (zzstr_in) { ZZGETC_STR; zzcharfull = 1; ZZINC;}

+	if (!(zzstream_in || zzfunc_in || zzstr_in)){

+		zzerr_in();

+	}

+}

+

+void

+#ifdef __USE_PROTOS

+zzerrstd(const char *s)

+#else

+zzerrstd(s)

+char *s;

+#endif

+{

+        zzLexErrCount++;                /* MR11 */

+        fprintf(stderr,

+                "%s near line %d (text was '%s')\n",

+                ((s == NULL) ? "Lexical error" : s),

+                zzline,zzlextext);

+}

+

+#ifdef __USE_PROTOS

+int zzerr_in(void)

+#else

+int zzerr_in()

+#endif

+{

+	fprintf(stderr,"No input stream, function, or string\n");

+	/* return eof to get out gracefully */

+	return EOF;

+}

+

+#endif

diff --git a/Source/Pccts/h/dlgdef.h b/Source/Pccts/h/dlgdef.h
new file mode 100644
index 0000000..733d256
--- /dev/null
+++ b/Source/Pccts/h/dlgdef.h
@@ -0,0 +1,128 @@
+/* dlgdef.h

+ * Things in scanner produced by dlg that should be visible to the outside

+ * world

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ZZDLGDEF_H

+#define ZZDLGDEF_H

+

+#include "pcctscfg.h"

+

+#ifndef zzchar_t

+#ifdef ZZWCHAR_T

+#define zzchar_t wchar_t

+#else

+#define zzchar_t char

+#endif

+#endif

+

+struct zzdlg_state {

+	FILE *stream;

+#ifdef __USE_PROTOS

+	int (*func_ptr)(void);

+#else

+	int (*func_ptr)();

+#endif

+	zzchar_t *str;

+	int auto_num;

+	int add_erase;

+	int lookc;

+	int char_full;

+	int begcol, endcol;

+	int line;

+	zzchar_t *lextext, *begexpr, *endexpr;

+	int bufsize;

+	int bufovf;

+	zzchar_t *nextpos;

+	int	class_num;

+};

+

+extern zzchar_t	*zzlextext;  	/* text of most recently matched token */

+extern zzchar_t	*zzbegexpr;	/* beginning of last reg expr recogn. */

+extern zzchar_t	*zzendexpr;	/* beginning of last reg expr recogn. */

+extern int	zzbufsize;	/* how long zzlextext is */

+extern int	zzbegcol;	/* column that first character of token is in*/

+extern int	zzendcol;	/* column that last character of token is in */

+extern int	zzline;		/* line current token is on */

+extern int	zzreal_line;		/* line of 1st portion of token that is not skipped */

+extern int	zzchar;		/* character to determine next state */

+extern int	zzbufovf;	/* indicates that buffer too small for text */

+#ifdef __USE_PROTOS

+extern void	(*zzerr)(const char *);/* pointer to error reporting function */

+#else

+extern void	(*zzerr)();

+#endif

+

+#ifdef USER_ZZMODE_STACK

+extern int     zzauto;

+#endif

+

+#ifdef __USE_PROTOS

+extern void	zzadvance(void);

+extern void	zzskip(void);	/* erase zzlextext, look for antoher token */

+extern void	zzmore(void);	/* keep zzlextext, look for another token */

+extern void	zzmode(int k);	/* switch to automaton 'k' */

+extern void	zzrdstream(FILE *);/* what stream to read from */

+extern void	zzclose_stream(void);/* close the current input stream */

+extern void	zzrdfunc(int (*)(void));/* what function to get char from */

+extern void zzrdstr( zzchar_t * );

+extern void	zzgettok(void);	/* get next token */

+extern void	zzreplchar(zzchar_t c);/* replace last recognized reg. expr. with

+					a character */

+extern void	zzreplstr(zzchar_t *s);/* replace last recognized reg. expr. with

+					a string */

+extern void zzsave_dlg_state(struct zzdlg_state *);

+extern void zzrestore_dlg_state(struct zzdlg_state *);

+extern int zzerr_in(void);

+extern void	zzerrstd(const char *);

+extern void zzerraction(void);

+

+#else

+

+extern void	zzadvance();

+extern void	zzskip();	/* erase zzlextext, look for antoher token */

+extern void	zzmore();	/* keep zzlextext, look for another token */

+extern void	zzmode(/*k*/);	/* switch to automaton 'k' */

+extern void	zzrdstream();	/* what stream to read from */

+extern void	zzclose_stream();/* close the current input stream */

+extern void	zzrdfunc();	/* what function to get char from */

+extern void zzrdstr();

+extern void	zzgettok();	/* get next token */

+extern void	zzreplchar();	/* replace last recognized reg. expr. with

+					a character */

+extern void	zzreplstr();	/* replace last recognized reg. expr. with

+					a string */

+extern void zzsave_dlg_state();

+extern void zzrestore_dlg_state();

+extern int zzerr_in();

+extern void	zzerrstd();

+extern void zzerraction();

+#endif

+

+#endif

diff --git a/Source/Pccts/h/err.h b/Source/Pccts/h/err.h
new file mode 100644
index 0000000..b2b196b
--- /dev/null
+++ b/Source/Pccts/h/err.h
@@ -0,0 +1,1170 @@
+/*

+ * err.h

+ *

+ * Standard error handling mechanism

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * Has grown to hold all kinds of stuff (err.h is increasingly misnamed)

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ERR_H

+#define ERR_H

+

+#include "pcctscfg.h"

+#include <stdlib.h>

+#include <assert.h>

+

+/*									      */

+/*  7-Apr-97  133MR1							      */

+/*		Proper choice of STDC and cplusplus pre-processor symbols (?) */

+/*									      */

+#include "pccts_string.h"

+

+#ifdef PCCTS_USE_STDARG

+#include "pccts_stdarg.h"

+#else

+#include <varargs.h>

+#endif

+

+#ifdef DUM

+/* Define usable bits per unsigned int word (used for set stuff) */

+#ifdef PC

+#define BSETWORDSIZE 16

+#define BSETLOGWORDSIZE	4

+#else

+#define	BSETWORDSIZE 32

+#define BSETLOGWORDSIZE 5

+#endif

+#endif

+

+#define	BSETWORDSIZE 8

+#define BSETLOGWORDSIZE 3		/* SetWordType is 8bits */

+

+#define	BSETMODWORD(x) ((x) & (BSETWORDSIZE-1))		/* x % BSETWORDSIZE */

+#define	BSETDIVWORD(x) ((x) >> BSETLOGWORDSIZE)		/* x / BSETWORDSIZE */

+

+/* This is not put into the global pccts_parser structure because it is

+ * hidden and does not need to be saved during a "save state" operation

+ */

+/* maximum of 32 bits/unsigned int and must be 8 bits/byte */

+static SetWordType bitmask[] = {

+	0x00000001, 0x00000002, 0x00000004, 0x00000008,

+	0x00000010, 0x00000020, 0x00000040, 0x00000080

+};

+

+#ifdef zzTRACE_RULES

+int  zzTraceOptionValueDefault=1;

+int  zzTraceOptionValue=1;

+int  zzTraceGuessOptionValue=1;

+char *zzTraceCurrentRuleName=NULL;

+int  zzTraceDepth=0;

+#endif

+

+int  zzGuessSeq=0;          /* MR10 */

+int  zzSyntaxErrCount=0;    /* MR11 */

+int  zzLexErrCount=0;       /* MR11 */

+

+void

+#ifdef __USE_PROTOS

+zzresynch(SetWordType *wd,SetWordType mask)

+#else

+zzresynch(wd,mask)

+SetWordType *wd, mask;

+#endif

+{

+	static int consumed = 1;

+

+	/* if you enter here without having consumed a token from last resynch

+	 * force a token consumption.

+	 */

+	if ( !consumed ) {zzCONSUME; consumed=1; return;}   /* MR10 */

+

+	/* if current token is in resynch set, we've got what we wanted */

+	if ( wd[LA(1)]&mask || LA(1) == zzEOF_TOKEN ) {consumed=0; return;}

+	

+	/* scan until we find something in the resynch set */

+	while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;}

+	consumed=1;

+}

+

+/*                                                                          */

+/*  7-Apr-97 133MR1 for C++ and MR7 for C                                   */

+/*   	     Change suggested by Eli Sternheim (eli@interhdl.com)           */

+/*                                                                          */

+

+void

+#ifdef __USE_PROTOS

+zzconsumeUntil(SetWordType *st)

+#else

+zzconsumeUntil(st)

+SetWordType *st;

+#endif

+{

+    int     tmp;                                                     /* MR7 */

+	while ( !zzset_el( (tmp=LA(1)), st) && tmp!=1 /* Eof */) {       /* MR7 */

+                                                      zzCONSUME; }   /* MR7 */

+}

+

+/*                                                                          */

+/*  7-Apr-97 133MR1 for C++ and MR7 for C                                   */

+/*   	     Change suggested by Eli Sternheim (eli@interhdl.com)           */

+/*                                                                          */

+

+void

+#ifdef __USE_PROTOS

+zzconsumeUntilToken(int t)

+#else

+zzconsumeUntilToken(t)

+int t;

+#endif

+{

+    int     tmp;                                                     /* MR7 */

+	while ( (tmp=LA(1)) !=t && tmp!=1 /* Eof */) { zzCONSUME; }      /* MR7 */

+}

+

+/* input looks like:

+ *		zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText)

+ * where the zzMiss stuff is set here to the token that did not match

+ * (and which set wasn't it a member of).

+ */

+

+#ifdef PCCTS_USE_STDARG

+void zzFAIL(int k, ...)

+#else

+void zzFAIL(va_alist)

+va_dcl

+#endif

+{

+#ifdef LL_K

+	static char text[LL_K*ZZLEXBUFSIZE+1];

+	SetWordType *f[LL_K];

+#else

+	static char text[ZZLEXBUFSIZE+1];

+	SetWordType *f[1];

+#endif

+	SetWordType **miss_set;

+	char **miss_text;

+	int *bad_tok;

+	char **bad_text;

+	int *err_k;

+	int i;

+	va_list ap;

+#ifndef PCCTS_USE_STDARG			/* MR20 */

+	int k;

+#endif

+#ifdef PCCTS_USE_STDARG         /* MR20 */

+	va_start(ap, k);

+#else

+	va_start(ap);

+	k = va_arg(ap, int);	/* how many lookahead sets? */

+#endif

+    assert(k <= sizeof(f)/sizeof(f[0]));    /* MR20 G. Hobbelt */

+	text[0] = '\0';

+	for (i=1; i<=k; i++)	/* collect all lookahead sets */

+	{

+		f[i-1] = va_arg(ap, SetWordType *);

+	}

+	for (i=1; i<=k; i++)	/* look for offending token */

+	{

+		if ( i>1 ) strcat(text, " ");

+		strcat(text, LATEXT(i));

+		if ( !zzset_el((unsigned)LA(i), f[i-1]) ) break;

+	}

+	miss_set = va_arg(ap, SetWordType **);

+	miss_text = va_arg(ap, char **);

+	bad_tok = va_arg(ap, int *);

+	bad_text = va_arg(ap, char **);

+	err_k = va_arg(ap, int *);

+	if ( i>k )

+	{

+		/* bad; lookahead is permutation that cannot be matched,

+		 * but, the ith token of lookahead is valid at the ith position

+		 * (The old LL sub 1 (k) versus LL(k) parsing technique)

+		 */

+		*miss_set = NULL;

+		*miss_text = zzlextext;

+		*bad_tok = LA(1);

+		*bad_text = LATEXT(1);

+		*err_k = k;

+		return;

+	}

+/*	fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/

+	*miss_set = f[i-1];

+	*miss_text = text;

+	*bad_tok = LA(i);

+	*bad_text = LATEXT(i);

+	if ( i==1 ) *err_k = 1;

+	else *err_k = k;

+}

+

+#ifdef __USE_PROTOS

+void zzTraceGuessDone(zzantlr_state *state)

+#else

+void zzTraceGuessDone(state)

+  zzantlr_state     *state;

+#endif

+{

+#ifdef zzTRACE_RULES

+#ifdef ZZCAN_GUESS

+

+  int   doIt=0;

+

+  if (zzTraceCurrentRuleName == NULL) return;

+

+  if (zzTraceOptionValue <= 0) {

+    doIt=0;

+  } else if (zzTraceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    fprintf(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d",

+        state->traceCurrentRuleName,

+        LATEXT(1),

+        state->traceDepth);

+    if (state->guessing != 0) {

+      fprintf(stderr," (guess mode continues - an enclosing guess is still active)");

+    } else {

+      fprintf(stderr," (guess mode ends)");

+    };

+    fprintf(stderr,"\n");

+  };

+#endif

+#endif

+}

+

+void

+#ifdef __USE_PROTOS

+zzsave_antlr_state(zzantlr_state *buf)

+#else

+zzsave_antlr_state(buf)

+zzantlr_state *buf;

+#endif

+{

+#ifdef LL_K

+	int     i;

+#endif

+

+#ifdef ZZCAN_GUESS

+	buf->guess_start = zzguess_start;

+	buf->guessing = zzguessing;

+#endif

+	buf->asp = zzasp;

+#ifdef GENAST

+	buf->ast_sp = zzast_sp;

+#endif

+#ifdef ZZINF_LOOK

+	buf->inf_labase = zzinf_labase;

+	buf->inf_last = zzinf_last;

+

+/* MR6 	Gunnar Rxnning (gunnar@candleweb.no)                                */

+/* MR6	  Additional state needs to be saved/restored                       */

+

+  	buf->inf_tokens = zzinf_tokens;                                  /* MR6 */

+	buf->inf_text = zzinf_text;                                      /* MR6 */

+	buf->inf_text_buffer = zzinf_text_buffer;                        /* MR6 */

+	buf->inf_line = zzinf_line;			                             /* MR6 */

+

+#endif

+#ifdef DEMAND_LOOK

+	buf->dirty = zzdirty;

+#endif

+#ifdef LL_K

+	for (i=0; i<LL_K; i++) buf->tokenLA[i] = zztokenLA[i];

+	for (i=0; i<LL_K; i++) strcpy(buf->textLA[i], zztextLA[i]);

+	buf->lap = zzlap;

+	buf->labase = zzlabase;

+#else

+	buf->token = zztoken;

+	strcpy(buf->text, zzlextext);

+#endif

+#ifdef zzTRACE_RULES

+

+    /* MR10 */

+

+    buf->traceOptionValue=zzTraceOptionValue;

+    buf->traceGuessOptionValue=zzTraceGuessOptionValue;

+    buf->traceCurrentRuleName=zzTraceCurrentRuleName;

+    buf->traceDepth=zzTraceDepth;

+#endif

+}

+

+void

+#ifdef __USE_PROTOS

+zzrestore_antlr_state(zzantlr_state *buf)

+#else

+zzrestore_antlr_state(buf)

+zzantlr_state *buf;

+#endif

+{

+

+#ifdef zzTRACE_RULES

+    int     prevTraceOptionValue;

+#endif

+

+#ifdef LL_K

+	int     i;

+#endif

+

+#ifdef ZZCAN_GUESS

+	zzguess_start = buf->guess_start;

+	zzguessing = buf->guessing;

+#endif

+	zzasp = buf->asp;

+#ifdef GENAST

+	zzast_sp = buf->ast_sp;

+#endif

+#ifdef ZZINF_LOOK

+	zzinf_labase = buf->inf_labase;

+	zzinf_last = buf->inf_last;

+

+/* MR6 	Gunnar Rxnning (gunnar@candleweb.no)                                */

+/* MR6	  Additional state needs to be saved/restored                       */

+

+	zzinf_tokens = buf->inf_tokens;                                  /* MR6 */

+	zzinf_text = buf->inf_text;                                      /* MR6 */

+	zzinf_text_buffer = buf->inf_text_buffer;                        /* MR6 */

+	zzinf_line = buf->inf_line;			                             /* MR6 */

+#endif

+#ifdef DEMAND_LOOK

+	zzdirty = buf->dirty;

+#endif

+#ifdef LL_K

+	for (i=0; i<LL_K; i++) zztokenLA[i] = buf->tokenLA[i];

+	for (i=0; i<LL_K; i++) strcpy(zztextLA[i], buf->textLA[i]);

+	zzlap = buf->lap;

+	zzlabase = buf->labase;

+#else

+	zztoken = buf->token;

+	strcpy(zzlextext, buf->text);

+#endif

+#ifdef zzTRACE_RULES

+

+    prevTraceOptionValue=zzTraceOptionValue;

+    zzTraceOptionValue=buf->traceOptionValue;

+    if ( (prevTraceOptionValue > 0) !=

+             (zzTraceOptionValue > 0)) {

+      if (zzTraceOptionValue > 0) {

+        fprintf(stderr,"trace enable restored in rule %s depth %d\n",

+                        zzTraceCurrentRuleName,zzTraceDepth);

+      };

+      if (zzTraceOptionValue <= 0) {

+        fprintf(stderr,"trace disable restored in rule %s depth %d\n",

+                        zzTraceCurrentRuleName,zzTraceDepth);

+      };

+    };

+

+    zzTraceOptionValue=buf->traceOptionValue;            /* MR10 */

+    zzTraceGuessOptionValue=buf->traceGuessOptionValue;  /* MR10 */

+    zzTraceCurrentRuleName=buf->traceCurrentRuleName;    /* MR10 */

+    zzTraceDepth=buf->traceDepth;                        /* MR10 */

+    zzTraceGuessDone(buf);                               /* MR10 */

+#endif

+}

+

+void

+#ifdef __USE_PROTOS

+zzedecode(SetWordType *a)

+#else

+zzedecode(a)

+SetWordType *a;

+#endif

+{

+	register SetWordType *p = a;

+	register SetWordType *endp = &(p[zzSET_SIZE]);

+	register unsigned e = 0;

+

+	if ( zzset_deg(a)>1 ) fprintf(stderr, " {");

+	do {

+		register SetWordType t = *p;

+		register SetWordType *b = &(bitmask[0]);

+		do {

+			if ( t & *b ) fprintf(stderr, " %s", zztokens[e]);

+			e++;

+		} while (++b < &(bitmask[sizeof(SetWordType)*8]));

+	} while (++p < endp);

+	if ( zzset_deg(a)>1 ) fprintf(stderr, " }");

+}

+

+#ifndef USER_ZZSYN

+/* standard error reporting function */

+void

+#ifdef __USE_PROTOS

+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)

+#else

+zzsyn(text, tok, egroup, eset, etok, k, bad_text)

+char *text, *egroup, *bad_text;

+int tok;

+int etok;

+int k;

+SetWordType *eset;

+#endif

+{

+	

+    zzSyntaxErrCount++;                             /* MR11 */

+	fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (tok==zzEOF_TOKEN)?"EOF":bad_text);

+	if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}

+	if ( k==1 ) fprintf(stderr, " missing");

+	else

+	{

+		fprintf(stderr, "; \"%s\" not", bad_text);

+		if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");

+	}

+	if ( zzset_deg(eset)>0 ) zzedecode(eset);

+	else fprintf(stderr, " %s", zztokens[etok]);

+	if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup);

+	fprintf(stderr, "\n");

+}

+#endif

+

+/* is b an element of set p? */

+int

+#ifdef __USE_PROTOS

+zzset_el(unsigned b, SetWordType *p)

+#else

+zzset_el(b,p)

+unsigned b;

+SetWordType *p;

+#endif

+{

+	return( p[BSETDIVWORD(b)] & bitmask[BSETMODWORD(b)] );

+}

+

+int

+#ifdef __USE_PROTOS

+zzset_deg(SetWordType *a)

+#else

+zzset_deg(a)

+SetWordType *a;

+#endif

+{

+	/* Fast compute degree of a set... the number

+	   of elements present in the set.  Assumes

+	   that all word bits are used in the set

+	*/

+	register SetWordType *p = a;

+	register SetWordType *endp = &(a[zzSET_SIZE]);

+	register int degree = 0;

+

+	if ( a == NULL ) return 0;

+	while ( p < endp )

+	{

+		register SetWordType t = *p;

+		register SetWordType *b = &(bitmask[0]);

+		do {

+			if (t & *b) ++degree;

+		} while (++b < &(bitmask[sizeof(SetWordType)*8]));

+		p++;

+	}

+

+	return(degree);

+}

+

+#ifdef DEMAND_LOOK

+

+#ifdef LL_K

+int

+#ifdef __USE_PROTOS

+_zzmatch(int _t, char **zzBadText, char **zzMissText,

+		int *zzMissTok, int *zzBadTok,

+		SetWordType **zzMissSet)

+#else

+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)

+int _t;

+char **zzBadText;

+char **zzMissText;

+int *zzMissTok, *zzBadTok;

+SetWordType **zzMissSet;

+#endif

+{

+	if ( zzdirty==LL_K ) {

+		zzCONSUME;

+	}

+	if ( LA(1)!=_t ) {

+		*zzBadText = *zzMissText=LATEXT(1);	

+		*zzMissTok= _t; *zzBadTok=LA(1);

+		*zzMissSet=NULL;				

+		return 0;

+	}

+	zzMakeAttr						

+	zzdirty++;						

+	zzlabase++;						

+	return 1;

+}

+

+int

+#ifdef __USE_PROTOS

+_zzmatch_wsig(int _t)

+#else

+_zzmatch_wsig(_t)

+int _t;

+#endif

+{

+	if ( zzdirty==LL_K ) {

+		zzCONSUME;

+	}

+	if ( LA(1)!=_t ) {

+		return 0;

+	}

+	zzMakeAttr						

+	zzdirty++;						

+	zzlabase++;						

+	return 1;

+}

+

+#else

+

+int

+#ifdef __USE_PROTOS

+_zzmatch(int _t, char **zzBadText, char **zzMissText,

+		 int *zzMissTok, int *zzBadTok, SetWordType **zzMissSet)

+#else

+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)

+int _t;

+char **zzBadText;

+char **zzMissText;

+int *zzMissTok, *zzBadTok;

+SetWordType **zzMissSet;

+#endif

+{								

+	if ( zzdirty ) {zzCONSUME;}		

+	if ( LA(1)!=_t ) {

+		*zzBadText = *zzMissText=LATEXT(1);	

+		*zzMissTok= _t; *zzBadTok=LA(1);

+		*zzMissSet=NULL;				

+		return 0;

+	}								

+	zzdirty = 1;					

+	zzMakeAttr						

+	return 1;

+}

+

+int

+#ifdef __USE_PROTOS

+_zzmatch_wsig(int _t)

+#else

+_zzmatch_wsig(_t)

+int _t;

+#endif

+{

+	if ( zzdirty ) {zzCONSUME;}		

+	if ( LA(1)!=_t ) {

+		return 0;

+	}

+	zzdirty = 1;					

+	zzMakeAttr						

+	return 1;

+}

+

+#endif /*LL_K*/

+

+#else

+

+int

+#ifdef __USE_PROTOS

+_zzmatch(int _t, char **zzBadText, char **zzMissText,

+		int *zzMissTok, int *zzBadTok,

+		SetWordType **zzMissSet)

+#else

+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)

+int _t;

+char **zzBadText;

+char **zzMissText;

+int *zzMissTok, *zzBadTok;

+SetWordType **zzMissSet;

+#endif

+{

+	if ( LA(1)!=_t ) {				

+		*zzBadText = *zzMissText=LATEXT(1);	

+		*zzMissTok= _t; *zzBadTok=LA(1);

+		*zzMissSet=NULL;				

+		return 0;

+	}

+	zzMakeAttr

+	return 1;

+}

+

+int

+#ifdef __USE_PROTOS

+_zzmatch_wsig(int _t)

+#else

+_zzmatch_wsig(_t)

+int _t;

+#endif

+{

+	if ( LA(1)!=_t ) return 0;

+	zzMakeAttr						

+	return 1;

+}

+

+#endif /*DEMAND_LOOK*/

+

+#ifdef ZZINF_LOOK

+void

+#ifdef __USE_PROTOS

+_inf_zzgettok(void)

+#else

+_inf_zzgettok()

+#endif

+{

+	if ( zzinf_labase >= zzinf_last )					

+		{NLA = zzEOF_TOKEN; strcpy(NLATEXT, "");}	

+	else {											

+		NLA = zzinf_tokens[zzinf_labase];

+		zzline = zzinf_line[zzinf_labase];	/* wrong in 1.21 */

+		strcpy(NLATEXT, zzinf_text[zzinf_labase]);		

+		zzinf_labase++; 								

+	}												

+}

+#endif

+

+#ifdef ZZINF_LOOK

+/* allocate default size text,token and line arrays;

+ * then, read all of the input reallocing the arrays as needed.

+ * Once the number of total tokens is known, the LATEXT(i) array (zzinf_text)

+ * is allocated and it's pointers are set to the tokens in zzinf_text_buffer.

+ */

+void

+#ifdef __USE_PROTOS

+zzfill_inf_look(void)

+#else

+zzfill_inf_look()

+#endif

+{

+	int tok, line;

+	int zzinf_token_buffer_size = ZZINF_DEF_TOKEN_BUFFER_SIZE;

+	int zzinf_text_buffer_size = ZZINF_DEF_TEXT_BUFFER_SIZE;

+	int zzinf_text_buffer_index = 0;

+	int zzinf_lap = 0;

+

+	/* allocate text/token buffers */

+	zzinf_text_buffer = (char *) malloc(zzinf_text_buffer_size);

+	if ( zzinf_text_buffer == NULL )

+	{

+		fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n",

+		zzinf_text_buffer_size);

+		exit(PCCTS_EXIT_FAILURE);									

+	}

+	zzinf_tokens = (int *) calloc(zzinf_token_buffer_size,sizeof(int));

+	if ( zzinf_tokens == NULL )

+	{

+		fprintf(stderr,	"cannot allocate token buffer (%d tokens)\n",

+				zzinf_token_buffer_size);

+		exit(PCCTS_EXIT_FAILURE);									

+	}

+    zzinf_line = (int *) calloc(zzinf_token_buffer_size,sizeof(int));

+    if ( zzinf_line == NULL )

+    {

+        fprintf(stderr, "cannot allocate line buffer (%d ints)\n",

+                zzinf_token_buffer_size);

+        exit(PCCTS_EXIT_FAILURE);

+	}

+

+	/* get tokens, copying text to text buffer */

+	zzinf_text_buffer_index = 0;

+	do {

+		zzgettok();

+		line = zzreal_line;

+		while ( zzinf_lap>=zzinf_token_buffer_size )

+		{

+			zzinf_token_buffer_size += ZZINF_BUFFER_TOKEN_CHUNK_SIZE;

+			zzinf_tokens = (int *) realloc(zzinf_tokens,

+												 zzinf_token_buffer_size*sizeof(int));

+			if ( zzinf_tokens == NULL )

+			{

+				fprintf(stderr, "cannot allocate lookahead token buffer (%d tokens)\n",

+						zzinf_token_buffer_size);

+				exit(PCCTS_EXIT_FAILURE);

+			}

+            zzinf_line = (int *) realloc(zzinf_line,

+                                         zzinf_token_buffer_size*sizeof(int));

+            if ( zzinf_line == NULL )

+            {

+                fprintf(stderr, "cannot allocate lookahead line buffer (%d ints)\n",

+                        zzinf_token_buffer_size);

+                exit(PCCTS_EXIT_FAILURE);

+			}

+

+		}

+		while ( (zzinf_text_buffer_index+strlen(NLATEXT)+1) >= zzinf_text_buffer_size )

+		{

+			zzinf_text_buffer_size += ZZINF_BUFFER_TEXT_CHUNK_SIZE;

+			zzinf_text_buffer = (char *) realloc(zzinf_text_buffer,

+												 zzinf_text_buffer_size);

+			if ( zzinf_text_buffer == NULL )

+			{

+				fprintf(stderr,	"cannot allocate lookahead text buffer (%d bytes)\n",

+						zzinf_text_buffer_size);

+				exit(PCCTS_EXIT_FAILURE);

+			}

+		}

+		/* record token and text and line of input symbol */

+		tok = zzinf_tokens[zzinf_lap] = NLA;

+		strcpy(&zzinf_text_buffer[zzinf_text_buffer_index], NLATEXT);

+		zzinf_text_buffer_index += strlen(NLATEXT)+1;

+        zzinf_line[zzinf_lap] = line;

+		zzinf_lap++;

+	} while (tok!=zzEOF_TOKEN);

+	zzinf_labase = 0;

+	zzinf_last = zzinf_lap-1;

+

+	/* allocate ptrs to text of ith token */

+	zzinf_text = (char **) calloc(zzinf_last+1,sizeof(char *));

+	if ( zzinf_text == NULL )

+	{

+		fprintf(stderr,	"cannot allocate lookahead text buffer (%d)\n",

+				zzinf_text_buffer_size);

+		exit(PCCTS_EXIT_FAILURE);										

+	}													

+	zzinf_text_buffer_index = 0;

+	zzinf_lap = 0;

+	/* set ptrs so that zzinf_text[i] is the text of the ith token found on input */

+	while (zzinf_lap<=zzinf_last)

+	{

+	    zzinf_text[zzinf_lap++] = &zzinf_text_buffer[zzinf_text_buffer_index];

+		zzinf_text_buffer_index += strlen(&zzinf_text_buffer[zzinf_text_buffer_index])+1;

+	}

+}

+#endif

+

+int

+#ifdef __USE_PROTOS

+_zzsetmatch(SetWordType *e, char **zzBadText, char **zzMissText,

+			int *zzMissTok, int *zzBadTok,

+			SetWordType **zzMissSet,

+			SetWordType *zzTokclassErrset /* MR23 */)

+#else

+_zzsetmatch(e, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet, zzTokclassErrset /* MR23 */)

+SetWordType *e;

+char **zzBadText;

+char **zzMissText;

+int *zzMissTok, *zzBadTok;

+SetWordType **zzMissSet;

+SetWordType *zzTokclassErrset;

+#endif

+{

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	if ( zzdirty==LL_K ) {zzCONSUME;}

+#else

+	if ( zzdirty ) {zzCONSUME;}

+#endif

+#endif

+	if ( !zzset_el((unsigned)LA(1), e) ) {

+		*zzBadText = LATEXT(1); *zzMissText=NULL;

+		*zzMissTok= 0; *zzBadTok=LA(1);

+		*zzMissSet=zzTokclassErrset; /* MR23 */

+		return 0;

+	}

+	zzMakeAttr           /* MR14 Ger Hobbelt (hobbelt@axa.nl) */

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	zzdirty++;

+    zzlabase++;          /* MR14 Ger Hobbelt (hobbelt@axa.nl) */

+#else

+	zzdirty = 1;

+#endif

+#endif

+	return 1;

+}

+

+int

+#ifdef __USE_PROTOS

+_zzmatch_wdfltsig(int tokenWanted, SetWordType *whatFollows)

+#else

+_zzmatch_wdfltsig(tokenWanted, whatFollows)

+int tokenWanted;

+SetWordType *whatFollows;

+#endif

+{

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	if ( zzdirty==LL_K ) {

+			zzCONSUME;

+	}

+#else

+	if ( zzdirty ) {zzCONSUME;}

+#endif

+#endif

+

+	if ( LA(1)!=tokenWanted )

+	{

+        zzSyntaxErrCount++;     /* MR11 */

+		fprintf(stderr,

+				"line %d: syntax error at \"%s\" missing %s\n",

+				zzline,

+				(LA(1)==zzEOF_TOKEN)?"<eof>":(char *)LATEXT(1),

+				zztokens[tokenWanted]);

+		zzconsumeUntil( whatFollows );

+		return 0;

+	}

+	else {

+		zzMakeAttr						

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+		zzdirty++;

+		zzlabase++;

+#else

+		zzdirty = 1;

+#endif

+#else

+/*		zzCONSUME;		 consume if not demand lookahead */

+#endif

+		return 1;

+	}

+}

+

+int

+#ifdef __USE_PROTOS

+_zzsetmatch_wdfltsig(SetWordType *tokensWanted,

+					 int tokenTypeOfSet,

+					 SetWordType *whatFollows)

+#else

+_zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows)

+SetWordType *tokensWanted;

+int tokenTypeOfSet;

+SetWordType *whatFollows;

+#endif

+{

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	if ( zzdirty==LL_K ) {zzCONSUME;}

+#else

+	if ( zzdirty ) {zzCONSUME;}

+#endif

+#endif

+	if ( !zzset_el((unsigned)LA(1), tokensWanted) )

+	{

+        zzSyntaxErrCount++;     /* MR11 */

+		fprintf(stderr,

+				"line %d: syntax error at \"%s\" missing %s\n",

+				zzline,

+				(LA(1)==zzEOF_TOKEN)?"<eof>":(char *)LATEXT(1),

+				zztokens[tokenTypeOfSet]);

+		zzconsumeUntil( whatFollows );

+		return 0;

+	}

+	else {

+		zzMakeAttr

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+		zzdirty++;

+		zzlabase++;

+#else

+		zzdirty = 1;

+#endif

+#else

+/*		zzCONSUME;		consume if not demand lookahead */

+#endif

+		return 1;

+	}

+}

+

+int

+#ifdef __USE_PROTOS

+_zzsetmatch_wsig(SetWordType *e)

+#else

+_zzsetmatch_wsig(e)

+SetWordType *e;

+#endif

+{

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	if ( zzdirty==LL_K ) {zzCONSUME;}

+#else

+	if ( zzdirty ) {zzCONSUME;}

+#endif

+#endif

+	if ( !zzset_el((unsigned)LA(1), e) ) return 0;

+	zzMakeAttr           /* MR14 Ger Hobbelt (hobbelt@axa.nl) */

+#ifdef DEMAND_LOOK

+#ifdef LL_K

+	zzdirty++;

+    zzlabase++;          /* MR14 Ger Hobbelt (hobbelt@axa.nl) */

+#else

+	zzdirty = 1;

+#endif

+#endif

+	return 1;

+}

+

+#ifdef USER_ZZMODE_STACK

+static int  zzmstk[ZZMAXSTK] = { -1 };

+static int  zzmdep = 0;

+static char zzmbuf[70];

+

+void

+#ifdef __USE_PROTOS

+zzmpush( int m )

+#else

+zzmpush( m )

+int m;

+#endif

+{

+   if(zzmdep == ZZMAXSTK - 1) {

+     sprintf(zzmbuf, "Mode stack overflow ");

+     zzerr(zzmbuf);

+   } else {

+     zzmstk[zzmdep++] = zzauto;

+     zzmode(m);

+   }

+}

+

+void

+#ifdef __USE_PROTOS

+zzmpop( void )

+#else

+zzmpop( )

+#endif

+{

+   if(zzmdep == 0)

+   {  sprintf(zzmbuf, "Mode stack underflow ");

+      zzerr(zzmbuf);

+   }

+   else

+   {  zzmdep--;

+      zzmode(zzmstk[zzmdep]);

+   }

+}

+

+void

+#ifdef __USE_PROTOS

+zzsave_mode_stack( int modeStack[], int *modeLevel )

+#else

+zzsave_mode_stack( modeStack, modeLevel )

+int modeStack[];

+int *modeLevel;

+#endif

+{

+  int i;

+  memcpy(modeStack, zzmstk, sizeof(zzmstk));

+  *modeLevel = zzmdep;

+  zzmdep = 0;

+

+  return;

+}

+

+void

+#ifdef __USE_PROTOS

+zzrestore_mode_stack( int modeStack[], int *modeLevel )

+#else

+zzrestore_mode_stack( modeStack, modeLevel )

+int modeStack[];

+int *modeLevel;

+#endif

+{

+  int i;

+

+  memcpy(zzmstk, modeStack, sizeof(zzmstk));

+  zzmdep = *modeLevel;

+

+  return;

+}

+#endif /* USER_ZZMODE_STACK */

+

+#ifdef __USE_PROTOS

+void zzTraceReset(void)

+#else

+void zzTraceReset()

+#endif

+{

+#ifdef zzTRACE_RULES

+  zzTraceOptionValue=zzTraceOptionValueDefault;

+  zzTraceGuessOptionValue=1;

+  zzTraceCurrentRuleName=NULL;

+  zzTraceDepth=0;

+#endif

+}

+

+#ifdef __USE_PROTOS

+void zzTraceGuessFail(void)

+#else

+void zzTraceGuessFail()

+#endif

+{

+

+#ifdef zzTRACE_RULES

+#ifdef ZZCAN_GUESS

+

+  int   doIt=0;

+

+  if (zzTraceOptionValue <= 0) {

+    doIt=0;

+  } else if (zzguessing && zzTraceGuessOptionValue <= 0) {

+    doIt=0;

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    fprintf(stderr,"guess failed\n");

+  };

+#endif

+#endif

+}

+

+/* zzTraceOption:

+     zero value turns off trace

+*/

+

+#ifdef __USE_PROTOS

+void zzTraceIn(char * rule)

+#else

+void zzTraceIn(rule)

+  char  *rule;

+#endif

+{

+#ifdef zzTRACE_RULES

+

+  int           doIt=0;

+

+  zzTraceDepth++;

+  zzTraceCurrentRuleName=rule;

+

+  if (zzTraceOptionValue <= 0) {

+    doIt=0;

+#ifdef ZZCAN_GUESS

+  } else if (zzguessing && zzTraceGuessOptionValue <= 0) {

+    doIt=0;

+#endif

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    fprintf(stderr,"enter rule %s {\"%s\"} depth %d",

+            rule,

+            LA(1)==1 ? "@" : (char *) LATEXT(1),    /* MR19 */

+            zzTraceDepth);

+#ifdef ZZCAN_GUESS

+    if (zzguessing) fprintf(stderr," guessing");

+#endif

+    fprintf(stderr,"\n");

+  };

+#endif

+  return;

+}

+

+#ifdef __USE_PROTOS

+void zzTraceOut(char * rule)

+#else

+void zzTraceOut(rule)

+  char  *rule;

+#endif

+{

+#ifdef zzTRACE_RULES

+  int       doIt=0;

+

+  zzTraceDepth--;

+

+  if (zzTraceOptionValue <= 0) {

+    doIt=0;

+#ifdef ZZCAN_GUESS

+  } else if (zzguessing && zzTraceGuessOptionValue <= 0) {

+    doIt=0;

+#endif

+  } else {

+    doIt=1;

+  };

+

+  if (doIt) {

+    fprintf(stderr,"exit rule %s {\"%s\"} depth %d",

+            rule,

+            LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */

+            zzTraceDepth+1);

+#ifdef ZZCAN_GUESS

+    if (zzguessing) fprintf(stderr," guessing");

+#endif

+    fprintf(stderr,"\n");

+  };

+#endif

+}

+

+#ifdef __USE_PROTOS

+int zzTraceOption(int delta)

+#else

+int zzTraceOption(delta)

+  int   delta;

+#endif

+{

+#ifdef zzTRACE_RULES

+    int     prevValue=zzTraceOptionValue;

+

+    zzTraceOptionValue=zzTraceOptionValue+delta;

+

+    if (zzTraceCurrentRuleName != NULL) {

+      if (prevValue <= 0 && zzTraceOptionValue > 0) {

+        fprintf(stderr,"trace enabled in rule %s depth %d\n",

+                                            zzTraceCurrentRuleName,zzTraceDepth);

+      };

+      if (prevValue > 0 && zzTraceOptionValue <= 0) {

+        fprintf(stderr,"trace disabled in rule %s depth %d\n",

+                                            zzTraceCurrentRuleName,zzTraceDepth);

+      };

+    };

+    return  prevValue;

+#else

+    return 0;

+#endif

+}

+

+#ifdef __USE_PROTOS

+int zzTraceGuessOption(int delta)

+#else

+int zzTraceGuessOption(delta)

+  int   delta;

+#endif

+{

+#ifdef zzTRACE_RULES

+#ifdef ZZCAN_GUESS

+    int     prevValue=zzTraceGuessOptionValue;

+

+    zzTraceGuessOptionValue=zzTraceGuessOptionValue+delta;

+

+    if (zzTraceCurrentRuleName != NULL) {

+      if (prevValue <= 0 && zzTraceGuessOptionValue > 0) {

+        fprintf(stderr,"guess trace enabled in rule %s depth %d\n",

+                                                zzTraceCurrentRuleName,zzTraceDepth);

+      };

+      if (prevValue > 0 && zzTraceGuessOptionValue <= 0) {

+        fprintf(stderr,"guess trace disabled in rule %s depth %d\n",

+                                                zzTraceCurrentRuleName,zzTraceDepth);

+      };

+    };

+    return prevValue;

+#else

+    return 0;

+#endif

+#else

+    return 0;

+#endif

+}

+

+#endif /* ERR_H */

diff --git a/Source/Pccts/h/int.h b/Source/Pccts/h/int.h
new file mode 100644
index 0000000..cdcaa92
--- /dev/null
+++ b/Source/Pccts/h/int.h
@@ -0,0 +1,37 @@
+/* ANTLR attribute definition -- long integers

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * ANTLR 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+#ifndef ZZINT_H

+#define ZZINT_H

+

+typedef long Attrib;

+

+#define zzcr_attr(a,tok,t)	*(a) = atol(t);

+

+#endif

diff --git a/Source/Pccts/h/pccts_assert.h b/Source/Pccts/h/pccts_assert.h
new file mode 100644
index 0000000..ff0dfb5
--- /dev/null
+++ b/Source/Pccts/h/pccts_assert.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_ASSERT_H__

+#define __PCCTS_ASSERT_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <cassert>

+#else

+#include <assert.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_iostream.h b/Source/Pccts/h/pccts_iostream.h
new file mode 100644
index 0000000..972b32c
--- /dev/null
+++ b/Source/Pccts/h/pccts_iostream.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_IOSTREAM_H__

+#define __PCCTS_IOSTREAM_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <iostream>

+#else

+#include <iostream.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_istream.h b/Source/Pccts/h/pccts_istream.h
new file mode 100644
index 0000000..e25cb8c
--- /dev/null
+++ b/Source/Pccts/h/pccts_istream.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_ISTREAM_H__

+#define __PCCTS_ISTREAM_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <istream>

+#else

+#include <istream.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_setjmp.h b/Source/Pccts/h/pccts_setjmp.h
new file mode 100644
index 0000000..9ea185c
--- /dev/null
+++ b/Source/Pccts/h/pccts_setjmp.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_SETJMP_H__

+#define __PCCTS_SETJMP_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <csetjmp>

+#else

+#include <setjmp.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_stdarg.h b/Source/Pccts/h/pccts_stdarg.h
new file mode 100644
index 0000000..e957430
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdarg.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDARG_H__

+#define __PCCTS_STDARG_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <cstdarg>

+#else

+#include <stdarg.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_stdio.h b/Source/Pccts/h/pccts_stdio.h
new file mode 100644
index 0000000..ac34d10
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdio.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDIO_H__

+#define __PCCTS_STDIO_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <cstdio>

+#else

+#include <stdio.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_stdlib.h b/Source/Pccts/h/pccts_stdlib.h
new file mode 100644
index 0000000..f0b344e
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdlib.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDLIB_H__

+#define __PCCTS_STDLIB_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <cstdlib>

+#else

+#include <stdlib.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pccts_string.h b/Source/Pccts/h/pccts_string.h
new file mode 100644
index 0000000..458a08a
--- /dev/null
+++ b/Source/Pccts/h/pccts_string.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STRING_H__

+#define __PCCTS_STRING_H__

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#include <cstring>

+#else

+#include <string.h>

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pcctscfg.h b/Source/Pccts/h/pcctscfg.h
new file mode 100644
index 0000000..0c3c5ba
--- /dev/null
+++ b/Source/Pccts/h/pcctscfg.h
@@ -0,0 +1,359 @@
+#ifndef PCCTS_CONFIG_H

+#define PCCTS_CONFIG_H

+/*

+ * pcctscfg.h (formerly config.h) (for ANTLR, DLG, and SORCERER)

+ *

+ * This is a simple configuration file that doesn't have config stuff

+ * in it, but it's a start.

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool

+ * Set (PCCTS) -- PCCTS is in the public domain.  An individual or

+ * company may do whatever they wish with source code distributed with

+ * PCCTS or the code generated by PCCTS, including the incorporation of

+ * PCCTS, or its output, into commerical software.

+ *

+ * We encourage users to develop software with PCCTS.  However, we do ask

+ * that credit is given to us for developing PCCTS.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like PCCTS and have developed a nice tool with the

+ * output, please mention that you developed it using PCCTS.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * Used by PCCTS 1.33 (SORCERER 1.00B11 and up)

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1989-2000

+ */

+

+/* This file knows about the following ``environments''

+	UNIX    (default)

+	DOS     (use #define PC)

+	MAC     (use #define MPW; has a few things for THINK C, Metrowerks)

+    MS/C++  (MR14 Microsoft Visual C++ environment uses symbol _MSC_VER)

+

+ */

+

+/* should test __STDC__ for 1, but some compilers don't set value, just def */

+

+#ifndef __USE_PROTOS

+#ifdef __STDC__

+#define __USE_PROTOS

+#endif

+#ifdef __cplusplus

+#define __USE_PROTOS

+#endif

+#endif

+

+#ifdef PCCTS_USE_NAMESPACE_STD

+#define PCCTS_NAMESPACE_STD     namespace std {}; using namespace std;

+#else

+#define PCCTS_NAMESPACE_STD

+#endif

+

+#include "pccts_stdio.h"

+#include "pccts_stdlib.h"

+

+/* largest file name size */

+

+#ifdef _MAX_PATH

+#define MaxFileName		_MAX_PATH /* MR9 RJV: MAX_PATH defined in stdlib.h (MSVC++ 5.0) */

+#else

+#define MaxFileName		300

+#endif

+

+/*

+*  Define PC32 if in a 32-bit PC environment (e.g. extended DOS or Win32).

+*  The macros tested here are defined by Watcom, Microsoft, Borland,

+*  and djgpp, respectively, when they are used as 32-bit compilers.

+*  Users of these compilers *must* be sure to define PC in their

+*  makefiles for this to work correctly.

+*/

+#ifdef PC

+# if (defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__) || \

+   defined(__GNUC__) || defined(__GNUG__))

+#     ifndef PC32

+#        define PC32

+#     endif

+#  endif

+#endif

+

+/* MR1  10-Apr-97  Default for PC is short file names			            */

+/* MR1		   Default for non-PC is long file names                		*/

+/* MR1		   Can override via command line option LONGFILENAMES           */

+

+#ifndef LONGFILENAMES

+#ifndef PC

+#define LONGFILENAMES

+#endif

+#endif

+

+#ifndef LONGFILENAMES

+#define ATOKEN_H			"AToken.h"

+#define ATOKPTR_H			"ATokPtr.h"

+#define ATOKPTR_IMPL_H		"ATokPtrIm.h"

+#define ATOKENBUFFER_H		"ATokBuf.h"

+#define ATOKENBUFFER_C      "ATokBuf.cpp"

+#define ATOKENSTREAM_H		"ATokStr.h"

+#define APARSER_H			"AParser.h"

+#define APARSER_C           "AParser.cpp"

+#define ASTBASE_H			"ASTBase.h"

+#define ASTBASE_C           "ASTBase.cpp"

+#define PCCTSAST_C          "PCCTSAST.cpp"

+#define LIST_C              "List.cpp"

+#define DLEXERBASE_H		"DLexBase.h"

+#define DLEXERBASE_C        "DLexBase.cpp"

+#define DLEXER_H            "DLexer.h"

+#define STREESUPPORT_C		"STreeSup.C"

+#else

+#define ATOKEN_H			"AToken.h"

+#define ATOKPTR_H			"ATokPtr.h"

+#define ATOKPTR_IMPL_H		"ATokPtrImpl.h"

+#define ATOKENBUFFER_H		"ATokenBuffer.h"

+#define ATOKENBUFFER_C		"ATokenBuffer.cpp"

+#define ATOKENSTREAM_H		"ATokenStream.h"

+#define APARSER_H			"AParser.h"

+#define APARSER_C			"AParser.cpp"

+#define ASTBASE_H			"ASTBase.h"

+#define ASTBASE_C		    "ASTBase.cpp"

+#define PCCTSAST_C			"PCCTSAST.cpp"

+#define LIST_C				"List.cpp"

+#define DLEXERBASE_H		"DLexerBase.h"

+#define DLEXERBASE_C		"DLexerBase.cpp"

+#define DLEXER_H			"DLexer.h"

+#define STREESUPPORT_C		"STreeSupport.cpp"

+#endif

+

+/* SORCERER Stuff */

+

+/* MR8 6-Aug-97     Change from ifdef PC to ifndef LONGFILENAMES            */

+

+#ifndef LONGFILENAMES

+#define STPARSER_H			"STreePar.h"

+#define STPARSER_C			"STreePar.C"

+#else

+#define STPARSER_H			"STreeParser.h"

+#define STPARSER_C			"STreeParser.cpp"

+#endif

+

+#ifdef MPW

+#define CPP_FILE_SUFFIX		".cp"

+#define CPP_FILE_SUFFIX_NO_DOT	"cp"

+#define OBJ_FILE_SUFFIX		".o"

+#else

+#ifdef PC

+#define CPP_FILE_SUFFIX		".cpp"

+#define CPP_FILE_SUFFIX_NO_DOT	"cpp"

+#define OBJ_FILE_SUFFIX		".obj"

+#else

+#ifdef __VMS

+#define CPP_FILE_SUFFIX		".cpp"

+#define CPP_FILE_SUFFIX_NO_DOT	"cpp"

+#define OBJ_FILE_SUFFIX		".obj"

+#else

+#define CPP_FILE_SUFFIX		".cpp"

+#define CPP_FILE_SUFFIX_NO_DOT	"cpp"

+#define OBJ_FILE_SUFFIX		".o"

+#endif

+#endif

+#endif

+

+/* User may redefine how line information looks */     /* make it #line MR7 */

+/* MR21 Use #ifndef */

+

+#ifndef LineInfoFormatStr

+#define LineInfoFormatStr "#line %d \"%s\"\n"

+#endif

+

+#ifdef MPW	                    /* Macintosh Programmer's Workshop */

+#define ErrHdr "File \"%s\"; Line %d #"

+#else

+#ifdef _MSC_VER                 /* MR14 Microsoft Visual C++ environment */

+#define ErrHdr "%s(%d) :"

+#else

+#define ErrHdr "%s, line %d:"   /* default */

+#endif

+#endif

+

+/* must assume old K&R cpp here, can't use #if defined(..)... */

+

+#ifdef MPW

+#define TopDirectory	":"

+#define DirectorySymbol	":"

+#define OutputDirectoryOption "Directory where all output files should go (default=\":\")"

+#else

+#ifdef PC

+#define TopDirectory	"."

+#define DirectorySymbol	"\\"

+#define OutputDirectoryOption "Directory where all output files should go (default=\".\")"

+#else

+#ifdef __VMS

+#define TopDirectory  "[000000]"

+#define DirectorySymbol       "]"

+#define OutputDirectoryOption "Directory where all output files should go (default=\"[]\")"

+#else

+#define TopDirectory	"."

+#define DirectorySymbol	"/"

+#define OutputDirectoryOption "Directory where all output files should go (default=\".\")"

+#endif

+#endif

+#endif

+

+#ifdef MPW

+

+/* Make sure we have prototypes for all functions under MPW */

+

+#include "pccts_string.h"

+#include "pccts_stdlib.h"

+

+/* MR6 2-Jun-97	Fixes false dependency caused by VC++ #include scanner	*/

+/* MR6		   Reported by Brad Schick (schick@interaccess.com)	*/

+#define	MPW_CursorCtl_Header <CursorCtl.h>

+#include MPW_CursorCtl_Header

+#ifdef __cplusplus

+extern "C" {

+#endif

+extern void fsetfileinfo (const char *filename, unsigned long newcreator, unsigned long newtype);

+#ifdef __cplusplus

+}

+#endif

+

+/* File creators for various popular development environments */

+

+#define MAC_FILE_CREATOR 'MPS '   /* MPW Text files */

+#if 0

+#define MAC_FILE_CREATOR 'KAHL'   /* THINK C/Symantec C++ Text files */

+#endif

+#if 0

+#define MAC_FILE_CREATOR 'CWIE'   /* Metrowerks C/C++ Text files */

+#endif

+

+#endif

+

+#ifdef MPW

+#define DAWDLE	SpinCursor(1)

+#else

+#define DAWDLE

+#endif

+

+#ifdef MPW

+#define SPECIAL_INITS

+#define SPECIAL_FOPEN

+#endif

+

+#ifdef MPW

+#ifdef __cplusplus

+inline

+#else

+static

+#endif

+void special_inits()

+{

+  InitCursorCtl((acurHandle) 0);

+}

+#endif

+

+#ifdef MPW

+#ifdef __cplusplus

+inline

+#else

+static

+#endif

+void special_fopen_actions(char * s)

+{

+  fsetfileinfo (s, MAC_FILE_CREATOR, 'TEXT');

+}

+#endif

+

+/* Define usable bits for set.c stuff */

+#define BytesPerWord	sizeof(unsigned)

+#define	WORDSIZE		(sizeof(unsigned)*8)

+#define LogWordSize     (WORDSIZE==16?4:5)

+

+#ifndef TRUE

+#define TRUE 1

+#endif

+#ifndef FALSE

+#define FALSE 0

+#endif

+

+#if defined(VAXC) || defined(__VMS)

+#include <ssdef.h>

+#define PCCTS_EXIT_SUCCESS 1

+#define PCCTS_EXIT_FAILURE SS$_ABORT

+#define zzDIE		return SS$_ABORT;

+#define zzDONE	return 1;

+

+#else /* !VAXC and !__VMS */

+

+#define PCCTS_EXIT_SUCCESS 0

+#define PCCTS_EXIT_FAILURE 1

+#define zzDIE		return 1;

+#define zzDONE	return 0;

+

+#endif

+

+#ifdef USER_ZZMODE_STACK

+# ifndef ZZSTACK_MAX_MODE

+#  define  ZZSTACK_MAX_MODE 32

+# endif

+# define  ZZMAXSTK (ZZSTACK_MAX_MODE * 2)

+#endif

+

+#ifndef DllExportPCCTS

+#define DllExportPCCTS

+#endif

+

+#ifdef PC

+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME

+#define PCCTS_CASE_INSENSITIVE_FILE_NAME

+#endif

+#endif

+

+#ifdef PC32

+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME

+#define PCCTS_CASE_INSENSITIVE_FILE_NAME

+#endif

+#endif

+

+#ifdef __VMS

+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME

+#define PCCTS_CASE_INSENSITIVE_FILE_NAME

+#endif

+#endif

+

+#ifdef __USE_PROTOS

+#ifndef PCCTS_USE_STDARG

+#define PCCTS_USE_STDARG

+#endif

+#endif

+

+#ifdef __STDC__

+#ifndef PCCTS_USE_STDARG

+#define PCCTS_USE_STDARG

+#endif

+#endif

+

+#ifdef __cplusplus

+#ifndef PCCTS_USE_STDARG

+#define PCCTS_USE_STDARG

+#endif

+#endif

+

+#ifdef _MSC_VER

+/*Turn off the warnings for:

+  unreferenced inline/local function has been removed

+*/

+#pragma warning(disable : 4514)

+/* function not expanded */

+#pragma warning(disable : 4710)

+#endif

+

+#endif

diff --git a/Source/Pccts/h/pcnames.bat b/Source/Pccts/h/pcnames.bat
new file mode 100644
index 0000000..8784aee
--- /dev/null
+++ b/Source/Pccts/h/pcnames.bat
@@ -0,0 +1,11 @@
+ren aparser.c aparser.cpp

+ren astbase.c astbase.cpp

+ren atokenbu.c atokbuf.cpp

+ren atokenbu.h atokbuf.h

+ren atokenst.h atokstr.h

+ren dlexerba.c dlexbase.cpp

+ren dlexerba.h dlexbase.h

+ren dlexer.c dlexer.cpp

+ren list.c list.cpp

+ren pblackbo.h pblckbox.h

+ren pcctsast.c pcctsast.cpp

diff --git a/Source/Pccts/h/slist.cpp b/Source/Pccts/h/slist.cpp
new file mode 100644
index 0000000..faf2fe4
--- /dev/null
+++ b/Source/Pccts/h/slist.cpp
@@ -0,0 +1,116 @@
+/*

+ * SList.C

+ *

+ * SOFTWARE RIGHTS

+ *

+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public

+ * domain.  An individual or company may do whatever they wish with

+ * source code distributed with SORCERER or the code generated by

+ * SORCERER, including the incorporation of SORCERER, or its output, into

+ * commerical software.

+ *

+ * We encourage users to develop software with SORCERER.  However, we do

+ * ask that credit is given to us for developing SORCERER.  By "credit",

+ * we mean that if you incorporate our source code into one of your

+ * programs (commercial product, research project, or otherwise) that you

+ * acknowledge this fact somewhere in the documentation, research report,

+ * etc...  If you like SORCERER and have developed a nice tool with the

+ * output, please mention that you developed it using SORCERER.  In

+ * addition, we ask that this header remain intact in our source code.

+ * As long as these guidelines are kept, we expect to continue enhancing

+ * this system and expect to make other tools available as they are

+ * completed.

+ *

+ * PCCTS 1.33

+ * Terence Parr

+ * Parr Research Corporation

+ * with Purdue University and AHPCRC, University of Minnesota

+ * 1992-2000

+ */

+

+#define ANTLR_SUPPORT_CODE

+

+#include "SList.h"

+#include "pccts_stdarg.h" // MR23

+

+/* Iterate over a list of elements; returns ptr to a new element

+ * in list upon every call and NULL when no more are left.

+ * Very useful like this:

+ *

+ *		cursor = mylist;

+ *		while ( (p=mylist->iterate(&cursor)) ) {

+ *			// place with element p

+ *		}

+ *

+ * The cursor must be initialized to point to the list to iterate over.

+ */

+void *SList::

+iterate(SListNode **cursor)

+{

+	void *e;

+

+	if ( cursor == NULL || *cursor==NULL ) return NULL;

+	if ( head == *cursor ) { *cursor = (*cursor)->next(); }

+	e = (*cursor)->elem();

+	(*cursor) = (*cursor)->next();

+	return e;

+}

+

+/* add an element to end of list. */

+void SList::

+add(void *e)

+{

+	SListNode *p, *tail=NULL;

+	require(e!=NULL, "slist_add: attempting to add NULL list element");

+

+	p = new SListNode;

+	require(p!=NULL, "add: cannot alloc new list node");

+	p->setElem(e);

+	if ( head == NULL )

+	{

+		head = tail = p;

+	}

+	else								/* find end of list */

+	{

+		tail->setNext(p);

+		tail = p;

+	}

+}

+

+void SList::

+lfree()

+{

+	SListNode *p,*q;

+

+	if ( head==NULL ) return;	/* empty list */

+	for (p = head; p!=NULL; p=q)

+	{

+		q = p->next();

+		free(p);

+	}

+}

+

+PCCTS_AST *SList::

+to_ast(SList list)

+{

+	PCCTS_AST *t=NULL, *last=NULL;

+	SListNode *p;

+

+	for (p = head; p!=NULL; p=p->next())

+	{

+		PCCTS_AST *u = (PCCTS_AST *)p->elem();

+		if ( last==NULL ) last = t = u;

+		else { last->setRight(u); last = u; }

+	}

+	return t;

+}

+

+// MR23

+int SList::printMessage(FILE* pFile, const char* pFormat, ...)

+{

+	va_list marker;

+	va_start( marker, pFormat );

+  	int iRet = vfprintf(pFile, pFormat, marker);

+	va_end( marker );

+	return iRet;

+}

diff --git a/Source/Pccts/history.ps b/Source/Pccts/history.ps
new file mode 100644
index 0000000..e2600d5
--- /dev/null
+++ b/Source/Pccts/history.ps
@@ -0,0 +1,473 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.06
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Italic
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.06 0
+%%Pages: 3
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.06 0
+
+/setpacking where {
+	pop
+	currentpacking
+	true setpacking
+} if
+
+/grops 120 dict dup begin 
+
+% The ASCII code of the space character.
+/SC 32 def
+
+/A /show load def
+/B { 0 SC 3 -1 roll widthshow } bind def
+/C { 0 exch ashow } bind def
+/D { 0 exch 0 SC 5 2 roll awidthshow } bind def
+/E { 0 rmoveto show } bind def
+/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def
+/G { 0 rmoveto 0 exch ashow } bind def
+/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/I { 0 exch rmoveto show } bind def
+/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def
+/K { 0 exch rmoveto 0 exch ashow } bind def
+/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/M { rmoveto show } bind def
+/N { rmoveto 0 SC 3 -1 roll widthshow } bind def
+/O { rmoveto 0 exch ashow } bind def
+/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/Q { moveto show } bind def 
+/R { moveto 0 SC 3 -1 roll widthshow } bind def
+/S { moveto 0 exch ashow } bind def
+/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+
+% name size font SF -
+
+/SF {
+	findfont exch
+	[ exch dup 0 exch 0 exch neg 0 0 ] makefont
+	dup setfont
+	[ exch /setfont cvx ] cvx bind def
+} bind def
+
+% name a c d font MF -
+
+/MF {
+	findfont
+	[ 5 2 roll
+	0 3 1 roll % b
+	neg 0 0 ] makefont
+	dup setfont
+	[ exch /setfont cvx ] cvx bind def
+} bind def
+
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+
+% Guess the page length.
+% This assumes that the imageable area is vertically centered on the page.
+% PLG - length
+
+/PLG {
+	gsave newpath clippath pathbbox grestore
+	exch pop add exch pop
+} bind def
+
+% BP -
+
+/BP {
+	/level0 save def
+	1 setlinecap
+	1 setlinejoin
+	72 RES div dup scale
+	LS {
+		90 rotate
+	} {
+		0 PL translate
+	} ifelse
+	1 -1 scale
+} bind def
+
+/EP {
+	level0 restore
+	showpage
+} bind def
+
+
+% centerx centery radius startangle endangle DA -
+
+/DA {
+	newpath arcn stroke
+} bind def
+
+% x y SN - x' y'
+% round a position to nearest (pixel + (.25,.25))
+
+/SN {
+	transform 
+	.25 sub exch .25 sub exch
+	round .25 add exch round .25 add exch
+	itransform
+} bind def
+	
+% endx endy startx starty DL -
+% we round the endpoints of the line, so that parallel horizontal
+% and vertical lines will appear even
+
+/DL {
+	SN
+	moveto
+	SN
+	lineto stroke
+} bind def
+
+% centerx centery radius DC -
+
+/DC {
+	newpath 0 360 arc closepath
+} bind def
+
+
+/TM matrix def
+
+%  width height centerx centery DE -
+
+/DE {
+	TM currentmatrix pop
+	translate scale newpath 0 0 .5 0 360 arc closepath
+	TM setmatrix
+} bind def
+
+% these are for splines
+
+/RC /rcurveto load def
+/RL /rlineto load def
+/ST /stroke load def
+/MT /moveto load def
+/CL /closepath load def
+
+% fill the last path
+
+% amount FL -
+
+/FL {
+	currentgray exch setgray fill setgray
+} bind def
+
+% fill with the ``current color''
+
+/BL /fill load def
+
+/LW /setlinewidth load def
+% new_font_name encoding_vector old_font_name RE -
+
+/RE {
+	findfont
+	dup maxlength dict begin
+	{
+		1 index /FID ne { def } { pop pop } ifelse
+	} forall
+	/Encoding exch def
+	dup /FontName exch def
+	currentdict end definefont pop
+} bind def
+
+/DEFS 0 def
+
+% hpos vpos EBEGIN -
+
+/EBEGIN {
+	moveto
+	DEFS begin
+} bind def
+
+/EEND /end load def
+
+/CNT 0 def
+/level1 0 def
+
+% llx lly newwid wid newht ht newllx newlly PBEGIN -
+
+/PBEGIN {
+	/level1 save def
+	translate
+	div 3 1 roll div exch scale
+	neg exch neg exch translate
+	% set the graphics state to default values
+	0 setgray
+	0 setlinecap
+	1 setlinewidth
+	0 setlinejoin
+	10 setmiterlimit
+	[] 0 setdash
+	/setstrokeadjust where {
+		pop
+		false setstrokeadjust
+	} if
+	/setoverprint where {
+		pop
+		false setoverprint
+	} if
+	newpath
+	/CNT countdictstack def
+	userdict begin
+	/showpage {} def
+} bind def
+
+/PEND {
+	clear
+	countdictstack CNT sub { end } repeat
+	level1 restore
+} bind def
+
+end def
+
+/setpacking where {
+	pop
+	setpacking
+} if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Italic@0
+ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 13/Times-Roman@0 SF(The History of PCCTS)228.232 84 Q/F1 11/Times-Roman@0
+SF(The Purdue Compiler)190.468 108 Q(-Construction T)-.22 E(ool Set)-.88 E/F2
+10/Times-Italic@0 SF -.92(Te)262.245 144 S -.37(re).92 G(nce P).37 E(arr)-.8 E
+/F3 10/Times-Roman@0 SF -.15(Pa)234.755 156 S(rr Research Corporation).15 E
+(Minneapolis, Minnesota)239.39 168 Q(and)280.78 180 Q(Uni)239.315 192 Q -.15
+(ve)-.25 G(rsity of Minnesota).15 E
+(Army High Performance Computing Research Center)180.38 204 Q F2
+([Updated 8-7-94])252.31 228 Q F1 .084(The PCCTS project be)97 259.6 R -.055
+(ga)-.165 G 2.834(na).055 G 2.833(sap)220.547 259.6 S(arser)240.876 259.6 Q
+.083(-generator project for a graduate course at Purdue Uni-)-.22 F -.165(ve)72
+275.6 S 1.085(rsity in the F).165 F 1.086
+(all of 1988 taught by Hank Dietz\212 translator)-.165 F 1.086
+(-writing systems.)-.22 F 1.086(Under the guid-)6.586 F .627
+(ance of Professor Dietz, the parser generator)72 291.6 R 3.377(,A)-.44 G .626
+(NTLR \(originally called YUCC\), continued after)285.18 291.6 R .253
+(the termination of the course and e)72 307.6 R -.165(ve)-.275 G .254
+(ntually became the subject of T).165 F .254(erence P)-.77 F(arr')-.165 E 3.004
+(sM)-.605 G(aster')445.083 307.6 Q 3.004(st)-.605 G(hesis.)479.25 307.6 Q
+(Originally)72 323.6 Q 4.092(,l)-.715 G -.165(ex)126.406 323.6 S 1.342
+(ical analysis w).165 F 1.342(as performed via ALX which w)-.11 F 1.342
+(as soon replaced by W)-.11 F 1.341(ill Cohen')-.44 F(s)-.605 E .594
+(DLG in the F)72 339.6 R .594(all of 1989 \(DF)-.165 F .595(A-based le)-.814 F
+.595(xical-analyzer generator)-.165 F 3.345(,a)-.44 G .595(lso an of)367.188
+339.6 R .595(fshoot of the graduate)-.275 F(translation course\).)72 355.6 Q
+.877(The alpha v)97 375.2 R .877(ersion of ANTLR w)-.165 F .877(as totally re)
+-.11 F .876(written resulting in 1.00B.)-.275 F -1.221(Ve)6.376 G .876
+(rsion 1.00B w)1.221 F(as)-.11 E 1.577(released via an internet ne)72 391.2 R
+1.577(wsgroup \(comp.compilers\) posting in February of 1990 and quickly)-.275
+F -.055(ga)72 407.2 S .356(thered a lar).055 F .356(ge follo)-.198 F 3.106
+(wing. 1.00B)-.275 F .356(generated only LL\(1\) parsers, b)3.106 F .356
+(ut allo)-.22 F .356(wed the mer)-.275 F .356(ged descrip-)-.198 F 1.859
+(tion of le)72 423.2 R 1.859(xical and syntactic analysis.)-.165 F 1.86
+(It had rudimentary attrib)7.359 F 1.86(ute handling similar to that of)-.22 F
+-.55 -1.32(YA C)72 439.2 T 3.549(Ca)1.32 G .799
+(nd did not incorporate rule parameters or return v)109.231 439.2 R .798
+(alues; do)-.275 F(wnw)-.275 E .798(ard inheritance w)-.11 F .798(as v)-.11 F
+(ery)-.165 E -.165(aw)72 455.2 S(kw).165 E 6.433(ard. 1.00B-generated)-.11 F
+3.684(parsers terminated upon the \214rst syntax error)6.433 F 9.184(.L)-.605 G
+-.165(ex)440.916 455.2 S 3.684(ical classes).165 F(\(modes\) were not allo)72
+471.2 Q(wed and DLG did not ha)-.275 E .33 -.165(ve a)-.22 H 2.75(ni).165 G
+(nteracti)305.959 471.2 Q .33 -.165(ve m)-.275 H(ode.).165 E .831
+(Upon starting his Ph.D. at Purdue in the F)97 490.8 R .83(all of 1990, T)-.165
+F .83(erence P)-.77 F .83(arr be)-.165 F -.055(ga)-.165 G 3.58(nt).055 G .83
+(he second total)436.351 490.8 R(re)72 506.8 Q 1.646(write of ANTLR.)-.275 F
+1.646(The method by which grammars may be practically analyzed to generate)
+7.146 F/F4 11/Times-Italic@0 SF(LL)72.638 522.8 Q F1(\().583 E F4(k).396 E F1
+3.849(\)l).737 G 1.099(ookahead information w)105.703 522.8 R 1.099(as disco)
+-.11 F -.165(ve)-.165 G 1.099(red in August of 1990 just before his return.)
+.165 F -1.221(Ve)6.598 G(rsion)1.221 E .626
+(1.00 incorporated this algorithm and included the AST mechanism, le)72 538.8 R
+.626(xical classes, error classes,)-.165 F .354(and automatic error reco)72
+554.8 R -.165(ve)-.165 G .353(ry; code quality and portability were higher).165
+F 5.853(.I)-.605 G 3.103(nF)395.965 554.8 S .353(ebruary of 1992 1.00)410.684
+554.8 R -.11(wa)72 570.8 S 2.76(sr).11 G .01
+(eleased via an article in SIGPLAN Notices.)95.418 570.8 R .01
+(Peter Dahl, Ph.D. candidate, and Professor Matt)5.51 F(O'K)72 586.8 Q 2.074
+(eefe \(both at the Uni)-.275 F -.165(ve)-.275 G 2.073
+(rsity of Minnesota\) tested this v).165 F 2.073(ersion e)-.165 F(xtensi)-.165
+E -.165(ve)-.275 G(ly).165 E 7.573(.D)-.715 G 2.073(ana Hogg)448.522 586.8 R
+(att)-.055 E .078(\(Micro Data Base Systems, Inc.\) came up with the idea of e\
+rror grouping \(strings attached to non-)72 602.8 R
+(terminals\) and tested 1.00 hea)72 618.8 Q(vily)-.22 E(.)-.715 E -1.221(Ve)97
+638.4 S .878(rsion 1.06 w)1.221 F .877
+(as released in December 1992 and represented a lar)-.11 F .877
+(ge feature enhancement)-.198 F -.165(ove)72 654.4 S 3.648(r1).165 G 3.648
+(.00. F)100.365 654.4 R .898(or e)-.165 F .899
+(xample, rudimentary semantic predicates were introduced, error messages were)
+-.165 F 2.281(signi\214cantly impro)72 670.4 R -.165(ve)-.165 G 5.031(df).165 G
+(or)181.953 670.4 Q F4(k)5.427 E F1 2.281
+(>1 lookahead and ANTLR parsers could indicate that lookahead).737 F 1.381
+(fetches were to occur only when necessary for the parse \(normally)72 686.4 R
+4.131(,t)-.715 G 1.381(he lookahead `)387.051 686.4 R(`pipe')-.814 E 4.132('w)
+-.814 G(as)494.837 686.4 Q 1.182(constantly full\).)72 702.4 R 1.182
+(Russell Quong joined the project in the Spring of 1992 to aid in the semantic)
+6.682 F .681(predicate design.)72 718.4 R(Be)6.181 E .681(ginning and adv)-.165
+F .682(anced tutorials were created and released as well.)-.275 F 3.432(Am)
+6.182 G(ak)485.179 718.4 Q(e-)-.11 E .993(\214le generator w)72 734.4 R .993
+(as included that sets up dependencies and such correctly for ANTLR and DLG.)
+-.11 F EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 11/Times-Roman@0 SF 2.75(-2-)278.837 52 S -1.221(Ve)72 88 S 1.414(ry fe)
+1.221 F 4.164(w1)-.275 G 1.414(.00 incompatibilities were introduced \(1.00 w)
+122.81 88 R 1.415(as quite dif)-.11 F 1.415(ferent from 1.00B in some)-.275 F
+(areas\).)72 104 Q 1.089(1.10 w)97 123.6 R 1.088
+(as released on August 31, 1993 and incorporated b)-.11 F 1.088(ug \214x)-.22 F
+1.088(es, a fe)-.165 F 3.838(wf)-.275 G 1.088(eature enhance-)433.59 123.6 R
+3.112(ments and a major ne)72 139.6 R 5.863(wc)-.275 G(apability \212)196.957
+139.6 Q 3.113(an arbitrary lookahead operator \(syntactic predicate\),)5.863 F
+/F1 11/Courier@0 SF(\(alpha\)?beta)72 155.6 Q F0 6.754(.T)C 1.254
+(his feature w)167.425 155.6 R 1.254
+(as co-designed with Professor Russell Quong also at Purdue.)-.11 F 3.297 -.88
+(To s)72 171.6 T 1.537
+(upport in\214nite lookahead, a preprocessor \215ag, ZZINF_LOOK, w).88 F 1.537
+(as created that forced the)-.11 F .21(ANTLR\(\) macro to tok)72 187.6 R .21
+(enize all input prior to parsing.)-.11 F .209(Hence, at an)5.709 F 2.959(ym)
+-.165 G .209(oment, an action or predi-)389.215 187.6 R .936
+(cate can see the entire input sentence.)72 203.6 R .936
+(The predicate mechanism of 1.06 w)6.436 F .937(as e)-.11 F .937
+(xtended to allo)-.165 F(w)-.275 E .55
+(multiple predicates to be hoisted; the syntactic conte)72 219.6 R .55
+(xt of a predicate w)-.165 F .55(as also mo)-.11 F -.165(ve)-.165 G 3.299(da)
+.165 G .549(long with)461.585 219.6 R(the predicate.)72 235.6 Q .754
+(In February of 1994, SORCERER \(a simple tree-parser generator\) w)97 255.2 R
+.755(as released.)-.11 F .755(This tool)6.255 F(allo)72 271.2 Q .6(ws the user\
+ to parse child-sibling trees by specifying a grammar rather than b)-.275 F
+.599(uilding a recur)-.22 F(-)-.22 E(si)72 287.2 Q -.165(ve)-.275 G 1.39
+(-descent tree w).165 F(alk)-.11 E 1.391(er by hand.)-.11 F -.88(Wo)6.891 G
+1.391(rk to).88 F -.11(wa)-.275 G 1.391
+(rds a library of tree transformations is underw).11 F(ay)-.11 E(.)-.715 E .581
+(Aaron Sa)72 303.2 R(wde)-.165 E 3.331(ya)-.165 G 3.331(tT)145.531 303.2 S .581
+(he Uni)158.641 303.2 R -.165(ve)-.275 G .58
+(rsity of Minnesota became a second author of SORCERER after the).165 F
+(initial release.)72 319.2 Q .627(On April 1, 1994, PCCTS 1.20 w)97 338.8 R
+.627(as released.)-.11 F .627(This w)6.127 F .627(as the \214rst v)-.11 F .627
+(ersion to acti)-.165 F -.165(ve)-.275 G .627(ly support).165 F 1.664
+(C++ output.)72 354.8 R 1.664(It also included important \214x)7.164 F 1.663
+(es re)-.165 F -.055(ga)-.165 G 1.663
+(rding semantic predicates and \(..\)+ subrules.).055 F(This v)72 370.8 Q
+(ersion also introduced tok)-.165 E(en classes, the `)-.11 E(`)-.814 E/F2 11
+/Times-Italic@0 SF(not)A F0 1.628 -.814('' o)D(perator).814 E 2.75(,a)-.44 G
+(nd tok)355.294 370.8 Q(en ranges.)-.11 E .764
+(On June 19, 1994, SORCERER 1.00B9 w)97 390.4 R .765(as released.)-.11 F .765
+(Gary Funck of Intrepid T)6.265 F(echnology)-.77 E .807
+(joined the SORCERER team and pro)72 406.4 R .807(vided v)-.165 F .807(ery v)
+-.165 F .807(aluable suggestions re)-.275 F -.055(ga)-.165 G .806(rding the `)
+.055 F(`transform')-.814 E(')-.814 E(mode of SORCERER.)72 422.4 Q 1.137
+(On August 8, 1994, PCCTS 1.21 w)97 442 R 1.137(as released.)-.11 F 1.138
+(It mainly cleaned up the C++ output and)6.637 F(included a number of b)72 458
+Q(ug \214x)-.22 E(es.)-.165 E .316(From the 1.21 release forw)97 477.6 R .316
+(ard, the maintenance and support of all PCCTS tools will be pri-)-.11 F 1.557
+(marily pro)72 493.6 R 1.557(vided by P)-.165 F 1.557
+(arr Research Corporation, Minneapolis MN---an or)-.165 F -.055(ga)-.198 G
+1.558(nization founded on).055 F 1.616(the principles of e)72 509.6 R 1.616
+(xcellence in research and inte)-.165 F 1.616(grity in b)-.165 F 1.616
+(usiness; we are de)-.22 F -.22(vo)-.275 G 1.616(ted to pro).22 F(viding)-.165
+E 1.202(really cool softw)72 525.6 R 1.202(are tools.)-.11 F 1.202
+(Please see \214le PCCTS.FUTURE for more information.)6.702 F 1.203(All PCCTS)
+6.703 F(tools currently in the public domain will continue to be in the public\
+ domain.)72 541.6 Q 1.198(Looking to)97 561.2 R -.11(wa)-.275 G 1.198
+(rds the future, a graphical user).11 F(-interf)-.22 E 1.197
+(ace is in the design phase.)-.11 F 1.197(This w)6.697 F(ould)-.11 E(allo)72
+577.2 Q 2.753(wu)-.275 G .003(sers to vie)104.42 577.2 R 2.753(wt)-.275 G .004
+(he syntax diagram representation of their grammars and w)162.509 577.2 R .004
+(ould highlight non-)-.11 F 1.181(deterministic productions.)72 593.2 R -.165
+(Pa)6.681 G 1.18(rsing can be traced graphically as well.).165 F 1.18
+(This system will be b)6.68 F(uilt)-.22 E .167(using a multiplatform windo)72
+609.2 R 2.917(wl)-.275 G(ibrary)211.73 609.2 Q 5.667(.W)-.715 G 2.917(ea)
+255.204 609.2 S .168(lso anticipate the introduction of a sophisticated error)
+267.889 609.2 R(handling mechanism called `)72 625.2 Q(`parser e)-.814 E
+(xception handling')-.165 E 2.75('i)-.814 G 2.75(nan)327.431 625.2 S
+(ear future release.)348.815 625.2 Q(Currently)97 644.8 Q 3.019(,P)-.715 G .269
+(CCTS is used at o)150.333 644.8 R -.165(ve)-.165 G 3.019(r1).165 G .269
+(000 kno)253.098 644.8 R .268(wn academic, go)-.275 F -.165(ve)-.165 G .268
+(rnment, and commercial sites).165 F .859(in 37 countries.)72 660.8 R .859
+(Of course, the true number of users is unkno)6.359 F .859(wn due to the lar)
+-.275 F .859(ge number of ftp)-.198 F(sites.)72 676.8 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 11/Times-Roman@0 SF 2.75(-3-)278.837 52 S(Credits)272.11 88 Q .44 LW
+472.162 103.75 103.838 103.75 DL(Idea/T)134.236 117 Q 52.987(ool Coder)-.88 F
+(Co-designer\(s\))345.436 117 Q 281.334 103.75 281.334 124.75 DL 209.273 103.75
+209.273 124.75 DL 209.273 124.75 103.838 124.75 DL 103.838 126.75 209.273
+126.75 DL 281.334 124.75 209.273 124.75 DL 209.273 126.75 281.334 126.75 DL
+472.162 124.75 281.334 124.75 DL 281.334 126.75 472.162 126.75 DL(ANTLR 1.00A)
+109.338 140 Q -.77(Te)217.523 140 S(rence P).77 E 13.75(arr Hank)-.165 F(Dietz)
+2.75 E 82.83(ALX T)109.338 156 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)
+2.75 E(ANTLR 1.00B)109.338 172 Q -.77(Te)217.523 172 S(rence P).77 E 13.75
+(arr Hank)-.165 F(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00B)109.338 188 Q -.44
+(Wi)217.523 188 S(ll Cohen).44 E -.77(Te)289.584 188 S(rence P).77 E(arr)-.165
+E 2.75(,H)-.44 G(ank Dietz)358.147 188 Q(NF)109.338 204 Q 2.75(AR)-.814 G
+30.778(elabelling W)140.611 204 R(ill Cohen)-.44 E/F1 11/Times-Italic@0 SF(LL)
+109.976 220 Q F0(\().583 E F1(k).396 E F0 2.75(\)a).737 G 40.447(nalysis T)
+143.768 220 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)2.75 E(ANTLR 1.00)
+109.338 236 Q -.77(Te)217.523 236 S(rence P).77 E 13.75(arr Hank)-.165 F
+(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00)109.338 252 Q -.44(Wi)217.523 252 S
+(ll Cohen).44 E -.77(Te)289.584 252 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G
+(ank Dietz)358.147 252 Q(ANTLR 1.06)109.338 268 Q -.77(Te)217.523 268 S
+(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong, Hank Dietz)-.44 E
+(DLG 1.06)109.338 284 Q -.44(Wi)217.523 284 S(ll Cohen).44 E -.77(Te)289.584
+284 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G(ank Dietz)358.147 284 Q
+(ANTLR 1.10)109.338 300 Q -.77(Te)217.523 300 S(rence P).77 E 13.75(arr W)-.165
+F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.20)109.338 316 Q -.77(Te)217.523 316
+S(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.21)
+109.338 332 Q -.77(Te)217.523 332 S(rence P).77 E 13.75(arr Russell)-.165 F
+(Quong)2.75 E(DLG 1.10)109.338 348 Q -.44(Wi)217.523 348 S(ll Cohen).44 E -.77
+(Te)289.584 348 S(rence P).77 E(arr)-.165 E(DLG 1.20)109.338 364 Q -.44(Wi)
+217.523 364 S(ll Cohen).44 E -.77(Te)289.584 364 S(rence P).77 E(arr)-.165 E
+(DLG 1.21)109.338 380 Q -.77(Te)217.523 380 S(rence P).77 E(arr)-.165 E
+(Semantic predicates)109.338 396 Q -.77(Te)217.523 396 S(rence P).77 E 13.75
+(arr Russell)-.165 F(Quonq)2.75 E(Syntactic predicates)109.338 412 Q -.77(Te)
+217.523 412 S(rence P).77 E 13.75(arr Russell)-.165 F(Quonq)2.75 E
+(SORCERER 1.00A)109.338 428 Q -.77(Te)217.523 428 S(rence P).77 E(arr)-.165 E
+(SORCERER 1.00B)109.338 444 Q -.77(Te)217.523 444 S(rence P).77 E 13.75
+(arr Aaron)-.165 F(Sa)2.75 E(wde)-.165 E(y)-.165 E(SORCERER 1.00B9)109.338 460
+Q -.77(Te)217.523 460 S(rence P).77 E 13.75(arr Aaron)-.165 F(Sa)2.75 E(wde)
+-.165 E 1.43 -.715(y, G)-.165 H(ary Funck).715 E 472.162 467.75 103.838 467.75
+DL 472.162 103.75 472.162 467.75 DL 103.838 103.75 103.838 467.75 DL EP
+%%Trailer
+end
+%%EOF
diff --git a/Source/Pccts/history.txt b/Source/Pccts/history.txt
new file mode 100644
index 0000000..89ad840
--- /dev/null
+++ b/Source/Pccts/history.txt
@@ -0,0 +1,186 @@
+

+

+

+                    The History of PCCTS

+

+         The Purdue Compiler-Construction Tool Set

+

+

+                        Terence Parr

+                 Parr Research Corporation

+                   Minneapolis, Minnesota

+                            and

+                  University of Minnesota

+      Army High Performance Computing Research Center

+

+                      [Updated 8-7-94]

+

+

+     The PCCTS project began as a parser-generator project for a  gra-

+duate  course  at Purdue University in the Fall of 1988 taught by Hank

+Dietz- translator-writing systems.  Under the  guidance  of  Professor

+Dietz, the parser generator, ANTLR (originally called YUCC), continued

+after the termination of the course and eventually became the  subject

+of  Terence  Parr's Master's thesis.  Originally, lexical analysis was

+performed via ALX which was soon replaced by Will Cohen's DLG  in  the

+Fall  of  1989 (DFA-based lexical-analyzer generator, also an offshoot

+of the graduate translation course).

+

+     The alpha version of ANTLR was  totally  rewritten  resulting  in

+1.00B.    Version   1.00B  was  released  via  an  internet  newsgroup

+(comp.compilers) posting in February of 1990 and  quickly  gathered  a

+large  following.  1.00B generated only LL(1) parsers, but allowed the

+merged description of lexical and syntactic analysis.  It had rudimen-

+tary  attribute  handling  similar  to that of YACC and did not incor-

+porate rule parameters or return values; downward inheritance was very

+awkward.   1.00B-generated  parsers  terminated  upon the first syntax

+error.  Lexical classes (modes) were not allowed and DLG did not  have

+an interactive mode.

+

+     Upon starting his Ph.D. at Purdue in the Fall  of  1990,  Terence

+Parr  began  the  second  total rewrite of ANTLR.  The method by which

+grammars may be  practically  analyzed  to  generate  LL(k)  lookahead

+information  was  discovered in August of 1990 just before his return.

+Version 1.00 incorporated this algorithm and included the AST  mechan-

+ism,  lexical  classes,  error  classes, and automatic error recovery;

+code quality and portability were higher.  In February  of  1992  1.00

+was  released  via  an  article in SIGPLAN Notices.  Peter Dahl, Ph.D.

+candidate, and Professor Matt O'Keefe (both at the University of  Min-

+nesota)  tested  this  version  extensively.  Dana Hoggatt (Micro Data

+Base Systems, Inc.) came up with the idea of error  grouping  (strings

+attached to non-terminals) and tested 1.00 heavily.

+

+     Version 1.06 was released in  December  1992  and  represented  a

+large  feature enhancement over 1.00.  For example, rudimentary seman-

+tic predicates were  introduced,  error  messages  were  significantly

+improved  for k>1 lookahead and ANTLR parsers could indicate that loo-

+kahead fetches were  to  occur  only  when  necessary  for  the  parse

+

+

+

+                                                                Page 1

+

+                                                                 PCCTS

+

+

+(normally,  the  lookahead "pipe" was constantly full).  Russell Quong

+joined the project in the Spring of 1992 to aid in the semantic predi-

+cate  design.   Beginning  and  advanced  tutorials  were  created and

+released as well.  A makefile generator  was  included  that  sets  up

+dependencies  and  such  correctly  for  ANTLR and DLG.  Very few 1.00

+incompatibilities were introduced (1.00 was quite different from 1.00B

+in some areas).

+

+     1.10 was released on August 31, 1993 and incorporated bug  fixes,

+a  few  feature enhancements and a major new capability - an arbitrary

+lookahead operator (syntactic predicate), (alpha)?beta.  This  feature

+was  co-designed with Professor Russell Quong also at Purdue.  To sup-

+port infinite lookahead, a preprocessor flag, ZZINF_LOOK, was  created

+that  forced the ANTLR() macro to tokenize all input prior to parsing.

+Hence, at any moment, an action or predicate can see the entire  input

+sentence.   The predicate mechanism of 1.06 was extended to allow mul-

+tiple predicates to be hoisted; the syntactic context of  a  predicate

+was also moved along with the predicate.

+

+     In February of 1994, SORCERER (a  simple  tree-parser  generator)

+was  released.  This tool allows the user to parse child-sibling trees

+by specifying a grammar rather than building a recursive-descent  tree

+walker  by  hand.   Work  towards a library of tree transformations is

+underway.  Aaron Sawdey at The University of Minnesota became a second

+author of SORCERER after the initial release.

+

+     On April 1, 1994, PCCTS 1.20 was released.  This  was  the  first

+version  to  actively  support C++ output.  It also included important

+fixes regarding semantic predicates and (..)+ subrules.  This  version

+also introduced token classes, the "not" operator, and token ranges.

+

+     On June 19, 1994, SORCERER 1.00B9 was released.   Gary  Funck  of

+Intrepid  Technology  joined the SORCERER team and provided very valu-

+able suggestions regarding the "transform" mode of SORCERER.

+

+     On August 8, 1994, PCCTS 1.21 was released.  It mainly cleaned up

+the C++ output and included a number of bug fixes.

+

+     From the 1.21 release forward, the maintenance and support of all

+PCCTS  tools  will be primarily provided by Parr Research Corporation,

+Minneapolis MN---an organization founded on the principles  of  excel-

+lence in research and integrity in business; we are devoted to provid-

+ing really cool software tools.  Please see file PCCTS.FUTURE for more

+information.  All PCCTS tools currently in the public domain will con-

+tinue to be in the public domain.

+

+     Looking towards the future, a graphical user-interface is in  the

+design  phase.   This  would  allow  users  to view the syntax diagram

+representation of their grammars and would highlight  nondeterministic

+productions.   Parsing can be traced graphically as well.  This system

+will be built using a multiplatform window library.  We  also  antici-

+pate  the  introduction  of  a  sophisticated error handling mechanism

+called "parser exception handling" in a near future release.

+

+

+

+

+                                                                Page 2

+

+                                                                 PCCTS

+

+

+     Currently, PCCTS is used at over 1000 known academic, government,

+and  commercial  sites in 37 countries.  Of course, the true number of

+users is unknown due to the large number of ftp sites.

+                               Credits

+

+_____________________________________________________________________________

+_____________________________________________________________________________

+|ANTLR 1.00A            Terence Parr   Hank Dietz                           |

+|ALX                    Terence Parr   Hank Dietz                           |

+|ANTLR 1.00B            Terence Parr   Hank Dietz, Will Cohen               |

+|DLG 1.00B              Will Cohen     Terence Parr, Hank Dietz             |

+|NFA Relabelling        Will Cohen                                          |

+|LL(k) analysis         Terence Parr   Hank Dietz                           |

+|ANTLR 1.00             Terence Parr   Hank Dietz, Will Cohen               |

+|DLG 1.00               Will Cohen     Terence Parr, Hank Dietz             |

+|ANTLR 1.06             Terence Parr   Will Cohen, Russell Quong, Hank Dietz|

+|DLG 1.06               Will Cohen     Terence Parr, Hank Dietz             |

+|ANTLR 1.10             Terence Parr   Will Cohen, Russell Quong            |

+|ANTLR 1.20             Terence Parr   Will Cohen, Russell Quong            |

+|ANTLR 1.21             Terence Parr   Russell Quong                        |

+|DLG 1.10               Will Cohen     Terence Parr                         |

+|DLG 1.20               Will Cohen     Terence Parr                         |

+|DLG 1.21               Terence Parr                                        |

+|Semantic predicates    Terence Parr   Russell Quonq                        |

+|Syntactic predicates   Terence Parr   Russell Quonq                        |

+|SORCERER 1.00A         Terence Parr                                        |

+|SORCERER 1.00B         Terence Parr   Aaron Sawdey                         |

+|SORCERER 1.00B9        Terence Parr   Aaron Sawdey, Gary Funck             |

+|___________________________________________________________________________|

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+                                                                Page 3

+

diff --git a/Source/Pccts/makefile b/Source/Pccts/makefile
new file mode 100644
index 0000000..f9b2dd2
--- /dev/null
+++ b/Source/Pccts/makefile
@@ -0,0 +1,66 @@
+#

+# Main makefile for PCCTS 1.33MR33	/* MRXXX */

+#

+# Terence Parr

+# Parr Research Corporation

+#

+# verbosity versus silence...

+PSss=

+#

+# this can be set to /user/local/bin etc...

+BINDIR=bin

+# This part added by Thomas Herter, M"unchen, Germany. See also manpages

+# target.

+MANDIR=$(HOME)/man

+MANEXT=1

+MANFILES=dlg/dlg.1 antlr/antlr.1

+

+#CC=cc

+#CC=gcc

+#COPT=-O2

+

+pccts:

+	@echo " "

+	@echo "             Welcome to PCCTS 1.33MR33 installation"

+	@echo " "

+	@echo "             (Version 1.33 Maintenance Release #33)" # mrxxx

+	@echo " "

+	@echo "                  Released 19 April 2002"

+	@echo " "

+	@echo "                        Featuring"

+	@echo "         ANTLR     -- ANother Tool for Language Recognition"

+	@echo "         DLG       -- DFA-based Lexical Analyzer Generator"

+	@echo "         SORCERER  -- Source-to-source translator (tree walker)" 

+	@echo " "

+	@echo "                  http://www.antlr.org"	

+	@echo " "

+	@echo "             Trouble reports to tmoog@polhode.com"

+	@echo "             Additional PCCTS 1.33 information at"

+	@echo "                  http://www.polhode.com"

+	@echo

+	@echo

+	@echo "To substitute gcc for CC to invoke compiler: make CC=gcc"

+	@echo "If there are problems with cr and lf try: unzip -a ..."

+	@echo

+#

+	@if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ; fi

+	@echo Making executables...

+	(cd ./antlr; $(MAKE) CC="$(CC)" COPT="$(COPT)")

+	@echo antlr executable now in $(BINDIR)

+	(cd ./dlg; $(MAKE) CC="$(CC)" COPT="$(COPT)")

+	@echo dlg executable now in $(BINDIR)

+	@echo

+	@echo "       PCCTS 1.33MR33 installation complete"  # MRXXX

+

+clean:

+	(cd ./antlr; $(MAKE) -s clean)

+	(cd ./dlg; $(MAKE) -s clean)

+

+

+manpages:

+	# mkdir -p $(MANDIR)/man$(MANEXT)

+	if [ ! -d $(MANDIR) ] ; then \

+	  mkdir $(MANDIR) ; fi

+	if [ ! -d $(MANDIR)/man$(MANEXT) ] ; then \

+	  mkdir $(MANDIR)/man$(MANEXT); fi

+	cp -p $(MANFILES) $(MANDIR)/man$(MANEXT)

diff --git a/Source/Pccts/support/genmk/genmk.c b/Source/Pccts/support/genmk/genmk.c
new file mode 100644
index 0000000..4952a30
--- /dev/null
+++ b/Source/Pccts/support/genmk/genmk.c
@@ -0,0 +1,1063 @@
+/*

+ * genmk -- a program to make makefiles for PCCTS

+ *

+ * ANTLR 1.33MR23

+ * Terence John Parr 1989 - 2000

+ * Purdue University

+ * U of MN

+ */

+

+#include <stdio.h>

+#include <string.h>

+#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */

+

+#ifdef VAXC

+#define DIE		return 0;

+#define DONE	return 1;

+#else

+#define DIE		return 1;

+#define DONE	return 0;

+#endif

+

+#ifndef require

+#define require(expr, err) {if ( !(expr) ) fatal(err);}

+#endif

+

+#define MAX_FILES	50

+#define MAX_CFILES	1600

+#define MAX_SFILES	50

+#define MAX_SORS	50

+#define MAX_CLASSES	50

+

+char *RENAME_OBJ_FLAG="-o",

+     *RENAME_EXE_FLAG="-o";

+

+char *dlg = "parser.dlg";

+char *err = "err.c";

+char *hdr = "stdpccts.h";

+char *tok = "tokens.h";

+char *mode = "mode.h";

+char *scan = "scan";

+

+char ATOKENBUFFER_O[100];

+char APARSER_O[100];

+char ASTBASE_O[100];

+char PCCTSAST_O[100];

+char LIST_O[100];

+char DLEXERBASE_O[100];

+

+/* Option flags */

+static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];

+static char *cfiles[MAX_CFILES];

+static char *sfiles[MAX_SORS][MAX_SFILES],*sclasses[MAX_SORS];

+static int  num_sfiles[MAX_SORS]; /*sorcerer files in group */

+static int  num_sors = 0; /*sorcerer groups */

+static int  num_files = 0; /* grammar files */

+static int  num_cfiles = 0; /* additional C/C++ files */

+static int  num_classes = 0; /* ANTLR classes */

+static int  user_lexer = 0;

+static char *user_token_types = NULL;

+static int  gen_CPP = 0;

+static char *outdir=".";

+static char *dlg_class = "DLGLexer";

+static int  gen_trees = 0;

+static int  gen_hoist = 0;

+static int  nondef_comp = 0; /* 1=compiler is non default */

+static char *compilerCCC="CC";

+static char *compilerCC="cc";

+static char *pccts_path="/usr/local/pccts";

+

+#ifdef __STDC__

+void help(void);

+void mk(char *project, char **files, int n, int argc, char **argv);

+void pfiles(char **files, int n, char *suffix);

+void fatal(char *msg);

+void warn(char *msg);

+#else

+void help();

+void mk();

+void pfiles();

+void fatal();

+void warn();

+#endif

+

+typedef struct _Opt {

+			char *option;

+			int arg;

+#ifdef __cplusplus

+			void (*process)(...);

+#else

+			void (*process)();

+#endif

+			char *descr;

+		} Opt;

+

+#ifdef __STDC__

+static void ProcessArgs(int, char **, Opt *);

+#else

+static void ProcessArgs();

+#endif

+

+static void

+#ifdef __STDC__

+pProj(char *s, char *t )

+#else

+pProj( s, t )

+char *s;

+char *t;

+#endif

+{

+	project = t;

+}

+

+static void

+#ifdef __STDC__

+pUL( char *s )

+#else

+pUL( s )

+char *s;

+#endif

+{

+	user_lexer = 1;

+}

+

+static void

+#ifdef __STDC__

+pCPP( char *s )

+#else

+pCPP( s )

+char *s;

+#endif

+{

+	gen_CPP = 1;

+}

+

+static void

+#ifdef __STDC__

+pUT( char *s, char *t )

+#else

+pUT( s, t )

+char *s;

+char *t;

+#endif

+{

+	user_token_types = t;

+}

+

+static void

+#ifdef __STDC__

+pTrees( char *s )

+#else

+pTrees( s )

+char *s;

+#endif

+{

+	gen_trees = 1;

+}

+

+static void

+#ifdef __STDC__

+pHoist( char *s )

+#else

+pHoist( s )

+char *s;

+#endif

+{

+	gen_hoist = 1;

+}

+

+static void

+#ifdef __STDC__

+pSor( char *s )

+#else

+pSor( s )

+char *s;

+#endif

+{

+	require(num_sors<MAX_SORS, "exceeded max # of sorcerer groups");

+	num_sors++;

+	pTrees(NULL); /* silently turn on tree generation */

+}

+

+static void

+#ifdef __STDC__

+pSFiles( char *s, char *t )

+#else

+pSFiles( s, t )

+char *s;

+char *t;

+#endif

+{

+	if (num_sors==0)

+	{

+		pSor(NULL);

+		warn("sorcerer input file before any '-sor' option");

+	}

+		

+	require(num_sfiles[num_sors-1]<MAX_SFILES,

+		 "exceeded max # of sorcerer input files");

+	sfiles[num_sors-1][num_sfiles[num_sors-1]++] = t;

+}

+

+static void

+#ifdef __STDC__

+pCFiles( char *s, char *t )

+#else

+pCFiles( s, t )

+char *s;

+char *t;

+#endif

+{

+	require(num_cfiles<MAX_CFILES, "exceeded max # of C/C++ input files");

+	cfiles[num_cfiles++] = t;

+}

+

+int

+#ifdef __STDC__

+isKnownSuffix( char *s )

+#else

+isKnownSuffix( s )

+	char *s;

+#endif

+{

+	if(s==NULL) return 0;

+	if (strcasecmp(s,".c")==0) return 1;

+	if (strcasecmp(s,".cc")==0) return 1;

+	if (strcasecmp(s,".cpp")==0) return 1;

+	if (strcasecmp(s,".cxx")==0) return 1;

+	if (strcasecmp(s,CPP_FILE_SUFFIX)==0) return 1;

+	if (strcasecmp(s,".sor")==0) return 2;

+	return 0;

+}

+

+static void

+#ifdef __STDC__

+pFile( char *s )

+#else

+pFile( s )

+char *s;

+#endif

+{

+	if ( *s=='-' )

+	{

+		fprintf(stderr, "invalid option: '%s'; ignored...",s);

+		return;

+	}

+	switch(isKnownSuffix(strrchr(s,'.')))

+	{

+	 case 1: /* c/c++ */

+		pCFiles("-cfiles",s);

+		return;

+	 case 2: /* sorcerer */

+		pSFiles("",s);

+		return;

+	 default: /* grammar (ANTLR) */

+		break;

+	}

+	require(num_files<MAX_FILES, "exceeded max # of input files");

+	files[num_files++] = s;

+}

+

+static void

+#ifdef __STDC__

+pClass( char *s, char *t )

+#else

+pClass( s, t )

+char *s;

+char *t;

+#endif

+{

+	if (num_sors==0)

+	{

+		require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");

+		classes[num_classes++] = t;

+	} else

+	{

+		sclasses[num_sors-1] = t; /* one class per sorcerer group (last valid) */

+	}

+}

+

+static void

+#ifdef __STDC__

+pDLGClass( char *s, char *t )

+#else

+pDLGClass( s, t )

+char *s;

+char *t;

+#endif

+{

+	if ( !gen_CPP ) {

+		fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");

+	}

+	else dlg_class = t;

+}

+

+static void

+#ifdef __STDC__

+pOdir( char *s, char *t )

+#else

+pOdir( s, t )

+char *s;

+char *t;

+#endif

+{

+	outdir = t;

+}

+

+static void

+#ifdef __STDC__

+pHdr( char *s, char *t )

+#else

+pHdr( s, t )

+char *s;

+char *t;

+#endif

+{

+	hdr = t;

+}

+

+static void

+#ifdef __STDC__

+pCompiler( char *s, char *t )

+#else

+pCompiler( s, t )

+char *s;

+char *t;

+#endif

+{

+	compilerCCC = t;

+	compilerCC = t;

+	nondef_comp = 1;

+}

+

+static void

+#ifdef __STDC__

+ppccts_path( char *s, char *t )

+#else

+ppccts_path( s, t )

+char *s;

+char *t;

+#endif

+{

+	pccts_path = t;

+}

+

+Opt options[] = {

+	{ "-CC", 0,	pCPP,			"Generate C++ output"},

+	{ "-class", 1,	pClass,		"Name of a grammar class defined in grammar (if C++)"},

+	{ "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},

+	{ "-header", 1,pHdr,		"Name of ANTLR standard header info (default=no file)"},

+	{ "-o", 1,	pOdir,			"Directory where output files should go (default=\".\")"},

+	{ "-project", 1,	pProj,	"Name of executable to create (default=t)"},

+	{ "-token-types", 1, pUT,	"Token types are in this file (don't use tokens.h)"},

+	{ "-trees", 0, pTrees,		"Generate ASTs"},

+	{ "-user-lexer", 0,	pUL,	"Do not create a DLG-based scanner"},

+	{ "-mrhoist",0,pHoist,      "Maintenance release style hoisting"},

+	{ "-cfiles",1,pCFiles,      "Additional files in C or C++ to compile"},

+	{ "-sor",0,pSor,           "Start of sorcerer group"},

+	{ "-pccts_path",1,ppccts_path,

+			"Path for $PCCTS directory (default is /usr/local/pccts)"},

+	{ "-compiler",1,pCompiler,

+			"Default compiler (default is CC/cc)"},

+	{ "*", 0,pFile, 	        "" },	/* anything else is a file */

+	{ NULL, 0, NULL, NULL }

+};

+

+#ifdef __STDC__

+extern char *DIR(void);

+#else

+extern char *DIR();

+#endif

+

+#ifdef __STDC__

+int main(int argc, char **argv)

+#else

+int main(argc, argv)

+int argc;

+char **argv;

+#endif

+{

+	int i;

+	

+	if ( argc == 1 ) { help(); DIE; }

+	for(i=0;i<MAX_SORS;i++) num_sfiles[i]=0;

+	

+	ProcessArgs(argc-1, &(argv[1]), options);

+

+	strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);

+	ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);

+	strcpy(APARSER_O, APARSER_C);

+	APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(APARSER_O, OBJ_FILE_SUFFIX);

+

+	strcpy(ASTBASE_O, ASTBASE_C);

+	ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(ASTBASE_O, OBJ_FILE_SUFFIX);

+

+	strcpy(PCCTSAST_O, PCCTSAST_C);

+	PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);

+

+	strcpy(LIST_O, LIST_C);

+	LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(LIST_O, OBJ_FILE_SUFFIX);

+

+	strcpy(DLEXERBASE_O, DLEXERBASE_C);

+	DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);

+

+	if ( num_files == 0 ) fatal("no grammar files specified; exiting...");

+	if ( !gen_CPP && num_classes>0 ) {

+		warn("can't define classes w/o C++ mode; turning on C++ mode...\n");

+		gen_CPP=1;

+	}

+	if (!gen_CPP && num_sors) {

+		warn("can't define sorcerer group in C mode (yet); turning on C++ mode...\n");

+		gen_CPP=1;

+	}

+	if ( gen_CPP && num_classes==0 ) {

+		fatal("must define classes >0 grammar classes in C++ mode\n");

+	}

+

+	mk(project, files, num_files, argc, argv);

+	DONE;

+}

+

+#ifdef __STDC__

+void help(void)

+#else

+void help()

+#endif

+{

+	Opt *p = options;

+	static char buf[1000+1];

+

+	fprintf(stderr, "genmk [options] f1.g ... fn.g\n");

+	while ( p->option!=NULL && *(p->option) != '*' )

+	{

+		buf[0]='\0';

+		if ( p->arg ) sprintf(buf, "%s ___", p->option);

+		else strcpy(buf, p->option);

+		fprintf(stderr, "\t%-16s   %s\n", buf, p->descr);

+		p++;

+	}

+}

+

+#ifdef __STDC__

+void mk(char *project, char **files, int n, int argc, char **argv)

+#else

+void mk(project, files, n, argc, argv)

+char *project;

+char **files;

+int n;

+int argc;

+char **argv;

+#endif

+{

+	int i,j;

+

+	printf("#\n");

+	printf("# PCCTS makefile for: ");

+	pfiles(files, n, NULL);

+	printf("\n");

+	printf("#\n");

+	printf("# Created from:");

+	for (i=0; i<argc; i++) printf(" %s", argv[i]);

+	printf("\n");

+	printf("#\n");

+	printf("# PCCTS release 1.33MR23\n");

+	printf("# Project: %s\n", project);

+	if ( gen_CPP ) printf("# C++ output\n");

+	else printf("# C output\n");

+	if ( user_lexer ) printf("# User-defined scanner\n");

+	else printf("# DLG scanner\n");

+	if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);

+	else printf("# ANTLR-defined token types\n");

+	printf("#\n");

+/***********

+	printf(".SUFFIXES:\n.SUFFIXES:\t.o .cpp .c .h .g .i .dlg .sor\n"); 

+ ***********/

+	if ( user_token_types!=NULL ) {

+		printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");

+		printf("TOKENS = %s", user_token_types);

+	}

+	else printf("TOKENS = %stokens.h", DIR());

+	printf("\n");

+	printf("#\n");

+	printf("# The following filenames must be consistent with ANTLR/DLG flags\n");

+	printf("DLG_FILE = %s%s\n", DIR(), dlg);

+	printf("ERR = %serr\n", DIR());

+	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);

+	else printf("HDR_FILE =\n");

+	if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);

+	if ( !gen_CPP ) printf("SCAN = %s\n", scan);

+	else printf("SCAN = %s%s\n", DIR(), dlg_class);

+

+	printf("PCCTS = %s\n",pccts_path);

+	printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);

+	if (num_sors>0) {

+		printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol);

+		printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n",

+			 	DirectorySymbol, DirectorySymbol);

+	}

+	printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);

+	printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);

+	printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);

+	if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol);

+	printf("CFLAGS = -I. -I$(ANTLR_H)");

+	if (num_sors>0) printf(" -I$(SOR_H)");

+	if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);

+	printf(" $(COTHER)");

+	printf("\n");

+	printf("AFLAGS =");

+	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);

+	if ( user_lexer ) printf(" -gx");

+	if ( gen_CPP ) printf(" -CC");

+	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);

+	if ( gen_trees ) printf(" -gt");

+	if ( gen_hoist ) {

+		printf(" -mrhoist on") ;

+	} else {

+		printf(" -mrhoist off");

+	};

+	printf(" $(AOTHER)");

+	printf("\n");

+	printf("DFLAGS = -C2 -i");

+	if ( gen_CPP ) printf(" -CC");

+	if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);

+	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);

+	printf(" $(DOTHER)");

+	printf("\n");

+	if (num_sors>0)

+	{

+		printf("SFLAGS = -CPP");

+		if ( strcmp(outdir,".")!=0 ) printf(" -out-dir %s", outdir);

+		printf(" $(SOTHER)\n");

+	}

+	printf("GRM = ");

+	pfiles(files, n, NULL);

+	printf("\n");

+	printf("SRC = ");

+	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);

+	else pfiles(files, n, "c");

+	if ( gen_CPP ) {

+		printf(" \\\n\t");

+		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" \\\n\t");

+		printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);

+		if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);

+		if ( gen_trees ) {

+			printf(" \\\n\t");

+			printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);

+			printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);

+/*			printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */

+			printf(" \\\n\t");

+		}

+		printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);

+	}

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);

+		else printf(" %s$(SCAN).c", DIR());

+	}

+	if ( !gen_CPP ) printf(" $(ERR).c");

+	for (i=0;i<num_sors;i++)

+	{

+		printf(" \\\n\t");

+		pclasses(&sclasses[i],1,CPP_FILE_SUFFIX_NO_DOT);

+		printf(" ");

+		pfiles(&sfiles[i][0],num_sfiles[i],CPP_FILE_SUFFIX_NO_DOT);

+	}

+	if(num_sors>0)

+		printf(" \\\n\t$(SOR_LIB)%sSTreeParser.cpp", DirectorySymbol);

+	if (num_cfiles>0)

+	{

+		printf(" \\\n\t");

+		pfiles(cfiles,num_cfiles,NULL);

+	}

+	printf("\n\n");

+	printf("OBJ = ");

+	pfiles(files, n, "o");

+	if ( gen_CPP ) {

+		printf(" \\\n\t");

+		pclasses(classes, num_classes, "o");

+		printf(" \\\n\t");

+		printf("%s%s", DIR(), APARSER_O);

+		if ( !user_lexer ) {

+			printf(" %s%s", DIR(), DLEXERBASE_O);

+		}

+		if ( gen_trees ) {

+			printf(" \\\n\t");

+			printf("%s%s", DIR(), ASTBASE_O);

+			printf(" %s%s", DIR(), PCCTSAST_O);

+/*			printf(" %s%s", DIR(), LIST_O); */

+			printf(" \\\n\t");

+		}

+		printf(" %s%s", DIR(), ATOKENBUFFER_O);

+	}

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);

+		else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);

+	}

+	if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);

+	for (i=0;i<num_sors;i++)

+	{

+		printf(" \\\n\t");

+		pclasses(&sclasses[i],1,"o");

+		printf(" ");

+		pfiles(&sfiles[i][0],num_sfiles[i],"o");

+	}

+	if(num_sors>0) printf(" \\\n\tSTreeParser.o");

+	if (num_cfiles>0)

+	{

+		printf(" \\\n\t");

+		pfiles(cfiles,num_cfiles,"o");

+	}

+	printf("\n\n");

+

+	printf("ANTLR_SPAWN = ");

+	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);

+	else pfiles(files, n, "c");

+	if ( gen_CPP ) {

+		printf(" ");

+		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" \\\n\t\t");

+		pclasses(classes, num_classes, "h");

+		if ( strcmp(hdr,"stdpccts.h")!=0 ) {

+			printf(" \\\n\t\t");

+			printf("$(HDR_FILE) stdpccts.h");

+		}

+	}

+	if ( user_lexer ) {

+		if ( !user_token_types ) printf(" $(TOKENS)");

+	}

+	else {

+		printf(" $(DLG_FILE)");

+		if ( !user_token_types ) printf(" $(TOKENS)");

+	}

+	if ( !gen_CPP ) printf(" $(ERR).c");

+	printf("\n");

+

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);

+		else printf("DLG_SPAWN = %s$(SCAN).c", DIR());

+		if ( gen_CPP ) printf(" $(SCAN).h");

+		if ( !gen_CPP ) printf(" $(MOD_FILE)");

+		printf("\n");

+	}

+

+	if ( gen_CPP ) {

+		if ( !nondef_comp )

+			printf("ifdef CXX\nCCC = $(CXX)\nendif\n\nifndef CCC\n");

+		printf("CCC = %s\n",compilerCCC);

+		if ( !nondef_comp ) printf("endif\n\n");

+	}

+	else

+	{

+		if ( !nondef_comp ) printf("ifndef CC\n");

+		printf("CC = %s\n",compilerCC);

+		if ( !nondef_comp ) printf("endif\n\n");

+	}

+

+	/* set up dependencies */

+	printf("\n%s : $(SRC) $(OBJ)\n", project);

+	printf("\t%s %s %s $(CFLAGS) $(OBJ)\n",

+		gen_CPP?"$(CCC)":"$(CC)",

+		RENAME_EXE_FLAG,

+		project);

+	printf("\n");

+

+	/* implicit rules */

+

+/*	if(gen_CPP)

+		printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");

+

+	printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",

+			gen_CPP?"$(CCC)":"$(CC)");

+*/

+	/* how to compile parser files */

+

+	for (i=0; i<num_files; i++)

+	{

+		pfiles(&files[i], 1, "o");

+		if ( user_lexer ) {

+			printf(" : $(TOKENS)");

+		}

+		else {

+			if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");

+			else printf(" : $(MOD_FILE) $(TOKENS)");

+		}

+		printf(" ");

+		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&files[i], 1, "c");

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+		printf("\n");

+		printf("\t%s -c $(CFLAGS) %s ",

+			gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+		pfiles(&files[i], 1, "o");

+		printf(" ");

+		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&files[i], 1, "c");

+		printf("\n\n");

+	}

+

+	for (i=0; i<num_cfiles; i++)

+	{

+		pfiles(&cfiles[i], 1, "o");

+		printf(" : ");

+		pfiles(&cfiles[i], 1, NULL);

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+/***	printf(" "); ***/

+/***	pfiles(&cfiles[i], 1, "h"); ***/

+		printf("\n");

+		printf("\t%s -c $(CFLAGS) %s ",

+			gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+		pfiles(&cfiles[i], 1, "o");

+		printf(" ");

+		pfiles(&cfiles[i], 1, NULL);

+		printf("\n\n");

+

+/*

+ *		pfiles(&cfiles[i], 1, "h");

+ *		printf(" :\ntouch ");

+ *		pfiles(&cfiles[i], 1, "h");

+ *		printf("\n\n");

+ */

+	}

+

+	/* how to compile err.c */

+	if ( !gen_CPP ) {

+		printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);

+		if ( !user_lexer ) printf(" $(TOKENS)");

+		printf("\n");

+		printf("\t%s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",

+			gen_CPP?"$(CCC)":"$(CC)",

+			RENAME_OBJ_FLAG,

+			OBJ_FILE_SUFFIX);

+		printf("\n\n");

+	}

+

+	/* how to compile Class.c */

+	for (i=0; i<num_classes; i++)

+	{

+		pclasses(&classes[i], 1, "o");

+		if ( user_lexer ) {

+			printf(" : $(TOKENS)");

+		}

+		else {

+			printf(" : $(TOKENS) $(SCAN).h");

+		}

+		printf(" ");

+		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" ");

+		pclasses(&classes[i], 1, "h");

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+		printf("\n");

+		printf("\t%s -c $(CFLAGS) %s ",

+			gen_CPP?"$(CCC)":"$(CC)",

+			RENAME_OBJ_FLAG);

+		pclasses(&classes[i], 1, "o");

+		printf(" ");

+		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf("\n\n");

+	}

+

+	/* how to compile scan.c */

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);

+		else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());

+		if ( !user_lexer ) printf(" $(TOKENS)");

+		printf("\n");

+		if ( gen_CPP ) printf("\t$(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",

+							RENAME_OBJ_FLAG,

+							OBJ_FILE_SUFFIX,

+							CPP_FILE_SUFFIX);

+		else printf("\t$(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",

+					RENAME_OBJ_FLAG,

+					DIR(),

+					OBJ_FILE_SUFFIX,

+					DIR());

+		printf("\n\n");

+	}

+/* how to compile sorcerer classes */

+	for (i=0;i<num_sors;i++)

+	{

+		pclasses(&sclasses[i], 1, "o");

+		printf(" : ");

+		pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" ");

+		pclasses(&sclasses[i], 1, "h");

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+		printf("\n");

+		printf("\t%s -c $(CFLAGS) %s ",

+				gen_CPP?"$(CCC)":"$(CC)",

+				RENAME_OBJ_FLAG);

+		pclasses(&sclasses[i], 1, "o");

+		printf(" ");

+		pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf("\n\n");

+/* how to compile i-th sorcerer's files*/

+		for (j=0; j<num_sfiles[i]; j++)

+		{

+			pfiles(&sfiles[i][j], 1, "o");

+			printf(" : ");

+			if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);

+			else pfiles(&sfiles[i][j], 1, "c");

+			if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+			printf("\n");

+			printf("\t%s -c $(CFLAGS) %s ",

+					gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+			pfiles(&sfiles[i][j], 1, "o");

+			printf(" ");

+			if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);

+			else pfiles(&sfiles[i][j], 1, "c");

+			printf("\n\n");

+		}

+		if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&sfiles[i][0], num_sfiles[i], "c");

+		if ( gen_CPP )

+		{

+			printf(" ");

+			pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+			printf(" ");

+			pclasses(&sclasses[i], 1, "h");

+			if ( strcmp(hdr,"stdpccts.h")!=0 ) 

+			{

+				printf(" ");

+				printf("$(HDR_FILE) stdpccts.h");

+			}

+		}

+		printf(" : ");

+		pfiles(&sfiles[i][0],num_sfiles[i],NULL);

+		printf("\n\t$(SOR) $(SFLAGS) ");

+		pfiles(&sfiles[i][0],num_sfiles[i],NULL);

+		printf("\n\n");

+	}

+	if(num_sors>0)

+	{

+		printf("STreeParser%s : $(SOR_LIB)%sSTreeParser.cpp\n",

+				OBJ_FILE_SUFFIX,DirectorySymbol);

+		printf("\t%s -c $(CFLAGS) %s ",

+				gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+		printf("STreeParser%s ",OBJ_FILE_SUFFIX);

+		printf("$(SOR_LIB)%sSTreeParser.cpp\n\n",DirectorySymbol);

+	}

+	

+	printf("$(ANTLR_SPAWN) : $(GRM)\n");

+	printf("\t$(ANTLR) $(AFLAGS) $(GRM)\n");

+

+	if ( !user_lexer )

+	{

+		printf("\n");

+		printf("$(DLG_SPAWN) : $(DLG_FILE)\n");

+		if ( gen_CPP ) printf("\t$(DLG) $(DFLAGS) $(DLG_FILE)\n");

+		else printf("\t$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");

+	}

+

+	/* do the makes for ANTLR/DLG support */

+	if ( gen_CPP ) {

+		printf("\n");

+		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);

+		printf("\t%s -c $(CFLAGS) %s ",

+				gen_CPP?"$(CCC)":"$(CC)",

+				RENAME_OBJ_FLAG);

+		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);

+		printf("\n");

+		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);

+		printf("\t%s -c $(CFLAGS) %s ",

+				gen_CPP?"$(CCC)":"$(CC)",

+				RENAME_OBJ_FLAG);

+		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);

+		if ( !user_lexer ) {

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);

+			printf("\t%s -c $(CFLAGS) %s ",

+					gen_CPP?"$(CCC)":"$(CC)",

+					RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);

+		}

+		if ( gen_trees ) {

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);

+			printf("\t%s -c $(CFLAGS) %s ",

+					gen_CPP?"$(CCC)":"$(CC)",

+					RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);

+			printf("\t%s -c $(CFLAGS) %s ",

+					gen_CPP?"$(CCC)":"$(CC)",

+					RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);

+			printf("\n");

+/*

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);

+			printf("\t%s -c $(CFLAGS) %s ",

+					gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);

+*/

+		}

+	}

+

+	/* clean and scrub targets */

+

+	printf("\nclean:\n");

+	printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project);

+	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);

+	printf("\n");

+

+	printf("\nscrub: clean\n");

+/*	printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); */

+/*	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); */

+	printf("\trm -f $(ANTLR_SPAWN)");

+	if ( !user_lexer ) printf(" $(DLG_SPAWN)");

+	for (i=0;i<num_sors;i++)

+	{

+		printf(" ");

+		if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&sfiles[i][0], num_sfiles[i], "c");

+		if ( gen_CPP )

+		{

+			printf(" ");

+			pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+			printf(" ");

+			pclasses(&sclasses[i], 1, "h");

+		}

+	}

+	printf("\n\n");

+}

+

+#ifdef __STDC__

+void pfiles(char **files, int n, char *suffix)

+#else

+void pfiles(files, n, suffix)

+char **files;

+int n;

+char *suffix;

+#endif

+{

+	int first=1;

+

+	while ( n>0 )

+	{

+		char *p = &(*files)[strlen(*files)-1];

+		if ( !first ) putchar(' ');

+		first=0;

+		while ( p > *files && *p != '.' ) --p;

+		if ( p == *files )

+		{

+			fprintf(stderr,

+					"genmk: filenames must be file.suffix format: %s\n",

+					*files);

+			exit(-1);

+		}

+		if ( suffix == NULL ) printf("%s", *files);

+		else

+		{

+			*p = '\0';

+			printf("%s", DIR());

+			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);

+			else printf("%s.%s", *files, suffix);

+			*p = '.';

+		}

+		files++;

+		--n;

+	}

+}

+

+#ifdef __STDC__

+pclasses(char **classes, int n, char *suffix)

+#else

+pclasses(classes, n, suffix)

+char **classes;

+int n;

+char *suffix;

+#endif

+{

+	int first=1;

+

+	while ( n>0 )

+	{

+		if ( !first ) putchar(' ');

+		first=0;

+		if ( suffix == NULL ) printf("%s", *classes);

+		else {

+			printf("%s", DIR());

+			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);

+			else printf("%s.%s", *classes, suffix);

+		}

+		classes++;

+		--n;

+	}

+}

+

+static void

+#ifdef __STDC__

+ProcessArgs( int argc, char **argv, Opt *options )

+#else

+ProcessArgs( argc, argv, options )

+int argc;

+char **argv;

+Opt *options;

+#endif

+{

+	Opt *p;

+	require(argv!=NULL, "ProcessArgs: command line NULL");

+

+	while ( argc-- > 0 )

+	{

+		p = options;

+		while ( p->option != NULL )

+		{

+			if ( strcmp(p->option, "*") == 0 ||

+				 strcmp(p->option, *argv) == 0 )

+			{

+				if ( p->arg )

+				{

+					(*p->process)( *argv, *(argv+1) );

+					argv++;

+					argc--;

+				}

+				else

+					(*p->process)( *argv );

+				break;

+			}

+			p++;

+		}

+		argv++;

+	}

+}

+

+#ifdef __STDC__

+void fatal( char *err_)

+#else

+void fatal( err_)

+char *err_;

+#endif

+{

+	fprintf(stderr, "genmk: %s\n", err_);

+	exit(1);

+}

+

+#ifdef __STDC__

+void warn( char *err_)

+#else

+void warn( err_)

+char *err_;

+#endif

+{

+	fprintf(stderr, "genmk: %s\n", err_);

+}

+

+#ifdef __STDC__

+char *DIR(void)

+#else

+char *DIR()

+#endif

+{

+	static char buf[200+1];

+	

+	if ( strcmp(outdir,TopDirectory)==0 ) return "";

+	sprintf(buf, "%s%s", outdir, DirectorySymbol);

+	return buf;

+}

diff --git a/Source/Pccts/support/genmk/genmk_old.c b/Source/Pccts/support/genmk/genmk_old.c
new file mode 100644
index 0000000..2cf9fad
--- /dev/null
+++ b/Source/Pccts/support/genmk/genmk_old.c
@@ -0,0 +1,762 @@
+/*

+ * genmk -- a program to make makefiles for PCCTS

+ *

+ * ANTLR 1.33MR10

+ * Terence John Parr 1989 - 1998

+ * Purdue University

+ * U of MN

+ */

+

+#include <stdio.h>

+#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */

+

+#ifdef VAXC

+#define DIE		return 0;

+#define DONE	return 1;

+#else

+#define DIE		return 1;

+#define DONE	return 0;

+#endif

+

+#ifndef require

+#define require(expr, err) {if ( !(expr) ) fatal(err);}

+#endif

+

+#define MAX_FILES	50

+#define MAX_CLASSES	50

+

+char *RENAME_OBJ_FLAG="-o",

+     *RENAME_EXE_FLAG="-o";

+

+char *dlg = "parser.dlg";

+char *err = "err.c";

+char *hdr = "stdpccts.h";

+char *tok = "tokens.h";

+char *mode = "mode.h";

+char *scan = "scan";

+

+char ATOKENBUFFER_O[100];

+char APARSER_O[100];

+char ASTBASE_O[100];

+char PCCTSAST_O[100];

+char LIST_O[100];

+char DLEXERBASE_O[100];

+

+/* Option flags */

+static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];

+static int	num_files = 0;

+static int	num_classes = 0;

+static int	user_lexer = 0;

+static char	*user_token_types = NULL;

+static int	gen_CPP = 0;

+static char *outdir=".";

+static char *dlg_class = "DLGLexer";

+static int	gen_trees = 0;

+static int  gen_hoist = 0;

+static char cfiles[1600]="";

+static char *compilerCCC="CC";

+static char *compilerCC="cc";

+static char *pccts_path="/usr/local/pccts";

+

+void help();

+void mk();

+void pfiles();

+void pclasses();

+void fatal();

+void warn();

+

+typedef struct _Opt {

+			char *option;

+			int  arg;

+#ifdef __cplusplus

+			void (*process)(...);

+#else

+			void (*process)();

+#endif

+			char *descr;

+		} Opt;

+

+#ifdef __STDC__

+static void ProcessArgs(int, char **, Opt *);

+#else

+static void ProcessArgs();

+#endif

+

+static void

+pProj( s, t )

+char *s;

+char *t;

+{

+	project = t;

+}

+

+static void

+pUL( s )

+char *s;

+{

+	user_lexer = 1;

+}

+

+static void

+pCPP( s )

+char *s;

+{

+	gen_CPP = 1;

+}

+

+static void

+pUT( s, t )

+char *s;

+char *t;

+{

+	user_token_types = t;

+}

+

+static void

+pTrees( s )

+char *s;

+{

+	gen_trees = 1;

+}

+

+static void

+pHoist( s )

+char *s;

+{

+	gen_hoist = 1;

+}

+

+static void

+#ifdef __STDC__

+pFile( char *s )

+#else

+pFile( s )

+char *s;

+#endif

+{

+	if ( *s=='-' )

+	{

+		fprintf(stderr, "invalid option: '%s'; ignored...",s);

+		return;

+	}

+

+	require(num_files<MAX_FILES, "exceeded max # of input files");

+	files[num_files++] = s;

+}

+

+static void

+#ifdef __STDC__

+pClass( char *s, char *t )

+#else

+pClass( s, t )

+char *s;

+char *t;

+#endif

+{

+	require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");

+	classes[num_classes++] = t;

+}

+

+static void

+#ifdef __STDC__

+pDLGClass( char *s, char *t )

+#else

+pDLGClass( s, t )

+char *s;

+char *t;

+#endif

+{

+	if ( !gen_CPP ) {

+		fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");

+	}

+	else dlg_class = t;

+}

+

+static void

+#ifdef __STDC__

+pOdir( char *s, char *t )

+#else

+pOdir( s, t )

+char *s;

+char *t;

+#endif

+{

+	outdir = t;

+}

+

+static void

+#ifdef __STDC__

+pHdr( char *s, char *t )

+#else

+pHdr( s, t )

+char *s;

+char *t;

+#endif

+{

+	hdr = t;

+}

+

+static void

+#ifdef __STDC__

+pCFiles( char *s, char *t )

+#else

+pCFiles( s, t )

+char *s;

+char *t;

+#endif

+{

+	strcat(strcat(cfiles," "), t);

+}

+

+static void

+#ifdef __STDC__

+pCompiler( char *s, char *t )

+#else

+pCompiler( s, t )

+char *s;

+char *t;

+#endif

+{

+        compilerCCC = t;

+	compilerCC = t;

+}

+

+static void

+#ifdef __STDC__

+ppccts_path( char *s, char *t )

+#else

+ppccts_path( s, t )

+char *s;

+char *t;

+#endif

+{

+        pccts_path = t;

+}

+

+Opt options[] = {

+    { "-CC", 0,	pCPP,			"Generate C++ output"},

+    { "-class", 1,	pClass,		"Name of a grammar class defined in grammar (if C++)"},

+    { "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},

+    { "-header", 1,pHdr,		"Name of ANTLR standard header info (default=no file)"},

+    { "-o", 1,	pOdir,			"Directory where output files should go (default=\".\")"},

+    { "-project", 1,	pProj,	"Name of executable to create (default=t)"},

+    { "-token-types", 1, pUT,	"Token types are in this file (don't use tokens.h)"},

+    { "-trees", 0, pTrees,		"Generate ASTs"},

+    { "-user-lexer", 0,	pUL,	"Do not create a DLG-based scanner"},

+    { "-mrhoist",0,pHoist,      "Maintenance release style hoisting"},

+    { "-cfiles",1,pCFiles,      "Additional files in C or C++ to compile"},

+    { "-pccts_path",1,ppccts_path,

+              "Path for $PCCTS directory (default is /usr/local/pccts)"},

+    { "-compiler",1,pCompiler,

+              "Default compiler (default is CC/cc)"},

+    { "*", 0,pFile, 	        "" },	/* anything else is a file */

+	{ NULL, 0, NULL, NULL }

+};

+

+extern char *DIR();

+

+int main(argc, argv)

+int argc;

+char **argv;

+{

+	if ( argc == 1 ) { help(); DIE; }

+	ProcessArgs(argc-1, &(argv[1]), options);

+

+	strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);

+	ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);

+	strcpy(APARSER_O, APARSER_C);

+	APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(APARSER_O, OBJ_FILE_SUFFIX);

+

+	strcpy(ASTBASE_O, ASTBASE_C);

+	ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(ASTBASE_O, OBJ_FILE_SUFFIX);

+

+	strcpy(PCCTSAST_O, PCCTSAST_C);

+	PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);

+

+	strcpy(LIST_O, LIST_C);

+	LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(LIST_O, OBJ_FILE_SUFFIX);

+

+	strcpy(DLEXERBASE_O, DLEXERBASE_C);

+	DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';

+	strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);

+

+	if ( num_files == 0 ) fatal("no grammar files specified; exiting...");

+	if ( !gen_CPP && num_classes>0 ) {

+		warn("can't define classes w/o C++ mode; turning on C++ mode...\n");

+		gen_CPP=1;

+	}

+	if ( gen_CPP && num_classes==0 ) {

+		fatal("must define classes >0 grammar classes in C++ mode\n");

+	}

+

+	mk(project, files, num_files, argc, argv);

+	DONE;

+}

+

+void help()

+{

+	Opt *p = options;

+	static char buf[1000+1];

+

+	fprintf(stderr, "genmk [options] f1.g ... fn.g\n");

+	while ( p->option!=NULL && *(p->option) != '*' )

+	{

+		buf[0]='\0';

+		if ( p->arg ) sprintf(buf, "%s ___", p->option);

+		else strcpy(buf, p->option);

+		fprintf(stderr, "\t%-16s   %s\n", buf, p->descr);

+		p++;

+	}

+}

+

+void mk(project, files, n, argc, argv)

+char *project;

+char **files;

+int n;

+int argc;

+char **argv;

+{

+	int i;

+

+	printf("#\n");

+	printf("# PCCTS makefile for: ");

+	pfiles(files, n, NULL);

+	printf("\n");

+	printf("#\n");

+	printf("# Created from:");

+	for (i=0; i<argc; i++) printf(" %s", argv[i]);

+	printf("\n");

+	printf("#\n");

+	printf("# PCCTS release 1.33MR21\n");

+	printf("# Project: %s\n", project);

+	if ( gen_CPP ) printf("# C++ output\n");

+	else printf("# C output\n");

+	if ( user_lexer ) printf("# User-defined scanner\n");

+	else printf("# DLG scanner\n");

+	if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);

+	else printf("# ANTLR-defined token types\n");

+	printf("#\n");

+	printf(".SUFFIXES:\n.SUFFIXES:      .o .cpp .c .h .g .i .dlg\n"); 

+	if ( user_token_types!=NULL ) {

+		printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");

+		printf("TOKENS = %s", user_token_types);

+	}

+	else printf("TOKENS = %stokens.h", DIR());

+	printf("\n");

+	printf("#\n");

+	printf("# The following filenames must be consistent with ANTLR/DLG flags\n");

+	printf("DLG_FILE = %s%s\n", DIR(), dlg);

+	printf("ERR = %serr\n", DIR());

+	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);

+	else printf("HDR_FILE =\n");

+	if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);

+	if ( !gen_CPP ) printf("SCAN = %s\n", scan);

+	else printf("SCAN = %s%s\n", DIR(), dlg_class);

+

+	printf("PCCTS = %s\n",pccts_path);

+	printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);

+	printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);

+	printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);

+	printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);

+	printf("CFLAGS = -I. -I$(ANTLR_H)");

+	if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);

+    printf(" $(COTHER)");

+	printf("\n");

+	printf("AFLAGS =");

+	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);

+	if ( user_lexer ) printf(" -gx");

+	if ( gen_CPP ) printf(" -CC");

+	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);

+	if ( gen_trees ) printf(" -gt");

+    if ( gen_hoist ) {

+      printf(" -mrhoist on") ;

+    } else {

+      printf(" -mrhoist off");

+    };

+    printf(" $(AOTHER)");

+	printf("\n");

+	printf("DFLAGS = -C2 -i");

+	if ( gen_CPP ) printf(" -CC");

+	if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);

+	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);

+    printf(" $(DOTHER)");

+	printf("\n");

+	printf("GRM = ");

+	pfiles(files, n, NULL);

+	printf("\n");

+	printf("MYFILES = %s\n",cfiles);

+	printf("SRC = ");

+	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);

+	else pfiles(files, n, "c");

+	if ( gen_CPP ) {

+		printf(" \\\n     ");

+		printf(" ");

+		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" \\\n      ");

+		printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);

+		if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);

+		if ( gen_trees ) {

+			printf(" \\\n      ");

+			printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);

+			printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);

+/*			printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */

+			printf(" \\\n      ");

+		}

+		printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);

+	}

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);

+		else printf(" %s$(SCAN).c", DIR());

+	}

+	if ( !gen_CPP ) printf(" $(ERR).c");

+	printf("\\\n	$(MYFILES)\n");

+	printf("OBJ = ");

+	pfiles(files, n, "o");

+	if ( gen_CPP ) {

+		printf(" \\\n     ");

+		printf(" ");

+		pclasses(classes, num_classes, "o");

+		printf(" \\\n      ");

+		printf(" %s%s", DIR(), APARSER_O);

+		if ( !user_lexer ) {

+			printf(" %s%s", DIR(), DLEXERBASE_O);

+		}

+		if ( gen_trees ) {

+			printf(" \\\n      ");

+			printf("%s%s", DIR(), ASTBASE_O);

+			printf(" %s%s", DIR(), PCCTSAST_O);

+/*			printf(" %s%s", DIR(), LIST_O); */

+			printf(" \\\n      ");

+		}

+		printf(" %s%s", DIR(), ATOKENBUFFER_O);

+	}

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);

+		else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);

+	}

+	if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);

+	printf("\\\n	$(MYFILES:.cpp=.o)\n");

+

+	printf("ANTLR_SPAWN = ");

+	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);

+	else pfiles(files, n, "c");

+	if ( gen_CPP ) {

+		printf(" ");

+		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" \\\n              ");

+		pclasses(classes, num_classes, "h");

+		if ( strcmp(hdr,"stdpccts.h")!=0 ) {

+			printf(" \\\n              ");

+			printf("$(HDR_FILE) stdpccts.h");

+		}

+	}

+	if ( user_lexer ) {

+		if ( !user_token_types ) printf(" $(TOKENS)");

+	}

+	else {

+		printf(" $(DLG_FILE)");

+		if ( !user_token_types ) printf(" $(TOKENS)");

+	}

+	if ( !gen_CPP ) printf(" $(ERR).c");

+	printf("\n");

+

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);

+		else printf("DLG_SPAWN = %s$(SCAN).c", DIR());

+		if ( gen_CPP ) printf(" $(SCAN).h");

+		if ( !gen_CPP ) printf(" $(MOD_FILE)");

+		printf("\n");

+	}

+

+	if ( gen_CPP ) {

+		printf("CCC = %s\n",compilerCCC);

+	}

+	else printf("CC = %s\n",compilerCC);

+

+	/* set up dependencies */

+	printf("\n%s : $(OBJ) $(SRC)\n", project);

+	printf("	%s %s %s $(CFLAGS) $(OBJ)\n",

+		   gen_CPP?"$(CCC)":"$(CC)",

+		   RENAME_EXE_FLAG,

+		   project);

+	printf("\n");

+

+	/* implicit rules */

+

+	if(gen_CPP)

+		printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");

+

+	printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",

+			gen_CPP?"$(CCC)":"$(CC)");

+

+	/* how to compile parser files */

+

+	for (i=0; i<num_files; i++)

+	{

+		pfiles(&files[i], 1, "o");

+		if ( user_lexer ) {

+			printf(" : $(TOKENS)");

+		}

+		else {

+			if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");

+			else printf(" : $(MOD_FILE) $(TOKENS)");

+		}

+		printf(" ");

+		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&files[i], 1, "c");

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+		printf("\n");

+		printf("	%s -c $(CFLAGS) %s ",

+		       gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+		pfiles(&files[i], 1, "o");

+		printf(" ");

+		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		else pfiles(&files[i], 1, "c");

+		printf("\n\n");

+	}

+

+	/* how to compile err.c */

+	if ( !gen_CPP ) {

+		printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);

+		if ( !user_lexer ) printf(" $(TOKENS)");

+		printf("\n");

+		printf("	%s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",

+			   gen_CPP?"$(CCC)":"$(CC)",

+			   RENAME_OBJ_FLAG,

+			   OBJ_FILE_SUFFIX);

+		printf("\n\n");

+	}

+

+	/* how to compile Class.c */

+	for (i=0; i<num_classes; i++)

+	{

+		pclasses(&classes[i], 1, "o");

+		if ( user_lexer ) {

+			printf(" : $(TOKENS)");

+		}

+		else {

+			printf(" : $(TOKENS) $(SCAN).h");

+		}

+		printf(" ");

+		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf(" ");

+		pclasses(&classes[i], 1, "h");

+		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");

+		printf("\n");

+		printf("	%s -c $(CFLAGS) %s ",

+			   gen_CPP?"$(CCC)":"$(CC)",

+			   RENAME_OBJ_FLAG);

+		pclasses(&classes[i], 1, "o");

+		printf(" ");

+		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);

+		printf("\n\n");

+	}

+

+	/* how to compile scan.c */

+	if ( !user_lexer ) {

+		if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);

+		else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());

+		if ( !user_lexer ) printf(" $(TOKENS)");

+		printf("\n");

+		if ( gen_CPP ) printf("	$(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",

+							  RENAME_OBJ_FLAG,

+							  OBJ_FILE_SUFFIX,

+							  CPP_FILE_SUFFIX);

+		else printf("	$(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",

+					RENAME_OBJ_FLAG,

+					DIR(),

+					OBJ_FILE_SUFFIX,

+					DIR());

+		printf("\n\n");

+	}

+

+	printf("$(ANTLR_SPAWN) : $(GRM)\n");

+	printf("	$(ANTLR) $(AFLAGS) $(GRM)\n");

+

+	if ( !user_lexer )

+	{

+		printf("\n");

+		printf("$(DLG_SPAWN) : $(DLG_FILE)\n");

+		if ( gen_CPP ) printf("	$(DLG) $(DFLAGS) $(DLG_FILE)\n");

+		else printf("	$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");

+	}

+

+	/* do the makes for ANTLR/DLG support */

+	if ( gen_CPP ) {

+		printf("\n");

+		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);

+		printf("	%s -c $(CFLAGS) %s ",

+			   gen_CPP?"$(CCC)":"$(CC)",

+			   RENAME_OBJ_FLAG);

+		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);

+		printf("\n");

+		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);

+		printf("	%s -c $(CFLAGS) %s ",

+			   gen_CPP?"$(CCC)":"$(CC)",

+			   RENAME_OBJ_FLAG);

+		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);

+		if ( !user_lexer ) {

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);

+			printf("	%s -c $(CFLAGS) %s ",

+				   gen_CPP?"$(CCC)":"$(CC)",

+				   RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);

+		}

+		if ( gen_trees ) {

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);

+			printf("	%s -c $(CFLAGS) %s ",

+				   gen_CPP?"$(CCC)":"$(CC)",

+				   RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);

+			printf("\n");

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);

+			printf("	%s -c $(CFLAGS) %s ",

+				   gen_CPP?"$(CCC)":"$(CC)",

+				   RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);

+			printf("\n");

+/*

+			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);

+			printf("	%s -c $(CFLAGS) %s ",

+			       gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);

+			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);

+*/

+		}

+	}

+

+	/* clean and scrub targets */

+

+	printf("\nclean:\n");

+	printf("	rm -f *%s core %s", OBJ_FILE_SUFFIX, project);

+	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);

+	printf("\n");

+

+	printf("\nscrub:\n");

+	printf("	rm -f *%s core %s", OBJ_FILE_SUFFIX, project);

+	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);

+	printf(" $(ANTLR_SPAWN)");

+	if ( !user_lexer ) printf(" $(DLG_SPAWN)");

+	printf("\n");

+}

+

+void pfiles(files, n, suffix)

+char **files;

+int n;

+char *suffix;

+{

+	int first=1;

+

+	while ( n>0 )

+	{

+		char *p = &(*files)[strlen(*files)-1];

+		if ( !first ) putchar(' ');

+		first=0;

+		while ( p > *files && *p != '.' ) --p;

+		if ( p == *files )

+		{

+			fprintf(stderr,

+					"genmk: filenames must be file.suffix format: %s\n",

+					*files);

+			exit(-1);

+		}

+		if ( suffix == NULL ) printf("%s", *files);

+		else

+		{

+			*p = '\0';

+			printf("%s", DIR());

+			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);

+			else printf("%s.%s", *files, suffix);

+			*p = '.';

+		}

+		files++;

+		--n;

+	}

+}

+

+void pclasses(classes, n, suffix)

+char **classes;

+int n;

+char *suffix;

+{

+	int first=1;

+

+	while ( n>0 )

+	{

+		if ( !first ) putchar(' ');

+		first=0;

+		if ( suffix == NULL ) printf("%s", *classes);

+		else {

+			printf("%s", DIR());

+			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);

+			else printf("%s.%s", *classes, suffix);

+		}

+		classes++;

+		--n;

+	}

+}

+

+static void

+#ifdef __STDC__

+ProcessArgs( int argc, char **argv, Opt *options )

+#else

+ProcessArgs( argc, argv, options )

+int argc;

+char **argv;

+Opt *options;

+#endif

+{

+	Opt *p;

+	require(argv!=NULL, "ProcessArgs: command line NULL");

+

+	while ( argc-- > 0 )

+	{

+		p = options;

+		while ( p->option != NULL )

+		{

+			if ( strcmp(p->option, "*") == 0 ||

+				 strcmp(p->option, *argv) == 0 )

+			{

+				if ( p->arg )

+				{

+					(*p->process)( *argv, *(argv+1) );

+					argv++;

+					argc--;

+				}

+				else

+					(*p->process)( *argv );

+				break;

+			}

+			p++;

+		}

+		argv++;

+	}

+}

+

+void fatal( err_)

+char *err_;

+{

+    fprintf(stderr, "genmk: %s\n", err_);

+    exit(1);

+}

+

+void warn( err_)

+char *err_;

+{

+    fprintf(stderr, "genmk: %s\n", err_);

+}

+

+char *DIR()

+{

+	static char buf[200+1];

+	

+	if ( strcmp(outdir,TopDirectory)==0 ) return "";

+	sprintf(buf, "%s%s", outdir, DirectorySymbol);

+	return buf;

+}

diff --git a/Source/Pccts/support/genmk/makefile b/Source/Pccts/support/genmk/makefile
new file mode 100644
index 0000000..a003c2f
--- /dev/null
+++ b/Source/Pccts/support/genmk/makefile
@@ -0,0 +1,29 @@
+##

+##  7-Apr-97

+##  added support/genmk/makefile to pccts 1.33MR1 distribution kit

+##		(support/genmk/makefile" omitted from 1.33 distribution kit)

+##

+SRC=genmk.c

+OBJ=genmk.o

+# Define PC if you use a PC OS (changes directory symbol and object file extension)

+# see pccts/h/pcctscfg.h

+CC=cc

+COPT=-O

+#CFLAGS=-I../../h -DPC

+CFLAGS=$(COPT) -I../../h

+BAG=../../bin/bag

+

+genmk: $(OBJ) $(SRC) ../../h/pcctscfg.h

+	$(CC) -o genmk $(OBJ)

+

+clean:

+	rm -rf core *.o

+

+scrub:

+	rm -rf genmk core *.o

+

+shar:

+	shar genmk.c makefile > genmk.shar

+

+archive:

+	$(BAG) genmk.c makefile > genmk.bag

diff --git a/Source/Pccts/support/rexpr/makefile b/Source/Pccts/support/rexpr/makefile
new file mode 100644
index 0000000..44caef1
--- /dev/null
+++ b/Source/Pccts/support/rexpr/makefile
@@ -0,0 +1,19 @@
+BAG=../../bin/bag

+SRC=test.c rexpr.c

+OBJ=test.o rexpr.o

+CFLAGS = -g

+

+test: $(OBJ) $(SRC)

+	cc -g -o texpr $(OBJ)

+

+shar:

+	shar makefile test.c rexpr.c rexpr.h > rexpr.shar

+

+archive:

+	$(BAG) makefile test.c rexpr.c rexpr.h > rexpr.bag

+

+clean:

+	rm -rf *.o core texpr

+

+scrub:

+	rm -rf *.o core texpr

diff --git a/Source/Pccts/support/rexpr/rexpr.c b/Source/Pccts/support/rexpr/rexpr.c
new file mode 100644
index 0000000..805bf65
--- /dev/null
+++ b/Source/Pccts/support/rexpr/rexpr.c
@@ -0,0 +1,586 @@
+/*

+ * This file contains code for

+ *

+ *      int rexpr(char *expr, char *s);

+ *

+ * which answers

+ *

+ *      1 if 's' is in the language described by the regular expression 'expr'

+ *      0 if it is not

+ *     -1 if the regular expression is invalid

+ *

+ * Language membership is determined by constructing a non-deterministic

+ * finite automata (NFA) from the regular expression.  A depth-

+ * first-search is performed on the NFA (graph) to check for a match of 's'.

+ * Each non-epsilon arc consumes one character from 's'.  Backtracking is

+ * performed to check all possible paths through the NFA.

+ *

+ * Regular expressions follow the meta-language:

+ *

+ * <regExpr>        ::= <andExpr> ( '|' <andExpr> )*

+ *

+ * <andExpr>        ::= <expr> ( <expr> )*

+ *

+ * <expr>           ::= {'~'} '[' <atomList> ']' <repeatSymbol>

+ *                      | '(' <regExpr> ')' <repeatSymbol>

+ *                      | '{' <regExpr> '}' <repeatSymbol>

+ *                      | <atom> <repeatSymbol>

+ *

+ * <repeatSymbol>   ::= { '*' | '+' }

+ *

+ * <atomList>       ::= <atom> ( <atom> )*

+ *                      | { <atomList> } <atom> '-' <atom> { <atomList> }

+ *

+ * <atom>           ::= Token[Atom]

+ *

+ * Notes:

+ *		~	means complement the set in [..]. i.e. all characters not listed

+ *		*	means match 0 or more times (can be on expression or atom)

+ *		+	means match 1 or more times (can be on expression or atom)

+ *		{}	optional

+ *		()	grouping

+ *		[]	set of atoms

+ *		x-y	all characters from x to y (found only in [..])

+ *		\xx the character with value xx

+ *

+ * Examples:

+ *		[a-z]+

+ *			match 1 or more lower-case letters (e.g. variable)

+ *

+ *		0x[0-9A-Fa-f]+

+ *			match a hex number with 0x on front (e.g. 0xA1FF)

+ *

+ *		[0-9]+.[0-9]+{e[0-9]+}

+ *			match a floating point number (e.g. 3.14e21)

+ *

+ * Code example:

+ *		if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword

+ *

+ * Terence Parr

+ * Purdue University

+ * April 1991

+ */

+

+#include <stdio.h>

+#include <ctype.h>

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif

+#include "rexpr.h"

+

+#ifdef __USE_PROTOS

+static int regExpr( GraphPtr g );

+static int andExpr( GraphPtr g );

+static int expr( GraphPtr g );

+static int repeatSymbol( GraphPtr g );

+static int atomList( char *p, int complement );

+static void next( void );

+static ArcPtr newGraphArc( void );

+static NodePtr newNode( void );

+static int ArcBetweenGraphNode( NodePtr i, NodePtr j, int label );

+static Graph BuildNFA_atom( int label );

+static Graph BuildNFA_AB( Graph A, Graph B );

+static Graph BuildNFA_AorB( Graph A, Graph B );

+static Graph BuildNFA_set( char *s );

+static Graph BuildNFA_Astar( Graph A );

+static Graph BuildNFA_Aplus( Graph A );

+static Graph BuildNFA_Aoptional( Graph A );

+#else

+static int regExpr();

+static int andExpr();

+static int expr();

+static int repeatSymbol();

+static int atomList();

+static void next();

+static ArcPtr newGraphArc();

+static NodePtr newNode();

+static int ArcBetweenGraphNode();

+static Graph BuildNFA_atom();

+static Graph BuildNFA_AB();

+static Graph BuildNFA_AorB();

+static Graph BuildNFA_set();

+static Graph BuildNFA_Astar();

+static Graph BuildNFA_Aplus();

+static Graph BuildNFA_Aoptional();

+#endif

+

+static char *_c;

+static int token, tokchar;

+static NodePtr accept;

+static NodePtr freelist = NULL;

+

+/*

+ * return 1 if s in language described by expr

+ *        0 if s is not

+ *       -1 if expr is an invalid regular expression

+ */

+#ifdef __USE_PROTOS

+static int rexpr(char *expr,char *s)

+#else

+static int rexpr(expr, s)

+char *expr, *s;

+#endif

+{

+	NodePtr p,q;

+	Graph nfa;

+	int result;

+

+	fprintf(stderr, "rexpr(%s,%s);\n", expr,s);

+	freelist = NULL;

+	_c = expr;

+	next();

+	if ( regExpr(&nfa) == -1 ) return -1;

+	accept = nfa.right;

+	result = match(nfa.left, s);

+	/* free all your memory */

+	p = q = freelist;

+	while ( p!=NULL ) { q = p->track; free(p); p = q; }

+	return result;

+}

+

+/*

+ * do a depth-first-search on the NFA looking for a path from start to

+ * accept state labelled with the characters of 's'.

+ */

+

+#ifdef __USE_PROTOS

+static int match(NodePtr automaton,char *s)

+#else

+static int match(automaton, s)

+NodePtr automaton;

+char *s;

+#endif

+{

+	ArcPtr p;

+	

+	if ( automaton == accept && *s == '\0' ) return 1;	/* match */

+

+	for (p=automaton->arcs; p!=NULL; p=p->next)			/* try all arcs */

+	{

+		if ( p->label == Epsilon )

+		{

+			if ( match(p->target, s) ) return 1;

+		}

+		else if ( p->label == *s )

+				if ( match(p->target, s+1) ) return 1;

+	}

+	return 0;

+}

+

+/*

+ * <regExpr>        ::= <andExpr> ( '|' {<andExpr>} )*

+ *

+ * Return -1 if syntax error

+ * Return  0 if none found

+ * Return  1 if a regExrp was found

+ */

+

+#ifdef __USE_PROTOS

+static int regExpr(GraphPtr g)

+#else

+static int regExpr(g)

+GraphPtr g;

+#endif

+{

+	Graph g1, g2;

+	

+	if ( andExpr(&g1) == -1 )

+	{

+		return -1;

+	}

+	

+	while ( token == '|' )

+	{

+		int a;

+		next();

+		a = andExpr(&g2);

+		if ( a == -1 ) return -1;	/* syntax error below */

+		else if ( !a ) return 1;	/* empty alternative */

+		g1 = BuildNFA_AorB(g1, g2);

+	}

+	

+	if ( token!='\0' ) return -1;

+

+	*g = g1;

+	return 1;

+}

+

+/*

+ * <andExpr>        ::= <expr> ( <expr> )*

+ */

+

+#ifdef __USE_PROTOS

+static int andExpr(GraphPtr g)

+#else

+static int andExpr(g)

+GraphPtr g;

+#endif

+{

+	Graph g1, g2;

+	

+	if ( expr(&g1) == -1 )

+	{

+		return -1;

+	}

+	

+	while ( token==Atom || token=='{' || token=='(' || token=='~' || token=='[' )

+	{

+		if (expr(&g2) == -1) return -1;

+		g1 = BuildNFA_AB(g1, g2);

+	}

+	

+	*g = g1;

+	return 1;

+}

+

+/*

+ * <expr>           ::=    {'~'} '[' <atomList> ']' <repeatSymbol>

+ *                      | '(' <regExpr> ')' <repeatSymbol>

+ *                      | '{' <regExpr> '}' <repeatSymbol>

+ *                      | <atom> <repeatSymbol>

+ */

+

+#ifdef __USE_PROTOS

+static int expr(GraphPtr g)

+#else

+static int expr(g)

+GraphPtr g;

+#endif

+{

+	int complement = 0;

+	char s[257];    /* alloc space for string of char in [] */

+	

+	if ( token == '~' || token == '[' )

+	{

+		if ( token == '~' ) {complement = 1; next();}

+		if ( token != '[' ) return -1;

+		next();

+		if ( atomList( s, complement ) == -1 ) return -1;

+		*g = BuildNFA_set( s );

+		if ( token != ']' ) return -1;

+		next();

+		repeatSymbol( g );

+		return 1;

+	}

+	if ( token == '(' )

+	{

+		next();

+		if ( regExpr( g ) == -1 ) return -1;

+		if ( token != ')' ) return -1;

+		next();

+		repeatSymbol( g );

+		return 1;

+	}

+	if ( token == '{' )

+	{

+		next();

+		if ( regExpr( g ) == -1 ) return -1;

+		if ( token != '}' ) return -1;

+		next();

+		/* S p e c i a l  C a s e   O p t i o n a l  {  } */

+		if ( token != '*' && token != '+' )

+		{

+			*g = BuildNFA_Aoptional( *g );

+		}

+		repeatSymbol( g );

+		return 1;

+	}

+	if ( token == Atom )

+	{

+		*g = BuildNFA_atom( tokchar );

+		next();

+		repeatSymbol( g );

+		return 1;

+	}

+	

+	return -1;

+}

+

+/*

+ * <repeatSymbol>   ::= { '*' | '+' }

+ */

+#ifdef __USE_PROTOS

+static int repeatSymbol(GraphPtr g)

+#else

+static int repeatSymbol(g)

+GraphPtr g;

+#endif

+{

+	switch ( token )

+	{

+		case '*' : *g = BuildNFA_Astar( *g ); next(); break;

+		case '+' : *g = BuildNFA_Aplus( *g ); next(); break;

+	}

+	return 1;

+}

+

+/*

+ * <atomList>       ::= <atom> { <atom> }*

+ *                      { <atomList> } <atom> '-' <atom> { <atomList> }

+ *

+ * a-b is same as ab

+ * q-a is same as q

+ */

+

+#ifdef __USE_PROTOS

+static int atomList(char *p, int complement)

+#else

+static int atomList(p, complement)

+char *p;

+int complement;

+#endif

+{

+	static unsigned char set[256];		/* no duplicates */

+	int first, last, i;

+	char *s = p;

+	

+	if ( token != Atom ) return -1;

+	

+	for (i=0; i<256; i++) set[i] = 0;

+	while ( token == Atom )

+	{

+		if ( !set[tokchar] ) *s++ = tokchar;

+		set[tokchar] = 1;    			/* Add atom to set */

+		next();

+		if ( token == '-' )         	/* have we found '-' */

+		{

+			first = *(s-1);             /* Get last char */

+			next();

+			if ( token != Atom ) return -1;

+			else

+			{

+				last = tokchar;

+			}

+			for (i = first+1; i <= last; i++)

+			{

+				if ( !set[tokchar] ) *s++ = i;

+				set[i] = 1;    			/* Add atom to set */

+			}

+			next();

+		}

+	}

+	*s = '\0';

+	if ( complement )

+	{

+		for (i=0; i<256; i++) set[i] = !set[i];

+		for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i;

+		*s = '\0';

+	}

+	return 1;

+}

+

+/* a somewhat stupid lexical analyzer */

+

+#ifdef __USE_PROTOS

+static void next(void)

+#else

+static void next()

+#endif

+{

+	while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++;

+	if ( *_c=='\\' )

+	{

+		_c++;

+		if ( isdigit(*_c) )

+		{

+			int n=0;

+			while ( isdigit(*_c) )

+			{

+				n = n*10 + (*_c++ - '0');

+			}

+			if ( n>255 ) n=255;

+			tokchar = n;

+		}

+		else

+		{

+			switch (*_c)

+			{

+				case 'n' : tokchar = '\n'; break;

+				case 't' : tokchar = '\t'; break;

+				case 'r' : tokchar = '\r'; break;

+				default  : tokchar = *_c;

+			}

+			_c++;

+		}

+		token = Atom;

+	}

+	else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' &&

+			  *_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' &&

+			  *_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' )

+	{

+		token = Atom;

+		tokchar = *_c++;

+	}

+	else

+	{

+		token = tokchar = *_c++;

+	}

+}

+

+/* N F A  B u i l d i n g  R o u t i n e s */

+

+#ifdef __USE_PROTOS

+static ArcPtr newGraphArc(void)

+#else

+static ArcPtr newGraphArc()

+#endif

+{

+	ArcPtr p;

+	p = (ArcPtr) calloc(1, sizeof(Arc));

+	if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}

+	if ( freelist != NULL ) p->track = (ArcPtr) freelist;

+	freelist = (NodePtr) p;

+	return p;

+}

+

+#ifdef __USE_PROTOS

+static NodePtr newNode(void)

+#else

+static NodePtr newNode()

+#endif

+{

+	NodePtr p;

+	p = (NodePtr) calloc(1, sizeof(Node));

+	if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}

+	if ( freelist != NULL ) p->track = freelist;

+	freelist = p;

+	return p;

+}

+

+#ifdef __USE_PROTOS

+static void ArcBetweenGraphNodes(NodePtr i,NodePtr j,int label)

+#else

+static void ArcBetweenGraphNodes(i, j, label)

+NodePtr i, j;

+int label;

+#endif

+{

+	ArcPtr a;

+	

+	a = newGraphArc();

+	if ( i->arcs == NULL ) i->arctail = i->arcs = a;

+	else {(i->arctail)->next = a; i->arctail = a;}

+	a->label = label;

+	a->target = j;

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_atom(int label)

+#else

+static Graph BuildNFA_atom(label)

+int label;

+#endif

+{

+	Graph g;

+	

+	g.left = newNode();

+	g.right = newNode();

+	ArcBetweenGraphNodes(g.left, g.right, label);

+	return( g );

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_AB(Graph A,Graph B)

+#else

+static Graph BuildNFA_AB(A, B)

+Graph A, B;

+#endif

+{

+	Graph g;

+	

+	ArcBetweenGraphNodes(A.right, B.left, Epsilon);

+	g.left = A.left;

+	g.right = B.right;

+	return( g );

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_AorB(Graph A,Graph B)

+#else

+static Graph BuildNFA_AorB(A, B)

+Graph A, B;

+#endif

+{

+	Graph g;

+	

+	g.left = newNode();

+	ArcBetweenGraphNodes(g.left, A.left, Epsilon);

+	ArcBetweenGraphNodes(g.left, B.left, Epsilon);

+	g.right = newNode();

+	ArcBetweenGraphNodes(A.right, g.right, Epsilon);

+	ArcBetweenGraphNodes(B.right, g.right, Epsilon);

+	return( g );

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_set(char *s)

+#else

+static Graph BuildNFA_set( s )

+char *s;

+#endif

+{

+	Graph g;

+	

+	if ( s == NULL ) return g;

+	

+	g.left = newNode();

+	g.right = newNode();

+	while ( *s != '\0' )

+	{

+		ArcBetweenGraphNodes(g.left, g.right, *s++);

+	}

+	return g;

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_Astar(Graph A)

+#else

+static Graph BuildNFA_Astar( A )

+Graph A;

+#endif

+{

+	Graph g;

+

+	g.left = newNode();

+	g.right = newNode();

+	

+	ArcBetweenGraphNodes(g.left, A.left, Epsilon);

+	ArcBetweenGraphNodes(g.left, g.right, Epsilon);

+	ArcBetweenGraphNodes(A.right, g.right, Epsilon);

+	ArcBetweenGraphNodes(A.right, A.left, Epsilon);

+	

+	return( g );

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_Aplus(Graph A)

+#else

+static Graph BuildNFA_Aplus( A )

+Graph A;

+#endif

+{

+	ArcBetweenGraphNodes(A.right, A.left, Epsilon);

+	

+	return( A );

+}

+

+#ifdef __USE_PROTOS

+static Graph BuildNFA_Aoptional(Graph A)

+#else

+static Graph BuildNFA_Aoptional( A )

+Graph A;

+#endif

+{

+	Graph g;

+	

+	g.left = newNode();

+	g.right = newNode();

+	

+	ArcBetweenGraphNodes(g.left, A.left, Epsilon);

+	ArcBetweenGraphNodes(g.left, g.right, Epsilon);

+	ArcBetweenGraphNodes(A.right, g.right, Epsilon);

+	

+	return( g );

+}

diff --git a/Source/Pccts/support/rexpr/rexpr.h b/Source/Pccts/support/rexpr/rexpr.h
new file mode 100644
index 0000000..e67a965
--- /dev/null
+++ b/Source/Pccts/support/rexpr/rexpr.h
@@ -0,0 +1,30 @@
+#define Atom	256		/* token Atom (an impossible char value) */

+#define Epsilon	257		/* epsilon arc (an impossible char value) */

+

+/* track field must be same for all node types */

+typedef struct _a {

+					struct _a *track;	/* track mem allocation */

+					int label;

+					struct _a *next;

+					struct _n *target;

+				} Arc, *ArcPtr;

+

+typedef struct _n {

+					struct _n *track;

+					ArcPtr arcs, arctail;

+				} Node, *NodePtr;

+

+typedef struct	{

+					NodePtr left,

+						 	right;

+				} Graph, *GraphPtr;

+

+#ifdef __USE_PROTOS

+int rexpr( char *expr, char *s );

+int match( NodePtr automaton, char *s );

+#else

+int rexpr();

+int match();

+#endif

+

+

diff --git a/Source/Pccts/support/rexpr/test.c b/Source/Pccts/support/rexpr/test.c
new file mode 100644
index 0000000..2619539
--- /dev/null
+++ b/Source/Pccts/support/rexpr/test.c
@@ -0,0 +1,19 @@
+#include <stdio.h>

+#include "rexpr.h"

+

+/*

+ * test for rexpr().

+ * To make this test:

+ *	cc -o rexpr test.c rexpr.c

+ * Then from command line type:

+ *	rexpr r string

+ * where r is the regular expression that decribes a language

+ * and string is the string to verify.

+ */

+main(argc,argv)

+int argc;

+char *argv[];

+{

+	if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n");

+	else printf("%d\n", rexpr(argv[1], argv[2]));

+}

diff --git a/Source/Pccts/support/set/set.c b/Source/Pccts/support/set/set.c
new file mode 100644
index 0000000..eb6fba7
--- /dev/null
+++ b/Source/Pccts/support/set/set.c
@@ -0,0 +1,816 @@
+/*	set.c

+

+	The following is a general-purpose set library originally developed

+	by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.

+	

+	Sets are now structs containing the #words in the set and

+	a pointer to the actual set words.

+	

+	Generally, sets need not be explicitly allocated.  They are

+	created/extended/shrunk when appropriate (e.g. in set_of()).

+	HOWEVER, sets need to be destroyed (free()ed) when they go out of scope

+	or are otherwise no longer needed.  A routine is provided to

+	free a set.

+	

+	Sets can be explicitly created with set_new(s, max_elem).

+	

+	Sets can be declared to have minimum size to reduce realloc traffic.

+	Default minimum size = 1.

+	

+	Sets can be explicitly initialized to have no elements (set.n == 0)

+	by using the 'empty' initializer:

+	

+	Examples:

+		set a = empty;	-- set_deg(a) == 0

+		

+		return( empty );

+	

+	Example set creation and destruction:

+	

+	set

+	set_of2(e,g)

+	unsigned e,g;

+	{

+		set a,b,c;

+		

+		b = set_of(e);		-- Creates space for b and sticks in e

+		set_new(c, g);		-- set_new(); set_orel() ==> set_of()

+		set_orel(g, &c);

+		a = set_or(b, c);

+		.

+		.

+		.

+		set_free(b);

+		set_free(c);

+		return( a );

+	}

+

+	1987 by Hank Dietz

+	

+	Modified by:

+		Terence Parr

+		Purdue University

+		October 1989

+

+	Made it smell less bad to C++ 7/31/93 -- TJP

+*/

+

+#include <stdio.h>

+#include "pcctscfg.h"

+#ifdef __STDC__

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif

+#include <string.h>

+

+#include "set.h"

+

+#define MIN(i,j) ( (i) > (j) ? (j) : (i))

+#define MAX(i,j) ( (i) < (j) ? (j) : (i))

+

+/* elems can be a maximum of 32 bits */

+static unsigned bitmask[] = {

+	0x00000001, 0x00000002, 0x00000004, 0x00000008,

+	0x00000010, 0x00000020, 0x00000040, 0x00000080,

+	0x00000100, 0x00000200, 0x00000400, 0x00000800,

+	0x00001000, 0x00002000, 0x00004000, 0x00008000,

+#if !defined(PC) || defined(PC32)

+	0x00010000, 0x00020000, 0x00040000, 0x00080000,

+	0x00100000, 0x00200000, 0x00400000, 0x00800000,

+	0x01000000, 0x02000000, 0x04000000, 0x08000000,

+	0x10000000, 0x20000000, 0x40000000, 0x80000000

+#endif

+};

+

+set empty = set_init;

+static unsigned min=1;

+

+#define StrSize		200

+

+#ifdef MEMCHK

+#define CHK(a)					\

+	if ( a.setword != NULL )	\

+	  if ( !valid(a.setword) )	\

+		{fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);}

+#else

+#define CHK(a)

+#endif

+

+/*

+ * Set the minimum size (in words) of a set to reduce realloc calls

+ */

+void

+#ifdef __USE_PROTOS

+set_size( unsigned n )

+#else

+set_size( n )

+unsigned n;

+#endif

+{

+	min = n;

+}

+

+unsigned int

+#ifdef __USE_PROTOS

+set_deg( set a )

+#else

+set_deg( a )

+set a;

+#endif

+{

+	/* Fast compute degree of a set... the number

+	   of elements present in the set.  Assumes

+	   that all word bits are used in the set

+	   and that SETSIZE(a) is a multiple of WORDSIZE.

+	*/

+	register unsigned *p = &(a.setword[0]);

+	register unsigned *endp = NULL; /* MR27 Avoid false memory check report */

+	register unsigned degree = 0;

+

+	CHK(a);

+	if ( a.n == 0 ) return(0);

+	endp = &(a.setword[a.n]);

+	while ( p < endp )

+	{

+		register unsigned t = *p;

+		register unsigned *b = &(bitmask[0]);

+		do {

+			if (t & *b) ++degree;

+		} while (++b < &(bitmask[WORDSIZE]));

+		p++;

+	}

+

+	return(degree);

+}

+

+set

+#ifdef __USE_PROTOS

+set_or( set b, set c )

+#else

+set_or( b, c )

+set b;

+set c;

+#endif

+{

+	/* Fast set union operation */

+	/* resultant set size is max(b, c); */

+	set *big;

+	set t;

+	unsigned int m,n;

+	register unsigned *r, *p, *q, *endp;

+

+	CHK(b); CHK(c);

+	t = empty;

+	if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;}

+	set_ext(&t, m);

+	r = t.setword;

+

+	/* Or b,c until max of smaller set */

+	q = c.setword;

+	p = b.setword;

+	endp = &(b.setword[n]);

+	while ( p < endp ) *r++ = *p++ | *q++;	

+

+	/* Copy rest of bigger set into result */

+	p = &(big->setword[n]);

+	endp = &(big->setword[m]);

+	while ( p < endp ) *r++ = *p++;

+

+	return(t);

+}

+

+set

+#ifdef __USE_PROTOS

+set_and( set b, set c )

+#else

+set_and( b, c )

+set b;

+set c;

+#endif

+{

+	/* Fast set intersection operation */

+	/* resultant set size is min(b, c); */

+	set t;

+	unsigned int n;

+	register unsigned *r, *p, *q, *endp;

+

+	CHK(b); CHK(c);

+	t = empty;

+	n = (b.n > c.n) ? c.n : b.n;

+	if ( n == 0 ) return t;		/* TJP 4-27-92 fixed for empty set */

+	set_ext(&t, n);

+	r = t.setword;

+

+	/* & b,c until max of smaller set */

+	q = c.setword;

+	p = b.setword;

+	endp = &(b.setword[n]);

+	while ( p < endp ) *r++ = *p++ & *q++;	

+

+	return(t);

+}

+

+set

+#ifdef __USE_PROTOS

+set_dif( set b, set c )

+#else

+set_dif( b, c )

+set b;

+set c;

+#endif

+{

+	/* Fast set difference operation b - c */

+	/* resultant set size is size(b) */

+	set t;

+	unsigned int n;

+	register unsigned *r, *p, *q, *endp;

+

+	CHK(b); CHK(c);

+	t = empty;

+	n = (b.n <= c.n) ? b.n : c.n ;

+	if ( b.n == 0 ) return t;		/* TJP 4-27-92 fixed for empty set */

+									/* WEC 12-1-92 fixed for c.n = 0 */

+	set_ext(&t, b.n);

+	r = t.setword;

+

+	/* Dif b,c until smaller set size */

+	q = c.setword;

+	p = b.setword;

+	endp = &(b.setword[n]);

+	while ( p < endp ) *r++ = *p++ & (~ *q++);	

+

+	/* Copy rest of b into result if size(b) > c */

+	if ( b.n > n )

+	{

+		p = &(b.setword[n]);

+		endp = &(b.setword[b.n]);

+		while ( p < endp ) *r++ = *p++;

+	}

+

+	return(t);

+}

+

+set

+#ifdef __USE_PROTOS

+set_of( unsigned b )

+#else

+set_of( b )

+unsigned b;

+#endif

+{

+	/* Fast singleton set constructor operation */

+	static set a;

+

+	if ( b == nil ) return( empty );

+	set_new(a, b);

+	a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];

+

+	return(a);

+}

+

+/*

+ * Extend (or shrink) the set passed in to have n words.

+ *

+ * if n is smaller than the minimum, boost n to have the minimum.

+ * if the new set size is the same as the old one, do nothing.

+ *

+ * TJP 4-27-92 Fixed so won't try to alloc 0 bytes

+ */

+void

+#ifdef __USE_PROTOS

+set_ext( set *a, unsigned int n )

+#else

+set_ext( a, n )

+set *a;

+unsigned int n;

+#endif

+{

+	register unsigned *p;

+	register unsigned *endp;

+	unsigned int size;

+	

+	CHK((*a));

+    if ( a->n == 0 )

+    {

+		if ( n == 0 ) return;

+		if (a->setword != NULL) {

+			free (a->setword);	/* MR20 */

+		}

+        a->setword = (unsigned *) calloc(n, BytesPerWord);

+        if ( a->setword == NULL )

+        {

+            fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);

+            exit(-1);

+        }

+        a->n = n;

+        return;

+    }

+	if ( n < min ) n = min;

+	if ( a->n == n || n == 0 ) return;

+	size = a->n;

+	a->n = n;

+	a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) );

+	if ( a->setword == NULL )

+	{

+		fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);

+		exit(-1);

+	}

+

+	p    = &(a->setword[size]);		/* clear from old size to new size */

+	endp = &(a->setword[a->n]);

+	do {

+		*p++ = 0;

+	} while ( p < endp );

+}

+

+set

+#ifdef __USE_PROTOS

+set_not( set a )

+#else

+set_not( a )

+set a;

+#endif

+{

+	/* Fast not of set a (assumes all bits used) */

+	/* size of resultant set is size(a) */

+	/* ~empty = empty cause we don't know how bit to make set */

+	set t;

+	register unsigned *r;

+	register unsigned *p = a.setword;

+	register unsigned *endp = &(a.setword[a.n]);

+

+	CHK(a);

+	t = empty;

+	if ( a.n == 0 ) return( empty );

+	set_ext(&t, a.n);

+	r = t.setword;

+	

+	do {

+		*r++ = (~ *p++);

+	} while ( p < endp );

+

+	return(t);

+}

+

+int

+#ifdef __USE_PROTOS

+set_equ( set a, set b )

+#else

+set_equ( a, b )

+set a;

+set b;

+#endif

+{

+/* 8-Nov-97     Make it work with sets of different sizes       */

+/*              Easy to understand, too.  Probably faster.      */

+/*              Check for a equal to b                          */

+

+    unsigned int    count;      /* MR11 */

+    unsigned int    i;          /* MR11 */

+

+	CHK(a); CHK(b);

+

+    count=MIN(a.n,b.n);

+    if (count == 0) return 1;

+    for (i=0; i < count; i++) {

+      if (a.setword[i] != b.setword[i]) return 0;

+    };

+    if (a.n < b.n) {

+      for (i=count; i < b.n; i++) {

+        if (b.setword[i] != 0) return 0;

+      }

+      return 1;

+    } else if (a.n > b.n) {

+      for (i=count; i < a.n; i++) {

+        if (a.setword[i] != 0) return 0;

+      }

+      return 1;

+    } else {

+      return 1;

+    };

+}

+

+int

+#ifdef __USE_PROTOS

+set_sub( set a, set b )

+#else

+set_sub( a, b )

+set a;

+set b;

+#endif

+{

+

+/* 8-Nov-97     Make it work with sets of different sizes       */

+/*              Easy to understand, too.  Probably faster.      */

+/*              Check for a is a PROPER subset of b             */

+

+    unsigned int    count;

+    unsigned int    i;

+

+	CHK(a); CHK(b);

+

+    if (a.n == 0) return 1;

+    count=MIN(a.n,b.n);

+    for (i=0; i < count; i++) {

+      if (a.setword[i] & ~b.setword[i]) return 0;

+    };

+    if (a.n <= b.n) {

+      return 1;

+    } else {

+      for (i=count; i<a.n ; i++) {

+        if (a.setword[i]) return 0;

+      };

+    };

+    return 1;

+}

+

+unsigned

+#ifdef __USE_PROTOS

+set_int( set b )

+#else

+set_int( b )

+set b;

+#endif

+{

+	/* Fast pick any element of the set b */

+	register unsigned *p = b.setword;

+	register unsigned *endp = &(b.setword[b.n]);

+

+	CHK(b);

+	if ( b.n == 0 ) return( nil );

+

+	do {

+		if (*p) {

+			/* Found a non-empty word of the set */

+			register unsigned i = ((p - b.setword) << LogWordSize);

+			register unsigned t = *p;

+			p = &(bitmask[0]);

+			while (!(*p & t)) {

+				++i; ++p;

+			}

+			return(i);

+		}

+	} while (++p < endp);

+

+	/* Empty -- only element it contains is nil */

+	return(nil);

+}

+

+int

+#ifdef __USE_PROTOS

+set_el( unsigned b, set a )

+#else

+set_el( b, a )

+unsigned b;

+set a;

+#endif

+{

+	CHK(a);

+	/* nil is an element of every set */

+	if (b == nil) return(1);

+	if ( a.n == 0 || NumWords(b) > a.n ) return(0);

+	

+	/* Otherwise, we have to check */

+	return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] );

+}

+

+int

+#ifdef __USE_PROTOS

+set_nil( set a )

+#else

+set_nil( a )

+set a;

+#endif

+{

+	/* Fast check for nil set */

+	register unsigned *p = a.setword;

+	register unsigned *endp;

+

+	CHK(a);

+	if ( a.n == 0 ) return(1);

+	endp = &(a.setword[a.n]);

+	

+	/* The set is not empty if any word used to store

+	   the set is non-zero.  This means one must be a

+	   bit careful about doing things like negation.

+	*/

+	do {

+		if (*p) return(0);

+	} while (++p < endp);

+	

+	return(1);

+}

+

+char *

+#ifdef __USE_PROTOS

+set_str( set a )

+#else

+set_str( a )

+set a;

+#endif

+{

+	/* Fast convert set a into ASCII char string...

+	   assumes that all word bits are used in the set

+	   and that SETSIZE is a multiple of WORDSIZE.

+	   Trailing 0 bits are removed from the string.

+	   if no bits are on or set is empty, "" is returned.

+	*/

+	register unsigned *p = a.setword;

+	register unsigned *endp = &(a.setword[a.n]);

+	static char str_tmp[StrSize+1];

+	register char *q = &(str_tmp[0]);

+

+	CHK(a);

+	if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );}

+	do {

+		register unsigned t = *p;

+		register unsigned *b = &(bitmask[0]);

+		do {

+			*(q++) = (char) ((t & *b) ? '1' : '0');

+		} while (++b < &(bitmask[WORDSIZE]));

+	} while (++p < endp);

+

+	/* Trim trailing 0s & NULL terminate the string */

+	while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q;

+	*q = 0;

+

+	return(&(str_tmp[0]));

+}

+

+set

+#ifdef __USE_PROTOS

+set_val( register char *s )

+#else

+set_val( s )

+register char *s;

+#endif

+{

+	/* Fast convert set ASCII char string into a set.

+	   If the string ends early, the remaining set bits

+	   are all made zero.

+	   The resulting set size is just big enough to hold all elements.

+	*/

+	static set a;

+	register unsigned *p, *endp;

+

+	set_new(a, strlen(s));

+	p = a.setword;

+	endp = &(a.setword[a.n]);

+	do {

+		register unsigned *b = &(bitmask[0]);

+		/* Start with a word with no bits on */

+		*p = 0;

+		do {

+			if (*s) {

+				if (*s == '1') {

+					/* Turn-on this bit */

+					*p |= *b;

+				}

+				++s;

+			}

+		} while (++b < &(bitmask[WORDSIZE]));

+	} while (++p < endp);

+

+	return(a);

+}

+

+/*

+ * Or element e into set a.  a can be empty.

+ */

+void

+#ifdef __USE_PROTOS

+set_orel( unsigned e, set *a )

+#else

+set_orel( e, a )

+unsigned e;

+set *a;

+#endif

+{

+	CHK((*a));

+	if ( e == nil ) return;

+	if ( NumWords(e) > a->n ) set_ext(a, NumWords(e));

+	a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)];

+}

+

+/*

+ * Or set b into set a.  a can be empty. does nothing if b empty.

+ */

+void

+#ifdef __USE_PROTOS

+set_orin( set *a, set b )

+#else

+set_orin( a, b )

+set *a;

+set b;

+#endif

+{

+	/* Fast set union operation */

+	/* size(a) is max(a, b); */

+	unsigned int m;

+	register unsigned *p,

+					  *q    = b.setword,

+					  *endq; /* MR20 */

+

+	CHK((*a)); CHK(b);

+	if ( b.n == 0 ) return;

+	endq = &(b.setword[b.n]); /* MR20 */

+	m = (a->n > b.n) ? a->n : b.n;

+	set_ext(a, m);

+	p = a->setword;

+	do {

+		*p++ |= *q++;

+	} while ( q < endq );

+}

+

+/*

+ * And set b into set a.  a can be empty. does nothing if b empty.

+ */

+void

+#ifdef __USE_PROTOS

+set_andin( set *a, set b )

+#else

+set_andin( a, b )

+set *a;

+set b;

+#endif

+{

+	/* Fast set intersection operation */

+	/* size(a) is max(a, b); */

+	unsigned int m;

+	register unsigned *p,

+					  *q    = b.setword,

+					  *endq = &(b.setword[b.n]);

+

+	CHK((*a)); CHK(b);

+	if ( b.n == 0 ) return;

+	m = (a->n > b.n) ? a->n : b.n;

+	set_ext(a, m);

+	p = a->setword;

+	do {

+		*p++ &= *q++;

+	} while ( q < endq );

+}

+

+void

+#ifdef __USE_PROTOS

+set_rm( unsigned e, set a )

+#else

+set_rm( e, a )

+unsigned e;

+set a;

+#endif

+{

+	/* Does not effect size of set */

+	CHK(a);

+	if ( (e == nil) || (NumWords(e) > a.n) ) return;

+	a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]);

+}

+

+void

+#ifdef __USE_PROTOS

+set_clr( set a )

+#else

+set_clr( a )

+set a;

+#endif

+{

+	/* Does not effect size of set */

+	register unsigned *p = a.setword;

+	register unsigned *endp;

+	

+	CHK(a);

+	if ( a.n == 0 ) return;

+	endp = &(a.setword[a.n]);

+	do {

+		*p++ = 0;

+	} while ( p < endp );

+}

+

+set

+#ifdef __USE_PROTOS

+set_dup( set a )

+#else

+set_dup( a )

+set a;

+#endif

+{

+	set b;

+	register unsigned *p,

+					  *q    = a.setword,

+					  *endq; /* MR20 */

+	

+	CHK(a);

+	b = empty;

+	if ( a.n == 0 ) return( empty );

+	endq = &(a.setword[a.n]);	/* MR20 */

+	set_ext(&b, a.n);

+	p = b.setword;

+	do {

+		*p++ = *q++;

+	} while ( q < endq );

+	

+	return(b);

+}

+

+/*

+ * Return a nil terminated list of unsigned ints that represents all

+ * "on" bits in the bit set.

+ *

+ * e.g. {011011} --> {1, 2, 4, 5, nil}

+ *

+ * _set_pdq and set_pdq are useful when an operation is required on each element

+ * of a set.  Normally, the sequence is:

+ *

+ *		while ( set_deg(a) > 0 ) {

+ *			e = set_int(a);

+ *			set_rm(e, a);

+ *			...process e...

+ *		}

+ * Now,

+ *

+ *		t = e = set_pdq(a);

+ *		while ( *e != nil ) {

+ *			...process *e...

+ *			e++;

+ *		}

+ *		free( t );

+ *

+ * We have saved many set calls and have not destroyed set a.

+ */

+void

+#ifdef __USE_PROTOS

+_set_pdq( set a, register unsigned *q )

+#else

+_set_pdq( a, q )

+set a;

+register unsigned *q;

+#endif

+{

+	register unsigned *p = a.setword,

+					  *endp = &(a.setword[a.n]);

+	register unsigned e=0;

+

+	CHK(a);

+	/* are there any space (possibility of elements)? */

+	if ( a.n == 0 ) return;

+	do {

+		register unsigned t = *p;

+		register unsigned *b = &(bitmask[0]);

+		do {

+			if ( t & *b ) *q++ = e;

+			++e;

+		} while (++b < &(bitmask[WORDSIZE]));

+	} while (++p < endp);

+	*q = nil;

+}

+

+/*

+ * Same as _set_pdq except allocate memory.  set_pdq is the natural function

+ * to use.

+ */

+unsigned *

+#ifdef __USE_PROTOS

+set_pdq( set a )

+#else

+set_pdq( a )

+set a;

+#endif

+{

+	unsigned *q;

+	int max_deg;

+	

+	CHK(a);

+	max_deg = WORDSIZE*a.n;

+	/* assume a.n!=0 & no elements is rare, but still ok */

+	if ( a.n == 0 ) return(NULL);

+	q = (unsigned *) malloc((max_deg+1)*BytesPerWord);

+	if ( q == NULL ) return( NULL );

+	_set_pdq(a, q);

+	return( q );

+}

+

+/* a function that produces a hash number for the set

+ */

+unsigned int

+#ifdef __USE_PROTOS

+set_hash( set a, register unsigned int mod )

+#else

+set_hash( a, mod )

+set a;

+register unsigned int mod;

+#endif

+{

+	/* Fast hash of set a (assumes all bits used) */

+	register unsigned *p = &(a.setword[0]);

+	register unsigned *endp = &(a.setword[a.n]);

+	register unsigned i = 0;

+

+	CHK(a);

+	while (p<endp){

+		i += (*p);

+		++p;

+	}

+

+	return(i % mod);

+}

diff --git a/Source/Pccts/support/set/set.h b/Source/Pccts/support/set/set.h
new file mode 100644
index 0000000..5d68152
--- /dev/null
+++ b/Source/Pccts/support/set/set.h
@@ -0,0 +1,121 @@
+#ifndef __GATE_SET_H

+#define __GATE_SET_H

+

+/*	set.h

+

+	The following is a general-purpose set library originally developed

+	by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.

+	

+	Sets are now structs containing the #words in the set and

+	a pointer to the actual set words.

+

+	1987 by Hank Dietz

+	

+	Modified by:

+		Terence Parr

+		Purdue University

+		October 1989

+

+		Added ANSI prototyping Dec. 1992 -- TJP

+*/

+

+#include "pcctscfg.h"

+

+#ifdef NOT_USED /* SEE config.h */

+/* Define usable bits per unsigned int word */

+#ifdef PC

+#define WORDSIZE 16

+#define LogWordSize	4

+#else

+#define	WORDSIZE 32

+#define LogWordSize 5

+#endif

+#define BytesPerWord	sizeof(unsigned)

+#endif

+

+#define	SETSIZE(a) ((a).n<<LogWordSize)		/* Maximum items per set */

+#define	MODWORD(x) ((x) & (WORDSIZE-1))		/* x % WORDSIZE */

+#define	DIVWORD(x) ((x) >> LogWordSize)		/* x / WORDSIZE */

+#define	nil	(~((unsigned) 0))	/* An impossible set member all bits on (big!) */

+

+typedef struct _set {

+			unsigned int n;		/* Number of words in set */

+			unsigned *setword;

+		} set;

+

+#define set_init	{0, NULL}

+#define set_null(a)	((a).setword==NULL)

+

+#define	NumBytes(x)		(((x)>>3)+1)						/* Num bytes to hold x */

+#define	NumWords(x)		((((unsigned)(x))>>LogWordSize)+1)	/* Num words to hold x */

+

+

+/* M a c r o s */

+

+/* make arg1 a set big enough to hold max elem # of arg2 */

+#define set_new(a,_max) \

+if (((a).setword=(unsigned *)calloc(NumWords(_max),BytesPerWord))==NULL) \

+        fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", _max); \

+        (a).n = NumWords(_max);

+

+#define set_free(a)									\

+	{if ( (a).setword != NULL ) free((char *)((a).setword));	\

+	(a) = empty;}

+

+#ifdef __USE_PROTOS

+extern void set_size( unsigned );

+extern unsigned int set_deg( set );

+extern set set_or( set, set );

+extern set set_and( set, set );

+extern set set_dif( set, set );

+extern set set_of( unsigned );

+extern void set_ext( set *, unsigned int );

+extern set set_not( set );

+extern int set_equ( set, set );

+extern int set_sub( set, set );

+extern unsigned set_int( set );

+extern int set_el( unsigned, set );

+extern int set_nil( set );

+extern char * set_str( set );

+extern set set_val( register char * );

+extern void set_orel( unsigned, set * );

+extern void set_orin( set *, set );

+extern void set_andin( set *, set );

+extern void set_rm( unsigned, set );

+extern void set_clr( set );

+extern set set_dup( set );

+extern void set_PDQ( set, register unsigned * );

+extern unsigned *set_pdq( set );

+extern void _set_pdq( set a, register unsigned *q );

+extern unsigned int set_hash( set, register unsigned int );

+#else

+extern void set_size();

+extern unsigned int set_deg();

+extern set set_or();

+extern set set_and();

+extern set set_dif();

+extern set set_of();

+extern void set_ext();

+extern set set_not();

+extern int set_equ();

+extern int set_sub();

+extern unsigned set_int();

+extern int set_el();

+extern int set_nil();

+extern char * set_str();

+extern set set_val();

+extern void set_orel();

+extern void set_orin();

+extern void set_andin();

+extern void set_rm();

+extern void set_clr();

+extern set set_dup();

+extern void set_PDQ();

+extern unsigned *set_pdq();

+extern void _set_pdq();

+extern unsigned int set_hash();

+#endif

+

+extern set empty;

+

+#endif

diff --git a/Source/Pccts/support/sym/sym.c b/Source/Pccts/support/sym/sym.c
new file mode 100644
index 0000000..eccce05
--- /dev/null
+++ b/Source/Pccts/support/sym/sym.c
@@ -0,0 +1,402 @@
+/*

+ * Simple symbol table manager using coalesced chaining to resolve collisions

+ *

+ * Doubly-linked lists are used for fast removal of entries.

+ *

+ * 'sym.h' must have a definition for typedef "Sym".  Sym must include at

+ * minimum the following fields:

+ *

+ *		...

+ *		char *symbol;

+ *		struct ... *next, *prev, **head, *scope;

+ *		unsigned int hash;

+ *		...

+ *

+ * 'template.h' can be used as a template to create a 'sym.h'.

+ *

+ * 'head' is &(table[hash(itself)]).

+ * The hash table is not resizable at run-time.

+ * The scope field is used to link all symbols of a current scope together.

+ * Scope() sets the current scope (linked list) to add symbols to.

+ * Any number of scopes can be handled.  The user passes the address of

+ * a pointer to a symbol table

+ * entry (INITIALIZED TO NULL first time).

+ *

+ * Available Functions:

+ *

+ *	zzs_init(s1,s2)	--	Create hash table with size s1, string table size s2.

+ *	zzs_done()		--	Free hash and string table created with zzs_init().

+ *	zzs_add(key,rec)--	Add 'rec' with key 'key' to the symbol table.

+ *	zzs_newadd(key)	--	create entry; add using 'key' to the symbol table.

+ *	zzs_get(key)	--	Return pointer to last record entered under 'key'

+ *						Else return NULL

+ *	zzs_del(p)		--	Unlink the entry associated with p.  This does

+ *						NOT free 'p' and DOES NOT remove it from a scope

+ *						list.  If it was a part of your intermediate code

+ *						tree or another structure.  It will still be there.

+ *			  			It is only removed from further consideration

+ *						by the symbol table.

+ *	zzs_keydel(s)	--	Unlink the entry associated with key s.

+ *						Calls zzs_del(p) to unlink.

+ *	zzs_scope(sc)	--	Specifies that everything added to the symbol

+ *			   			table with zzs_add() is added to the list (scope)

+ *						'sc'.  'sc' is of 'Sym **sc' type and must be

+ *						initialized to NULL before trying to add anything

+ *						to it (passing it to zzs_scope()).  Scopes can be

+ *					    switched at any time and merely links a set of

+ *						symbol table entries.  If a NULL pointer is

+ *						passed, the current scope is returned.

+ *	zzs_rmscope(sc)	--	Remove (zzs_del()) all elements of scope 'sc'

+ *						from the symbol table.  The entries are NOT

+ *						free()'d.  A pointer to the first

+ *			   			element in the "scope" is returned.  The user

+ *			   			can then manipulate the list as he/she chooses

+ *			   			(such as freeing them all). NOTE that this

+ *			   			function sets your scope pointer to NULL,

+ *			   			but returns a pointer to the list for you to use.

+ *	zzs_stat()		--	Print out the symbol table and some relevant stats.

+ *	zzs_new(key)	--	Create a new record with calloc() of type Sym.

+ *			   			Add 'key' to the string table and make the new

+ *			   			records 'symbol' pointer point to it.

+ *	zzs_strdup(s)	--	Add s to the string table and return a pointer

+ *			   			to it.  Very fast allocation routine

+ *						and does not require strlen() nor calloc().

+ *

+ * Example:

+ *

+ *	#include <stdio.h>

+ *	#include "sym.h"

+ *

+ *	main()

+ *	{

+ *	    Sym *scope1=NULL, *scope2=NULL, *a, *p;

+ *	

+ *	    zzs_init(101, 100);

+ *	

+ *	    a = zzs_new("Apple");	zzs_add(a->symbol, a);	-- No scope

+ *	    zzs_scope( &scope1 );	-- enter scope 1

+ *	    a = zzs_new("Plum");	zzs_add(a->symbol, a);

+ *	    zzs_scope( &scope2 );	-- enter scope 2

+ *	    a = zzs_new("Truck");	zzs_add(a->symbol, a);

+ *	

+ *    	p = zzs_get("Plum");

+ *    	if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n");

+ *	

+ *    	p = zzs_rmscope(&scope1)

+ *    	for (; p!=NULL; p=p->scope) {printf("Scope1:  %s\n", p->symbol);}

+ *    	p = zzs_rmscope(&scope2)

+ *    	for (; p!=NULL; p=p->scope) {printf("Scope2:  %s\n", p->symbol);}

+ * }

+ *

+ * Terence Parr

+ * Purdue University

+ * February 1990

+ *

+ * CHANGES

+ *

+ *	Terence Parr

+ *	May 1991

+ *		Renamed functions to be consistent with ANTLR

+ *		Made HASH macro

+ *		Added zzs_keydel()

+ *		Added zzs_newadd()

+ *		Fixed up zzs_stat()

+ *

+ *	July 1991

+ *		Made symbol table entry save its hash code for fast comparison

+ *			during searching etc...

+ */

+

+#include <stdio.h>

+#if defined(__STDC__) || defined(__USE_PROTOS)

+#include <string.h>

+#include <stdlib.h>

+#else

+#include <malloc.h>

+#endif

+#include "sym.h"

+

+#define StrSame		0

+

+static Sym **CurScope = NULL;

+static unsigned size = 0;

+static Sym **table=NULL;

+static char *strings;

+static char *strp;

+static int strsize = 0;

+

+#ifdef __USE_PROTOS

+void zzs_init(int sz,int strs)

+#else

+void zzs_init(sz, strs)

+int sz, strs;

+#endif

+{

+	if ( sz <= 0 || strs <= 0 ) return;

+	table = (Sym **) calloc(sz, sizeof(Sym *));

+	if ( table == NULL )

+	{

+		fprintf(stderr, "Cannot allocate table of size %d\n", sz);

+		exit(1);

+	}

+	strings = (char *) calloc(strs, sizeof(char));

+	if ( strings == NULL )

+	{

+		fprintf(stderr, "Cannot allocate string table of size %d\n", strs);

+		exit(1);

+	}

+	size = sz;

+	strsize = strs;

+	strp = strings;

+}

+

+#ifdef __USE_PROTOS

+void zzs_done(void)

+#else

+void zzs_done()

+#endif

+{

+	if ( table != NULL ) free( table );

+	if ( strings != NULL ) free( strings );

+}

+

+#ifdef __USE_PROTOS

+void zzs_add(char *key,Sym rec)

+#else

+void zzs_add(key, rec)

+char *key;

+register Sym *rec;

+#endif

+{

+	register unsigned int h=0;

+	register char *p=key;

+	

+	HASH(p, h);

+	rec->hash = h;					/* save hash code for fast comp later */

+	h %= size;

+	

+	if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;}

+	rec->next = table[h];			/* Add to doubly-linked list */

+	rec->prev = NULL;

+	if ( rec->next != NULL ) (rec->next)->prev = rec;

+	table[h] = rec;

+	rec->head = &(table[h]);

+}

+

+#ifdef __USE_PROTOS

+Sym * zzs_get(char *key)

+#else

+Sym * zzs_get(key)

+char *key;

+#endif

+{

+	register unsigned int h=0;

+	register char *p=key;

+	register Sym *q;

+	

+	HASH(p, h);

+	

+	for (q = table[h%size]; q != NULL; q = q->next)

+	{

+		if ( q->hash == h )		/* do we even have a chance of matching? */

+			if ( strcmp(key, q->symbol) == StrSame ) return( q );

+	}

+	return( NULL );

+}

+

+/*

+ * Unlink p from the symbol table.  Hopefully, it's actually in the

+ * symbol table.

+ *

+ * If p is not part of a bucket chain of the symbol table, bad things

+ * will happen.

+ *

+ * Will do nothing if all list pointers are NULL

+ */

+#ifdef __USE_PROTOS

+void zzs_del(Sym *p)

+#else

+void zzs_del(p)

+register Sym *p;

+#endif

+{

+	if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);}

+	if ( p->prev == NULL )	/* Head of list */

+	{

+		register Sym **t = p->head;

+		

+		if ( t == NULL ) return;	/* not part of symbol table */

+		(*t) = p->next;

+		if ( (*t) != NULL ) (*t)->prev = NULL;

+	}

+	else

+	{

+		(p->prev)->next = p->next;

+		if ( p->next != NULL ) (p->next)->prev = p->prev;

+	}

+	p->next = p->prev = NULL;	/* not part of symbol table anymore */

+	p->head = NULL;

+}

+

+#ifdef __USE_PROTOS

+void zzs_keydel(char *key)

+#else

+void zzs_keydel(key)

+char *key;

+#endif

+{

+	Sym *p = zzs_get(key);

+

+	if ( p != NULL ) zzs_del( p );

+}

+

+/* S c o p e  S t u f f */

+

+/* Set current scope to 'scope'; return current scope if 'scope' == NULL */

+

+#ifdef __USE_PROTOS

+Sym ** zzs_scope(Sym **scope)

+#else

+Sym ** zzs_scope(scope)

+Sym **scope;

+#endif

+{

+	if ( scope == NULL ) return( CurScope );

+	CurScope = scope;

+	return( scope );

+}

+

+/* Remove a scope described by 'scope'.  Return pointer to 1st element in scope */

+

+#ifdef __USE_PROTOS

+Sym * zzs_rmscope(Sym **scope)

+#else

+Sym * zzs_rmscope(scope)

+register Sym **scope;

+#endif

+{

+	register Sym *p;

+	Sym *start;

+

+	if ( scope == NULL ) return(NULL);

+	start = p = *scope;

+	for (; p != NULL; p=p->scope) { zzs_del( p ); }

+	*scope = NULL;

+	return( start );

+}

+

+#ifdef __USE_PROTOS

+void zzs_stat(void)

+#else

+void zzs_stat()

+#endif

+{

+	static unsigned short count[20];

+	unsigned int i,n=0,low=0, hi=0;

+	register Sym **p;

+	float avg=0.0;

+	

+	for (i=0; i<20; i++) count[i] = 0;

+	for (p=table; p<&(table[size]); p++)

+	{

+		register Sym *q = *p;

+		unsigned int len;

+		

+		if ( q != NULL && low==0 ) low = p-table;

+		len = 0;

+		if ( q != NULL ) printf("[%d]", p-table);

+		while ( q != NULL )

+		{

+			len++;

+			n++;

+			printf(" %s", q->symbol);

+			q = q->next;

+			if ( q == NULL ) printf("\n");

+		}

+		if ( len>=20 ) printf("zzs_stat: count table too small\n");

+		else count[len]++;

+		if ( *p != NULL ) hi = p-table;

+	}

+

+	printf("Storing %d recs used %d hash positions out of %d\n",

+			n, size-count[0], size);

+	printf("%f %% utilization\n",

+			((float)(size-count[0]))/((float)size));

+	for (i=0; i<20; i++)

+	{

+		if ( count[i] != 0 )

+		{

+			avg += (((float)(i*count[i]))/((float)n)) * i;

+			printf("Buckets of len %d == %d (%f %% of recs)\n",

+					i, count[i], 100.0*((float)(i*count[i]))/((float)n));

+		}

+	}

+	printf("Avg bucket length %f\n", avg);

+	printf("Range of hash function: %d..%d\n", low, hi);

+}

+

+/*

+ * Given a string, this function allocates and returns a pointer to a

+ * symbol table record whose "symbol" pointer is reset to a position

+ * in the string table.

+ */

+

+#ifdef __USE_PROTOS

+Sym * zzs_new(char *text)

+#else

+Sym * zzs_new(text)

+char *text;

+#endif

+{

+	Sym *p;

+	

+	if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 )

+	{

+		fprintf(stderr,"Out of memory\n");

+		exit(1);

+	}

+	p->symbol = zzs_strdup(text);

+	

+	return p;

+}

+

+/* create a new symbol table entry and add it to the symbol table */

+

+#ifdef __USE_PROTOS

+Sym * zzs_newadd(char *text)

+#else

+Sym * zzs_newadd(text)

+char *text;

+#endif

+{

+	Sym *p = zzs_new(text);

+	if ( p != NULL ) zzs_add(text, p);

+	return p;

+}

+

+/* Add a string to the string table and return a pointer to it.

+ * Bump the pointer into the string table to next avail position.

+ */

+

+#ifdef __USE_PROTOS

+char * zzs_strdup(char *s)

+#else

+char * zzs_strdup(s)

+register char *s;

+#endif

+{

+	register char *start=strp;

+

+	while ( *s != '\0' )

+	{

+		if ( strp >= &(strings[strsize-2]) )

+		{

+			fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize);

+			exit(-1);

+		}

+		*strp++ = *s++;

+	}

+	*strp++ = '\0';

+

+	return( start );

+}

diff --git a/Source/Pccts/support/sym/template.h b/Source/Pccts/support/sym/template.h
new file mode 100644
index 0000000..ee6e665
--- /dev/null
+++ b/Source/Pccts/support/sym/template.h
@@ -0,0 +1,41 @@
+/* T e m p l a t e  F o r  S y m b o l  T a b l e  M a n a g e r */

+

+/* define some hash function */

+#ifndef HASH

+#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++;

+#endif

+

+/* minimum symbol table record */

+typedef struct _sym {

+			char *symbol;

+			struct _sym *next, *prev, **head, *scope;

+			unsigned int hash;

+		} Sym, *SymPtr;

+

+#ifdef __USE_PROTOS

+void zzs_init(int, int);

+void zzs_done(void);

+void zzs_add(char *, Sym *);

+Sym *zzs_get(char *);

+void zzs_del(Sym *);

+void zzs_keydel(char *);

+Sym **zzs_scope(Sym **);

+Sym *zzs_rmscope(Sym **);

+void zzs_stat(void);

+Sym *zzs_new(char *);

+Sym *zzs_newadd(char *);

+char *zzs_strdup(char *);

+#else

+void zzs_init();

+void zzs_done();

+void zzs_add();

+Sym *zzs_get();

+void zzs_del();

+void zzs_keydel();

+Sym **zzs_scope();

+Sym *zzs_rmscope();

+void zzs_stat();

+Sym *zzs_new();

+Sym *zzs_newadd();

+char *zzs_strdup();

+#endif

diff --git a/Source/PeCoffLoader/BasePeCoff.c b/Source/PeCoffLoader/BasePeCoff.c
new file mode 100644
index 0000000..9c25e1f
--- /dev/null
+++ b/Source/PeCoffLoader/BasePeCoff.c
@@ -0,0 +1,1060 @@
+/*++

+

+Copyright (c) 2004 - 2005, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PeCoffLoader.c

+

+Abstract:

+

+  Tiano PE/COFF loader 

+

+Revision History

+

+--*/

+

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Library/PeCoffLib.h>

+

+STATIC

+RETURN_STATUS

+PeCoffLoaderGetPeHeader (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,

+  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,

+  OUT    EFI_TE_IMAGE_HEADER           *TeHdr

+  );

+

+STATIC

+RETURN_STATUS

+PeCoffLoaderCheckImageType (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,

+  IN     EFI_IMAGE_NT_HEADERS          *PeHdr,

+  IN     EFI_TE_IMAGE_HEADER           *TeHdr

+  );

+

+STATIC

+VOID                            *

+PeCoffLoaderImageAddress (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,

+  IN     UINTN                         Address

+  );

+

+

+STATIC

+RETURN_STATUS

+PeCoffLoaderGetPeHeader (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,

+  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,

+  OUT    EFI_TE_IMAGE_HEADER           *TeHdr

+  )

+/*++

+

+Routine Description:

+

+  Retrieves the PE or TE Header from a PE/COFF or TE image

+

+Arguments:

+

+  ImageContext  - The context of the image being loaded

+

+  PeHdr         - The buffer in which to return the PE header

+  

+  TeHdr         - The buffer in which to return the TE header

+

+Returns:

+

+  RETURN_SUCCESS if the PE or TE Header is read, 

+  Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.

+

+--*/

+{

+  RETURN_STATUS            Status;

+  EFI_IMAGE_DOS_HEADER  DosHdr;

+  UINTN                 Size;

+

+  ImageContext->IsTeImage = FALSE;

+  //

+  // Read the DOS image headers

+  //

+  Size = sizeof (EFI_IMAGE_DOS_HEADER);

+  Status = ImageContext->ImageRead (

+                          ImageContext->Handle,

+                          0,

+                          &Size,

+                          &DosHdr

+                          );

+  if (RETURN_ERROR (Status)) {

+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+    return Status;

+  }

+

+  ImageContext->PeCoffHeaderOffset = 0;

+  if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {

+    //

+    // DOS image header is present, so read the PE header after the DOS image header

+    //

+    ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;

+  }

+  //

+  // Read the PE/COFF Header

+  //

+  Size = sizeof (EFI_IMAGE_NT_HEADERS);

+  Status = ImageContext->ImageRead (

+                          ImageContext->Handle,

+                          ImageContext->PeCoffHeaderOffset,

+                          &Size,

+                          PeHdr

+                          );

+  if (RETURN_ERROR (Status)) {

+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+    return Status;

+  }

+  //

+  // Check the PE/COFF Header Signature. If not, then try to read a TE header

+  //

+  if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {

+    Size = sizeof (EFI_TE_IMAGE_HEADER);

+    Status = ImageContext->ImageRead (

+                            ImageContext->Handle,

+                            0,

+                            &Size,

+                            TeHdr

+                            );

+    if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {

+      return RETURN_UNSUPPORTED;

+    }

+

+    ImageContext->IsTeImage = TRUE;

+  }

+

+  return RETURN_SUCCESS;

+}

+

+STATIC

+RETURN_STATUS

+PeCoffLoaderCheckImageType (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,

+  IN     EFI_IMAGE_NT_HEADERS                  *PeHdr,

+  IN     EFI_TE_IMAGE_HEADER                   *TeHdr

+  )

+/*++

+

+Routine Description:

+

+  Checks the PE or TE header of a PE/COFF or TE image to determine if it supported

+

+Arguments:

+

+  ImageContext  - The context of the image being loaded

+

+  PeHdr         - The buffer in which to return the PE header

+  

+  TeHdr         - The buffer in which to return the TE header

+

+Returns:

+

+  RETURN_SUCCESS if the PE/COFF or TE image is supported

+  RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.

+

+--*/

+{

+  //

+  // See if the machine type is supported.  We support a native machine type (IA-32/Itanium-based)

+  // and the machine type for the Virtual Machine.

+  //

+  if (ImageContext->IsTeImage == FALSE) {

+    ImageContext->Machine = PeHdr->FileHeader.Machine;

+  } else {

+    ImageContext->Machine = TeHdr->Machine;

+  }

+

+  if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {

+    ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;

+    return RETURN_UNSUPPORTED;

+  }

+

+  //

+  // See if the image type is supported.  We support EFI Applications,

+  // EFI Boot Service Drivers, and EFI Runtime Drivers.

+  //

+  if (ImageContext->IsTeImage == FALSE) {

+    ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;

+  } else {

+    ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);

+  }

+

+

+  return RETURN_SUCCESS;

+}

+

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderGetImageInfo (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT           *ImageContext

+  )

+/*++

+

+Routine Description:

+

+  Retrieves information on a PE/COFF image

+

+Arguments:

+

+  This         - Calling context

+  ImageContext - The context of the image being loaded

+

+Returns:

+

+  RETURN_SUCCESS           - The information on the PE/COFF image was collected.

+  RETURN_INVALID_PARAMETER - ImageContext is NULL.

+  RETURN_UNSUPPORTED       - The PE/COFF image is not supported.

+  Otherwise             - The error status from reading the PE/COFF image using the

+                          ImageContext->ImageRead() function

+

+--*/

+{

+  RETURN_STATUS                      Status;

+  EFI_IMAGE_NT_HEADERS            PeHdr;

+  EFI_TE_IMAGE_HEADER             TeHdr;

+  EFI_IMAGE_DATA_DIRECTORY        *DebugDirectoryEntry;

+  UINTN                           Size;

+  UINTN                           Index;

+  UINTN                           DebugDirectoryEntryRva;

+  UINTN                           DebugDirectoryEntryFileOffset;

+  UINTN                           SectionHeaderOffset;

+  EFI_IMAGE_SECTION_HEADER        SectionHeader;

+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;

+

+  if (NULL == ImageContext) {

+    return RETURN_INVALID_PARAMETER;

+  }

+  //

+  // Assume success

+  //

+  ImageContext->ImageError  = IMAGE_ERROR_SUCCESS;

+

+  Status                    = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);

+  if (RETURN_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Verify machine type

+  //

+  Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr);

+  if (RETURN_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Retrieve the base address of the image

+  //

+  if (!(ImageContext->IsTeImage)) {

+    ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;

+  } else {

+    ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase);

+  }

+  //

+  // Initialize the alternate destination address to 0 indicating that it

+  // should not be used.

+  //

+  ImageContext->DestinationAddress = 0;

+

+  //

+  // Initialize the codeview pointer.

+  //

+  ImageContext->CodeView    = NULL;

+  ImageContext->PdbPointer  = NULL;

+

+  //

+  // Three cases with regards to relocations:

+  // - Image has base relocs, RELOCS_STRIPPED==0    => image is relocatable

+  // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable

+  // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but

+  //   has no base relocs to apply

+  // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.

+  //

+  // Look at the file header to determine if relocations have been stripped, and

+  // save this info in the image context for later use.

+  //

+  if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {

+    ImageContext->RelocationsStripped = TRUE;

+  } else {

+    ImageContext->RelocationsStripped = FALSE;

+  }

+

+  if (!(ImageContext->IsTeImage)) {

+    ImageContext->ImageSize         = (UINT64) PeHdr.OptionalHeader.SizeOfImage;

+    ImageContext->SectionAlignment  = PeHdr.OptionalHeader.SectionAlignment;

+    ImageContext->SizeOfHeaders     = PeHdr.OptionalHeader.SizeOfHeaders;

+

+    //

+    // Modify ImageSize to contain .PDB file name if required and initialize

+    // PdbRVA field...

+    //

+    if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {

+      DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);

+

+      DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;

+

+      //

+      // Determine the file offset of the debug directory...  This means we walk

+      // the sections to find which section contains the RVA of the debug

+      // directory

+      //

+      DebugDirectoryEntryFileOffset = 0;

+

+      SectionHeaderOffset = (UINTN)(

+                               ImageContext->PeCoffHeaderOffset +

+                               sizeof (UINT32) + 

+                               sizeof (EFI_IMAGE_FILE_HEADER) + 

+                               PeHdr.FileHeader.SizeOfOptionalHeader

+                               );

+

+      for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) {

+        //

+        // Read section header from file

+        //

+        Size = sizeof (EFI_IMAGE_SECTION_HEADER);

+        Status = ImageContext->ImageRead (

+                                 ImageContext->Handle,

+                                 SectionHeaderOffset,

+                                 &Size,

+                                 &SectionHeader

+                                 );

+        if (RETURN_ERROR (Status)) {

+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+          return Status;

+        }

+

+        if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&

+            DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {

+            DebugDirectoryEntryFileOffset =

+            DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;

+          break;

+        }

+

+        SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);

+      }

+

+      if (DebugDirectoryEntryFileOffset != 0) {

+        for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {

+          //

+          // Read next debug directory entry

+          //

+          Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);

+          Status = ImageContext->ImageRead (

+                                   ImageContext->Handle,

+                                   DebugDirectoryEntryFileOffset,

+                                   &Size,

+                                   &DebugEntry

+                                   );

+          if (RETURN_ERROR (Status)) {

+            ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+            return Status;

+          }

+

+          if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {

+            ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));

+            if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {

+              ImageContext->ImageSize += DebugEntry.SizeOfData;

+            }

+

+            return RETURN_SUCCESS;

+          }

+        }

+      }

+    }

+  } else {

+    ImageContext->ImageSize         = 0;

+    ImageContext->SectionAlignment  = 4096;

+    ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize;

+

+    DebugDirectoryEntry             = &TeHdr.DataDirectory[1];

+    DebugDirectoryEntryRva          = DebugDirectoryEntry->VirtualAddress;

+    SectionHeaderOffset             = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));

+

+    DebugDirectoryEntryFileOffset   = 0;

+

+    for (Index = 0; Index < TeHdr.NumberOfSections;) {

+      //

+      // Read section header from file

+      //

+      Size = sizeof (EFI_IMAGE_SECTION_HEADER);

+      Status = ImageContext->ImageRead (

+                               ImageContext->Handle,

+                               SectionHeaderOffset,

+                               &Size,

+                               &SectionHeader

+                               );

+      if (RETURN_ERROR (Status)) {

+        ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+        return Status;

+      }

+

+      if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&

+          DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {

+        DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -

+          SectionHeader.VirtualAddress +

+          SectionHeader.PointerToRawData +

+          sizeof (EFI_TE_IMAGE_HEADER) -

+          TeHdr.StrippedSize;

+

+        //

+        // File offset of the debug directory was found, if this is not the last

+        // section, then skip to the last section for calculating the image size.

+        //

+        if (Index < (UINTN) TeHdr.NumberOfSections - 1) {

+          SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);

+          Index = TeHdr.NumberOfSections - 1;

+          continue;

+        }

+      }

+

+      //

+      // In Te image header there is not a field to describe the ImageSize.

+      // Actually, the ImageSize equals the RVA plus the VirtualSize of 

+      // the last section mapped into memory (Must be rounded up to 

+      // a mulitple of Section Alignment). Per the PE/COFF specification, the

+      // section headers in the Section Table must appear in order of the RVA

+      // values for the corresponding sections. So the ImageSize can be determined

+      // by the RVA and the VirtualSize of the last section header in the

+      // Section Table.

+      //

+      if ((++Index) == (UINTN) TeHdr.NumberOfSections) {

+        ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +

+                                   ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);

+      }

+

+      SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);

+    }

+

+    if (DebugDirectoryEntryFileOffset != 0) {

+      for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {

+        //

+        // Read next debug directory entry

+        //

+        Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);

+        Status = ImageContext->ImageRead (

+                                 ImageContext->Handle,

+                                 DebugDirectoryEntryFileOffset,

+                                 &Size,

+                                 &DebugEntry

+                                 );

+        if (RETURN_ERROR (Status)) {

+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+          return Status;

+        }

+

+        if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {

+          ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));

+          return RETURN_SUCCESS;

+        }

+      }

+    }

+  }

+

+  return RETURN_SUCCESS;

+}

+

+STATIC

+VOID *

+PeCoffLoaderImageAddress (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,

+  IN     UINTN                                 Address

+  )

+/*++

+

+Routine Description:

+

+  Converts an image address to the loaded address

+

+Arguments:

+

+  ImageContext  - The context of the image being loaded

+

+  Address       - The address to be converted to the loaded address

+

+Returns:

+

+  NULL if the address can not be converted, otherwise, the converted address

+

+--*/

+{

+  if (Address >= ImageContext->ImageSize) {

+    ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;

+    return NULL;

+  }

+

+  return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);

+}

+

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderRelocateImage (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext

+  )

+/*++

+

+Routine Description:

+

+  Relocates a PE/COFF image in memory

+

+Arguments:

+

+  This         - Calling context

+

+  ImageContext - Contains information on the loaded image to relocate

+

+Returns:

+

+  RETURN_SUCCESS      if the PE/COFF image was relocated

+  RETURN_LOAD_ERROR   if the image is not a valid PE/COFF image

+  RETURN_UNSUPPORTED  not support

+

+--*/

+{

+  RETURN_STATUS                Status;

+  EFI_IMAGE_NT_HEADERS      *PeHdr;

+  EFI_TE_IMAGE_HEADER       *TeHdr;

+  EFI_IMAGE_DATA_DIRECTORY  *RelocDir;

+  UINT64                    Adjust;

+  EFI_IMAGE_BASE_RELOCATION *RelocBase;

+  EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;

+  UINT16                    *Reloc;

+  UINT16                    *RelocEnd;

+  CHAR8                     *Fixup;

+  CHAR8                     *FixupBase;

+  UINT16                    *F16;

+  UINT32                    *F32;

+  CHAR8                     *FixupData;

+  PHYSICAL_ADDRESS      BaseAddress;

+

+  PeHdr = NULL;

+  TeHdr = NULL;

+  //

+  // Assume success

+  //

+  ImageContext->ImageError = IMAGE_ERROR_SUCCESS;

+

+  //

+  // If there are no relocation entries, then we are done

+  //

+  if (ImageContext->RelocationsStripped) {

+    return RETURN_SUCCESS;

+  }

+

+  //

+  // If the destination address is not 0, use that rather than the

+  // image address as the relocation target.

+  //

+  if (ImageContext->DestinationAddress) {

+    BaseAddress = ImageContext->DestinationAddress;

+  } else {

+    BaseAddress = ImageContext->ImageAddress;

+  }

+

+  if (!(ImageContext->IsTeImage)) {

+    PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + 

+                                            ImageContext->PeCoffHeaderOffset);

+    Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;

+    PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress;

+

+    //

+    // Find the relocation block

+    //

+    // Per the PE/COFF spec, you can't assume that a given data directory

+    // is present in the image. You have to check the NumberOfRvaAndSizes in

+    // the optional header to verify a desired directory entry is there.

+    //

+    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {

+      RelocDir  = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];

+      RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);

+      RelocBaseEnd = PeCoffLoaderImageAddress (

+                      ImageContext,

+                      RelocDir->VirtualAddress + RelocDir->Size - 1

+                      );

+    } else {

+      //

+      // Set base and end to bypass processing below.

+      //

+      RelocBase = RelocBaseEnd = 0;

+    }

+  } else {

+    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);

+    Adjust            = (UINT64) (BaseAddress - TeHdr->ImageBase);

+    TeHdr->ImageBase  = (UINT64) (BaseAddress);

+

+    //

+    // Find the relocation block

+    //

+    RelocDir = &TeHdr->DataDirectory[0];

+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(

+                                    ImageContext->ImageAddress + 

+                                    RelocDir->VirtualAddress +

+                                    sizeof(EFI_TE_IMAGE_HEADER) - 

+                                    TeHdr->StrippedSize

+                                    );

+    RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);

+  }

+  

+  //

+  // Run the relocation information and apply the fixups

+  //

+  FixupData = ImageContext->FixupData;

+  while (RelocBase < RelocBaseEnd) {

+

+    Reloc     = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));

+    RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);

+    if (!(ImageContext->IsTeImage)) {

+      FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);

+    } else {

+      FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +

+                    RelocBase->VirtualAddress +

+                    sizeof(EFI_TE_IMAGE_HEADER) - 

+                    TeHdr->StrippedSize

+                    );

+    }

+

+    if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||

+        (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + 

+          (UINTN)ImageContext->ImageSize)) {

+      ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;

+      return RETURN_LOAD_ERROR;

+    }

+

+    //

+    // Run this relocation record

+    //

+    while (Reloc < RelocEnd) {

+

+      Fixup = FixupBase + (*Reloc & 0xFFF);

+      switch ((*Reloc) >> 12) {

+      case EFI_IMAGE_REL_BASED_ABSOLUTE:

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGH:

+        F16   = (UINT16 *) Fixup;

+        *F16 = (UINT16) (*F16 + ((UINT16) ((UINT32) Adjust >> 16)));

+        if (FixupData != NULL) {

+          *(UINT16 *) FixupData = *F16;

+          FixupData             = FixupData + sizeof (UINT16);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_LOW:

+        F16   = (UINT16 *) Fixup;

+        *F16  = (UINT16) (*F16 + (UINT16) Adjust);

+        if (FixupData != NULL) {

+          *(UINT16 *) FixupData = *F16;

+          FixupData             = FixupData + sizeof (UINT16);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGHLOW:

+        F32   = (UINT32 *) Fixup;

+        *F32  = *F32 + (UINT32) Adjust;

+        if (FixupData != NULL) {

+          FixupData             = ALIGN_POINTER (FixupData, sizeof (UINT32));

+          *(UINT32 *) FixupData = *F32;

+          FixupData             = FixupData + sizeof (UINT32);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGHADJ:

+        //

+        // Return the same EFI_UNSUPPORTED return code as

+        // PeCoffLoaderRelocateImageEx() returns if it does not recognize

+        // the relocation type.

+        //

+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;

+        return RETURN_UNSUPPORTED;

+

+      default:

+        Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);

+        if (RETURN_ERROR (Status)) {

+          ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;

+          return Status;

+        }

+      }

+

+      //

+      // Next relocation record

+      //

+      Reloc += 1;

+    }

+

+    //

+    // Next reloc block

+    //

+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;

+  }

+

+  return RETURN_SUCCESS;

+}

+

+RETURN_STATUS

+EFIAPI

+PeCoffLoaderLoadImage (

+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext

+  )

+/*++

+

+Routine Description:

+

+  Loads a PE/COFF image into memory

+

+Arguments:

+

+  This         - Calling context

+

+  ImageContext - Contains information on image to load into memory

+

+Returns:

+

+  RETURN_SUCCESS            if the PE/COFF image was loaded

+  RETURN_BUFFER_TOO_SMALL   if the caller did not provide a large enough buffer

+  RETURN_LOAD_ERROR         if the image is a runtime driver with no relocations

+  RETURN_INVALID_PARAMETER  if the image address is invalid

+

+--*/

+{

+  RETURN_STATUS                            Status;

+  EFI_IMAGE_NT_HEADERS                  *PeHdr;

+  EFI_TE_IMAGE_HEADER                   *TeHdr;

+  PE_COFF_LOADER_IMAGE_CONTEXT  CheckContext;

+  EFI_IMAGE_SECTION_HEADER              *FirstSection;

+  EFI_IMAGE_SECTION_HEADER              *Section;

+  UINTN                                 NumberOfSections;

+  UINTN                                 Index;

+  CHAR8                                 *Base;

+  CHAR8                                 *End;

+  CHAR8                                 *MaxEnd;

+  EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;

+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;

+  UINTN                                 Size;

+  UINT32                                TempDebugEntryRva;

+

+  PeHdr = NULL;

+  TeHdr = NULL;

+  //

+  // Assume success

+  //

+  ImageContext->ImageError = IMAGE_ERROR_SUCCESS;

+

+  //

+  // Copy the provided context info into our local version, get what we

+  // can from the original image, and then use that to make sure everything

+  // is legit.

+  //

+  CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));

+

+  Status = PeCoffLoaderGetImageInfo (&CheckContext);

+  if (RETURN_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Make sure there is enough allocated space for the image being loaded

+  //

+  if (ImageContext->ImageSize < CheckContext.ImageSize) {

+    ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;

+    return RETURN_BUFFER_TOO_SMALL;

+  }

+

+  //

+  // If there's no relocations, then make sure it's not a runtime driver,

+  // and that it's being loaded at the linked address.

+  //

+  if (CheckContext.RelocationsStripped) {

+    //

+    // If the image does not contain relocations and it is a runtime driver

+    // then return an error.

+    //

+    if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {

+      ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;

+      return RETURN_LOAD_ERROR;

+    }

+    //

+    // If the image does not contain relocations, and the requested load address

+    // is not the linked address, then return an error.

+    //

+    if (CheckContext.ImageAddress != ImageContext->ImageAddress) {

+      ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;

+      return RETURN_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Make sure the allocated space has the proper section alignment

+  //

+  if (!(ImageContext->IsTeImage)) {

+    if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {

+      ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;

+      return RETURN_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Read the entire PE/COFF or TE header into memory

+  //

+  if (!(ImageContext->IsTeImage)) {

+    Status = ImageContext->ImageRead (

+                            ImageContext->Handle,

+                            0,

+                            &ImageContext->SizeOfHeaders,

+                            (VOID *) (UINTN) ImageContext->ImageAddress

+                            );

+

+    PeHdr = (EFI_IMAGE_NT_HEADERS *)

+      ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);

+

+    FirstSection = (EFI_IMAGE_SECTION_HEADER *) (

+                      (UINTN)ImageContext->ImageAddress +

+                      ImageContext->PeCoffHeaderOffset +

+                      sizeof(UINT32) + 

+                      sizeof(EFI_IMAGE_FILE_HEADER) + 

+                      PeHdr->FileHeader.SizeOfOptionalHeader

+      );

+    NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections);

+  } else {

+    Status = ImageContext->ImageRead (

+                            ImageContext->Handle,

+                            0,

+                            &ImageContext->SizeOfHeaders,

+                            (void *) (UINTN) ImageContext->ImageAddress

+                            );

+

+    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);

+

+    FirstSection = (EFI_IMAGE_SECTION_HEADER *) (

+          (UINTN)ImageContext->ImageAddress +

+          sizeof(EFI_TE_IMAGE_HEADER)

+          );

+    NumberOfSections  = (UINTN) (TeHdr->NumberOfSections);

+

+  }

+

+  if (RETURN_ERROR (Status)) {

+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+    return RETURN_LOAD_ERROR;

+  }

+

+  //

+  // Load each section of the image

+  //

+  Section = FirstSection;

+  for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {

+

+    //

+    // Compute sections address

+    //

+    Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);

+    End = PeCoffLoaderImageAddress (

+            ImageContext,

+            Section->VirtualAddress + Section->Misc.VirtualSize - 1

+            );

+    if (ImageContext->IsTeImage) {

+      Base  = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);

+      End   = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);

+    }

+

+    if (End > MaxEnd) {

+      MaxEnd = End;

+    }

+    //

+    // If the base start or end address resolved to 0, then fail.

+    //

+    if ((Base == NULL) || (End == NULL)) {

+      ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;

+      return RETURN_LOAD_ERROR;

+    }

+

+    //

+    // Read the section

+    //

+    Size = (UINTN) Section->Misc.VirtualSize;

+    if ((Size == 0) || (Size > Section->SizeOfRawData)) {

+      Size = (UINTN) Section->SizeOfRawData;

+    }

+

+    if (Section->SizeOfRawData) {

+      if (!(ImageContext->IsTeImage)) {

+        Status = ImageContext->ImageRead (

+                                ImageContext->Handle,

+                                Section->PointerToRawData,

+                                &Size,

+                                Base

+                                );

+      } else {

+        Status = ImageContext->ImageRead (

+                                ImageContext->Handle,

+                                Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,

+                                &Size,

+                                Base

+                                );

+      }

+

+      if (RETURN_ERROR (Status)) {

+        ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+        return Status;

+      }

+    }

+

+    //

+    // If raw size is less then virt size, zero fill the remaining

+    //

+

+    if (Size < Section->Misc.VirtualSize) {

+      ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);

+    }

+

+    //

+    // Next Section

+    //

+    Section += 1;

+  }

+

+  //

+  // Get image's entry point

+  //

+  if (!(ImageContext->IsTeImage)) {

+    ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (

+                                                                ImageContext,

+                                                                PeHdr->OptionalHeader.AddressOfEntryPoint

+                                                                );

+  } else {

+    ImageContext->EntryPoint =  (PHYSICAL_ADDRESS) (

+                       (UINTN)ImageContext->ImageAddress +

+                       (UINTN)TeHdr->AddressOfEntryPoint +

+                       (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -

+          (UINTN) TeHdr->StrippedSize

+      );

+  }

+

+  //

+  // Determine the size of the fixup data

+  //

+  // Per the PE/COFF spec, you can't assume that a given data directory

+  // is present in the image. You have to check the NumberOfRvaAndSizes in

+  // the optional header to verify a desired directory entry is there.

+  //

+  if (!(ImageContext->IsTeImage)) {

+    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {

+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)

+        &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];

+      ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);

+    } else {

+      ImageContext->FixupDataSize = 0;

+    }

+  } else {

+    DirectoryEntry              = &TeHdr->DataDirectory[0];

+    ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);

+  }

+  //

+  // Consumer must allocate a buffer for the relocation fixup log.

+  // Only used for runtime drivers.

+  //

+  ImageContext->FixupData = NULL;

+

+  //

+  // Load the Codeview info if present

+  //

+  if (ImageContext->DebugDirectoryEntryRva != 0) {

+    if (!(ImageContext->IsTeImage)) {

+      DebugEntry = PeCoffLoaderImageAddress (

+                    ImageContext,

+                    ImageContext->DebugDirectoryEntryRva

+                    );

+    } else {

+      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(

+                                               ImageContext->ImageAddress +

+                                               ImageContext->DebugDirectoryEntryRva +

+                                               sizeof(EFI_TE_IMAGE_HEADER) -

+                                               TeHdr->StrippedSize

+                                               );

+    }

+

+    if (DebugEntry != NULL) {

+      TempDebugEntryRva = DebugEntry->RVA;

+      if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {

+        Section--;

+        if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {

+          TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;

+        } else {

+          TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;

+        }

+      }

+

+      if (TempDebugEntryRva != 0) {

+        if (!(ImageContext->IsTeImage)) {

+          ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);

+        } else {

+          ImageContext->CodeView = (VOID *)(

+                      (UINTN)ImageContext->ImageAddress +

+                      (UINTN)TempDebugEntryRva +

+                      (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -

+                (UINTN) TeHdr->StrippedSize

+            );

+        }

+

+        if (ImageContext->CodeView == NULL) {

+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+          return RETURN_LOAD_ERROR;

+        }

+

+        if (DebugEntry->RVA == 0) {

+          Size = DebugEntry->SizeOfData;

+          if (!(ImageContext->IsTeImage)) {

+            Status = ImageContext->ImageRead (

+                                    ImageContext->Handle,

+                                    DebugEntry->FileOffset,

+                                    &Size,

+                                    ImageContext->CodeView

+                                    );

+          } else {

+            Status = ImageContext->ImageRead (

+                                    ImageContext->Handle,

+                                    DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,

+                                    &Size,

+                                    ImageContext->CodeView

+                                    );

+            //

+            // Should we apply fix up to this field according to the size difference between PE and TE?

+            // Because now we maintain TE header fields unfixed, this field will also remain as they are

+            // in original PE image.

+            //

+          }

+

+          if (RETURN_ERROR (Status)) {

+            ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;

+            return RETURN_LOAD_ERROR;

+          }

+

+          DebugEntry->RVA = TempDebugEntryRva;

+        }

+

+        switch (*(UINT32 *) ImageContext->CodeView) {

+        case CODEVIEW_SIGNATURE_NB10:

+          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);

+          break;

+

+        case CODEVIEW_SIGNATURE_RSDS:

+          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);

+          break;

+

+        default:

+          break;

+        }

+      }

+    }

+  }

+

+  return Status;

+}

diff --git a/Source/PeCoffLoader/Common/EfiImage.h b/Source/PeCoffLoader/Common/EfiImage.h
new file mode 100644
index 0000000..9528e6b
--- /dev/null
+++ b/Source/PeCoffLoader/Common/EfiImage.h
@@ -0,0 +1,701 @@
+/** @file

+  EFI image format for PE32+. Please note some data structures are different

+  for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64

+

+  @bug Fix text - doc as defined in MSFT EFI specification.

+

+  Copyright (c) 2006, Intel Corporation                                                         

+  All rights reserved. This program and the accompanying materials                          

+  are licensed and made available under the terms and conditions of the BSD License         

+  which accompanies this distribution.  The full text of the license may be found at        

+  http://opensource.org/licenses/bsd-license.php                                            

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+  Module Name:  EfiImage.h

+

+**/

+

+#ifndef __EFI_IMAGE_H__

+#define __EFI_IMAGE_H__

+

+//

+// PE32+ Subsystem type for EFI images

+//

+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION         10

+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11

+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12

+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13

+

+//

+// BugBug: Need to get a real answer for this problem. This is not in the

+//         PE specification.

+//

+//         A SAL runtime driver does not get fixed up when a transition to

+//         virtual mode is made. In all other cases it should be treated

+//         like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image

+//

+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER  13

+

+//

+// PE32+ Machine type for EFI images

+//

+#define IMAGE_FILE_MACHINE_I386     0x014c

+#define IMAGE_FILE_MACHINE_IA64     0x0200

+#define IMAGE_FILE_MACHINE_EBC      0x0EBC

+#define IMAGE_FILE_MACHINE_X64      0x8664

+//

+// Support old names for backward compatible

+//

+#define EFI_IMAGE_MACHINE_IA32      IMAGE_FILE_MACHINE_I386 

+#define EFI_IMAGE_MACHINE_IA64      IMAGE_FILE_MACHINE_IA64  

+#define EFI_IMAGE_MACHINE_IPF       IMAGE_FILE_MACHINE_IA64  

+#define EFI_IMAGE_MACHINE_EBC       IMAGE_FILE_MACHINE_EBC  

+#define EFI_IMAGE_MACHINE_X64       IMAGE_FILE_MACHINE_X64

+

+#define EFI_IMAGE_DOS_SIGNATURE     0x5A4D      // MZ

+#define EFI_IMAGE_OS2_SIGNATURE     0x454E      // NE

+#define EFI_IMAGE_OS2_SIGNATURE_LE  0x454C      // LE

+#define EFI_IMAGE_NT_SIGNATURE      0x00004550  // PE00

+#define EFI_IMAGE_EDOS_SIGNATURE    0x44454550  // PEED

+

+///

+/// PE images can start with an optional DOS header, so if an image is run

+///  under DOS it can print an error message.

+///

+typedef struct {

+  UINT16  e_magic;    // Magic number

+  UINT16  e_cblp;     // Bytes on last page of file

+  UINT16  e_cp;       // Pages in file

+  UINT16  e_crlc;     // Relocations

+  UINT16  e_cparhdr;  // Size of header in paragraphs

+  UINT16  e_minalloc; // Minimum extra paragraphs needed

+  UINT16  e_maxalloc; // Maximum extra paragraphs needed

+  UINT16  e_ss;       // Initial (relative) SS value

+  UINT16  e_sp;       // Initial SP value

+  UINT16  e_csum;     // Checksum

+  UINT16  e_ip;       // Initial IP value

+  UINT16  e_cs;       // Initial (relative) CS value

+  UINT16  e_lfarlc;   // File address of relocation table

+  UINT16  e_ovno;     // Overlay number

+  UINT16  e_res[4];   // Reserved words

+  UINT16  e_oemid;    // OEM identifier (for e_oeminfo)

+  UINT16  e_oeminfo;  // OEM information; e_oemid specific

+  UINT16  e_res2[10]; // Reserved words

+  UINT32  e_lfanew;   // File address of new exe header

+} EFI_IMAGE_DOS_HEADER;

+

+///

+/// File header format.

+///

+typedef struct {

+  UINT16  Machine;

+  UINT16  NumberOfSections;

+  UINT32  TimeDateStamp;

+  UINT32  PointerToSymbolTable;

+  UINT32  NumberOfSymbols;

+  UINT16  SizeOfOptionalHeader;

+  UINT16  Characteristics;

+} EFI_IMAGE_FILE_HEADER;

+

+#define EFI_IMAGE_SIZEOF_FILE_HEADER        20

+

+#define EFI_IMAGE_FILE_RELOCS_STRIPPED      0x0001  // Relocation info stripped from file.

+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE     0x0002  // File is executable  (i.e. no unresolved externel references).

+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004  // Line nunbers stripped from file.

+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008  // Local symbols stripped from file.

+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO    0x0080  // Bytes of machine word are reversed.

+#define EFI_IMAGE_FILE_32BIT_MACHINE        0x0100  // 32 bit word machine.

+#define EFI_IMAGE_FILE_DEBUG_STRIPPED       0x0200  // Debugging info stripped from file in .DBG file

+#define EFI_IMAGE_FILE_SYSTEM               0x1000  // System File.

+#define EFI_IMAGE_FILE_DLL                  0x2000  // File is a DLL.

+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI    0x8000  // Bytes of machine word are reversed.

+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN      0

+#define EFI_IMAGE_FILE_MACHINE_I386         0x14c   // Intel 386.

+#define EFI_IMAGE_FILE_MACHINE_R3000        0x162   // MIPS* little-endian, 0540 big-endian

+#define EFI_IMAGE_FILE_MACHINE_R4000        0x166   // MIPS* little-endian

+#define EFI_IMAGE_FILE_MACHINE_ALPHA        0x184   // Alpha_AXP*

+#define EFI_IMAGE_FILE_MACHINE_POWERPC      0x1F0   // IBM* PowerPC Little-Endian

+#define EFI_IMAGE_FILE_MACHINE_TAHOE        0x7cc   // Intel EM machine

+//

+// * Other names and brands may be claimed as the property of others.

+//

+

+///

+/// Directory format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  Size;

+} EFI_IMAGE_DATA_DIRECTORY;

+

+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16

+

+typedef struct {

+  UINT16  Magic;

+  UINT8   MajorLinkerVersion;

+  UINT8   MinorLinkerVersion;

+  UINT32  SizeOfCode;

+  UINT32  SizeOfInitializedData;

+  UINT32  SizeOfUninitializedData;

+  UINT32  AddressOfEntryPoint;

+  UINT32  BaseOfCode;

+  UINT32  BaseOfData;

+  UINT32  BaseOfBss;

+  UINT32  GprMask;

+  UINT32  CprMask[4];

+  UINT32  GpValue;

+} EFI_IMAGE_ROM_OPTIONAL_HEADER;

+

+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC      0x107

+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER  sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)

+

+typedef struct {

+  EFI_IMAGE_FILE_HEADER         FileHeader;

+  EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;

+} EFI_IMAGE_ROM_HEADERS;

+

+///

+/// @attention

+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64

+/// are for use ONLY by tools.  All proper EFI code MUST use

+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!

+///

+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b

+

+typedef struct {

+  //

+  // Standard fields.

+  //

+  UINT16                    Magic;

+  UINT8                     MajorLinkerVersion;

+  UINT8                     MinorLinkerVersion;

+  UINT32                    SizeOfCode;

+  UINT32                    SizeOfInitializedData;

+  UINT32                    SizeOfUninitializedData;

+  UINT32                    AddressOfEntryPoint;

+  UINT32                    BaseOfCode;

+  UINT32                    BaseOfData;

+  //

+  // NT additional fields.

+  //

+  UINT32                    ImageBase;

+  UINT32                    SectionAlignment;

+  UINT32                    FileAlignment;

+  UINT16                    MajorOperatingSystemVersion;

+  UINT16                    MinorOperatingSystemVersion;

+  UINT16                    MajorImageVersion;

+  UINT16                    MinorImageVersion;

+  UINT16                    MajorSubsystemVersion;

+  UINT16                    MinorSubsystemVersion;

+  UINT32                    Win32VersionValue;

+  UINT32                    SizeOfImage;

+  UINT32                    SizeOfHeaders;

+  UINT32                    CheckSum;

+  UINT16                    Subsystem;

+  UINT16                    DllCharacteristics;

+  UINT32                    SizeOfStackReserve;

+  UINT32                    SizeOfStackCommit;

+  UINT32                    SizeOfHeapReserve;

+  UINT32                    SizeOfHeapCommit;

+  UINT32                    LoaderFlags;

+  UINT32                    NumberOfRvaAndSizes;

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];

+} EFI_IMAGE_OPTIONAL_HEADER32;

+

+///

+/// @attention

+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64

+/// are for use ONLY by tools.  All proper EFI code MUST use

+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!

+///

+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b

+

+typedef struct {

+  //

+  // Standard fields.

+  //

+  UINT16                    Magic;

+  UINT8                     MajorLinkerVersion;

+  UINT8                     MinorLinkerVersion;

+  UINT32                    SizeOfCode;

+  UINT32                    SizeOfInitializedData;

+  UINT32                    SizeOfUninitializedData;

+  UINT32                    AddressOfEntryPoint;

+  UINT32                    BaseOfCode;

+  //

+  // NT additional fields.

+  //

+  UINT64                    ImageBase;

+  UINT32                    SectionAlignment;

+  UINT32                    FileAlignment;

+  UINT16                    MajorOperatingSystemVersion;

+  UINT16                    MinorOperatingSystemVersion;

+  UINT16                    MajorImageVersion;

+  UINT16                    MinorImageVersion;

+  UINT16                    MajorSubsystemVersion;

+  UINT16                    MinorSubsystemVersion;

+  UINT32                    Win32VersionValue;

+  UINT32                    SizeOfImage;

+  UINT32                    SizeOfHeaders;

+  UINT32                    CheckSum;

+  UINT16                    Subsystem;

+  UINT16                    DllCharacteristics;

+  UINT64                    SizeOfStackReserve;

+  UINT64                    SizeOfStackCommit;

+  UINT64                    SizeOfHeapReserve;

+  UINT64                    SizeOfHeapCommit;

+  UINT32                    LoaderFlags;

+  UINT32                    NumberOfRvaAndSizes;

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];

+} EFI_IMAGE_OPTIONAL_HEADER64;

+

+///

+/// @attention

+/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY

+/// by tools.  All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!

+///

+typedef struct {

+  UINT32                      Signature;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;

+} EFI_IMAGE_NT_HEADERS32;

+

+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)

+

+typedef struct {

+  UINT32                      Signature;

+  EFI_IMAGE_FILE_HEADER       FileHeader;

+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;

+} EFI_IMAGE_NT_HEADERS64;

+

+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)

+

+//

+// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the

+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build.  Same for

+// EFI_IMAGE_NT_HEADERS.  These definitions MUST be used by ALL EFI code.

+//

+#if   defined (MDE_CPU_IA32) && !defined (BUILDING_TOOLS) || \

+      defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IA32_TARGET)

+

+// typedef EFI_IMAGE_OPTIONAL_HEADER32     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS32          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_IPF) && !defined (BUILDING_TOOLS) || \

+      defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IPF_TARGET)

+

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_X64) && !defined (BUILDING_TOOLS) || \

+      defined (BUILDING_TOOLS) && defined (TOOL_BUILD_X64_TARGET)

+

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \

+  (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))

+

+#elif defined (MDE_CPU_EBC)

+

+//

+// This is just to make sure you can cross compile with the EBC compiiler.

+// It does not make sense to have a PE loader coded in EBC. You need to 

+// understand the basic 

+//

+typedef EFI_IMAGE_OPTIONAL_HEADER64     EFI_IMAGE_OPTIONAL_HEADER;

+typedef EFI_IMAGE_NT_HEADERS64          EFI_IMAGE_NT_HEADERS;

+

+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC

+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)

+

+#else

+#error Unknown Processor Type

+#endif

+

+

+#define EFI_IMAGE_FIRST_SECTION(ntheader) \

+    ( \

+      (EFI_IMAGE_SECTION_HEADER *) \

+        ( \

+          (UINT32) ntheader + \

+          FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \

+          ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \

+        ) \

+    )

+

+//

+// Subsystem Values

+//

+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN     0

+#define EFI_IMAGE_SUBSYSTEM_NATIVE      1

+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2

+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.

+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI     5

+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI   7

+

+//

+// Directory Entries

+//

+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT      0

+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT      1

+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE    2

+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION   3

+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY    4

+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC   5

+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG       6

+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT   7

+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR   8

+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS         9

+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10

+

+//

+// Section header format.

+//

+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8

+

+typedef struct {

+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];

+  union {

+    UINT32  PhysicalAddress;

+    UINT32  VirtualSize;

+  } Misc;

+  UINT32  VirtualAddress;

+  UINT32  SizeOfRawData;

+  UINT32  PointerToRawData;

+  UINT32  PointerToRelocations;

+  UINT32  PointerToLinenumbers;

+  UINT16  NumberOfRelocations;

+  UINT16  NumberOfLinenumbers;

+  UINT32  Characteristics;

+} EFI_IMAGE_SECTION_HEADER;

+

+#define EFI_IMAGE_SIZEOF_SECTION_HEADER       40

+

+#define EFI_IMAGE_SCN_TYPE_NO_PAD             0x00000008  // Reserved.

+#define EFI_IMAGE_SCN_CNT_CODE                0x00000020

+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA    0x00000040

+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA  0x00000080

+

+#define EFI_IMAGE_SCN_LNK_OTHER               0x00000100  // Reserved.

+#define EFI_IMAGE_SCN_LNK_INFO                0x00000200  // Section contains comments or some other type of information.

+#define EFI_IMAGE_SCN_LNK_REMOVE              0x00000800  // Section contents will not become part of image.

+#define EFI_IMAGE_SCN_LNK_COMDAT              0x00001000

+

+#define EFI_IMAGE_SCN_ALIGN_1BYTES            0x00100000

+#define EFI_IMAGE_SCN_ALIGN_2BYTES            0x00200000

+#define EFI_IMAGE_SCN_ALIGN_4BYTES            0x00300000

+#define EFI_IMAGE_SCN_ALIGN_8BYTES            0x00400000

+#define EFI_IMAGE_SCN_ALIGN_16BYTES           0x00500000

+#define EFI_IMAGE_SCN_ALIGN_32BYTES           0x00600000

+#define EFI_IMAGE_SCN_ALIGN_64BYTES           0x00700000

+

+#define EFI_IMAGE_SCN_MEM_DISCARDABLE         0x02000000

+#define EFI_IMAGE_SCN_MEM_NOT_CACHED          0x04000000

+#define EFI_IMAGE_SCN_MEM_NOT_PAGED           0x08000000

+#define EFI_IMAGE_SCN_MEM_SHARED              0x10000000

+#define EFI_IMAGE_SCN_MEM_EXECUTE             0x20000000

+#define EFI_IMAGE_SCN_MEM_READ                0x40000000

+#define EFI_IMAGE_SCN_MEM_WRITE               0x80000000

+

+///

+/// Symbol format.

+///

+#define EFI_IMAGE_SIZEOF_SYMBOL 18

+

+//

+// Section values.

+//

+// Symbols have a section number of the section in which they are

+// defined. Otherwise, section numbers have the following meanings:

+//

+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0  // Symbol is undefined or is common.

+#define EFI_IMAGE_SYM_ABSOLUTE  (UINT16) -1 // Symbol is an absolute value.

+#define EFI_IMAGE_SYM_DEBUG     (UINT16) -2 // Symbol is a special debug item.

+//

+// Type (fundamental) values.

+//

+#define EFI_IMAGE_SYM_TYPE_NULL   0   // no type.

+#define EFI_IMAGE_SYM_TYPE_VOID   1   //

+#define EFI_IMAGE_SYM_TYPE_CHAR   2   // type character.

+#define EFI_IMAGE_SYM_TYPE_SHORT  3   // type short integer.

+#define EFI_IMAGE_SYM_TYPE_INT    4

+#define EFI_IMAGE_SYM_TYPE_LONG   5

+#define EFI_IMAGE_SYM_TYPE_FLOAT  6

+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7

+#define EFI_IMAGE_SYM_TYPE_STRUCT 8

+#define EFI_IMAGE_SYM_TYPE_UNION  9

+#define EFI_IMAGE_SYM_TYPE_ENUM   10  // enumeration.

+#define EFI_IMAGE_SYM_TYPE_MOE    11  // member of enumeration.

+#define EFI_IMAGE_SYM_TYPE_BYTE   12

+#define EFI_IMAGE_SYM_TYPE_WORD   13

+#define EFI_IMAGE_SYM_TYPE_UINT   14

+#define EFI_IMAGE_SYM_TYPE_DWORD  15

+

+//

+// Type (derived) values.

+//

+#define EFI_IMAGE_SYM_DTYPE_NULL      0 // no derived type.

+#define EFI_IMAGE_SYM_DTYPE_POINTER   1

+#define EFI_IMAGE_SYM_DTYPE_FUNCTION  2

+#define EFI_IMAGE_SYM_DTYPE_ARRAY     3

+

+//

+// Storage classes.

+//

+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION   (UINT8) -1

+#define EFI_IMAGE_SYM_CLASS_NULL              0

+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC         1

+#define EFI_IMAGE_SYM_CLASS_EXTERNAL          2

+#define EFI_IMAGE_SYM_CLASS_STATIC            3

+#define EFI_IMAGE_SYM_CLASS_REGISTER          4

+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF      5

+#define EFI_IMAGE_SYM_CLASS_LABEL             6

+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL   7

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT  8

+#define EFI_IMAGE_SYM_CLASS_ARGUMENT          9

+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG        10

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION   11

+#define EFI_IMAGE_SYM_CLASS_UNION_TAG         12

+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION   13

+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC  14

+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG          15

+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM    16

+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM    17

+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD         18

+#define EFI_IMAGE_SYM_CLASS_BLOCK             100

+#define EFI_IMAGE_SYM_CLASS_FUNCTION          101

+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT     102

+#define EFI_IMAGE_SYM_CLASS_FILE              103

+#define EFI_IMAGE_SYM_CLASS_SECTION           104

+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL     105

+

+//

+// type packing constants

+//

+#define EFI_IMAGE_N_BTMASK  017

+#define EFI_IMAGE_N_TMASK   060

+#define EFI_IMAGE_N_TMASK1  0300

+#define EFI_IMAGE_N_TMASK2  0360

+#define EFI_IMAGE_N_BTSHFT  4

+#define EFI_IMAGE_N_TSHIFT  2

+

+//

+// Communal selection types.

+//

+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES    1

+#define EFI_IMAGE_COMDAT_SELECT_ANY             2

+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE       3

+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH     4

+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE     5

+

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2

+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3

+

+///

+/// Relocation format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  SymbolTableIndex;

+  UINT16  Type;

+} EFI_IMAGE_RELOCATION;

+

+#define EFI_IMAGE_SIZEOF_RELOCATION 10

+

+//

+// I386 relocation types.

+//

+#define EFI_IMAGE_REL_I386_ABSOLUTE 0   // Reference is absolute, no relocation is necessary

+#define EFI_IMAGE_REL_I386_DIR16    01  // Direct 16-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_REL16    02  // PC-relative 16-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_DIR32    06  // Direct 32-bit reference to the symbols virtual address

+#define EFI_IMAGE_REL_I386_DIR32NB  07  // Direct 32-bit reference to the symbols virtual address, base not included

+#define EFI_IMAGE_REL_I386_SEG12    011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address

+#define EFI_IMAGE_REL_I386_SECTION  012

+#define EFI_IMAGE_REL_I386_SECREL   013

+#define EFI_IMAGE_REL_I386_REL32    024 // PC-relative 32-bit reference to the symbols virtual address

+

+///

+/// Based relocation format.

+///

+typedef struct {

+  UINT32  VirtualAddress;

+  UINT32  SizeOfBlock;

+} EFI_IMAGE_BASE_RELOCATION;

+

+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION  8

+

+//

+// Based relocation types.

+//

+#define EFI_IMAGE_REL_BASED_ABSOLUTE      0

+#define EFI_IMAGE_REL_BASED_HIGH          1

+#define EFI_IMAGE_REL_BASED_LOW           2

+#define EFI_IMAGE_REL_BASED_HIGHLOW       3

+#define EFI_IMAGE_REL_BASED_HIGHADJ       4

+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR  5

+#define EFI_IMAGE_REL_BASED_IA64_IMM64    9

+#define EFI_IMAGE_REL_BASED_DIR64         10

+

+///

+/// Line number format.

+///

+typedef struct {

+  union {

+    UINT32  SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.

+    UINT32  VirtualAddress;   // Virtual address of line number.

+  } Type;

+  UINT16  Linenumber;         // Line number.

+} EFI_IMAGE_LINENUMBER;

+

+#define EFI_IMAGE_SIZEOF_LINENUMBER 6

+

+//

+// Archive format.

+//

+#define EFI_IMAGE_ARCHIVE_START_SIZE        8

+#define EFI_IMAGE_ARCHIVE_START             "!<arch>\n"

+#define EFI_IMAGE_ARCHIVE_END               "`\n"

+#define EFI_IMAGE_ARCHIVE_PAD               "\n"

+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER     "/               "

+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER  "//              "

+

+typedef struct {

+  UINT8 Name[16];     // File member name - `/' terminated.

+  UINT8 Date[12];     // File member date - decimal.

+  UINT8 UserID[6];    // File member user id - decimal.

+  UINT8 GroupID[6];   // File member group id - decimal.

+  UINT8 Mode[8];      // File member mode - octal.

+  UINT8 Size[10];     // File member size - decimal.

+  UINT8 EndHeader[2]; // String to end header.

+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;

+

+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60

+

+//

+// DLL support.

+//

+

+///

+/// DLL Export Format

+///

+typedef struct {

+  UINT32  Characteristics;

+  UINT32  TimeDateStamp;

+  UINT16  MajorVersion;

+  UINT16  MinorVersion;

+  UINT32  Name;

+  UINT32  Base;

+  UINT32  NumberOfFunctions;

+  UINT32  NumberOfNames;

+  UINT32  AddressOfFunctions;

+  UINT32  AddressOfNames;

+  UINT32  AddressOfNameOrdinals;

+} EFI_IMAGE_EXPORT_DIRECTORY;

+

+///

+/// DLL support.

+/// Import Format

+///

+typedef struct {

+  UINT16  Hint;

+  UINT8   Name[1];

+} EFI_IMAGE_IMPORT_BY_NAME;

+

+typedef struct {

+  union {

+    UINT32                    Function;

+    UINT32                    Ordinal;

+    EFI_IMAGE_IMPORT_BY_NAME  *AddressOfData;

+  } u1;

+} EFI_IMAGE_THUNK_DATA;

+

+#define EFI_IMAGE_ORDINAL_FLAG              0x80000000

+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal)  ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)

+#define EFI_IMAGE_ORDINAL(Ordinal)          (Ordinal & 0xffff)

+

+typedef struct {

+  UINT32                Characteristics;

+  UINT32                TimeDateStamp;

+  UINT32                ForwarderChain;

+  UINT32                Name;

+  EFI_IMAGE_THUNK_DATA  *FirstThunk;

+} EFI_IMAGE_IMPORT_DESCRIPTOR;

+

+///

+/// Debug Format

+///

+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2

+

+typedef struct {

+  UINT32  Characteristics;

+  UINT32  TimeDateStamp;

+  UINT16  MajorVersion;

+  UINT16  MinorVersion;

+  UINT32  Type;

+  UINT32  SizeOfData;

+  UINT32  RVA;

+  UINT32  FileOffset;

+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;

+

+#define CODEVIEW_SIGNATURE_NB10 0x3031424E  // "NB10"

+typedef struct {

+  UINT32  Signature;                        // "NB10"

+  UINT32  Unknown;

+  UINT32  Unknown2;

+  UINT32  Unknown3;

+  //

+  // Filename of .PDB goes here

+  //

+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;

+

+#define CODEVIEW_SIGNATURE_RSDS 0x53445352  // "RSDS"

+typedef struct {

+  UINT32  Signature;                        // "RSDS"

+  UINT32  Unknown;

+  UINT32  Unknown2;

+  UINT32  Unknown3;

+  UINT32  Unknown4;

+  UINT32  Unknown5;

+  //

+  // Filename of .PDB goes here

+  //

+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;

+

+///

+/// Header format for TE images

+///

+typedef struct {

+  UINT16                    Signature;            // signature for TE format = "VZ"

+  UINT16                    Machine;              // from the original file header

+  UINT8                     NumberOfSections;     // from the original file header

+  UINT8                     Subsystem;            // from original optional header

+  UINT16                    StrippedSize;         // how many bytes we removed from the header

+  UINT32                    AddressOfEntryPoint;  // offset to entry point -- from original optional header

+  UINT32                    BaseOfCode;           // from original image -- required for ITP debug

+  UINT64                    ImageBase;            // from original file header

+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[2];     // only base relocation and debug directory

+} EFI_TE_IMAGE_HEADER;

+

+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56      // "VZ"

+

+//

+// Data directory indexes in our TE image header

+//

+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0

+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1

+

+#endif

diff --git a/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c b/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c
new file mode 100644
index 0000000..f58e8d0
--- /dev/null
+++ b/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c
@@ -0,0 +1,56 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    PeCoffLoaderEx.c

+

+Abstract:

+

+    IA-32 Specific relocation fixups

+

+Revision History

+

+--*/

+

+#include <Common/UefiBaseTypes.h>

+

+RETURN_STATUS

+PeCoffLoaderRelocateImageEx (

+  IN UINT16      *Reloc,

+  IN OUT CHAR8   *Fixup,

+  IN OUT CHAR8   **FixupData,

+  IN UINT64      Adjust

+  )

+/*++

+

+Routine Description:

+

+  Performs an IA-32 specific relocation fixup

+

+Arguments:

+

+  Reloc      - Pointer to the relocation record

+

+  Fixup      - Pointer to the address to fix up

+

+  FixupData  - Pointer to a buffer to log the fixups

+

+  Adjust     - The offset to adjust the fixup

+

+Returns:

+

+  EFI_UNSUPPORTED   - Unsupported now

+

+--*/

+{

+  return RETURN_UNSUPPORTED;

+}

diff --git a/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c b/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c
new file mode 100644
index 0000000..3f39899
--- /dev/null
+++ b/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c
@@ -0,0 +1,249 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    PeCoffLoaderEx.c

+

+Abstract:

+

+    Fixes Intel Itanium(TM) specific relocation types

+

+

+Revision History

+

+--*/

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Library/PeCoffLib.h>

+

+

+

+

+

+#define EXT_IMM64(Value, Address, Size, InstPos, ValPos)  \

+    Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)

+

+#define INS_IMM64(Value, Address, Size, InstPos, ValPos)  \

+    *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \

+          ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)

+

+#define IMM64_IMM7B_INST_WORD_X         3  

+#define IMM64_IMM7B_SIZE_X              7  

+#define IMM64_IMM7B_INST_WORD_POS_X     4  

+#define IMM64_IMM7B_VAL_POS_X           0  

+

+#define IMM64_IMM9D_INST_WORD_X         3  

+#define IMM64_IMM9D_SIZE_X              9  

+#define IMM64_IMM9D_INST_WORD_POS_X     18  

+#define IMM64_IMM9D_VAL_POS_X           7  

+

+#define IMM64_IMM5C_INST_WORD_X         3  

+#define IMM64_IMM5C_SIZE_X              5  

+#define IMM64_IMM5C_INST_WORD_POS_X     13  

+#define IMM64_IMM5C_VAL_POS_X           16  

+

+#define IMM64_IC_INST_WORD_X            3  

+#define IMM64_IC_SIZE_X                 1  

+#define IMM64_IC_INST_WORD_POS_X        12  

+#define IMM64_IC_VAL_POS_X              21  

+

+#define IMM64_IMM41a_INST_WORD_X        1  

+#define IMM64_IMM41a_SIZE_X             10  

+#define IMM64_IMM41a_INST_WORD_POS_X    14  

+#define IMM64_IMM41a_VAL_POS_X          22  

+

+#define IMM64_IMM41b_INST_WORD_X        1  

+#define IMM64_IMM41b_SIZE_X             8  

+#define IMM64_IMM41b_INST_WORD_POS_X    24  

+#define IMM64_IMM41b_VAL_POS_X          32  

+

+#define IMM64_IMM41c_INST_WORD_X        2  

+#define IMM64_IMM41c_SIZE_X             23  

+#define IMM64_IMM41c_INST_WORD_POS_X    0  

+#define IMM64_IMM41c_VAL_POS_X          40  

+

+#define IMM64_SIGN_INST_WORD_X          3  

+#define IMM64_SIGN_SIZE_X               1  

+#define IMM64_SIGN_INST_WORD_POS_X      27  

+#define IMM64_SIGN_VAL_POS_X            63  

+

+RETURN_STATUS

+PeCoffLoaderRelocateImageEx (

+  IN UINT16      *Reloc,

+  IN OUT CHAR8   *Fixup, 

+  IN OUT CHAR8   **FixupData,

+  IN UINT64      Adjust

+  )

+/*++

+

+Routine Description:

+

+  Performs an Itanium-based specific relocation fixup

+

+Arguments:

+

+  Reloc      - Pointer to the relocation record

+

+  Fixup      - Pointer to the address to fix up

+

+  FixupData  - Pointer to a buffer to log the fixups

+

+  Adjust     - The offset to adjust the fixup

+

+Returns:

+

+  Status code

+

+--*/

+{

+  UINT64      *F64;

+  UINT64      FixupVal;

+

+  switch ((*Reloc) >> 12) {

+

+    case EFI_IMAGE_REL_BASED_DIR64:

+      F64 = (UINT64 *) Fixup;

+      *F64 = *F64 + (UINT64) Adjust;

+      if (*FixupData != NULL) {

+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));

+        *(UINT64 *)(*FixupData) = *F64;

+        *FixupData = *FixupData + sizeof(UINT64);

+      }

+      break;

+

+    case EFI_IMAGE_REL_BASED_IA64_IMM64:

+

+      //

+      // Align it to bundle address before fixing up the

+      // 64-bit immediate value of the movl instruction.

+      //

+

+      Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));

+      FixupVal = (UINT64)0;

+                       

+      // 

+      // Extract the lower 32 bits of IMM64 from bundle

+      //

+      EXT_IMM64(FixupVal,

+                (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,

+                IMM64_IMM7B_SIZE_X,

+                IMM64_IMM7B_INST_WORD_POS_X,

+                IMM64_IMM7B_VAL_POS_X

+                );

+

+      EXT_IMM64(FixupVal,

+                (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,

+                IMM64_IMM9D_SIZE_X,

+                IMM64_IMM9D_INST_WORD_POS_X,

+                IMM64_IMM9D_VAL_POS_X

+                );

+

+      EXT_IMM64(FixupVal,

+                (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,

+                IMM64_IMM5C_SIZE_X,

+                IMM64_IMM5C_INST_WORD_POS_X,

+                IMM64_IMM5C_VAL_POS_X

+                );

+

+      EXT_IMM64(FixupVal,

+                (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,

+                IMM64_IC_SIZE_X,

+                IMM64_IC_INST_WORD_POS_X,

+                IMM64_IC_VAL_POS_X

+                );

+

+      EXT_IMM64(FixupVal,

+                (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,

+                IMM64_IMM41a_SIZE_X,

+                IMM64_IMM41a_INST_WORD_POS_X,

+                IMM64_IMM41a_VAL_POS_X

+                );

+                       

+      // 

+      // Update 64-bit address

+      //

+      FixupVal += Adjust;

+

+      // 

+      // Insert IMM64 into bundle

+      //

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),

+                IMM64_IMM7B_SIZE_X,

+                IMM64_IMM7B_INST_WORD_POS_X,

+                IMM64_IMM7B_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),

+                IMM64_IMM9D_SIZE_X,

+                IMM64_IMM9D_INST_WORD_POS_X,

+                IMM64_IMM9D_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),

+                IMM64_IMM5C_SIZE_X,

+                IMM64_IMM5C_INST_WORD_POS_X,

+                IMM64_IMM5C_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),

+                IMM64_IC_SIZE_X,

+                IMM64_IC_INST_WORD_POS_X,

+                IMM64_IC_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),

+                IMM64_IMM41a_SIZE_X,

+                IMM64_IMM41a_INST_WORD_POS_X,

+                IMM64_IMM41a_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),

+                IMM64_IMM41b_SIZE_X,

+                IMM64_IMM41b_INST_WORD_POS_X,

+                IMM64_IMM41b_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),

+                IMM64_IMM41c_SIZE_X,

+                IMM64_IMM41c_INST_WORD_POS_X,

+                IMM64_IMM41c_VAL_POS_X

+                );

+

+      INS_IMM64(FixupVal,

+                ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),

+                IMM64_SIGN_SIZE_X,

+                IMM64_SIGN_INST_WORD_POS_X,

+                IMM64_SIGN_VAL_POS_X

+                );

+

+      F64 = (UINT64 *) Fixup;

+      if (*FixupData != NULL) {

+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));

+        *(UINT64 *)(*FixupData) = *F64;

+        *FixupData = *FixupData + sizeof(UINT64);

+      }

+      break;

+

+    default:

+      return RETURN_UNSUPPORTED;

+  }

+

+  return RETURN_SUCCESS;

+}

diff --git a/Source/PeCoffLoader/X64/PeCoffLoaderEx.c b/Source/PeCoffLoader/X64/PeCoffLoaderEx.c
new file mode 100644
index 0000000..1e6cc34
--- /dev/null
+++ b/Source/PeCoffLoader/X64/PeCoffLoaderEx.c
@@ -0,0 +1,74 @@
+/*++

+

+Copyright 2005, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+

+Module Name:

+

+  PeCoffLoaderEx.c

+

+Abstract:

+

+  x64 Specific relocation fixups

+

+Revision History

+

+--*/

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Library/PeCoffLib.h>

+

+

+

+

+RETURN_STATUS

+PeCoffLoaderRelocateImageEx (

+  IN UINT16      *Reloc,

+  IN OUT CHAR8   *Fixup, 

+  IN OUT CHAR8   **FixupData,

+  IN UINT64      Adjust

+  )

+/*++

+

+Routine Description:

+  Performs an x64 specific relocation fixup

+

+Arguments:

+  Reloc      - Pointer to the relocation record

+  Fixup      - Pointer to the address to fix up

+  FixupData  - Pointer to a buffer to log the fixups

+  Adjust     - The offset to adjust the fixup

+

+Returns:

+  None

+

+--*/

+{

+  UINT64      *F64;

+

+  switch ((*Reloc) >> 12) {

+

+    case EFI_IMAGE_REL_BASED_DIR64:

+      F64 = (UINT64 *) Fixup;

+      *F64 = *F64 + (UINT64) Adjust;

+      if (*FixupData != NULL) {

+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));

+        *(UINT64 *)(*FixupData) = *F64;

+        *FixupData = *FixupData + sizeof(UINT64);

+      }

+      break;

+

+    default:

+      return RETURN_UNSUPPORTED;

+  }

+

+  return RETURN_SUCCESS;

+}

diff --git a/Source/PeCoffLoader/build.xml b/Source/PeCoffLoader/build.xml
new file mode 100644
index 0000000..c6137bd
--- /dev/null
+++ b/Source/PeCoffLoader/build.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK PeCoffLoader

+  Copyright (c) 2006, Intel Corporation

+-->

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LibName" value="PeCoffLoader"/>

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR_IA32" value="${PACKAGE_DIR}/${LibName}/tmp/Ia32"/>

+  <property name="BUILD_DIR_X64" value="${PACKAGE_DIR}/${LibName}/tmp/X64"/>

+  <property name="BUILD_DIR_IPF" value="${PACKAGE_DIR}/${LibName}/tmp/Ipf"/>

+

+  <target name="GenTool" depends="init, PeCoffLoaderLib">

+    <echo message="The EDK Library: ${LibName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Library: ${LibName}"/>

+    <mkdir dir="${BUILD_DIR_IA32}"/>

+    <mkdir dir="${BUILD_DIR_X64}"/>

+    <mkdir dir="${BUILD_DIR_IPF}"/>

+

+    <condition property="syslibdirs" value="">

+      <os family="mac"/>

+    </condition>

+    

+    <condition property="syslibs" value="">

+      <os family="mac"/>

+    </condition>

+    

+    <condition property="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs">

+      <os family="windows"/>

+    </condition>

+    

+    <condition property="syslibs" value="uuid">

+      <os family="windows"/>

+    </condition>

+    

+    <condition property="syslibdirs" value="/usr/lib">

+      <os name="Linux"/>

+    </condition>

+    

+    <condition property="syslibs" value="uuid">

+      <os name="Linux"/>

+    </condition>

+    

+  </target>

+

+  <target name="PeCoffLoaderLib" depends="init, PeCoffLoader_Ia32, PeCoffLoader_Ipf, PeCoffLoader_X64"/>

+

+  <target name="PeCoffLoader_Ia32" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR_IA32}" 

+        outfile="${LIB_DIR}/${LibName}_Ia32"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_IA32_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${LibName}" 

+        includes="BasePeCoff.c Ia32/PeCoffLoaderEx.c" />

+

+      <includepath path="${PACKAGE_DIR}/${LibName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="PeCoffLoader_Ipf" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR_IPF}" 

+        outfile="${LIB_DIR}/${LibName}_Ipf"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_IPF_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${LibName}" 

+        includes="BasePeCoff.c Ipf/PeCoffLoaderEx.c" />

+

+      <includepath path="${PACKAGE_DIR}/${LibName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="PeCoffLoader_X64" >

+    <cc name="${ToolChain}" objdir="${BUILD_DIR_X64}" 

+        outfile="${LIB_DIR}/${LibName}_X64"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+

+      <defineset>

+        <define name="BUILDING_TOOLS"/>

+        <define name="TOOL_BUILD_X64_TARGET"/>

+      </defineset>

+    

+      <fileset dir="${basedir}/${LibName}" 

+        includes="BasePeCoff.c X64/PeCoffLoaderEx.c" />

+

+      <includepath path="${PACKAGE_DIR}/${LibName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR_IA32}" includes="*.obj"/>

+      <fileset dir="${BUILD_DIR_X64}" includes="*.obj"/>

+      <fileset dir="${BUILD_DIR_IPF}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${LibName}${ext_exe}"/>  

+    <delete dir="${PACKAGE_DIR}/${LibName}/tmp">

+    </delete>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR_IA32}"/>

+      <fileset dir="${BUILD_DIR_X64}"/>

+      <fileset dir="${BUILD_DIR_IPF}"/>

+      <fileset file="${LIB_DIR}/${LibName}_Ia32${ext_static}"/>

+      <fileset file="${BIN_DIR}/${LibName}_X64${ext_static}"/>

+      <fileset file="${BIN_DIR}/${LibName}_IPF${ext_static}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/PeiRebase/PeiRebaseExe.c b/Source/PeiRebase/PeiRebaseExe.c
new file mode 100644
index 0000000..27c646e
--- /dev/null
+++ b/Source/PeiRebase/PeiRebaseExe.c
@@ -0,0 +1,1059 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  PeiRebaseExe.c

+

+Abstract:

+

+  This contains all code necessary to build the PeiRebase.exe utility.

+  This utility relies heavily on the PeiRebase DLL.  Definitions for both

+  can be found in the PEI Rebase Utility Specification, review draft.

+

+--*/

+

+#include <stdlib.h>

+#include <stdio.h>

+#include <string.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Library/PeCoffLib.h>

+

+#include "CommonLib.h"

+#include "ParseInf.h"

+#include "FvLib.h"

+#include "EfiUtilityMsgs.h"

+#include "PeiRebaseExe.h"

+

+EFI_STATUS

+ReadHeader (

+  IN FILE       *InputFile,

+  OUT UINT32    *FvSize,

+  OUT BOOLEAN   *ErasePolarity

+  );

+

+int

+main (

+  int  argc,

+  char **argv

+  )

+/*++

+

+Routine Description:

+

+  This utility relocates PEI XIP PE32s in a FV.

+

+Arguments:

+

+  argc          - Number of command line arguments

+  argv[]:

+  BaseAddress     The base address to use for rebasing the FV.  The correct 

+                  format is a hex number preceded by 0x.

+  InputFileName   The name of the input FV file.

+  OutputFileName  The name of the output FV file.

+  MapFileName     The name of the map file of relocation info.

+

+  Arguments come in pair in any order.

+    -I InputFileName 

+    -O OutputFileName

+    -B BaseAddress 

+    -M MapFileName 

+

+Returns:

+

+  0   No error conditions detected.

+  1   One or more of the input parameters is invalid.

+  2   A resource required by the utility was unavailable.  

+      Most commonly this will be memory allocation or file creation.

+  3   PeiRebase.dll could not be loaded.

+  4   Error executing the PEI rebase.

+

+--*/

+{

+  UINT8                       Index;

+  CHAR8                       InputFileName[_MAX_PATH];

+  CHAR8                       OutputFileName[_MAX_PATH];

+  CHAR8                       MapFileName[_MAX_PATH];

+  EFI_PHYSICAL_ADDRESS        BaseAddress;

+  BOOLEAN                     BaseAddressSet;

+  EFI_STATUS                  Status;

+  FILE                        *InputFile;

+  FILE                        *OutputFile;

+  FILE                        *MapFile;

+  UINT64                      FvOffset;

+  UINT32                      FileCount;

+  int                         BytesRead;

+  EFI_FIRMWARE_VOLUME_HEADER  *FvImage;

+  UINT32                      FvSize;

+  EFI_FFS_FILE_HEADER         *CurrentFile;

+  BOOLEAN                     ErasePolarity;

+  EFI_PHYSICAL_ADDRESS        CurrentFileBaseAddress;

+

+  ErasePolarity = FALSE;

+  //

+  // Set utility name for error/warning reporting purposes.

+  //

+  SetUtilityName (UTILITY_NAME);

+  //

+  // Verify the correct number of arguments

+  //

+  if (argc != MAX_ARGS) {

+    PrintUsage ();

+    return STATUS_ERROR;

+  }

+

+  //

+  // Initialize variables

+  //

+  InputFileName[0]  = 0;

+  OutputFileName[0] = 0;

+  MapFileName[0]    = 0;

+  BaseAddress       = 0;

+  BaseAddressSet    = FALSE;

+  FvOffset          = 0;

+  FileCount         = 0;

+  ErasePolarity     = FALSE;

+  InputFile         = NULL;

+  OutputFile        = NULL;

+  MapFile           = NULL;

+  FvImage           = NULL;

+

+  //

+  // Parse the command line arguments

+  //

+  for (Index = 1; Index < MAX_ARGS; Index += 2) {

+    //

+    // Make sure argument pair begin with - or /

+    //

+    if (argv[Index][0] != '-' && argv[Index][0] != '/') {

+      PrintUsage ();

+      Error (NULL, 0, 0, argv[Index], "unrecognized option");

+      return STATUS_ERROR;

+    }

+    //

+    // Make sure argument specifier is only one letter

+    //

+    if (argv[Index][2] != 0) {

+      PrintUsage ();

+      Error (NULL, 0, 0, argv[Index], "unrecognized option");

+      return STATUS_ERROR;

+    }    

+    //

+    // Determine argument to read

+    //

+    switch (argv[Index][1]) {

+    case 'I':

+    case 'i':

+      if (strlen (InputFileName) == 0) {

+        strcpy (InputFileName, argv[Index + 1]);

+      } else {

+        PrintUsage ();

+        Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");

+        return STATUS_ERROR;

+      }

+      break;

+

+    case 'O':

+    case 'o':

+      if (strlen (OutputFileName) == 0) {

+        strcpy (OutputFileName, argv[Index + 1]);

+      } else {

+        PrintUsage ();

+        Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");

+        return STATUS_ERROR;

+      }

+      break;

+

+    case 'B':

+    case 'b':

+      if (!BaseAddressSet) {

+        Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);

+        if (EFI_ERROR (Status)) {

+          PrintUsage ();

+          Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");

+          return STATUS_ERROR;

+        }

+

+        BaseAddressSet = TRUE;

+      } else {

+        PrintUsage ();

+        Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");

+        return STATUS_ERROR;

+      }

+      break;

+

+    case 'M':

+    case 'm':

+      if (strlen (MapFileName) == 0) {

+        strcpy (MapFileName, argv[Index + 1]);

+      } else {

+        PrintUsage ();

+        Error (NULL, 0, 0, argv[Index + 1], "only one -m MapFileName may be specified");

+        return STATUS_ERROR;

+      }

+      break;

+

+    default:

+      PrintUsage ();

+      Error (NULL, 0, 0, argv[Index], "unrecognized argument");

+      return STATUS_ERROR;

+      break;

+    }

+  }

+

+  //

+  // Create the Map file if we need it

+  //

+  if (strlen (MapFileName) != 0) {

+    MapFile = fopen (MapFileName, "w");

+    if (MapFile == NULL) {

+      Error (NULL, 0, 0, MapFileName, "failed to open map file");

+      goto Finish;

+    }

+  } 

+

+  //

+  // Open the file containing the FV

+  //

+  InputFile = fopen (InputFileName, "rb");

+  if (InputFile == NULL) {

+    Error (NULL, 0, 0, InputFileName, "could not open input file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Determine size of FV

+  //

+  Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "could not parse the FV header", NULL);

+    goto Finish;

+  }

+  //

+  // Allocate a buffer for the FV image

+  //

+  FvImage = malloc (FvSize);

+  if (FvImage == NULL) {

+    Error (NULL, 0, 0, "application error", "memory allocation failed");

+    goto Finish;

+  }

+  //

+  // Read the entire FV to the buffer

+  //

+  BytesRead = fread (FvImage, 1, FvSize, InputFile);

+  fclose (InputFile);

+  InputFile = NULL;

+  if ((unsigned int) BytesRead != FvSize) {

+    Error (NULL, 0, 0, InputFileName, "failed to read from file");

+    goto Finish;

+  }

+  //

+  // Prepare to walk the FV image

+  //

+  InitializeFvLib (FvImage, FvSize);

+  //

+  // Get the first file

+  //

+  Status = GetNextFile (NULL, &CurrentFile);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);

+    goto Finish;

+  }

+  //

+  // Check if each file should be rebased

+  //

+  while (CurrentFile != NULL) {

+    //

+    // Rebase this file

+    //

+    CurrentFileBaseAddress  = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);

+    Status                  = FfsRebase (CurrentFile, CurrentFileBaseAddress, MapFile);

+

+    if (EFI_ERROR (Status)) {

+      switch (Status) {

+

+      case EFI_INVALID_PARAMETER:

+        Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);

+        break;

+

+      case EFI_ABORTED:

+        Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);

+        break;

+

+      case EFI_OUT_OF_RESOURCES:

+        Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);

+        break;

+

+      case EFI_NOT_FOUND:

+        Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);

+        break;

+

+      default:

+        Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);

+        break;

+      }

+

+      goto Finish;

+    }

+

+    //

+    // Get the next file

+    //

+    Status = GetNextFile (CurrentFile, &CurrentFile);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);

+      goto Finish;

+    }

+  }

+  //

+  // Open the output file

+  //

+  OutputFile = fopen (OutputFileName, "wb");

+  if (OutputFile == NULL) {

+    Error (NULL, 0, 0, OutputFileName, "failed to open output file");

+    goto Finish;

+  }

+

+  if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {

+    Error (NULL, 0, 0, "failed to write to output file", 0);

+    goto Finish;

+  }

+

+Finish:

+  if (InputFile != NULL) {

+    fclose (InputFile);

+  }

+  //

+  // If we created an output file, and there was an error, remove it so

+  // subsequent builds will rebuild it.

+  //

+  if (OutputFile != NULL) {

+    if (GetUtilityStatus () == STATUS_ERROR) {

+      remove (OutputFileName);

+    }

+

+    fclose (OutputFile);

+  }

+

+  if (MapFile != NULL) {

+    fclose (MapFile);

+  }

+

+  if (FvImage != NULL) {

+    free (FvImage);

+  }

+

+  return GetUtilityStatus ();

+}

+

+EFI_STATUS

+ReadHeader (

+  IN FILE       *InputFile,

+  OUT UINT32    *FvSize,

+  OUT BOOLEAN   *ErasePolarity

+  )

+/*++

+

+Routine Description:

+

+  This function determines the size of the FV and the erase polarity.  The 

+  erase polarity is the FALSE value for file state.

+

+Arguments:

+

+  InputFile       The file that contains the FV image.

+  FvSize          The size of the FV.

+  ErasePolarity   The FV erase polarity.

+    

+Returns:

+ 

+  EFI_SUCCESS             Function completed successfully.

+  EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.

+  EFI_ABORTED             The function encountered an error.

+

+--*/

+{

+  EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;

+  EFI_FV_BLOCK_MAP_ENTRY      BlockMap;

+  UINTN                       Signature[2];

+  UINTN                       BytesRead;

+  UINT32                      Size;

+

+  BytesRead = 0;

+  Size      = 0;

+  //

+  // Check input parameters

+  //

+  if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {

+    Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Read the header

+  //

+  fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);

+  BytesRead     = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);

+  Signature[0]  = VolumeHeader.Signature;

+  Signature[1]  = 0;

+

+  //

+  // Get erase polarity

+  //

+  if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {

+    *ErasePolarity = TRUE;

+  }

+

+  do {

+    fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);

+    BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);

+

+    if (BlockMap.NumBlocks != 0) {

+      Size += BlockMap.NumBlocks * BlockMap.BlockLength;

+    }

+

+  } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));

+

+  if (VolumeHeader.FvLength != Size) {

+    Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);

+    return EFI_ABORTED;

+  }

+

+  *FvSize = Size;

+

+  rewind (InputFile);

+

+  return EFI_SUCCESS;

+}

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION,

+    UTILITY_DATE

+    );

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress [-M MapFile]\n",

+    UTILITY_NAME

+    );

+  printf ("  Where:\n");

+  printf ("    InputFileName is the name of the EFI FV file to rebase.\n");

+  printf ("    OutputFileName is the desired output file name.\n");

+  printf ("    BaseAddress is the FV base address to rebase agains.\n");

+  printf ("    MapFileName is an optional map file of the relocations\n");

+  printf ("  Argument pair may be in any order.\n\n");

+}

+

+EFI_STATUS

+FfsRebase (

+  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,

+  IN EFI_PHYSICAL_ADDRESS       BaseAddress,

+  IN FILE                       *MapFile      OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  This function determines if a file is XIP and should be rebased.  It will 

+  rebase any PE32 sections found in the file using the base address.

+  

+Arguments:

+

+  FfsFile           A pointer to Ffs file image.

+  BaseAddress       The base address to use for rebasing the file image.

+  MapFile           Optional file to dump relocation information into

+

+Returns:

+

+  EFI_SUCCESS             The image was properly rebased.

+  EFI_INVALID_PARAMETER   An input parameter is invalid.

+  EFI_ABORTED             An error occurred while rebasing the input file image.

+  EFI_OUT_OF_RESOURCES    Could not allocate a required resource.

+  EFI_NOT_FOUND           No compressed sections could be found.

+

+--*/

+{

+  EFI_STATUS                            Status;

+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;

+  UINTN                                 MemoryImagePointer;

+  UINTN                                 MemoryImagePointerAligned;

+  EFI_PHYSICAL_ADDRESS                  ImageAddress;

+  UINT64                                ImageSize;

+  EFI_PHYSICAL_ADDRESS                  EntryPoint;

+  UINT32                                Pe32ImageSize;

+  UINT32                                NewPe32BaseAddress;

+  UINTN                                 Index;

+  EFI_FILE_SECTION_POINTER              CurrentPe32Section;

+  EFI_FFS_FILE_STATE                    SavedState;

+  EFI_IMAGE_NT_HEADERS                  *PeHdr;

+  UINT32                                *PeHdrSizeOfImage;

+  UINT32                                *PeHdrChecksum;

+  UINT32                                FoundCount;

+  EFI_TE_IMAGE_HEADER                   *TEImageHeader;

+  UINT8                                 *TEBuffer;

+  EFI_IMAGE_DOS_HEADER                  *DosHeader;

+  UINT8                                 FileGuidString[80];

+  UINT32                                TailSize;

+  EFI_FFS_FILE_TAIL                     TailValue;

+

+  //

+  // Verify input parameters

+  //

+  if (FfsFile == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  //

+  // Convert the GUID to a string so we can at least report which file

+  // if we find an error.

+  //

+  PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);

+  if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+    TailSize = sizeof (EFI_FFS_FILE_TAIL);

+  } else {

+    TailSize = 0;

+  }

+  

+  //

+  // Do some cursory checks on the FFS file contents

+  //

+  Status = VerifyFfsFile (FfsFile);

+  if (EFI_ERROR (Status)) {

+    Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);

+    return EFI_INVALID_PARAMETER;

+  }

+

+  memset (&ImageContext, 0, sizeof (ImageContext));

+

+  //

+  // Check if XIP file type. If not XIP, don't rebase.

+  //

+  if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&

+      FfsFile->Type != EFI_FV_FILETYPE_PEIM &&

+      FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&

+      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER

+      ) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Rebase each PE32 section

+  //

+  Status      = EFI_SUCCESS;

+  FoundCount  = 0;

+  for (Index = 1;; Index++) {

+    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);

+    if (EFI_ERROR (Status)) {

+      break;

+    }

+

+    FoundCount++;

+

+    //

+    // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section

+    //

+    NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);

+

+    //

+    // Initialize context

+    //

+    memset (&ImageContext, 0, sizeof (ImageContext));

+    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));

+    ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;

+

+    Status                  = PeCoffLoaderGetImageInfo (&ImageContext);

+

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);

+      return Status;

+    }

+    //

+    // Allocate a buffer for the image to be loaded into.

+    //

+    Pe32ImageSize       = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);

+    MemoryImagePointer  = (UINTN) (malloc (Pe32ImageSize + 0x1000));

+    if (MemoryImagePointer == 0) {

+      Error (NULL, 0, 0, "memory allocation failure", NULL);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);

+    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);

+    

+

+    ImageContext.ImageAddress = MemoryImagePointerAligned;

+

+    Status                    = PeCoffLoaderLoadImage (&ImageContext);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);

+      free ((VOID *) MemoryImagePointer);

+      return Status;

+    }

+

+    ImageContext.DestinationAddress = NewPe32BaseAddress;

+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);

+      free ((VOID *) MemoryImagePointer);

+      return Status;

+    }

+

+    ImageAddress  = ImageContext.ImageAddress;

+    ImageSize     = ImageContext.ImageSize;

+    EntryPoint    = ImageContext.EntryPoint;

+

+    if (ImageSize > Pe32ImageSize) {

+      Error (

+        NULL,

+        0,

+        0,

+        "rebased image is larger than original PE32 image",

+        "0x%X > 0x%X, file %s",

+        ImageSize,

+        Pe32ImageSize,

+        FileGuidString

+        );

+      free ((VOID *) MemoryImagePointer);

+      return EFI_ABORTED;

+    }

+    //

+    // Since we may have updated the Codeview RVA, we need to insure the PE

+    // header indicates the image is large enough to contain the Codeview data

+    // so it will be loaded properly later if the PEIM is reloaded into memory...

+    //

+    PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);

+    if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {

+      PeHdrSizeOfImage     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);

+      PeHdrChecksum        = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);

+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {

+      PeHdrSizeOfImage     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);

+      PeHdrChecksum        = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);

+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {

+      PeHdrSizeOfImage     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);

+      PeHdrChecksum        = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);

+    } else {

+      Error (

+        NULL,

+        0,

+        0,

+        "unknown machine type in PE32 image",

+        "machine type=0x%X, file=%s",

+        (UINT32) PeHdr->FileHeader.Machine,

+        FileGuidString

+        );

+      free ((VOID *) MemoryImagePointer);

+      return EFI_ABORTED;

+    }

+

+    if (*PeHdrSizeOfImage != ImageContext.ImageSize) {

+      *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;

+      if (*PeHdrChecksum) {

+        *PeHdrChecksum = 0;

+      }

+    }

+

+    memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);

+    

+    //

+    // Get EntryPoint in Flash Region.

+    //

+    EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;

+

+    //

+    // If a map file was selected output mapping information for any file that

+    // was rebased.

+    //

+    if (MapFile != NULL) {

+      fprintf (MapFile, "PE32 File: %s Base:%08lx", FileGuidString, BaseAddress);

+      fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);

+      if (ImageContext.PdbPointer != NULL) {

+        fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);

+      }

+      fprintf (MapFile, "\n");

+    }

+

+    free ((VOID *) MemoryImagePointer);

+

+    //

+    // Now update file checksum

+    //

+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      TailSize = sizeof (EFI_FFS_FILE_TAIL);

+    } else {

+      TailSize = 0;

+    }

+

+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+      SavedState  = FfsFile->State;

+      FfsFile->IntegrityCheck.Checksum.File = 0;

+      FfsFile->State                        = 0;

+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (

+                                                  (UINT8 *) FfsFile,

+                                                  GetLength (FfsFile->Size) - TailSize

+                                                  );

+      } else {

+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+      }

+

+      FfsFile->State = SavedState;

+    }

+    //

+    // Update tail if present

+    //

+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));

+      *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;

+    }

+  }

+  //

+  // Now process TE sections

+  //

+  for (Index = 1;; Index++) {

+    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);

+    if (EFI_ERROR (Status)) {

+      break;

+    }

+

+    FoundCount++;

+

+    //

+    // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off

+    // by GenTEImage

+    //

+    TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));

+

+    NewPe32BaseAddress = ((UINT32) BaseAddress) +

+      (

+        (UINTN) CurrentPe32Section.Pe32Section +

+        sizeof (EFI_COMMON_SECTION_HEADER) +

+        sizeof (EFI_TE_IMAGE_HEADER) -

+        TEImageHeader->StrippedSize -

+        (UINTN) FfsFile

+      );

+

+    //

+    // Allocate a buffer to unshrink the image into.

+    //

+    Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -

+    sizeof (EFI_TE_IMAGE_HEADER);

+    Pe32ImageSize += TEImageHeader->StrippedSize;

+    TEBuffer = (UINT8 *) malloc (Pe32ImageSize);

+    if (TEBuffer == NULL) {

+      Error (NULL, 0, 0, "failed to allocate memory", NULL);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    //

+    // Expand the image into our buffer and fill in critical fields in the DOS header

+    // Fill in fields required by the loader.

+    // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value

+    // itself.

+    //

+    memset (TEBuffer, 0, Pe32ImageSize);

+    DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;

+    DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;

+    *(UINT32 *) (TEBuffer + 0x3C) = 0x40;

+    PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);

+    PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;

+    PeHdr->FileHeader.Machine = TEImageHeader->Machine;

+    PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;

+

+    //

+    // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and

+    // the 0x40 bytes for our DOS header.

+    //

+    PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));

+    PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));

+    PeHdr->OptionalHeader.AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;

+    PeHdr->OptionalHeader.BaseOfCode  = TEImageHeader->BaseOfCode;

+    PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;

+    PeHdr->OptionalHeader.Subsystem   = TEImageHeader->Subsystem;

+    PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;

+    PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *

+    sizeof (EFI_IMAGE_SECTION_HEADER) - 12;

+

+    //

+    // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image

+    //

+    if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||

+        (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)

+        ) {

+      PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;

+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

+    }

+

+    if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||

+        (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)

+        ) {

+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;

+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;

+      if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {

+        PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;

+      }

+    }

+    //

+    // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility

+    //

+    PeHdr->OptionalHeader.SectionAlignment = 0x10;

+

+    //

+    // Copy the rest of the image to its original offset

+    //

+    memcpy (

+      TEBuffer + TEImageHeader->StrippedSize,

+      (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),

+      GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -

+      sizeof (EFI_TE_IMAGE_HEADER)

+      );

+

+    //

+    // Initialize context

+    //

+    memset (&ImageContext, 0, sizeof (ImageContext));

+    ImageContext.Handle     = (VOID *) TEBuffer;

+    ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;

+

+    Status                  = PeCoffLoaderGetImageInfo (&ImageContext);

+

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);

+      free (TEBuffer);

+      return Status;

+    }

+    //

+    // Allocate a buffer for the image to be loaded into.

+    //

+    MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));

+    if (MemoryImagePointer == 0) {

+      Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);

+      free (TEBuffer);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);

+    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);

+    

+

+    ImageContext.ImageAddress = MemoryImagePointerAligned;

+    Status                    = PeCoffLoaderLoadImage (&ImageContext);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);

+      free (TEBuffer);

+      free ((VOID *) MemoryImagePointer);

+      return Status;

+    }

+

+    ImageContext.DestinationAddress = NewPe32BaseAddress;

+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);

+      free ((VOID *) MemoryImagePointer);

+      free (TEBuffer);

+      return Status;

+    }

+

+    ImageAddress  = ImageContext.ImageAddress;

+    ImageSize     = ImageContext.ImageSize;

+    EntryPoint    = ImageContext.EntryPoint;

+

+    //

+    // Since we may have updated the Codeview RVA, we need to insure the PE

+    // header indicates the image is large enough to contain the Codeview data

+    // so it will be loaded properly later if the PEIM is reloaded into memory...

+    //

+    PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);

+    if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {

+      PeHdrSizeOfImage     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);

+      PeHdrChecksum        = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);

+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {

+      PeHdrSizeOfImage     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);

+      PeHdrChecksum        = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);

+    } else {

+      Error (

+        NULL,

+        0,

+        0,

+        "unknown machine type in TE image",

+        "machine type=0x%X, file=%s",

+        (UINT32) PeHdr->FileHeader.Machine,

+        FileGuidString

+        );

+      free ((VOID *) MemoryImagePointer);

+      free (TEBuffer);

+      return EFI_ABORTED;

+    }

+

+    if (*PeHdrSizeOfImage != ImageContext.ImageSize) {

+      *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;

+      if (*PeHdrChecksum) {

+        *PeHdrChecksum = 0;

+      }

+    }

+

+    TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));

+    memcpy (

+      (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),

+      (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),

+      GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -

+      sizeof (EFI_TE_IMAGE_HEADER)

+      );

+    

+    //

+    // Get EntryPoint in Flash Region.

+    //

+    EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;

+

+    //

+    // If a map file was selected output mapping information for any file that

+    // was rebased.

+    //

+    if (MapFile != NULL) {

+      fprintf (MapFile, "TE   File: %s Base:%08lx", FileGuidString, BaseAddress);

+      fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);

+      if (ImageContext.PdbPointer != NULL) {

+        fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);

+      }

+      fprintf (MapFile, "\n");

+    }

+

+    free ((VOID *) MemoryImagePointer);

+    free (TEBuffer);

+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      TailSize = sizeof (EFI_FFS_FILE_TAIL);

+    } else {

+      TailSize = 0;

+    }

+    //

+    // Now update file checksum

+    //

+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+      SavedState  = FfsFile->State;

+      FfsFile->IntegrityCheck.Checksum.File = 0;

+      FfsFile->State                        = 0;

+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {

+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (

+                                                  (UINT8 *) FfsFile,

+                                                  GetLength (FfsFile->Size) - TailSize

+                                                  );

+      } else {

+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+      }

+

+      FfsFile->State = SavedState;

+    }

+    //

+    // Update tail if present

+    //

+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {

+      TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));

+      *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;

+    }

+  }

+  //

+  // If we found no files, then emit an error if no compressed sections either

+  //

+  if (FoundCount == 0) {

+    Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);

+    if (EFI_ERROR (Status)) {

+      Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);

+      return EFI_NOT_FOUND;

+    }

+  }

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+FfsRebaseImageRead (

+  IN     VOID    *FileHandle,

+  IN     UINTN   FileOffset,

+  IN OUT UINT32  *ReadSize,

+  OUT    VOID    *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file

+

+Arguments:

+

+  FileHandle - The handle to the PE/COFF file

+

+  FileOffset - The offset, in bytes, into the file to read

+

+  ReadSize   - The number of bytes to read from the file starting at FileOffset

+

+  Buffer     - A pointer to the buffer to read the data into.

+

+Returns:

+

+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset

+

+--*/

+{

+  CHAR8   *Destination8;

+  CHAR8   *Source8;

+  UINT32  Length;

+

+  Destination8  = Buffer;

+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);

+  Length        = *ReadSize;

+  while (Length--) {

+    *(Destination8++) = *(Source8++);

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/Source/PeiRebase/PeiRebaseExe.h b/Source/PeiRebase/PeiRebaseExe.h
new file mode 100644
index 0000000..b05baef
--- /dev/null
+++ b/Source/PeiRebase/PeiRebaseExe.h
@@ -0,0 +1,155 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+  

+  PeiRebaseExe.h

+

+Abstract:

+

+  Definitions for the PeiRebase exe utility.

+

+--*/

+

+#ifndef _EFI_PEIM_FIXUP_EXE_H

+#define _EFI_PEIM_FIXUP_EXE_H

+

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Common/FirmwareVolumeHeader.h>

+#include <Common/MultiPhase.h>

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "PeiRebase"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION 0

+#define UTILITY_MINOR_VERSION 1

+#define UTILITY_DATE          __DATE__

+

+//

+// The maximum number of arguments accepted from the command line.

+//

+#define MAX_ARGS  9

+

+//

+// The file copy buffer size

+//

+#define FILE_COPY_BUFFER_SIZE 512

+

+//

+// The function that displays general utility information

+//

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+//

+// The function that displays the utility usage message.

+//

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+//

+// Internal function declarations

+//

+EFI_STATUS

+FfsRebaseImageRead (

+  IN     VOID    *FileHandle,

+  IN     UINTN   FileOffset,

+  IN OUT UINT32  *ReadSize,

+  OUT    VOID    *Buffer

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FileHandle  - GC_TODO: add argument description

+  FileOffset  - GC_TODO: add argument description

+  ReadSize    - GC_TODO: add argument description

+  Buffer      - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+FfsRebase (

+  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,

+  IN EFI_PHYSICAL_ADDRESS       BaseAddress,

+  IN FILE                       *MapFile      OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FfsFile     - GC_TODO: add argument description

+  BaseAddress - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/Source/PeiRebase/build.xml b/Source/PeiRebase/build.xml
new file mode 100644
index 0000000..7c719b7
--- /dev/null
+++ b/Source/PeiRebase/build.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK PeiRebase Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="PeiRebase"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="Tool" depends="init, PeiRebase_Ia32, PeiRebase_Ipf, PeiRebase_X64"/>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="PeiRebase_Ia32" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}_Ia32"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_Ia32"/>

+    </cc>

+  </target>

+

+  <target name="PeiRebase_Ipf" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}_Ipf"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_Ipf"/>

+    </cc>

+  </target>

+

+  <target name="PeiRebase_X64" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}_X64"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" />

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_X64"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}_*${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>

+      <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/SecApResetVectorFixup/SecApResetVectorFixup.c b/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
new file mode 100644
index 0000000..4426457
--- /dev/null
+++ b/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
@@ -0,0 +1,363 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+    SecApResetVectorFixup.c

+

+Abstract:

+

+    This utility is part of build process for IA32 Fvrecovery.fv whose total size

+    is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset 

+    vector at the zero vector of Fv header.

+    

+      PEI FV after using the tool

+    

+    -------------------------

+    |zzz                    |

+    |                       |

+    |                       |

+    |      FFS              |

+    |                       |

+    |                       |

+    |                       |

+    |---------------------- |

+    |       PAD             |

+    |                       |

+    |.......................|  --- 

+    |                       |   |

+    |xxx                    |   | 128K    

+    |---------------------- |   | 

+    |       VTF (SEC)       |   |

+    -------------------------  ---

+    

+    1. zzz --> Zero vector, which is beyond the 128K limited address space

+    2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD

+       file area.

+    3. After the build process ,the PAD guid is changed to a new GUID to avoid 

+       the PAD definition confusing. If there is some problem, try to disable

+       UpdatePadFileGuid

+    

+     

+    

+--*/

+

+#include "SecApResetVectorFixup.h"

+

+

+EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };

+EFI_GUID  NewFvPadFileNameGuid     = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };

+

+//

+// jmp 0xf000:0xffd0 (0xFFFFFFD0)

+//

+UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s - Tiano IA32 SEC Ap Reset Vector Fixup Utility."" Version %i.%i\n\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION

+    );

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf ("Usage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);

+  printf ("  Where:\n");

+  printf ("\tInputFvrecoveryFile   - Name of the IA32 input Fvrecovery.fv file.\n");

+  printf ("\tOutputFvrecoveryFile  - Name of the IA32 output Fvrecovery.fv file.\n");

+}

+

+

+VOID 

+UpdatePadFileGuid (

+  IN     EFI_FIRMWARE_VOLUME_HEADER  *FvHeader,

+  IN     EFI_FFS_FILE_HEADER         *FileHeader,

+  IN     UINT32                      FileLength,

+  IN OUT EFI_GUID                    *Guid

+  )

+/*++

+

+Routine Description:

+

+  Update the Pad File Guid to change it to other guid and update

+  the checksum

+

+Arguments:

+  FvHeader   - EFI_FIRMWARE_VOLUME_HEADER 

+  FileHeader - The FFS PAD file header.

+  FileLength - The FFS PAD file length.

+  Guid       - The Guid to compare and if it is PAD Guid, update it to new Guid

+Returns:

+  VOID

+--*/

+

+{

+  if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {

+    //

+    // Set new Pad file guid

+    // 

+    memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));

+

+

+

+    FileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;

+    FileHeader->Attributes = 0;

+    //

+    // Fill in checksums and state, must be zero during checksum calculation.

+    //

+    FileHeader->IntegrityCheck.Checksum.Header = 0;

+    FileHeader->IntegrityCheck.Checksum.File   = 0;

+    FileHeader->State                          = 0;

+    FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));

+    if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {

+      FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);

+    } else {

+      FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

+    }

+

+    FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;

+

+    if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {

+      FileHeader->State = (UINT8)~(FileHeader->State);

+    }    

+  }

+  

+}

+

+

+STATUS

+main (

+  IN INTN   argc,

+  IN CHAR8  **argv

+  )

+/*++

+

+Routine Description:

+

+  Main function.

+

+Arguments:

+

+  argc - Number of command line parameters.

+  argv - Array of pointers to parameter strings.

+

+Returns:

+  STATUS_SUCCESS - Utility exits successfully.

+  STATUS_ERROR   - Some error occurred during execution.

+

+--*/

+{

+  FILE                        *FpIn;

+  FILE                        *FpOut;

+  UINT32                      FvrecoveryFileSize;

+  UINT8                       *FileBuffer;

+  UINT8                       *FileBufferRaw;

+  UINT64                      FvLength;

+  UINT32                      Offset;

+  UINT32                      FileLength;

+  UINT32                      FileOccupiedSize;

+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;

+  EFI_FFS_FILE_HEADER         *FileHeader;

+  EFI_GUID                    *TempGuid;

+  UINT8                       *FixPoint;

+  UINT32                      TempResult;

+  UINT32                      Index;

+  UINT32                      IpiVector;

+

+  TempGuid = NULL;

+  SetUtilityName (UTILITY_NAME);

+

+  //

+  // Display utility information

+  //

+  PrintUtilityInfo ();

+

+  //

+  // Verify the correct number of arguments

+  //

+  if (argc != MAX_ARGS) {

+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);

+    PrintUsage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Open the Input Fvrecovery.fv file

+  //

+  if ((FpIn = fopen (argv[1], "rb")) == NULL) {

+    Error (NULL, 0, 0, "Unable to open file", argv[1]);

+    return STATUS_ERROR;

+  }

+  //

+  // Get the Input Fvrecovery.fv file size

+  //

+  fseek (FpIn, 0, SEEK_END);

+  FvrecoveryFileSize = ftell (FpIn);

+  //

+  // Read the contents of input file to memory buffer

+  //

+  FileBuffer    = NULL;

+  FileBufferRaw = NULL;

+  FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);

+  if (NULL == FileBufferRaw) {

+    Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);

+    fclose (FpIn);

+    return STATUS_ERROR;

+  }

+  TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);

+  FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);

+  fseek (FpIn, 0, SEEK_SET);

+  TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);

+  if (TempResult != FvrecoveryFileSize) {

+    Error (NULL, 0, 0, "Read input file error!", NULL);

+    free ((VOID *)FileBufferRaw);

+    fclose (FpIn);

+    return STATUS_ERROR;

+  }

+  //

+  // Close the input Fvrecovery.fv file

+  //

+  fclose (FpIn);

+  //

+  // Find the pad FFS file

+  //

+  FvHeader         = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;

+  FvLength         = FvHeader->FvLength;

+  FileHeader       = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);

+  FileLength       = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;

+  FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);

+  Offset           = (UINT32)FileHeader - (UINT32)FileBuffer;

+  

+  while (Offset < FvLength) {

+    TempGuid = (EFI_GUID *)&(FileHeader->Name);

+    FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;

+    FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);

+    if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {

+      break;

+    }

+    FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);

+    Offset = (UINT32)FileHeader - (UINT32)FileBuffer;

+  }

+

+  if (Offset >= FvLength) {

+    Error (NULL, 0, 0, "No pad file found!", NULL);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR;

+  }

+  //

+  // Find the position to place Ap reset vector, the offset

+  // between the position and the end of Fvrecovery.fv file

+  // should not exceed 128kB to prevent Ap reset vector from

+  // outside legacy E and F segment

+  //

+  FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));

+  TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);

+  FixPoint +=TempResult;

+  if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {

+    Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR;  

+  }

+  while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {

+    FixPoint += 0x1000;

+  }

+  FixPoint -= 0x1000;

+  if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {

+    Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR; 

+  }    

+  //

+  // Fix up Ap reset vector and calculate the IPI vector

+  //

+  for (Index = 0; Index < 5; Index++) {

+    FixPoint[Index] = ApResetVector[Index];

+  } 

+  TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);

+  TempResult >>= 12;

+  IpiVector = TempResult & 0x0FF;

+  

+  

+  UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);

+

+  //

+  // Open the output Fvrecovery.fv file

+  //

+  if ((FpOut = fopen (argv[2], "w+b")) == NULL) {

+    Error (NULL, 0, 0, "Unable to open file", argv[2]);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR;

+  }

+  //

+  // Write the output Fvrecovery.fv file

+  //

+  if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {

+    Error (NULL, 0, 0, "Write output file error!", NULL);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR;   

+  }

+  //

+  //

+  //

+  fseek (FpOut, -8, SEEK_END);

+  if ((fwrite (&IpiVector, 1, sizeof(UINT32), FpOut)) != sizeof(UINT32)) {

+    Error (NULL, 0, 0, "Write output file error!", NULL);

+    free ((VOID *)FileBufferRaw);

+    return STATUS_ERROR;

+  }  

+  //

+  // Close the output Fvrecovery.fv file

+  //

+  fclose (FpOut);

+  free ((VOID *)FileBufferRaw);

+  return STATUS_SUCCESS;

+}

+

diff --git a/Source/SecApResetVectorFixup/SecApResetVectorFixup.h b/Source/SecApResetVectorFixup/SecApResetVectorFixup.h
new file mode 100644
index 0000000..6d234e3
--- /dev/null
+++ b/Source/SecApResetVectorFixup/SecApResetVectorFixup.h
@@ -0,0 +1,104 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  SecApResetVectorFixup.h

+

+Abstract:

+

+  Definitions for the SecApResetVectorFixup utility.

+

+--*/

+

+#ifndef _SEC_AP_RESET_VECTOR_FIXUP_H

+#define _SEC_AP_RESET_VECTOR_FIXUP_H

+

+#include <stdio.h>

+#include <stdlib.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+#include <Common/FirmwareFileSystem.h>

+#include <Common/FirmwareVolumeHeader.h>

+

+#include "EfiUtilityMsgs.c"

+#include "CommonLib.h"

+

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "SecApResetVectorFixup"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION 0

+#define UTILITY_MINOR_VERSION 1

+#define UTILITY_DATE          __DATE__

+

+//

+// The maximum number of arguments accepted from the command line.

+//

+#define MAX_ARGS        3

+#define BUF_SIZE        (8 * 1024)

+

+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \

+  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))

+

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+;

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+;

+

+

+#endif

diff --git a/Source/SecApResetVectorFixup/build.xml b/Source/SecApResetVectorFixup/build.xml
new file mode 100644
index 0000000..5148d9d
--- /dev/null
+++ b/Source/SecApResetVectorFixup/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK SecApResetVectorFixup Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="SecApResetVectorFixup"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/SecFixup/SecFixup.c b/Source/SecFixup/SecFixup.c
new file mode 100644
index 0000000..c2d46a1
--- /dev/null
+++ b/Source/SecFixup/SecFixup.c
@@ -0,0 +1,362 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+    SecFixup.c

+

+Abstract:

+

+    This utility is part of build process for IA32 SEC FFS file.

+    

+    It fixup the reset vector data. The reset vector data binary file

+    will be wrapped as a RAW section and be located immediately after

+    the PE/TE section.

+

+    The SEC EXE file can be either PE or TE file.

+    

+--*/

+

+#include <stdio.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/EfiImage.h>

+#include <Common/FirmwareVolumeImageFormat.h>

+

+#include "EfiUtilityMsgs.c"

+#include "SecFixup.h"

+

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the standard utility information to SDTOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf (

+    "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",

+    UTILITY_NAME,

+    UTILITY_MAJOR_VERSION,

+    UTILITY_MINOR_VERSION

+    );

+}

+

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Displays the utility usage syntax to STDOUT

+

+Arguments:

+

+  None

+

+Returns:

+

+  None

+

+--*/

+{

+  printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);

+  printf ("  Where:\n");

+  printf ("\tSecExeFile           - Name of the IA32 SEC EXE file.\n");

+  printf ("\tResetVectorDataFile  - Name of the reset vector data binary file.\n");

+  printf ("\tOutputFileName       - Name of the output file.\n\n");

+}

+

+STATUS

+main (

+  IN INTN   argc,

+  IN CHAR8  **argv

+  )

+/*++

+

+Routine Description:

+

+  Main function.

+

+Arguments:

+

+  argc - Number of command line parameters.

+  argv - Array of pointers to parameter strings.

+

+Returns:

+  STATUS_SUCCESS - Utility exits successfully.

+  STATUS_ERROR   - Some error occurred during execution.

+

+--*/

+{

+  FILE    *FpIn;

+

+  FILE    *FpOut;

+  UINT32  AddressOfEntryPoint;

+  INT32   DestRel;

+  STATUS  Status;

+  UINT32  SecFileSize;

+

+  SetUtilityName (UTILITY_NAME);

+

+  //

+  // Display utility information

+  //

+  PrintUtilityInfo ();

+

+  //

+  // Verify the correct number of arguments

+  //

+  if (argc != MAX_ARGS) {

+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);

+    PrintUsage ();

+    return STATUS_ERROR;

+  }

+  //

+  // Open the SEC exe file

+  //

+  if ((FpIn = fopen (argv[1], "rb")) == NULL) {

+    Error (NULL, 0, 0, "Unable to open file", argv[1]);

+    return STATUS_ERROR;

+  }

+  //

+  // Get the entry point of the EXE file

+  //

+  Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);

+  if (Status != STATUS_SUCCESS) {

+    fclose (FpIn);

+    return STATUS_ERROR;

+  }

+  //

+  // Get the SEC file size

+  //

+  fseek (FpIn, 0, SEEK_END);

+  SecFileSize = ftell (FpIn);

+

+  //

+  // Close the SEC file

+  //

+  fclose (FpIn);

+

+  //

+  // Open the reset vector data file

+  //

+  if ((FpIn = fopen (argv[2], "rb")) == NULL) {

+    Error (NULL, 0, 0, "Unable to open file", argv[2]);

+    return STATUS_ERROR;

+  }

+  //

+  // Open the output file

+  //

+  if ((FpOut = fopen (argv[3], "w+b")) == NULL) {

+    Error (NULL, 0, 0, "Unable to open file", argv[3]);

+    fclose (FpIn);

+    return STATUS_ERROR;

+  }

+  //

+  // Copy the input file to the output file

+  //

+  if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {

+    fclose (FpIn);

+    fclose (FpOut);

+    return STATUS_ERROR;

+  }

+  //

+  // Close the reset vector data file

+  //

+  fclose (FpIn);

+

+  //

+  // Fix the destination relative in the jmp instruction

+  // in the reset vector data structure

+  //

+  fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);

+  DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);

+  if (DestRel <= -65536) {

+    Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);

+    fclose (FpOut);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {

+    Error (NULL, 0, 0, "Failed to write to the output file", NULL);

+    fclose (FpOut);

+    return STATUS_ERROR;

+  }

+  //

+  // Close the output file

+  //

+  fclose (FpOut);

+

+  return STATUS_SUCCESS;

+}

+

+STATUS

+GetEntryPoint (

+  IN  FILE   *ExeFile,

+  OUT UINT32 *EntryPoint

+  )

+/*++

+

+Routine Description:

+

+  Get the address of the entry point of a PE/TE file.

+

+Arguments:

+

+  PeFile     - File pointer to the specified PE/TE file.

+  EntryPoint - Buffer for the address of the entry point to be returned.

+

+Returns:

+  STATUS_SUCCESS - Function completed successfully.

+  STATUS_ERROR   - Error occured.

+

+--*/

+// GC_TODO:    ExeFile - add argument and description to function comment

+{

+  EFI_IMAGE_DOS_HEADER    DosHeader;

+  EFI_IMAGE_NT_HEADERS32  NtHeader;

+  EFI_TE_IMAGE_HEADER     TeHeader;

+

+  //

+  // Check if it is a TE file

+  //

+  fseek (ExeFile, 0, SEEK_SET);

+  //

+  // Attempt to read the TE header

+  //

+  if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {

+    if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {

+      if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {

+        Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);

+        return STATUS_ERROR;

+      }

+

+      *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;

+      return STATUS_SUCCESS;

+    }

+  }

+  //

+  // Check if it is a PE file

+  //

+  fseek (ExeFile, 0, SEEK_SET);

+  //

+  // Attempt to read the DOS header

+  //

+  if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {

+    goto InvalidFile;

+  }

+  //

+  // Check the magic number

+  //

+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    goto InvalidFile;

+  }

+  //

+  // Position into the file and read the NT PE header

+  //

+  fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);

+  if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {

+    goto InvalidFile;

+  }

+  //

+  // Check the PE signature in the header

+  //

+  if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {

+    goto InvalidFile;

+  }

+  //

+  // Make sure the PE file is PE32 for IA32

+  //

+  if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||

+      NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC

+      ) {

+    Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // Get the entry point from the optional header

+  //

+  *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;

+  return STATUS_SUCCESS;

+

+InvalidFile:

+  Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);

+  return STATUS_ERROR;

+}

+

+STATUS

+CopyFile (

+  FILE    *FpIn,

+  FILE    *FpOut

+  )

+/*++

+

+Routine Description:

+

+  Copy file.

+

+Arguments:

+

+  FpIn  - File pointer to the source file.

+  FpOut - File pointer to the destination file.

+

+Returns:

+  STATUS_SUCCESS - Function completed successfully.

+  STATUS_ERROR   - Error occured.

+

+--*/

+{

+  INTN  FileSize;

+

+  INTN  Offset;

+

+  INTN  Length;

+  UINT8 Buffer[BUF_SIZE];

+

+  fseek (FpIn, 0, SEEK_END);

+  FileSize = ftell (FpIn);

+

+  fseek (FpIn, 0, SEEK_SET);

+  fseek (FpOut, 0, SEEK_SET);

+

+  Offset = 0;

+  while (Offset < FileSize) {

+    Length = sizeof (Buffer);

+    if (FileSize - Offset < Length) {

+      Length = FileSize - Offset;

+    }

+

+    if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {

+      Error (NULL, 0, 0, "Copy file error", NULL);

+      return STATUS_ERROR;

+    }

+

+    Offset += Length;

+  }

+

+  return STATUS_SUCCESS;

+}

diff --git a/Source/SecFixup/SecFixup.h b/Source/SecFixup/SecFixup.h
new file mode 100644
index 0000000..3694b15
--- /dev/null
+++ b/Source/SecFixup/SecFixup.h
@@ -0,0 +1,146 @@
+/*++

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+  

+  SecFixup.h

+

+Abstract:

+

+  Definitions for the SecFixup utility.

+

+--*/

+

+#ifndef _SEC_FIXUP_H

+#define _SEC_FIXUP_H

+

+//

+// Utility Name

+//

+#define UTILITY_NAME  "SecFixup"

+

+//

+// Utility version information

+//

+#define UTILITY_MAJOR_VERSION 0

+#define UTILITY_MINOR_VERSION 1

+#define UTILITY_DATE          __DATE__

+

+//

+// The maximum number of arguments accepted from the command line.

+//

+#define MAX_ARGS        4

+

+#define DEST_REL_OFFSET 13

+#define BUF_SIZE        (8 * 1024)

+

+//

+// The function that displays general utility information

+//

+VOID

+PrintUtilityInfo (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+//

+// The function that displays the utility usage message.

+//

+VOID

+PrintUsage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+//

+// The function that gets the entry point of a PE/TE file.

+//

+STATUS

+GetEntryPoint (

+  IN  FILE   *ExeFile,

+  OUT UINT32 *EntryPoint

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  ExeFile     - GC_TODO: add argument description

+  EntryPoint  - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+//

+// The function that copies a file.

+//

+STATUS

+CopyFile (

+  FILE    *FpIn,

+  FILE    *FpOut

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  FpIn  - GC_TODO: add argument description

+  FpOut - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/Source/SecFixup/build.xml b/Source/SecFixup/build.xml
new file mode 100644
index 0000000..2abb1da
--- /dev/null
+++ b/Source/SecFixup/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK SecFixup Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="SecFixup"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/SetStamp/SetStamp.c b/Source/SetStamp/SetStamp.c
new file mode 100644
index 0000000..539aced
--- /dev/null
+++ b/Source/SetStamp/SetStamp.c
@@ -0,0 +1,475 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  SetStamp.c

+

+Abstract:

+  Set Date/Time Stamp of Portable Executable (PE) format file

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <time.h>

+

+#define LINE_MAXLEN 80

+

+void

+PrintUsage (

+  void

+  )

+/*++

+Routine Description:

+  print usage of setstamp command

+

+Arguments:

+  void

+

+Returns:

+  None

+--*/

+{

+  //

+  // print usage of command

+  //

+  printf ("Usage: SetStamp <PE-File> <TIME-File>\n");

+}

+

+int

+GetDateTime (

+  FILE      *fp,

+  time_t    *ltime

+  )

+/*++

+Routine Description:

+  Read the date and time from TIME file. If the date/time string is

+"NOW NOW", write the current date and time to TIME file and set it to

+ltime. Else, set the date and time of TIME file to ltime.

+

+Arguments:

+  fp              - The pointer of TIME file

+  ltime           - Date and time

+

+Returns:

+  =  0            - Success

+  = -1            - Failed

+--*/

+{

+  char      buffer[LINE_MAXLEN];

+  struct tm stime;

+  struct tm *now;

+

+  if (fgets (buffer, LINE_MAXLEN, fp) == NULL) {

+    printf ("Error: Cannot read TIME file.\n");

+    return -1;

+  }

+  //

+  // compare the value with "NOW NOW", write TIME file if equal

+  //

+  if (strncmp (buffer, "NOW NOW", 7) == 0) {

+    //

+    // get system current time and date

+    //

+    time (ltime);

+

+    now = localtime (ltime);

+    if (now == NULL) {

+      printf ("Error: Cannot get local time.\n");

+      return -1;

+    }

+

+    if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) {

+      printf ("Error: Cannot format time string.\n");

+      return -1;

+    }

+    //

+    // write TIME file

+    //

+    if (fseek (fp, 0, SEEK_SET) != 0) {

+      printf ("Error: Cannot move location of TIME file.\n");

+      return -1;

+    }

+

+    if (fputs (buffer, fp) == EOF) {

+      printf ("Error: Cannot write time string to TIME file.\n");

+      return -1;

+    }

+    //

+    // ltime has been set as current time and date, return

+    //

+    return 0;

+  }

+  //

+  // get the date and time from buffer

+  //

+  if (6 != sscanf (

+            buffer,

+            "%d-%d-%d %d:%d:%d",

+            &stime.tm_year,

+            &stime.tm_mon,

+            &stime.tm_mday,

+            &stime.tm_hour,

+            &stime.tm_min,

+            &stime.tm_sec

+            )) {

+    printf ("Error: Invaild date or time!\n");

+    return -1;

+  }

+  //

+  // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it

+  //

+  stime.tm_mon -= 1;

+

+  //

+  // in struct, Year (current year minus 1900)

+  // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038

+  //

+  //

+  // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)

+  //

+  if (stime.tm_year <= 38) {

+    stime.tm_year += 100;

+  }

+  //

+  // convert 1970 -> 70, 2000 -> 100, ...

+  //

+  else if (stime.tm_year >= 1970) {

+    stime.tm_year -= 1900;

+  }

+  //

+  // convert the date and time to time_t format

+  //

+  *ltime = mktime (&stime);

+  if (*ltime == (time_t) - 1) {

+    printf ("Error: Invalid date or time!\n");

+    return -1;

+  }

+

+  return 0;

+}

+

+int

+ReadFromFile (

+  FILE      *fp,

+  long      offset,

+  void      *buffer,

+  int       size

+  )

+/*++

+Routine Description:

+  read data from a specified location of file

+

+Arguments:

+  fp              - file pointer

+  offset          - number of bytes from beginning of file

+  buffer          - buffer used to store data

+  size            - size of buffer

+

+Returns:

+  =  0            - Success

+  = -1            - Failed

+--*/

+{

+  //

+  // set file pointer to the specified location of file

+  //

+  if (fseek (fp, offset, SEEK_SET) != 0) {

+    printf ("Error: Cannot move the current location of the file.\n");

+    return -1;

+  }

+  //

+  // read data from the file

+  //

+  if (fread (buffer, size, 1, fp) != 1) {

+    printf ("Error: Cannot read data from the file.\n");

+    return -1;

+  }

+

+  return 0;

+}

+

+int

+WriteToFile (

+  FILE      *fp,

+  long      offset,

+  void      *buffer,

+  int       size

+  )

+/*++

+Routine Description:

+  write data to a specified location of file

+

+Arguments:

+  fp              - file pointer

+  offset          - number of bytes from beginning of file

+  buffer          - buffer used to store data

+  size            - size of buffer

+

+Returns:

+  =  0            - Success

+  = -1            - Failed

+--*/

+{

+  //

+  // set file pointer to the specified location of file

+  //

+  if (fseek (fp, offset, SEEK_SET) != 0) {

+    printf ("Error: Cannot move the current location of the file.\n");

+    return -1;

+  }

+  //

+  // write data to the file

+  //

+  if (fwrite (buffer, size, 1, fp) != 1) {

+    perror ("Error: Cannot write data to the file.\n");

+    return -1;

+  }

+

+  return 0;

+}

+

+int

+SetStamp (

+  FILE      *fp,

+  time_t    ltime

+  )

+/*++

+Routine Description:

+  set Date/Time Stamp of the file

+

+Arguments:

+  fp              - file pointer

+  ltime           - time and date

+

+Returns:

+  =  0            - Success

+  = -1            - Failed

+--*/

+{

+  unsigned char header[4];

+  unsigned long offset;

+  unsigned long NumberOfRvaAndSizes;

+  unsigned int  nvalue;

+  unsigned long lvalue;

+

+  //

+  // read the header of file

+  //

+  if (ReadFromFile (fp, 0, header, 2) != 0) {

+    return -1;

+  }

+  //

+  // "MZ" -- the header of image file (PE)

+  //

+  if (strncmp ((char *) header, "MZ", 2) != 0) {

+    printf ("Error: Invalid Image file.\n");

+    return -1;

+  }

+  //

+  // At location 0x3C, the stub has the file offset to the

+  // PE signature.

+  //

+  if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {

+    return -1;

+  }

+  //

+  // read the header of optional

+  //

+  if (ReadFromFile (fp, offset, header, 4) != 0) {

+    return -1;

+  }

+  //

+  // "PE\0\0" -- the signature of optional header

+  //

+  if (strncmp ((char *) header, "PE\0\0", 4) != 0) {

+    printf ("Error: Invalid PE format file.\n");

+    return -1;

+  }

+  //

+  // Add 8 to skip PE signature (4-byte), Machine (2-byte) and

+  // NumberOfSection (2-byte)

+  //

+  offset += 8;

+

+  if (WriteToFile (fp, offset, &ltime, 4) != 0) {

+    return -1;

+  }

+  //

+  // Add 16 to skip COFF file header, and get to optional header.

+  //

+  offset += 16;

+

+  //

+  // Check the magic field, 0x10B for PE32 and 0x20B for PE32+

+  //

+  if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {

+    return -1;

+  }

+  //

+  // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.

+  // Else it is 108.

+  //

+  switch (nvalue & 0xFFFF) {

+  case 0x10B:

+    offset += 92;

+    break;

+

+  case 0x20B:

+    offset += 108;

+    break;

+

+  default:

+    printf ("Error: Sorry! The Magic value is unknown.\n");

+    return -1;

+  }

+  //

+  // get the value of NumberOfRvaAndSizes

+  //

+  if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {

+    return -1;

+  }

+  //

+  // Date/time stamp exists in Export Table, Import Table, Resource Table,

+  // Debug Table and Delay Import Table. And in Import Table and Delay Import

+  // Table, it will be set when bound. So here only set the date/time stamp

+  // of Export Table, Resource Table and Debug Table.

+  //

+  //

+  // change date/time stamp of Export Table, the offset of Export Table

+  // is 4 + 0 * 8 = 4. And the offset of stamp is 4.

+  //

+  if (NumberOfRvaAndSizes >= 1) {

+    if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) {

+      return -1;

+    }

+

+    if (lvalue != 0) {

+      if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {

+        return -1;

+      }

+    }

+  }

+  //

+  // change date/time stamp of Resource Table, the offset of Resource Table

+  // is 4 + 2 * 8 = 20. And the offset of stamp is 4.

+  //

+  if (NumberOfRvaAndSizes >= 3) {

+    if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) {

+      return -1;

+    }

+

+    if (lvalue != 0) {

+      if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {

+        return -1;

+      }

+    }

+  }

+  //

+  // change date/time stamp of Debug Table, offset of Debug Table

+  // is 4 + 6 * 8 = 52. And the offset of stamp is 4.

+  //

+  if (NumberOfRvaAndSizes >= 7) {

+    if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {

+      return -1;

+    }

+

+    if (lvalue != 0) {

+      if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {

+        return -1;

+      }

+    }

+    //

+    // change the date/time stamp of Debug Data

+    //

+    if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) {

+      return -1;

+    }

+    //

+    // get the signature of debug data

+    //

+    if (ReadFromFile (fp, lvalue, header, 2) != 0) {

+      return -1;

+    }

+    //

+    // "NB" - the signature of Debug Data

+    // Need Review: (From Spec. is "NB05", From .dll is "NB10")

+    //

+    if (strncmp ((char *) header, "NB", 2) == 0) {

+      if (WriteToFile (fp, lvalue + 8, &ltime, 4) != 0) {

+        return -1;

+      }

+    }

+  }

+

+  return 0;

+}

+

+int

+main (

+  int       argc,

+  char      *argv[]

+  )

+{

+  FILE    *fp;

+  time_t  ltime;

+

+  //

+  // check the number of parameters

+  //

+  if (argc != 3) {

+    PrintUsage ();

+    return -1;

+  }

+  //

+  // open the TIME file, if not exists, return

+  //

+  fp = fopen (argv[2], "r+");

+  if (fp == NULL) {

+    return 0;

+  }

+  //

+  // get time and date from file

+  //

+  if (GetDateTime (fp, &ltime) != 0) {

+    fclose (fp);

+    return -1;

+  }

+  //

+  // close the TIME file

+  //

+  fclose (fp);

+

+  //

+  // open the PE file

+  //

+  fp = fopen (argv[1], "r+b");

+  if (fp == NULL) {

+    printf ("Error: Cannot open the PE file!\n");

+    return -1;

+  }

+  //

+  // set time and date stamp to the PE file

+  //

+  if (SetStamp (fp, ltime) != 0) {

+    fclose (fp);

+    return -1;

+  }

+

+  printf ("Set Date/Time Stamp to %s", ctime (&ltime));

+

+  //

+  // close the PE file

+  //

+  fclose (fp);

+

+  return 0;

+}

diff --git a/Source/SetStamp/build.xml b/Source/SetStamp/build.xml
new file mode 100644
index 0000000..ff8d6ed
--- /dev/null
+++ b/Source/SetStamp/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK SetStamp Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="SetStamp"/>

+  <property name="FileSet" value="SetStamp.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/SplitFile/SplitFile.c b/Source/SplitFile/SplitFile.c
new file mode 100644
index 0000000..a1bda7d
--- /dev/null
+++ b/Source/SplitFile/SplitFile.c
@@ -0,0 +1,131 @@
+/*

+

+Copyright (c)  1999-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available 

+under the terms and conditions of the BSD License which accompanies this 

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+*/

+

+// GC_TODO: fix comment to start with /*++

+#include "stdio.h"

+#include "string.h"

+#include "stdlib.h"

+

+void

+helpmsg (

+  void

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  printf (

+    "SplitFile Filename Offset\n""   Filename = Input file to split\n""   Offset = offset at which to split file\n"

+    "\n\n""SplitFile will break a file in two pieces at the requested offset\n"

+    "  outputting Filename1 and Filename2\n"

+    );

+}

+

+int

+main (

+  int argc,

+  char*argv[]

+  )

+/*++

+

+Routine Description:

+

+  GC_TODO: Add function description

+

+Arguments:

+

+  argc  - GC_TODO: add argument description

+  ]     - GC_TODO: add argument description

+

+Returns:

+

+  GC_TODO: add return values

+

+--*/

+{

+  FILE          *In;

+

+  FILE          *Out1;

+

+  FILE          *Out2;

+  char          OutName1[512];

+  char          OutName2[512];

+  unsigned long Index;

+  unsigned long splitpoint;

+  char          CharC;

+

+  if (argc != 3) {

+    helpmsg ();

+    return -1;

+  }

+

+  In = fopen (argv[1], "rb");

+  if (In == NULL) {

+    printf ("Unable to open file \"%s\"\n", argv[1]);

+    return -1;

+  }

+

+  strncpy (OutName1, argv[1], 510);

+  strncpy (OutName2, argv[1], 510);

+  strcat (OutName1, "1");

+  strcat (OutName2, "2");

+

+  Out1 = fopen (OutName1, "wb");

+  if (Out1 == NULL) {

+    printf ("Unable to open file \"%s\"\n", OutName1);

+    return -1;

+  }

+

+  Out2 = fopen (OutName2, "wb");

+  if (Out2 == NULL) {

+    printf ("Unable to open file \"%s\"\n", OutName2);

+    return -1;

+  }

+

+  splitpoint = atoi (argv[2]);

+

+  for (Index = 0; Index < splitpoint; Index++) {

+    CharC = (char) fgetc (In);

+    if (feof (In)) {

+      break;

+    }

+

+    fputc (CharC, Out1);

+  }

+

+  for (;;) {

+    CharC = (char) fgetc (In);

+    if (feof (In)) {

+      break;

+    }

+

+    fputc (CharC, Out2);

+  }

+

+  fclose (In);

+  fclose (Out1);

+  fclose (Out2);

+

+  return 0;

+}

diff --git a/Source/SplitFile/build.xml b/Source/SplitFile/build.xml
new file mode 100644
index 0000000..71e307b
--- /dev/null
+++ b/Source/SplitFile/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK SplitFile Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="SplitFile"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/StrGather/StrGather.c b/Source/StrGather/StrGather.c
new file mode 100644
index 0000000..9eb5c5a
--- /dev/null
+++ b/Source/StrGather/StrGather.c
@@ -0,0 +1,2531 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  StrGather.c  

+

+Abstract:

+

+  Parse a strings file and create or add to a string database file.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <ctype.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+#include "StrGather.h"

+#include "StringDB.h"

+

+#define TOOL_VERSION  "0.31"

+

+#ifndef MAX_PATH

+#define MAX_PATH                    255

+#endif

+#define MAX_NEST_DEPTH              20  // just in case we get in an endless loop.

+#define MAX_STRING_IDENTIFIER_NAME  100 // number of wchars

+#define MAX_LINE_LEN                200

+#define STRING_TOKEN                "STRING_TOKEN"

+#define DEFAULT_BASE_NAME           "BaseName"

+//

+// Operational modes for this utility

+//

+#define MODE_UNKNOWN  0

+#define MODE_PARSE    1

+#define MODE_SCAN     2

+#define MODE_DUMP     3

+

+//

+// We keep a linked list of these for the source files we process

+//

+typedef struct _SOURCE_FILE {

+  FILE                *Fptr;

+  WCHAR               *FileBuffer;

+  WCHAR               *FileBufferPtr;

+  UINT32              FileSize;

+  CHAR8               FileName[MAX_PATH];

+  UINT32              LineNum;

+  BOOLEAN             EndOfFile;

+  BOOLEAN             SkipToHash;

+  struct _SOURCE_FILE *Previous;

+  struct _SOURCE_FILE *Next;

+  WCHAR               ControlCharacter;

+} SOURCE_FILE;

+

+#define DEFAULT_CONTROL_CHARACTER UNICODE_SLASH

+

+//

+// Here's all our globals. We need a linked list of include paths, a linked

+// list of source files, a linked list of subdirectories (appended to each

+// include path when searching), and a couple other fields.

+//

+static struct {

+  SOURCE_FILE                 SourceFiles;

+  TEXT_STRING_LIST            *IncludePaths;                    // all include paths to search

+  TEXT_STRING_LIST            *LastIncludePath;

+  TEXT_STRING_LIST            *ScanFileName;

+  TEXT_STRING_LIST            *LastScanFileName;

+  TEXT_STRING_LIST            *SkipExt;                         // if -skipext .uni

+  TEXT_STRING_LIST            *LastSkipExt;

+  TEXT_STRING_LIST            *IndirectionFileName;

+  TEXT_STRING_LIST            *LastIndirectionFileName;

+  TEXT_STRING_LIST            *DatabaseFileName;

+  TEXT_STRING_LIST            *LastDatabaseFileName;

+  WCHAR_STRING_LIST           *Language;

+  WCHAR_STRING_LIST           *LastLanguage;

+  WCHAR_MATCHING_STRING_LIST  *IndirectionList;                 // from indirection file(s)

+  WCHAR_MATCHING_STRING_LIST  *LastIndirectionList;

+  BOOLEAN                     Verbose;                          // for more detailed output

+  BOOLEAN                     VerboseDatabaseWrite;             // for more detailed output when writing database

+  BOOLEAN                     VerboseDatabaseRead;              // for more detailed output when reading database

+  BOOLEAN                     NewDatabase;                      // to start from scratch

+  BOOLEAN                     IgnoreNotFound;                   // when scanning

+  BOOLEAN                     VerboseScan;

+  BOOLEAN                     UnquotedStrings;                  // -uqs option

+  CHAR8                       OutputDatabaseFileName[MAX_PATH];

+  CHAR8                       StringHFileName[MAX_PATH];

+  CHAR8                       StringCFileName[MAX_PATH];        // output .C filename

+  CHAR8                       DumpUFileName[MAX_PATH];          // output unicode dump file name

+  CHAR8                       HiiExportPackFileName[MAX_PATH];  // HII export pack file name

+  CHAR8                       BaseName[MAX_PATH];               // base filename of the strings file

+  UINT32                      Mode;

+} mGlobals;

+

+static

+BOOLEAN

+IsValidIdentifierChar (

+  CHAR8     Char,

+  BOOLEAN   FirstChar

+  );

+

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+SkipTo (

+  SOURCE_FILE *SourceFile,

+  WCHAR       WChar,

+  BOOLEAN     StopAfterNewline

+  );

+

+static

+UINT32

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+UINT32

+GetStringIdentifierName (

+  IN SOURCE_FILE  *SourceFile,

+  IN OUT WCHAR    *StringIdentifierName,

+  IN UINT32       StringIdentifierNameLen

+  );

+

+static

+UINT32

+GetLanguageIdentifierName (

+  IN SOURCE_FILE  *SourceFile,

+  IN OUT WCHAR    *LanguageIdentifierName,

+  IN UINT32       LanguageIdentifierNameLen,

+  IN BOOLEAN      Optional

+  );

+

+static

+WCHAR *

+GetPrintableLanguageName (

+  IN SOURCE_FILE  *SourceFile

+  );

+

+static

+STATUS

+AddCommandLineLanguage (

+  IN CHAR8         *Language

+  );

+

+static

+WCHAR *

+GetQuotedString (

+  SOURCE_FILE *SourceFile,

+  BOOLEAN     Optional

+  );

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  );

+

+static

+STATUS

+ParseFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+FILE  *

+FindFile (

+  IN CHAR8    *FileName,

+  OUT CHAR8   *FoundFileName,

+  IN UINT32   FoundFileNameLen

+  );

+

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  );

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+UINT32

+wstrcmp (

+  WCHAR *Buffer,

+  WCHAR *Str

+  );

+

+static

+void

+Usage (

+  VOID

+  );

+

+static

+void

+FreeLists (

+  VOID

+  );

+

+static

+void

+ProcessTokenString (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+ProcessTokenInclude (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+ProcessTokenScope (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+ProcessTokenLanguage (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+void

+ProcessTokenLangDef (

+  SOURCE_FILE *SourceFile

+  );

+

+static

+STATUS

+ScanFiles (

+  TEXT_STRING_LIST *ScanFiles

+  );

+

+static

+STATUS

+ParseIndirectionFiles (

+  TEXT_STRING_LIST    *Files

+  );

+

+STATUS

+StringDBCreateHiiExportPack (

+  CHAR8               *OutputFileName

+  );

+

+int

+main (

+  int   Argc,

+  char  *Argv[]

+  )

+/*++

+

+Routine Description:

+

+  Call the routine to parse the command-line options, then process the file.

+  

+Arguments:

+

+  Argc - Standard C main() argc and argv.

+  Argv - Standard C main() argc and argv.

+

+Returns:

+

+  0       if successful

+  nonzero otherwise

+  

+--*/

+{

+  STATUS  Status;

+

+  SetUtilityName (PROGRAM_NAME);

+  //

+  // Process the command-line arguments

+  //

+  Status = ProcessArgs (Argc, Argv);

+  if (Status != STATUS_SUCCESS) {

+    return Status;

+  }

+  //

+  // Initialize the database manager

+  //

+  StringDBConstructor ();

+  //

+  // We always try to read in an existing database file. It may not

+  // exist, which is ok usually.

+  //

+  if (mGlobals.NewDatabase == 0) {

+    //

+    // Read all databases specified.

+    //

+    for (mGlobals.LastDatabaseFileName = mGlobals.DatabaseFileName;

+         mGlobals.LastDatabaseFileName != NULL;

+         mGlobals.LastDatabaseFileName = mGlobals.LastDatabaseFileName->Next

+        ) {

+      Status = StringDBReadDatabase (mGlobals.LastDatabaseFileName->Str, TRUE, mGlobals.VerboseDatabaseRead);

+      if (Status != STATUS_SUCCESS) {

+        return Status;

+      }

+    }

+  }

+  //

+  // Read indirection file(s) if specified

+  //

+  if (ParseIndirectionFiles (mGlobals.IndirectionFileName) != STATUS_SUCCESS) {

+    goto Finish;

+  }

+  //

+  // If scanning source files, do that now

+  //

+  if (mGlobals.Mode == MODE_SCAN) {

+    ScanFiles (mGlobals.ScanFileName);

+  } else if (mGlobals.Mode == MODE_PARSE) {

+    //

+    // Parsing a unicode strings file

+    //

+    mGlobals.SourceFiles.ControlCharacter = DEFAULT_CONTROL_CHARACTER;

+    Status = ProcessIncludeFile (&mGlobals.SourceFiles, NULL);

+    if (Status != STATUS_SUCCESS) {

+      goto Finish;

+    }

+  }

+  //

+  // Create the string defines header file if there have been no errors.

+  //

+  ParserSetPosition (NULL, 0);

+  if ((mGlobals.StringHFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {

+    Status = StringDBDumpStringDefines (mGlobals.StringHFileName, mGlobals.BaseName);

+    if (Status != EFI_SUCCESS) {

+      goto Finish;

+    }

+  }

+  //

+  // Dump the strings to a .c file if there have still been no errors.

+  //

+  if ((mGlobals.StringCFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {

+    Status = StringDBDumpCStrings (

+              mGlobals.StringCFileName,

+              mGlobals.BaseName,

+              mGlobals.Language,

+              mGlobals.IndirectionList

+              );

+    if (Status != EFI_SUCCESS) {

+      goto Finish;

+    }

+  }

+  //

+  // Dump the database if requested

+  //

+  if ((mGlobals.DumpUFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {

+    StringDBDumpDatabase (NULL, mGlobals.DumpUFileName, FALSE);

+  }

+  //

+  // Dump the string data as HII binary string pack if requested

+  //

+  if ((mGlobals.HiiExportPackFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {

+    StringDBCreateHiiExportPack (mGlobals.HiiExportPackFileName);

+  }

+  //

+  // Always update the database if no errors and not in dump mode. If they specified -od

+  // for an output database file name, then use that name. Otherwise use the name of

+  // the first database file specified with -db

+  //

+  if ((mGlobals.Mode != MODE_DUMP) && (GetUtilityStatus () < STATUS_ERROR)) {

+    if (mGlobals.OutputDatabaseFileName[0]) {

+      Status = StringDBWriteDatabase (mGlobals.OutputDatabaseFileName, mGlobals.VerboseDatabaseWrite);

+    } else {

+      Status = StringDBWriteDatabase (mGlobals.DatabaseFileName->Str, mGlobals.VerboseDatabaseWrite);

+    }

+

+    if (Status != EFI_SUCCESS) {

+      goto Finish;

+    }

+  }

+

+Finish:

+  //

+  // Free up memory

+  //

+  FreeLists ();

+  StringDBDestructor ();

+  return GetUtilityStatus ();

+}

+

+static

+STATUS

+ProcessIncludeFile (

+  SOURCE_FILE *SourceFile,

+  SOURCE_FILE *ParentSourceFile

+  )

+/*++

+

+Routine Description:

+

+  Given a source file, open the file and parse it

+  

+Arguments:

+

+  SourceFile        - name of file to parse

+  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.

+

+Returns:

+

+  Standard status.

+  

+--*/

+{

+  static UINT32 NestDepth = 0;

+  CHAR8         FoundFileName[MAX_PATH];

+  STATUS        Status;

+

+  Status = STATUS_SUCCESS;

+  NestDepth++;

+  //

+  // Print the file being processed. Indent so you can tell the include nesting

+  // depth.

+  //

+  if (mGlobals.Verbose) {

+    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);

+  }

+

+  //

+  // Make sure we didn't exceed our maximum nesting depth

+  //

+  if (NestDepth > MAX_NEST_DEPTH) {

+    Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+  //

+  // Try to open the file locally, and if that fails try along our include paths.

+  //

+  strcpy (FoundFileName, SourceFile->FileName);

+  if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {

+    //

+    // Try to find it among the paths if it has a parent (that is, it is included

+    // by someone else).

+    //

+    if (ParentSourceFile == NULL) {

+      Error (NULL, 0, 0, SourceFile->FileName, "file not found");

+      return STATUS_ERROR;

+    }

+

+    SourceFile->Fptr = FindFile (SourceFile->FileName, FoundFileName, sizeof (FoundFileName));

+    if (SourceFile->Fptr == NULL) {

+      Error (ParentSourceFile->FileName, ParentSourceFile->LineNum, 0, SourceFile->FileName, "include file not found");

+      return STATUS_ERROR;

+    }

+  }

+  //

+  // Process the file found

+  //

+  ProcessFile (SourceFile);

+Finish:

+  //

+  // Close open files and return status

+  //

+  if (SourceFile->Fptr != NULL) {

+    fclose (SourceFile->Fptr);

+  }

+

+  return Status;

+}

+

+static

+STATUS

+ProcessFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  //

+  // Get the file size, and then read the entire thing into memory.

+  // Allocate space for a terminator character.

+  //

+  fseek (SourceFile->Fptr, 0, SEEK_END);

+  SourceFile->FileSize = ftell (SourceFile->Fptr);

+  fseek (SourceFile->Fptr, 0, SEEK_SET);

+  SourceFile->FileBuffer = (WCHAR *) malloc (SourceFile->FileSize + sizeof (WCHAR));

+  if (SourceFile->FileBuffer == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return STATUS_ERROR;

+  }

+

+  fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);

+  SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (WCHAR))] = UNICODE_NULL;

+  //

+  // Pre-process the file to replace comments with spaces

+  //

+  PreprocessFile (SourceFile);

+  //

+  // Parse the file

+  //

+  ParseFile (SourceFile);

+  free (SourceFile->FileBuffer);

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+ParseFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  BOOLEAN InComment;

+  UINT32  Len;

+

+  //

+  // First character of a unicode file is special. Make sure

+  //

+  if (SourceFile->FileBufferPtr[0] != UNICODE_FILE_START) {

+    Error (SourceFile->FileName, 1, 0, SourceFile->FileName, "file does not appear to be a unicode file");

+    return STATUS_ERROR;

+  }

+

+  SourceFile->FileBufferPtr++;

+  InComment = FALSE;

+  //

+  // Print the first line if in verbose mode

+  //

+  if (mGlobals.Verbose) {

+    printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);

+  }

+  //

+  // Since the syntax is relatively straightforward, just switch on the next char

+  //

+  while (!EndOfFile (SourceFile)) {

+    //

+    // Check for whitespace

+    //

+    if (SourceFile->FileBufferPtr[0] == UNICODE_SPACE) {

+      SourceFile->FileBufferPtr++;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_TAB) {

+      SourceFile->FileBufferPtr++;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {

+      SourceFile->FileBufferPtr++;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      if (mGlobals.Verbose) {

+        printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);

+      }

+

+      InComment = FALSE;

+    } else if (SourceFile->FileBufferPtr[0] == 0) {

+      SourceFile->FileBufferPtr++;

+    } else if (InComment) {

+      SourceFile->FileBufferPtr++;

+    } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {

+      SourceFile->FileBufferPtr += 2;

+      InComment = TRUE;

+    } else if (SourceFile->SkipToHash && (SourceFile->FileBufferPtr[0] != SourceFile->ControlCharacter)) {

+      SourceFile->FileBufferPtr++;

+    } else {

+      SourceFile->SkipToHash = FALSE;

+      if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+          ((Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"include")) > 0)

+          ) {

+        SourceFile->FileBufferPtr += Len + 1;

+        ProcessTokenInclude (SourceFile);

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"scope")) > 0

+              ) {

+        SourceFile->FileBufferPtr += Len + 1;

+        ProcessTokenScope (SourceFile);

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"language")) > 0

+              ) {

+        SourceFile->FileBufferPtr += Len + 1;

+        ProcessTokenLanguage (SourceFile);

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"langdef")) > 0

+              ) {

+        SourceFile->FileBufferPtr += Len + 1;

+        ProcessTokenLangDef (SourceFile);

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"string")) > 0

+              ) {

+        SourceFile->FileBufferPtr += Len + 1;

+        ProcessTokenString (SourceFile);

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"EFI_BREAKPOINT()")) > 0

+              ) {

+        SourceFile->FileBufferPtr += Len;

+        //

+        // BUGBUG: Caling EFI_BREAKOINT() is breaking the link.  What is the proper action for this tool

+        // in this condition?

+        //

+//        EFI_BREAKPOINT ();

+      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&

+               (SourceFile->FileBufferPtr[1] == UNICODE_EQUAL_SIGN)

+              ) {

+        SourceFile->ControlCharacter = SourceFile->FileBufferPtr[2];

+        SourceFile->FileBufferPtr += 3;

+      } else {

+        Error (SourceFile->FileName, SourceFile->LineNum, 0, "unrecognized token", "%S", SourceFile->FileBufferPtr);

+        //

+        // Treat rest of line as a comment.

+        //

+        InComment = TRUE;

+      }

+    }

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+void

+PreprocessFile (

+  SOURCE_FILE *SourceFile

+  )

+/*++

+

+Routine Description:

+  Preprocess a file to replace all carriage returns with NULLs so

+  we can print lines from the file to the screen.

+  

+Arguments:

+  SourceFile - structure that we use to keep track of an input file.

+

+Returns:

+  Nothing.

+  

+--*/

+{

+  BOOLEAN InComment;

+

+  RewindFile (SourceFile);

+  InComment = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    //

+    // If a line-feed, then no longer in a comment

+    //

+    if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      InComment = 0;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {

+      //

+      // Replace all carriage returns with a NULL so we can print stuff

+      //

+      SourceFile->FileBufferPtr[0] = 0;

+      SourceFile->FileBufferPtr++;

+    } else if (InComment) {

+      SourceFile->FileBufferPtr[0] = UNICODE_SPACE;

+      SourceFile->FileBufferPtr++;

+    } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {

+      SourceFile->FileBufferPtr += 2;

+      InComment = TRUE;

+    } else {

+      SourceFile->FileBufferPtr++;

+    }

+  }

+  //

+  // Could check for end-of-file and still in a comment, but

+  // should not be necessary. So just restore the file pointers.

+  //

+  RewindFile (SourceFile);

+}

+

+static

+WCHAR *

+GetPrintableLanguageName (

+  IN SOURCE_FILE  *SourceFile

+  )

+{

+  WCHAR   *String;

+  WCHAR   *Start;

+  WCHAR   *Ptr;

+  UINT32  Len;

+

+  SkipWhiteSpace (SourceFile);

+  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      "expected quoted printable language name",

+      "%S",

+      SourceFile->FileBufferPtr

+      );

+    SourceFile->SkipToHash = TRUE;

+    return NULL;

+  }

+

+  Len = 0;

+  SourceFile->FileBufferPtr++;

+  Start = Ptr = SourceFile->FileBufferPtr;

+  while (!EndOfFile (SourceFile)) {

+    if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {

+      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);

+      break;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {

+      break;

+    }

+

+    SourceFile->FileBufferPtr++;

+    Len++;

+  }

+

+  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {

+    Warning (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      "missing closing quote on printable language name string",

+      "%S",

+      Start

+      );

+  } else {

+    SourceFile->FileBufferPtr++;

+  }

+  //

+  // Now allocate memory for the string and save it off

+  //

+  String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));

+  if (String == NULL) {

+    Error (NULL, 0, 0, "memory allocation failed", NULL);

+    return NULL;

+  }

+  //

+  // Copy the string from the file buffer to the local copy.

+  // We do no reformatting of it whatsoever at this point.

+  //

+  Ptr = String;

+  while (Len > 0) {

+    *Ptr = *Start;

+    Start++;

+    Ptr++;

+    Len--;

+  }

+

+  *Ptr = 0;

+  //

+  // Now format the string to convert \wide and \narrow controls

+  //

+  StringDBFormatString (String);

+  return String;

+}

+

+static

+WCHAR *

+GetQuotedString (

+  SOURCE_FILE *SourceFile,

+  BOOLEAN     Optional

+  )

+{

+  WCHAR   *String;

+  WCHAR   *Start;

+  WCHAR   *Ptr;

+  UINT32  Len;

+  BOOLEAN PreviousBackslash;

+

+  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {

+    if (!Optional) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);

+    }

+

+    return NULL;

+  }

+

+  Len = 0;

+  SourceFile->FileBufferPtr++;

+  Start             = Ptr = SourceFile->FileBufferPtr;

+  PreviousBackslash = FALSE;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) && (!PreviousBackslash)) {

+      break;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {

+      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);

+      PreviousBackslash = FALSE;

+    } else if (SourceFile->FileBufferPtr[0] == UNICODE_BACKSLASH) {

+      PreviousBackslash = TRUE;

+    } else {

+      PreviousBackslash = FALSE;

+    }

+

+    SourceFile->FileBufferPtr++;

+    Len++;

+  }

+

+  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);

+  } else {

+    SourceFile->FileBufferPtr++;

+  }

+  //

+  // Now allocate memory for the string and save it off

+  //

+  String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));

+  if (String == NULL) {

+    Error (NULL, 0, 0, "memory allocation failed", NULL);

+    return NULL;

+  }

+  //

+  // Copy the string from the file buffer to the local copy.

+  // We do no reformatting of it whatsoever at this point.

+  //

+  Ptr = String;

+  while (Len > 0) {

+    *Ptr = *Start;

+    Start++;

+    Ptr++;

+    Len--;

+  }

+

+  *Ptr = 0;

+  return String;

+}

+//

+// Parse:

+//    #string STR_ID_NAME

+//

+// All we can do is call the string database to add the string identifier. Unfortunately

+// he'll have to keep track of the last identifier we added.

+//

+static

+void

+ProcessTokenString (

+  SOURCE_FILE *SourceFile

+  )

+{

+  WCHAR   StringIdentifier[MAX_STRING_IDENTIFIER_NAME];

+  UINT16  StringId;

+  //

+  // Extract the string identifier name and add it to the database.

+  //

+  if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) {

+    StringId = STRING_ID_INVALID;

+    StringDBAddStringIdentifier (StringIdentifier, &StringId, 0);

+  } else {

+    //

+    // Error recovery -- skip to the next #

+    //

+    SourceFile->SkipToHash = TRUE;

+  }

+}

+

+static

+BOOLEAN

+EndOfFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  //

+  // The file buffer pointer will typically get updated before the End-of-file flag in the

+  // source file structure, so check it first.

+  //

+  if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (WCHAR)) {

+    SourceFile->EndOfFile = TRUE;

+    return TRUE;

+  }

+

+  if (SourceFile->EndOfFile) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+static

+UINT32

+GetStringIdentifierName (

+  IN SOURCE_FILE  *SourceFile,

+  IN OUT WCHAR    *StringIdentifierName,

+  IN UINT32       StringIdentifierNameLen

+  )

+{

+  UINT32  Len;

+  WCHAR   *From;

+  WCHAR   *Start;

+

+  //

+  // Skip whitespace

+  //

+  SkipWhiteSpace (SourceFile);

+  if (SourceFile->EndOfFile) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-file encountered", "expected string identifier");

+    return 0;

+  }

+  //

+  // Verify first character of name is [A-Za-z]

+  //

+  Len = 0;

+  StringIdentifierNameLen /= 2;

+  From  = SourceFile->FileBufferPtr;

+  Start = SourceFile->FileBufferPtr;

+  if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) ||

+      ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))

+      ) {

+    //

+    // Do nothing

+    //

+  } else {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid character in string identifier name", "%S", Start);

+    return 0;

+  }

+

+  while (!EndOfFile (SourceFile)) {

+    if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) ||

+        ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) ||

+        ((SourceFile->FileBufferPtr[0] >= UNICODE_0) && (SourceFile->FileBufferPtr[0] <= UNICODE_9)) ||

+        (SourceFile->FileBufferPtr[0] == UNICODE_UNDERSCORE)

+        ) {

+      Len++;

+      if (Len >= StringIdentifierNameLen) {

+        Error (SourceFile->FileName, SourceFile->LineNum, 0, "string identifier name too long", "%S", Start);

+        return 0;

+      }

+

+      *StringIdentifierName = SourceFile->FileBufferPtr[0];

+      StringIdentifierName++;

+      SourceFile->FileBufferPtr++;

+    } else if (SkipWhiteSpace (SourceFile) == 0) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid string identifier name", "%S", Start);

+      return 0;

+    } else {

+      break;

+    }

+  }

+  //

+  // Terminate the copy of the string.

+  //

+  *StringIdentifierName = 0;

+  return Len;

+}

+

+static

+UINT32

+GetLanguageIdentifierName (

+  IN SOURCE_FILE  *SourceFile,

+  IN OUT WCHAR    *LanguageIdentifierName,

+  IN UINT32       LanguageIdentifierNameLen,

+  IN BOOLEAN      Optional

+  )

+{

+  UINT32  Len;

+  WCHAR   *From;

+  WCHAR   *Start;

+  //

+  // Skip whitespace

+  //

+  SkipWhiteSpace (SourceFile);

+  if (SourceFile->EndOfFile) {

+    if (!Optional) {

+      Error (

+        SourceFile->FileName,

+        SourceFile->LineNum,

+        0,

+        "end-of-file encountered",

+        "expected language identifier"

+        );

+    }

+

+    return 0;

+  }

+  //

+  // This function is called to optionally get a language identifier name in:

+  //   #string STR_ID eng "the string"

+  // If it's optional, and we find a double-quote, then return now.

+  //

+  if (Optional) {

+    if (*SourceFile->FileBufferPtr == UNICODE_DOUBLE_QUOTE) {

+      return 0;

+    }

+  }

+

+  Len = 0;

+  LanguageIdentifierNameLen /= 2;

+  //

+  // Internal error if we weren't given at least 4 WCHAR's to work with.

+  //

+  if (LanguageIdentifierNameLen < LANGUAGE_IDENTIFIER_NAME_LEN + 1) {

+    Error (

+      SourceFile->FileName,

+      SourceFile->LineNum,

+      0,

+      "app error -- language identifier name length is invalid",

+      NULL

+      );

+  }

+

+  From  = SourceFile->FileBufferPtr;

+  Start = SourceFile->FileBufferPtr;

+  while (!EndOfFile (SourceFile)) {

+    if (((SourceFile->FileBufferPtr[0] >= UNICODE_a) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))) {

+      Len++;

+      if (Len > LANGUAGE_IDENTIFIER_NAME_LEN) {

+        Error (SourceFile->FileName, SourceFile->LineNum, 0, "language identifier name too long", "%S", Start);

+        return 0;

+      }

+

+      *LanguageIdentifierName = SourceFile->FileBufferPtr[0];

+      SourceFile->FileBufferPtr++;

+      LanguageIdentifierName++;

+    } else if (!IsWhiteSpace (SourceFile)) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid language identifier name", "%S", Start);

+      return 0;

+    } else {

+      break;

+    }

+  }

+  //

+  // Terminate the copy of the string.

+  //

+  *LanguageIdentifierName = 0;

+  return Len;

+}

+

+static

+void

+ProcessTokenInclude (

+  SOURCE_FILE *SourceFile

+  )

+{

+  CHAR8       IncludeFileName[MAX_PATH];

+  CHAR8       *To;

+  UINT32      Len;

+  BOOLEAN     ReportedError;

+  SOURCE_FILE IncludedSourceFile;

+

+  ReportedError = FALSE;

+  if (SkipWhiteSpace (SourceFile) == 0) {

+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);

+  }

+  //

+  // Should be quoted file name

+  //

+  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);

+    goto FailDone;

+  }

+

+  SourceFile->FileBufferPtr++;

+  //

+  // Copy the filename as ascii to our local string

+  //

+  To  = IncludeFileName;

+  Len = 0;

+  while (!EndOfFile (SourceFile)) {

+    if ((SourceFile->FileBufferPtr[0] == UNICODE_CR) || (SourceFile->FileBufferPtr[0] == UNICODE_LF)) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);

+      goto FailDone;

+    }

+

+    if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {

+      SourceFile->FileBufferPtr++;

+      break;

+    }

+    //

+    // If too long, then report the error once and process until the closing quote

+    //

+    Len++;

+    if (!ReportedError && (Len >= sizeof (IncludeFileName))) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);

+      ReportedError = TRUE;

+    }

+

+    if (!ReportedError) {

+      *To = UNICODE_TO_ASCII (SourceFile->FileBufferPtr[0]);

+      To++;

+    }

+

+    SourceFile->FileBufferPtr++;

+  }

+

+  if (!ReportedError) {

+    *To = 0;

+    memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));

+    strcpy (IncludedSourceFile.FileName, IncludeFileName);

+    IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;

+    ProcessIncludeFile (&IncludedSourceFile, SourceFile);

+    //

+    // printf ("including file '%s'\n", IncludeFileName);

+    //

+  }

+

+  return ;

+FailDone:

+  //

+  // Error recovery -- skip to next #

+  //

+  SourceFile->SkipToHash = TRUE;

+}

+

+static

+void

+ProcessTokenScope (

+  SOURCE_FILE *SourceFile

+  )

+{

+  WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME];

+  //

+  // Extract the scope name

+  //

+  if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) {

+    StringDBSetScope (StringIdentifier);

+  }

+}

+//

+// Parse:  #langdef eng "English"

+//         #langdef chn "\wideChinese"

+//

+static

+void

+ProcessTokenLangDef (

+  SOURCE_FILE *SourceFile

+  )

+{

+  WCHAR   LanguageIdentifier[MAX_STRING_IDENTIFIER_NAME];

+  UINT32  Len;

+  WCHAR   *PrintableName;

+  //

+  // Extract the 3-character language identifier

+  //

+  Len = GetLanguageIdentifierName (SourceFile, LanguageIdentifier, sizeof (LanguageIdentifier), FALSE);

+  if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", NULL);

+  } else {

+    //

+    // Extract the printable name

+    //

+    PrintableName = GetPrintableLanguageName (SourceFile);

+    if (PrintableName != NULL) {

+      ParserSetPosition (SourceFile->FileName, SourceFile->LineNum);

+      StringDBAddLanguage (LanguageIdentifier, PrintableName);

+      free (PrintableName);

+      return ;

+    }

+  }

+  //

+  // Error recovery -- skip to next #

+  //

+  SourceFile->SkipToHash = TRUE;

+}

+

+static

+BOOLEAN

+ApparentQuotedString (

+  SOURCE_FILE *SourceFile

+  )

+{

+  WCHAR *Ptr;

+  //

+  // See if the first and last nonblank characters on the line are double quotes

+  //

+  for (Ptr = SourceFile->FileBufferPtr; *Ptr && (*Ptr == UNICODE_SPACE); Ptr++)

+    ;

+  if (*Ptr != UNICODE_DOUBLE_QUOTE) {

+    return FALSE;

+  }

+

+  while (*Ptr) {

+    Ptr++;

+  }

+

+  Ptr--;

+  for (; *Ptr && (*Ptr == UNICODE_SPACE); Ptr--)

+    ;

+  if (*Ptr != UNICODE_DOUBLE_QUOTE) {

+    return FALSE;

+  }

+

+  return TRUE;

+}

+//

+// Parse:

+//   #language eng "some string " "more string"

+//

+static

+void

+ProcessTokenLanguage (

+  SOURCE_FILE *SourceFile

+  )

+{

+  WCHAR   *String;

+  WCHAR   *SecondString;

+  WCHAR   *TempString;

+  WCHAR   *From;

+  WCHAR   *To;

+  WCHAR   Language[LANGUAGE_IDENTIFIER_NAME_LEN + 1];

+  UINT32  Len;

+  BOOLEAN PreviousNewline;

+  //

+  // Get the language identifier

+  //

+  Language[0] = 0;

+  Len         = GetLanguageIdentifierName (SourceFile, Language, sizeof (Language), TRUE);

+  if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) {

+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", "%S", Language);

+    SourceFile->SkipToHash = TRUE;

+    return ;

+  }

+  //

+  // Extract the string value. It's either a quoted string that starts on the current line, or

+  // an unquoted string that starts on the following line and continues until the next control

+  // character in column 1.

+  // Look ahead to find a quote or a newline

+  //

+  if (SkipTo (SourceFile, UNICODE_DOUBLE_QUOTE, TRUE)) {

+    String = GetQuotedString (SourceFile, FALSE);

+    if (String != NULL) {

+      //

+      // Set the position in the file of where we are parsing for error

+      // reporting purposes. Then start looking ahead for additional

+      // quoted strings, and concatenate them until we get a failure

+      // back from the string parser.

+      //

+      Len = StrLen (String) + 1;

+      ParserSetPosition (SourceFile->FileName, SourceFile->LineNum);

+      do {

+        SkipWhiteSpace (SourceFile);

+        SecondString = GetQuotedString (SourceFile, TRUE);

+        if (SecondString != NULL) {

+          Len += StrLen (SecondString);

+          TempString = (WCHAR *) malloc (Len * sizeof (WCHAR));

+          if (TempString == NULL) {

+            Error (NULL, 0, 0, "application error", "failed to allocate memory");

+            return ;

+          }

+

+          StrCpy (TempString, String);

+          StrCat (TempString, SecondString);

+          free (String);

+          free (SecondString);

+          String = TempString;

+        }

+      } while (SecondString != NULL);

+      StringDBAddString (Language, NULL, NULL, String, TRUE, 0);

+      free (String);

+    } else {

+      //

+      // Error was reported at lower level. Error recovery mode.

+      //

+      SourceFile->SkipToHash = TRUE;

+    }

+  } else {

+    if (!mGlobals.UnquotedStrings) {

+      //

+      // They're using unquoted strings. If the next non-blank character is a double quote, and the

+      // last non-blank character on the line is a double quote, then more than likely they're using

+      // quotes, so they need to put the quoted string on the end of the previous line

+      //

+      if (ApparentQuotedString (SourceFile)) {

+        Warning (

+          SourceFile->FileName,

+          SourceFile->LineNum,

+          0,

+          "unexpected quoted string on line",

+          "specify -uqs option if necessary"

+          );

+      }

+    }

+    //

+    // Found end-of-line (hopefully). Skip over it and start taking in characters

+    // until we find a control character at the start of a line.

+    //

+    Len             = 0;

+    From            = SourceFile->FileBufferPtr;

+    PreviousNewline = FALSE;

+    while (!EndOfFile (SourceFile)) {

+      if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {

+        PreviousNewline = TRUE;

+        SourceFile->LineNum++;

+      } else {

+        Len++;

+        if (PreviousNewline && (SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter)) {

+          break;

+        }

+

+        PreviousNewline = FALSE;

+      }

+

+      SourceFile->FileBufferPtr++;

+    }

+

+    if ((Len == 0) && EndOfFile (SourceFile)) {

+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "unexpected end of file", NULL);

+      SourceFile->SkipToHash = TRUE;

+      return ;

+    }

+    //

+    // Now allocate a buffer, copy the characters, and add the string.

+    //

+    String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));

+    if (String == NULL) {

+      Error (NULL, 0, 0, "application error", "failed to allocate memory");

+      return ;

+    }

+

+    To = String;

+    while (From < SourceFile->FileBufferPtr) {

+      switch (*From) {

+      case UNICODE_LF:

+      case 0:

+        break;

+

+      default:

+        *To = *From;

+        To++;

+        break;

+      }

+

+      From++;

+    }

+

+    //

+    // String[Len] = 0;

+    //

+    *To = 0;

+    StringDBAddString (Language, NULL, NULL, String, TRUE, 0);

+  }

+}

+

+static

+BOOLEAN

+IsWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  switch (SourceFile->FileBufferPtr[0]) {

+  case UNICODE_NULL:

+  case UNICODE_CR:

+  case UNICODE_SPACE:

+  case UNICODE_TAB:

+  case UNICODE_LF:

+    return TRUE;

+

+  default:

+    return FALSE;

+  }

+}

+

+static

+UINT32

+SkipWhiteSpace (

+  SOURCE_FILE *SourceFile

+  )

+{

+  UINT32  Count;

+

+  Count = 0;

+  while (!EndOfFile (SourceFile)) {

+    Count++;

+    switch (*SourceFile->FileBufferPtr) {

+    case UNICODE_NULL:

+    case UNICODE_CR:

+    case UNICODE_SPACE:

+    case UNICODE_TAB:

+      SourceFile->FileBufferPtr++;

+      break;

+

+    case UNICODE_LF:

+      SourceFile->FileBufferPtr++;

+      SourceFile->LineNum++;

+      if (mGlobals.Verbose) {

+        printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);

+      }

+      break;

+

+    default:

+      return Count - 1;

+    }

+  }

+  //

+  // Some tokens require trailing whitespace. If we're at the end of the

+  // file, then we count that as well.

+  //

+  if ((Count == 0) && (EndOfFile (SourceFile))) {

+    Count++;

+  }

+

+  return Count;

+}

+

+static

+UINT32

+wstrcmp (

+  WCHAR *Buffer,

+  WCHAR *Str

+  )

+{

+  UINT32  Len;

+

+  Len = 0;

+  while (*Str == *Buffer) {

+    Buffer++;

+    Str++;

+    Len++;

+  }

+

+  if (*Str) {

+    return 0;

+  }

+

+  return Len;

+}

+//

+// Given a filename, try to find it along the include paths.

+//

+static

+FILE *

+FindFile (

+  IN CHAR8   *FileName,

+  OUT CHAR8  *FoundFileName,

+  IN UINT32  FoundFileNameLen

+  )

+{

+  FILE              *Fptr;

+  TEXT_STRING_LIST  *List;

+

+  //

+  // Traverse the list of paths and try to find the file

+  //

+  List = mGlobals.IncludePaths;

+  while (List != NULL) {

+    //

+    // Put the path and filename together

+    //

+    if (strlen (List->Str) + strlen (FileName) + 1 > FoundFileNameLen) {

+      Error (PROGRAM_NAME, 0, 0, NULL, "internal error - cannot concatenate path+filename");

+      return NULL;

+    }

+    //

+    // Append the filename to this include path and try to open the file.

+    //

+    strcpy (FoundFileName, List->Str);

+    strcat (FoundFileName, FileName);

+    if ((Fptr = fopen (FoundFileName, "rb")) != NULL) {

+      //

+      // Return the file pointer

+      //

+      return Fptr;

+    }

+

+    List = List->Next;

+  }

+  //

+  // Not found

+  //

+  FoundFileName[0] = 0;

+  return NULL;

+}

+//

+// Process the command-line arguments

+//

+static

+STATUS

+ProcessArgs (

+  int   Argc,

+  char  *Argv[]

+  )

+{

+  TEXT_STRING_LIST  *NewList;

+  //

+  // Clear our globals

+  //

+  memset ((char *) &mGlobals, 0, sizeof (mGlobals));

+  strcpy (mGlobals.BaseName, DEFAULT_BASE_NAME);

+  //

+  // Skip program name

+  //

+  Argc--;

+  Argv++;

+

+  if (Argc == 0) {

+    Usage ();

+    return STATUS_ERROR;

+  }

+

+  mGlobals.Mode = MODE_UNKNOWN;

+  //

+  // Process until no more -args.

+  //

+  while ((Argc > 0) && (Argv[0][0] == '-')) {

+    //

+    // -parse option

+    //

+    if (stricmp (Argv[0], "-parse") == 0) {

+      if (mGlobals.Mode != MODE_UNKNOWN) {

+        Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);

+        return STATUS_ERROR;

+      }

+

+      mGlobals.Mode = MODE_PARSE;

+      //

+      // -scan option

+      //

+    } else if (stricmp (Argv[0], "-scan") == 0) {

+      if (mGlobals.Mode != MODE_UNKNOWN) {

+        Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);

+        return STATUS_ERROR;

+      }

+

+      mGlobals.Mode = MODE_SCAN;

+      //

+      // -vscan verbose scanning option

+      //

+    } else if (stricmp (Argv[0], "-vscan") == 0) {

+      mGlobals.VerboseScan = TRUE;

+      //

+      // -dump option

+      //

+    } else if (stricmp (Argv[0], "-dump") == 0) {

+      if (mGlobals.Mode != MODE_UNKNOWN) {

+        Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);

+        return STATUS_ERROR;

+      }

+

+      mGlobals.Mode = MODE_DUMP;

+    } else if (stricmp (Argv[0], "-uqs") == 0) {

+      mGlobals.UnquotedStrings = TRUE;

+      //

+      // -i path    add include search path when parsing

+      //

+    } else if (stricmp (Argv[0], "-i") == 0) {

+      //

+      // check for one more arg

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing include path");

+        return STATUS_ERROR;

+      }

+      //

+      // Allocate memory for a new list element, fill it in, and

+      // add it to our list of include paths. Always make sure it

+      // has a "\" on the end of it.

+      //

+      NewList = malloc (sizeof (TEXT_STRING_LIST));

+      if (NewList == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));

+      NewList->Str = malloc (strlen (Argv[1]) + 2);

+      if (NewList->Str == NULL) {

+        free (NewList);

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      strcpy (NewList->Str, Argv[1]);

+      if (NewList->Str[strlen (NewList->Str) - 1] != '\\') {

+        strcat (NewList->Str, "\\");

+      }

+      //

+      // Add it to our linked list

+      //

+      if (mGlobals.IncludePaths == NULL) {

+        mGlobals.IncludePaths = NewList;

+      } else {

+        mGlobals.LastIncludePath->Next = NewList;

+      }

+

+      mGlobals.LastIncludePath = NewList;

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-if") == 0) {

+      //

+      // Indirection file -- check for one more arg

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing indirection file name");

+        return STATUS_ERROR;

+      }

+      //

+      // Allocate memory for a new list element, fill it in, and

+      // add it to our list of include paths. Always make sure it

+      // has a "\" on the end of it.

+      //

+      NewList = malloc (sizeof (TEXT_STRING_LIST));

+      if (NewList == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));

+      NewList->Str = malloc (strlen (Argv[1]) + 1);

+      if (NewList->Str == NULL) {

+        free (NewList);

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      strcpy (NewList->Str, Argv[1]);

+      //

+      // Add it to our linked list

+      //

+      if (mGlobals.IndirectionFileName == NULL) {

+        mGlobals.IndirectionFileName = NewList;

+      } else {

+        mGlobals.LastIndirectionFileName->Next = NewList;

+      }

+

+      mGlobals.LastIndirectionFileName = NewList;

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-db") == 0) {

+      //

+      // -db option to specify a database file.

+      // Check for one more arg (the database file name)

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database file name");

+        return STATUS_ERROR;

+      }

+

+      NewList = malloc (sizeof (TEXT_STRING_LIST));

+      if (NewList == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));

+      NewList->Str = malloc (strlen (Argv[1]) + 1);

+      if (NewList->Str == NULL) {

+        free (NewList);

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      strcpy (NewList->Str, Argv[1]);

+      //

+      // Add it to our linked list

+      //

+      if (mGlobals.DatabaseFileName == NULL) {

+        mGlobals.DatabaseFileName = NewList;

+      } else {

+        mGlobals.LastDatabaseFileName->Next = NewList;

+      }

+

+      mGlobals.LastDatabaseFileName = NewList;

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-ou") == 0) {

+      //

+      // -ou option to specify an output unicode file to

+      // which we can dump our database.

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database dump output file name");

+        return STATUS_ERROR;

+      }

+

+      if (mGlobals.DumpUFileName[0] == 0) {

+        strcpy (mGlobals.DumpUFileName, Argv[1]);

+      } else {

+        Error (PROGRAM_NAME, 0, 0, Argv[1], "-ou option already specified with '%s'", mGlobals.DumpUFileName);

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-hpk") == 0) {

+      //

+      // -hpk option to create an HII export pack of the input database file

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing raw string data dump output file name");

+        return STATUS_ERROR;

+      }

+

+      if (mGlobals.HiiExportPackFileName[0] == 0) {

+        strcpy (mGlobals.HiiExportPackFileName, Argv[1]);

+      } else {

+        Error (PROGRAM_NAME, 0, 0, Argv[1], "-or option already specified with '%s'", mGlobals.HiiExportPackFileName);

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {

+      Usage ();

+      return STATUS_ERROR;

+    } else if (stricmp (Argv[0], "-v") == 0) {

+      mGlobals.Verbose = 1;

+    } else if (stricmp (Argv[0], "-vdbw") == 0) {

+      mGlobals.VerboseDatabaseWrite = 1;

+    } else if (stricmp (Argv[0], "-vdbr") == 0) {

+      mGlobals.VerboseDatabaseRead = 1;

+    } else if (stricmp (Argv[0], "-newdb") == 0) {

+      mGlobals.NewDatabase = 1;

+    } else if (stricmp (Argv[0], "-ignorenotfound") == 0) {

+      mGlobals.IgnoreNotFound = 1;

+    } else if (stricmp (Argv[0], "-oc") == 0) {

+      //

+      // check for one more arg

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output C filename");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.StringCFileName, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-bn") == 0) {

+      //

+      // check for one more arg

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing base name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.BaseName, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-oh") == 0) {

+      //

+      // -oh to specify output .h defines file name

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output .h filename");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.StringHFileName, Argv[1]);

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-skipext") == 0) {

+      //

+      // -skipext to skip scanning of files with certain filename extensions

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing filename extension");

+        return STATUS_ERROR;

+      }

+      //

+      // Allocate memory for a new list element, fill it in, and

+      // add it to our list of excluded extensions. Always make sure it

+      // has a "." as the first character.

+      //

+      NewList = malloc (sizeof (TEXT_STRING_LIST));

+      if (NewList == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));

+      NewList->Str = malloc (strlen (Argv[1]) + 2);

+      if (NewList->Str == NULL) {

+        free (NewList);

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+

+      if (Argv[1][0] == '.') {

+        strcpy (NewList->Str, Argv[1]);

+      } else {

+        NewList->Str[0] = '.';

+        strcpy (NewList->Str + 1, Argv[1]);

+      }

+      //

+      // Add it to our linked list

+      //

+      if (mGlobals.SkipExt == NULL) {

+        mGlobals.SkipExt = NewList;

+      } else {

+        mGlobals.LastSkipExt->Next = NewList;

+      }

+

+      mGlobals.LastSkipExt = NewList;

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-lang") == 0) {

+      //

+      // "-lang eng" or "-lang spa+cat" to only output certain languages

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing language name");

+        Usage ();

+        return STATUS_ERROR;

+      }

+

+      if (AddCommandLineLanguage (Argv[1]) != STATUS_SUCCESS) {

+        return STATUS_ERROR;

+      }

+

+      Argc--;

+      Argv++;

+    } else if (stricmp (Argv[0], "-od") == 0) {

+      //

+      // Output database file name -- check for another arg

+      //

+      if ((Argc <= 1) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output database file name");

+        return STATUS_ERROR;

+      }

+

+      strcpy (mGlobals.OutputDatabaseFileName, Argv[1]);

+      Argv++;

+      Argc--;

+    } else {

+      //

+      // Unrecognized arg

+      //

+      Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");

+      Usage ();

+      return STATUS_ERROR;

+    }

+

+    Argv++;

+    Argc--;

+  }

+  //

+  // Make sure they specified the mode parse/scan/dump

+  //

+  if (mGlobals.Mode == MODE_UNKNOWN) {

+    Error (NULL, 0, 0, "must specify one of -parse/-scan/-dump", NULL);

+    return STATUS_ERROR;

+  }

+  //

+  // All modes require a database filename

+  //

+  if (mGlobals.DatabaseFileName == 0) {

+    Error (NULL, 0, 0, "must specify a database filename using -db DbFileName", NULL);

+    Usage ();

+    return STATUS_ERROR;

+  }

+  //

+  // If dumping the database file, then return immediately if all

+  // parameters check out.

+  //

+  if (mGlobals.Mode == MODE_DUMP) {

+    //

+    // Not much use if they didn't specify -oh or -oc or -ou or -hpk

+    //

+    if ((mGlobals.DumpUFileName[0] == 0) &&

+        (mGlobals.StringHFileName[0] == 0) &&

+        (mGlobals.StringCFileName[0] == 0) &&

+        (mGlobals.HiiExportPackFileName[0] == 0)

+        ) {

+      Error (NULL, 0, 0, "-dump without -oc/-oh/-ou/-hpk is a NOP", NULL);

+      return STATUS_ERROR;

+    }

+

+    return STATUS_SUCCESS;

+  }

+  //

+  // Had to specify source string file and output string defines header filename.

+  //

+  if (mGlobals.Mode == MODE_SCAN) {

+    if (Argc < 1) {

+      Error (PROGRAM_NAME, 0, 0, NULL, "must specify at least one source file to scan with -scan");

+      Usage ();

+      return STATUS_ERROR;

+    }

+    //

+    // Get the list of filenames

+    //

+    while (Argc > 0) {

+      NewList = malloc (sizeof (TEXT_STRING_LIST));

+      if (NewList == NULL) {

+        Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL);

+        return STATUS_ERROR;

+      }

+

+      memset (NewList, 0, sizeof (TEXT_STRING_LIST));

+      NewList->Str = (CHAR8 *) malloc (strlen (Argv[0]) + 1);

+      if (NewList->Str == NULL) {

+        Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL);

+        return STATUS_ERROR;

+      }

+

+      strcpy (NewList->Str, Argv[0]);

+      if (mGlobals.ScanFileName == NULL) {

+        mGlobals.ScanFileName = NewList;

+      } else {

+        mGlobals.LastScanFileName->Next = NewList;

+      }

+

+      mGlobals.LastScanFileName = NewList;

+      Argc--;

+      Argv++;

+    }

+  } else {

+    //

+    // Parse mode -- must specify an input unicode file name

+    //

+    if (Argc < 1) {

+      Error (PROGRAM_NAME, 0, 0, NULL, "must specify input unicode string file name with -parse");

+      Usage ();

+      return STATUS_ERROR;

+    }

+

+    strcpy (mGlobals.SourceFiles.FileName, Argv[0]);

+  }

+

+  return STATUS_SUCCESS;

+}

+//

+// Found "-lang eng,spa+cat" on the command line. Parse the

+// language list and save the setting for later processing.

+//

+static

+STATUS

+AddCommandLineLanguage (

+  IN CHAR8         *Language

+  )

+{

+  WCHAR_STRING_LIST *WNewList;

+  WCHAR             *From;

+  WCHAR             *To;

+  //

+  // Keep processing the input string until we find the end.

+  //

+  while (*Language) {

+    //

+    // Allocate memory for a new list element, fill it in, and

+    // add it to our list.

+    //

+    WNewList = MALLOC (sizeof (WCHAR_STRING_LIST));

+    if (WNewList == NULL) {

+      Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+      return STATUS_ERROR;

+    }

+

+    memset ((char *) WNewList, 0, sizeof (WCHAR_STRING_LIST));

+    WNewList->Str = malloc ((strlen (Language) + 1) * sizeof (WCHAR));

+    if (WNewList->Str == NULL) {

+      free (WNewList);

+      Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+      return STATUS_ERROR;

+    }

+    //

+    // Copy it as unicode to our new structure. Then remove the

+    // plus signs in it, and verify each language name is 3 characters

+    // long. If we find a comma, then we're done with this group, so

+    // break out.

+    //

+    UnicodeSPrint (WNewList->Str, (strlen (Language) + 1) * sizeof (WCHAR), L"%a", Language);

+    From = To = WNewList->Str;

+    while (*From) {

+      if (*From == L',') {

+        break;

+      }

+

+      if ((StrLen (From) < LANGUAGE_IDENTIFIER_NAME_LEN) ||

+            (

+              (From[LANGUAGE_IDENTIFIER_NAME_LEN] != 0) &&

+              (From[LANGUAGE_IDENTIFIER_NAME_LEN] != UNICODE_PLUS_SIGN) &&

+              (From[LANGUAGE_IDENTIFIER_NAME_LEN] != L',')

+            )

+          ) {

+        Error (PROGRAM_NAME, 0, 0, Language, "invalid format for language name on command line");

+        FREE (WNewList->Str);

+        FREE (WNewList);

+        return STATUS_ERROR;

+      }

+

+      StrnCpy (To, From, LANGUAGE_IDENTIFIER_NAME_LEN);

+      To += LANGUAGE_IDENTIFIER_NAME_LEN;

+      From += LANGUAGE_IDENTIFIER_NAME_LEN;

+      if (*From == L'+') {

+        From++;

+      }

+    }

+

+    *To = 0;

+    //

+    // Add it to our linked list

+    //

+    if (mGlobals.Language == NULL) {

+      mGlobals.Language = WNewList;

+    } else {

+      mGlobals.LastLanguage->Next = WNewList;

+    }

+

+    mGlobals.LastLanguage = WNewList;

+    //

+    // Skip to next entry (comma-separated list)

+    //

+    while (*Language) {

+      if (*Language == L',') {

+        Language++;

+        break;

+      }

+

+      Language++;

+    }

+  }

+

+  return STATUS_SUCCESS;

+}

+//

+// The contents of the text file are expected to be (one per line)

+//   STRING_IDENTIFIER_NAME   ScopeName

+// For example:

+//   STR_ID_MY_FAVORITE_STRING   IBM

+//

+static

+STATUS

+ParseIndirectionFiles (

+  TEXT_STRING_LIST    *Files

+  )

+{

+  FILE                        *Fptr;

+  CHAR8                       Line[200];

+  CHAR8                       *StringName;

+  CHAR8                       *ScopeName;

+  CHAR8                       *End;

+  UINT32                      LineCount;

+  WCHAR_MATCHING_STRING_LIST  *NewList;

+

+  Line[sizeof (Line) - 1] = 0;

+  Fptr                    = NULL;

+  while (Files != NULL) {

+    Fptr      = fopen (Files->Str, "r");

+    LineCount = 0;

+    if (Fptr == NULL) {

+      Error (NULL, 0, 0, Files->Str, "failed to open input indirection file for reading");

+      return STATUS_ERROR;

+    }

+

+    while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+      //

+      // remove terminating newline for error printing purposes.

+      //

+      if (Line[strlen (Line) - 1] == '\n') {

+        Line[strlen (Line) - 1] = 0;

+      }

+

+      LineCount++;

+      if (Line[sizeof (Line) - 1] != 0) {

+        Error (Files->Str, LineCount, 0, "line length exceeds maximum supported", NULL);

+        goto Done;

+      }

+

+      StringName = Line;

+      while (*StringName && (isspace (*StringName))) {

+        StringName++;

+      }

+

+      if (*StringName) {

+        if ((*StringName == '_') || isalpha (*StringName)) {

+          End = StringName;

+          while ((*End) && (*End == '_') || (isalnum (*End))) {

+            End++;

+          }

+

+          if (isspace (*End)) {

+            *End = 0;

+            End++;

+            while (isspace (*End)) {

+              End++;

+            }

+

+            if (*End) {

+              ScopeName = End;

+              while (*End && !isspace (*End)) {

+                End++;

+              }

+

+              *End = 0;

+              //

+              // Add the string name/scope pair

+              //

+              NewList = malloc (sizeof (WCHAR_MATCHING_STRING_LIST));

+              if (NewList == NULL) {

+                Error (NULL, 0, 0, "memory allocation error", NULL);

+                goto Done;

+              }

+

+              memset (NewList, 0, sizeof (WCHAR_MATCHING_STRING_LIST));

+              NewList->Str1 = (WCHAR *) malloc ((strlen (StringName) + 1) * sizeof (WCHAR));

+              NewList->Str2 = (WCHAR *) malloc ((strlen (ScopeName) + 1) * sizeof (WCHAR));

+              if ((NewList->Str1 == NULL) || (NewList->Str2 == NULL)) {

+                Error (NULL, 0, 0, "memory allocation error", NULL);

+                goto Done;

+              }

+

+              UnicodeSPrint (NewList->Str1, strlen (StringName) + 1, L"%a", StringName);

+              UnicodeSPrint (NewList->Str2, strlen (ScopeName) + 1, L"%a", ScopeName);

+              if (mGlobals.IndirectionList == NULL) {

+                mGlobals.IndirectionList = NewList;

+              } else {

+                mGlobals.LastIndirectionList->Next = NewList;

+              }

+

+              mGlobals.LastIndirectionList = NewList;

+            } else {

+              Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'");

+              goto Done;

+            }

+          } else {

+            Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'");

+            goto Done;

+          }

+        } else {

+          Error (Files->Str, LineCount, 0, StringName, "invalid string identifier");

+          goto Done;

+        }

+      }

+    }

+

+    fclose (Fptr);

+    Fptr  = NULL;

+    Files = Files->Next;

+  }

+

+Done:

+  if (Fptr != NULL) {

+    fclose (Fptr);

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+ScanFiles (

+  TEXT_STRING_LIST *ScanFiles

+  )

+{

+  char              Line[MAX_LINE_LEN];

+  FILE              *Fptr;

+  UINT32            LineNum;

+  char              *Cptr;

+  char              *SavePtr;

+  char              *TermPtr;

+  char              *StringTokenPos;

+  TEXT_STRING_LIST  *SList;

+  BOOLEAN           SkipIt;

+

+  //

+  // Put a null-terminator at the end of the line. If we read in

+  // a line longer than we support, then we can catch it.

+  //

+  Line[MAX_LINE_LEN - 1] = 0;

+  //

+  // Process each file. If they gave us a skip extension list, then

+  // skip it if the extension matches.

+  //

+  while (ScanFiles != NULL) {

+    SkipIt = FALSE;

+    for (SList = mGlobals.SkipExt; SList != NULL; SList = SList->Next) {

+      if ((strlen (ScanFiles->Str) > strlen (SList->Str)) &&

+          (strcmp (ScanFiles->Str + strlen (ScanFiles->Str) - strlen (SList->Str), SList->Str) == 0)

+          ) {

+        SkipIt = TRUE;

+        //

+        // printf ("Match: %s : %s\n", ScanFiles->Str, SList->Str);

+        //

+        break;

+      }

+    }

+

+    if (!SkipIt) {

+      if (mGlobals.VerboseScan) {

+        printf ("Scanning %s\n", ScanFiles->Str);

+      }

+

+      Fptr = fopen (ScanFiles->Str, "r");

+      if (Fptr == NULL) {

+        Error (NULL, 0, 0, ScanFiles->Str, "failed to open input file for scanning");

+        return STATUS_ERROR;

+      }

+

+      LineNum = 0;

+      while (fgets (Line, sizeof (Line), Fptr) != NULL) {

+        LineNum++;

+        if (Line[MAX_LINE_LEN - 1] != 0) {

+          Error (ScanFiles->Str, LineNum, 0, "line length exceeds maximum supported by tool", NULL);

+          fclose (Fptr);

+          return STATUS_ERROR;

+        }

+        //

+        // Remove the newline from the input line so we can print a warning message

+        //

+        if (Line[strlen (Line) - 1] == '\n') {

+          Line[strlen (Line) - 1] = 0;

+        }

+        //

+        // Terminate the line at // comments

+        //

+        Cptr = strstr (Line, "//");

+        if (Cptr != NULL) {

+          *Cptr = 0;

+        }

+

+        Cptr = Line;

+        while ((Cptr = strstr (Cptr, STRING_TOKEN)) != NULL) {

+          //

+          // Found "STRING_TOKEN". Make sure we don't have NUM_STRING_TOKENS or

+          // something like that. Then make sure it's followed by

+          // an open parenthesis, a string identifier, and then a closing

+          // parenthesis.

+          //

+          if (mGlobals.VerboseScan) {

+            printf (" %d: %s", LineNum, Cptr);

+          }

+

+          if (((Cptr == Line) || (!IsValidIdentifierChar (*(Cptr - 1), FALSE))) &&

+              (!IsValidIdentifierChar (*(Cptr + sizeof (STRING_TOKEN) - 1), FALSE))

+              ) {

+            StringTokenPos  = Cptr;

+            SavePtr         = Cptr;

+            Cptr += strlen (STRING_TOKEN);

+            while (*Cptr && isspace (*Cptr) && (*Cptr != '(')) {

+              Cptr++;

+            }

+

+            if (*Cptr != '(') {

+              Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)");

+            } else {

+              //

+              // Skip over the open-parenthesis and find the next non-blank character

+              //

+              Cptr++;

+              while (isspace (*Cptr)) {

+                Cptr++;

+              }

+

+              SavePtr = Cptr;

+              if ((*Cptr == '_') || isalpha (*Cptr)) {

+                while ((*Cptr == '_') || (isalnum (*Cptr))) {

+                  Cptr++;

+                }

+

+                TermPtr = Cptr;

+                while (*Cptr && isspace (*Cptr)) {

+                  Cptr++;

+                }

+

+                if (*Cptr != ')') {

+                  Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)");

+                }

+

+                if (*TermPtr) {

+                  *TermPtr  = 0;

+                  Cptr      = TermPtr + 1;

+                } else {

+                  Cptr = TermPtr;

+                }

+                //

+                // Add the string identifier to the list of used strings

+                //

+                ParserSetPosition (ScanFiles->Str, LineNum);

+                StringDBSetStringReferenced (SavePtr, mGlobals.IgnoreNotFound);

+                if (mGlobals.VerboseScan) {

+                  printf ("...referenced %s", SavePtr);

+                }

+              } else {

+                Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected valid string identifier name");

+              }

+            }

+          } else {

+            //

+            // Found it, but it's a substring of something else. Advance our pointer.

+            //

+            Cptr++;

+          }

+

+          if (mGlobals.VerboseScan) {

+            printf ("\n");

+          }

+        }

+      }

+

+      fclose (Fptr);

+    } else {

+      //

+      // Skipping this file type

+      //

+      if (mGlobals.VerboseScan) {

+        printf ("Skip scanning of %s\n", ScanFiles->Str);

+      }

+    }

+

+    ScanFiles = ScanFiles->Next;

+  }

+

+  return STATUS_SUCCESS;

+}

+//

+// Free the global string lists we allocated memory for

+//

+static

+void

+FreeLists (

+  VOID

+  )

+{

+  TEXT_STRING_LIST  *Temp;

+  WCHAR_STRING_LIST *WTemp;

+

+  //

+  // Traverse the include paths, freeing each

+  //

+  while (mGlobals.IncludePaths != NULL) {

+    Temp = mGlobals.IncludePaths->Next;

+    free (mGlobals.IncludePaths->Str);

+    free (mGlobals.IncludePaths);

+    mGlobals.IncludePaths = Temp;

+  }

+  //

+  // If we did a scan, then free up our

+  // list of files to scan.

+  //

+  while (mGlobals.ScanFileName != NULL) {

+    Temp = mGlobals.ScanFileName->Next;

+    free (mGlobals.ScanFileName->Str);

+    free (mGlobals.ScanFileName);

+    mGlobals.ScanFileName = Temp;

+  }

+  //

+  // If they gave us a list of filename extensions to

+  // skip on scan, then free them up.

+  //

+  while (mGlobals.SkipExt != NULL) {

+    Temp = mGlobals.SkipExt->Next;

+    free (mGlobals.SkipExt->Str);

+    free (mGlobals.SkipExt);

+    mGlobals.SkipExt = Temp;

+  }

+  //

+  // Free up any languages specified

+  //

+  while (mGlobals.Language != NULL) {

+    WTemp = mGlobals.Language->Next;

+    free (mGlobals.Language->Str);

+    free (mGlobals.Language);

+    mGlobals.Language = WTemp;

+  }

+  //

+  // Free up our indirection list

+  //

+  while (mGlobals.IndirectionList != NULL) {

+    mGlobals.LastIndirectionList = mGlobals.IndirectionList->Next;

+    free (mGlobals.IndirectionList->Str1);

+    free (mGlobals.IndirectionList->Str2);

+    free (mGlobals.IndirectionList);

+    mGlobals.IndirectionList = mGlobals.LastIndirectionList;

+  }

+

+  while (mGlobals.IndirectionFileName != NULL) {

+    mGlobals.LastIndirectionFileName = mGlobals.IndirectionFileName->Next;

+    free (mGlobals.IndirectionFileName->Str);

+    free (mGlobals.IndirectionFileName);

+    mGlobals.IndirectionFileName = mGlobals.LastIndirectionFileName;

+  }

+}

+

+static

+BOOLEAN

+IsValidIdentifierChar (

+  CHAR8     Char,

+  BOOLEAN   FirstChar

+  )

+{

+  //

+  // If it's the first character of an identifier, then

+  // it must be one of [A-Za-z_].

+  //

+  if (FirstChar) {

+    if (isalpha (Char) || (Char == '_')) {

+      return TRUE;

+    }

+  } else {

+    //

+    // If it's not the first character, then it can

+    // be one of [A-Za-z_0-9]

+    //

+    if (isalnum (Char) || (Char == '_')) {

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

+

+static

+void

+RewindFile (

+  SOURCE_FILE *SourceFile

+  )

+{

+  SourceFile->LineNum       = 1;

+  SourceFile->FileBufferPtr = SourceFile->FileBuffer;

+  SourceFile->EndOfFile     = 0;

+}

+

+static

+BOOLEAN

+SkipTo (

+  SOURCE_FILE *SourceFile,

+  WCHAR       WChar,

+  BOOLEAN     StopAfterNewline

+  )

+{

+  while (!EndOfFile (SourceFile)) {

+    //

+    // Check for the character of interest

+    //

+    if (SourceFile->FileBufferPtr[0] == WChar) {

+      return TRUE;

+    } else {

+      if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {

+        SourceFile->LineNum++;

+        if (StopAfterNewline) {

+          SourceFile->FileBufferPtr++;

+          if (SourceFile->FileBufferPtr[0] == 0) {

+            SourceFile->FileBufferPtr++;

+          }

+

+          return FALSE;

+        }

+      }

+

+      SourceFile->FileBufferPtr++;

+    }

+  }

+

+  return FALSE;

+}

+

+static

+void

+Usage (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Print usage information for this utility.

+  

+Arguments:

+

+  None.

+

+Returns:

+

+  Nothing.

+  

+--*/

+{

+  int               Index;

+  static const char *Str[] = {

+    "",

+    PROGRAM_NAME " version "TOOL_VERSION " -- process unicode strings file",

+    "  Usage: "PROGRAM_NAME " -parse {parse options} [FileNames]",

+    "         "PROGRAM_NAME " -scan {scan options} [FileName]",

+    "         "PROGRAM_NAME " -dump {dump options}",

+    "    Common options include:",

+    "      -h or -?         for this help information",

+    "      -db Database     required name of output/input database file",

+    "      -bn BaseName     for use in the .h and .c output files",

+    "                       Default = "DEFAULT_BASE_NAME,

+    "      -v               for verbose output",

+    "      -vdbw            for verbose output when writing database",

+    "      -vdbr            for verbose output when reading database",

+    "      -od FileName     to specify an output database file name",

+    "    Parse options include:",

+    "      -i IncludePath   add IncludePath to list of search paths",

+    "      -newdb           to not read in existing database file",

+    "      -uqs             to indicate that unquoted strings are used",

+    "      FileNames        name of one or more unicode files to parse",

+    "    Scan options include:",

+    "      -scan            scan text file(s) for STRING_TOKEN() usage",

+    "      -skipext .ext    to skip scan of files with .ext filename extension",

+    "      -ignorenotfound  ignore if a given STRING_TOKEN(STR) is not ",

+    "                       found in the database",

+    "      FileNames        one or more files to scan",

+    "    Dump options include:",

+    "      -oc FileName     write string data to FileName",

+    "      -oh FileName     write string defines to FileName",

+    "      -ou FileName     dump database to unicode file FileName",

+    "      -lang Lang       only dump for the language 'Lang'",

+    "      -if FileName     to specify an indirection file",

+    "      -hpk FileName    to create an HII export pack of the strings",

+    "",

+    "  The expected process is to parse a unicode string file to create an initial",

+    "  database of string identifier names and string definitions. Then text files",

+    "  should be scanned for STRING_TOKEN() usages, and the referenced",

+    "  strings will be tagged as used in the database. After all files have been",

+    "  scanned, then the database should be dumped to create the necessary output",

+    "  files.",

+    "",

+    NULL

+  };

+  for (Index = 0; Str[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Str[Index]);

+  }

+}

diff --git a/Source/StrGather/StrGather.h b/Source/StrGather/StrGather.h
new file mode 100644
index 0000000..65dc15c
--- /dev/null
+++ b/Source/StrGather/StrGather.h
@@ -0,0 +1,84 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  StrGather.h

+

+Abstract:

+

+  Common defines and prototypes for StrGather.

+  

+--*/

+

+#ifndef _STR_GATHER_H_

+#define _STR_GATHER_H_

+

+#define MALLOC(size)  malloc (size)

+#define FREE(ptr)     free (ptr)

+

+#define PROGRAM_NAME  "StrGather"

+

+typedef CHAR16  WCHAR;

+

+#define UNICODE_TO_ASCII(w)   (INT8) ((w) & 0xFF)

+#define ASCII_TO_UNICODE(a)   (WCHAR) ((UINT8) (a))

+

+#define UNICODE_HASH          L'#'

+#define UNICODE_BACKSLASH     L'\\'

+#define UNICODE_SLASH         L'/'

+#define UNICODE_EQUAL_SIGN    L'='

+#define UNICODE_PLUS_SIGN     L'+'

+

+#define UNICODE_FILE_START    0xFEFF

+#define UNICODE_CR            0x000D

+#define UNICODE_LF            0x000A

+#define UNICODE_NULL          0x0000

+#define UNICODE_SPACE         L' '

+#define UNICODE_SLASH         L'/'

+#define UNICODE_DOUBLE_QUOTE  L'"'

+#define UNICODE_Z             L'Z'

+#define UNICODE_z             L'z'

+#define UNICODE_A             L'A'

+#define UNICODE_a             L'a'

+#define UNICODE_F             L'F'

+#define UNICODE_f             L'f'

+#define UNICODE_UNDERSCORE    L'_'

+#define UNICODE_0             L'0'

+#define UNICODE_9             L'9'

+#define UNICODE_TAB           L'\t'

+#define UNICODE_NBR_STRING    L"\\nbr"

+#define UNICODE_BR_STRING     L"\\br"

+#define UNICODE_WIDE_STRING   L"\\wide"

+#define UNICODE_NARROW_STRING L"\\narrow"

+

+//

+// This is the length of a valid string identifier

+//

+#define LANGUAGE_IDENTIFIER_NAME_LEN  3

+

+typedef struct _TEXT_STRING_LIST {

+  struct _TEXT_STRING_LIST  *Next;

+  CHAR8                     *Str;

+} TEXT_STRING_LIST;

+

+typedef struct _WCHAR_STRING_LIST {

+  struct _WCHAR_STRING_LIST *Next;

+  WCHAR                     *Str;

+} WCHAR_STRING_LIST;

+

+typedef struct _WCHAR_MATCHING_STRING_LIST {

+  struct _WCHAR_MATCHING_STRING_LIST  *Next;

+  WCHAR                               *Str1;

+  WCHAR                               *Str2;

+} WCHAR_MATCHING_STRING_LIST;

+

+#endif // #ifndef _STR_GATHER_H_

diff --git a/Source/StrGather/StringDB.c b/Source/StrGather/StringDB.c
new file mode 100644
index 0000000..16ef052
--- /dev/null
+++ b/Source/StrGather/StringDB.c
@@ -0,0 +1,2759 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  StringDB.c

+

+Abstract:

+

+  String database implementation

+  

+--*/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>  // for tolower()

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/MultiPhase.h>

+#include <Common/InternalFormRepresentation.h>

+#include <Protocol/UgaDraw.h>  // for EFI_UGA_PIXEL definition

+#include <Protocol/Hii.h>

+

+#include "EfiUtilityMsgs.h"

+#include "StrGather.h"

+#include "StringDB.h"

+

+

+#define STRING_OFFSET RELOFST

+

+#define STRING_DB_KEY (('S' << 24) | ('D' << 16) | ('B' << 8) | 'K')

+//

+// Version supported by this tool

+//

+#define STRING_DB_VERSION             0x00010000

+

+#define STRING_DB_MAJOR_VERSION_MASK  0xFFFF0000

+#define STRING_DB_MINOR_VERSION_MASK  0x0000FFFF

+

+#define DEFINE_STR                    L"// #define"

+

+#define LANGUAGE_CODE_WIDTH           4

+//

+// This is the header that gets written to the top of the

+// output binary database file.

+//

+typedef struct {

+  UINT32  Key;

+  UINT32  HeaderSize;

+  UINT32  Version;

+  UINT32  NumStringIdenfiers;

+  UINT32  StringIdentifiersSize;

+  UINT32  NumLanguages;

+} STRING_DB_HEADER;

+

+//

+// When we write out data to the database, we have a UINT16 identifier, which

+// indicates what follows, followed by the data. Here's the structure.

+//

+typedef struct {

+  UINT16  DataType;

+  UINT16  Reserved;

+} DB_DATA_ITEM_HEADER;

+

+#define DB_DATA_TYPE_INVALID              0x0000

+#define DB_DATA_TYPE_STRING_IDENTIFIER    0x0001

+#define DB_DATA_TYPE_LANGUAGE_DEFINITION  0x0002

+#define DB_DATA_TYPE_STRING_DEFINITION    0x0003

+#define DB_DATA_TYPE_LAST                 DB_DATA_TYPE_STRING_DEFINITION

+

+//

+// We have to keep track of a list of languages, each of which has its own

+// list of strings. Define a structure to keep track of all languages and

+// their list of strings.

+//

+typedef struct _STRING_LIST {

+  struct _STRING_LIST *Next;

+  UINT32              Size;         // number of bytes in string, including null terminator

+  WCHAR               *LanguageName;

+  WCHAR               *StringName;  // for example STR_ID_TEXT1

+  WCHAR               *Scope;       //

+  WCHAR               *Str;         // the actual string

+  UINT16              Flags;        // properties of this string (used, undefined)

+} STRING_LIST;

+

+typedef struct _LANGUAGE_LIST {

+  struct _LANGUAGE_LIST *Next;

+  WCHAR                 LanguageName[4];

+  WCHAR                 *PrintableLanguageName;

+  STRING_LIST           *String;

+  STRING_LIST           *LastString;

+} LANGUAGE_LIST;

+

+//

+// We also keep track of all the string identifier names, which we assign unique

+// values to. Create a structure to keep track of them all.

+//

+typedef struct _STRING_IDENTIFIER {

+  struct _STRING_IDENTIFIER *Next;

+  UINT32                    Index;  // only need 16 bits, but makes it easier with UINT32

+  WCHAR                     *StringName;

+  UINT16                    Flags;  // if someone referenced it via STRING_TOKEN()

+} STRING_IDENTIFIER;

+//

+// Keep our globals in this structure to be as modular as possible.

+//

+typedef struct {

+  FILE              *StringDBFptr;

+  LANGUAGE_LIST     *LanguageList;

+  LANGUAGE_LIST     *LastLanguageList;

+  LANGUAGE_LIST     *CurrentLanguage;         // keep track of the last language they used

+  STRING_IDENTIFIER *StringIdentifier;

+  STRING_IDENTIFIER *LastStringIdentifier;

+  UINT8             *StringDBFileName;

+  UINT32            NumStringIdentifiers;

+  UINT32            NumStringIdentifiersReferenced;

+  STRING_IDENTIFIER *CurrentStringIdentifier; // keep track of the last string identifier they added

+  WCHAR             *CurrentScope;

+} STRING_DB_DATA;

+

+static STRING_DB_DATA mDBData;

+

+static const char     *mSourceFileHeader[] = {

+  "//",

+  "//  DO NOT EDIT -- auto-generated file",

+  "//",

+  "//  This file is generated by the string gather utility",

+  "//",

+  NULL

+};

+

+static

+STRING_LIST           *

+StringDBFindString (

+  WCHAR                       *LanguageName,

+  WCHAR                       *StringName,

+  WCHAR                       *Scope,

+  WCHAR_STRING_LIST           *LanguagesOfInterest,

+  WCHAR_MATCHING_STRING_LIST  *IndirectionList

+  );

+

+static

+STRING_IDENTIFIER     *

+StringDBFindStringIdentifierByName (

+  WCHAR *Name

+  );

+

+static

+STRING_IDENTIFIER     *

+StringDBFindStringIdentifierByIndex (

+  UINT32    Index

+  );

+

+static

+LANGUAGE_LIST         *

+StringDBFindLanguageList (

+  WCHAR *LanguageName

+  );

+

+static

+void

+StringDBWriteStandardFileHeader (

+  FILE *OutFptr

+  );

+

+static

+WCHAR                 *

+AsciiToWchar (

+  CHAR8 *Str

+  );

+

+static

+WCHAR                 *

+DuplicateString (

+  WCHAR   *Str

+  );

+

+static

+STATUS

+StringDBWriteStringIdentifier (

+  FILE                *DBFptr,

+  UINT16              StringId,

+  UINT16              Flags,

+  WCHAR               *IdentifierName

+  );

+

+static

+STATUS

+StringDBReadStringIdentifier (

+  FILE                *DBFptr

+  );

+

+static

+STATUS

+StringDBWriteLanguageDefinition (

+  FILE            *DBFptr,

+  WCHAR           *LanguageName,

+  WCHAR           *PrintableLanguageName

+  );

+

+static

+STATUS

+StringDBReadLanguageDefinition (

+  FILE            *DBFptr

+  );

+

+static

+STATUS

+StringDBWriteString (

+  FILE            *DBFptr,

+  UINT16          Flags,

+  WCHAR           *Language,

+  WCHAR           *StringName,

+  WCHAR           *Scope,

+  WCHAR           *Str

+  );

+

+static

+STATUS

+StringDBReadString (

+  FILE            *DBFptr

+  );

+

+static

+STATUS

+StringDBReadGenericString (

+  FILE      *DBFptr,

+  UINT16    *Size,

+  WCHAR     **Str

+  );

+

+static

+STATUS

+StringDBWriteGenericString (

+  FILE      *DBFptr,

+  WCHAR     *Str

+  );

+

+static

+void

+StringDBAssignStringIndexes (

+  VOID

+  );

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+  Constructor function for the string database handler.

+

+Arguments:

+  None.

+

+Returns:

+  None.

+

+--*/

+void

+StringDBConstructor (

+  VOID

+  )

+{

+  memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA));

+  mDBData.CurrentScope = DuplicateString (L"NULL");

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+  Destructor function for the string database handler.

+

+Arguments:

+  None.

+

+Returns:

+  None.

+

+--*/

+void

+StringDBDestructor (

+  VOID

+  )

+{

+  LANGUAGE_LIST     *NextLang;

+  STRING_LIST       *NextStr;

+  STRING_IDENTIFIER *NextIdentifier;

+  //

+  // Close the database file if it's open

+  //

+  if (mDBData.StringDBFptr != NULL) {

+    fclose (mDBData.StringDBFptr);

+    mDBData.StringDBFptr = NULL;

+  }

+  //

+  // If we've allocated any strings/languages, free them up

+  //

+  while (mDBData.LanguageList != NULL) {

+    NextLang = mDBData.LanguageList->Next;

+    //

+    // Free up all strings for this language

+    //

+    while (mDBData.LanguageList->String != NULL) {

+      NextStr = mDBData.LanguageList->String->Next;

+      FREE (mDBData.LanguageList->String->Str);

+      FREE (mDBData.LanguageList->String);

+      mDBData.LanguageList->String = NextStr;

+    }

+

+    FREE (mDBData.LanguageList->PrintableLanguageName);

+    FREE (mDBData.LanguageList);

+    mDBData.LanguageList = NextLang;

+  }

+  //

+  // Free up string identifiers

+  //

+  while (mDBData.StringIdentifier != NULL) {

+    NextIdentifier = mDBData.StringIdentifier->Next;

+    FREE (mDBData.StringIdentifier->StringName);

+    FREE (mDBData.StringIdentifier);

+    mDBData.StringIdentifier = NextIdentifier;

+  }

+  //

+  // Free the filename

+  //

+  if (mDBData.StringDBFileName != NULL) {

+    FREE (mDBData.StringDBFileName);

+    mDBData.StringDBFileName = NULL;

+  }

+  //

+  // We save a copy of the scope, so free it up if we

+  // have one.

+  //

+  if (mDBData.CurrentScope != NULL) {

+    FREE (mDBData.CurrentScope);

+    mDBData.CurrentScope = NULL;

+  }

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Dump the contents of a database to an output C file.

+

+Arguments:

+

+  FileName        - name of the output file to write 

+  BaseName        - used for the name of the C array defined

+  Languages       - list of languages of interest

+

+Returns:

+

+  STATUS

+

+Notes:

+

+  Languages is a pointer to a linked list of languages specified on

+  the command line. Format is "eng" and "spa+cat". For this, print

+  the strings for eng. Print the strings for spa too, but if one is

+  missing look for a cat string and print if it it exists.

+

+--*/

+STATUS

+StringDBDumpCStrings (

+  CHAR8                       *FileName,

+  CHAR8                       *BaseName,

+  WCHAR_STRING_LIST           *LanguagesOfInterest,

+  WCHAR_MATCHING_STRING_LIST  *IndirectionList

+  )

+{

+  FILE                        *Fptr;

+  LANGUAGE_LIST               *Lang;

+  STRING_LIST                 *CurrString;

+  STRING_LIST                 EmptyString;

+  UINT32                      Offset;

+  UINT32                      StringIndex;

+  UINT32                      TempIndex;

+  UINT32                      BytesThisLine;

+  EFI_HII_STRING_PACK         StringPack;

+  UINT8                       *Ptr;

+  UINT32                      Len;

+  WCHAR                       ZeroString[1];

+  WCHAR_STRING_LIST           *LOIPtr;

+  BOOLEAN                     LanguageOk;

+  WCHAR                       *TempStringPtr;

+  WCHAR                       *LangName;

+  STRING_IDENTIFIER           *StringIdentifier;

+  WCHAR                       Line[200];

+

+  if ((Fptr = fopen (FileName, "w")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output C string file");

+    return STATUS_ERROR;

+  }

+  //

+  // Assign index values to the string identifiers

+  //

+  StringDBAssignStringIndexes ();

+  //

+  // Write the standard header to the output file, then the structure

+  // definition header.

+  //

+  StringDBWriteStandardFileHeader (Fptr);

+  fprintf (Fptr, "\nunsigned char %s[] = {\n", BaseName);

+  //

+  // If a given string is not defined, then we'll use this one.

+  //

+  memset (&EmptyString, 0, sizeof (EmptyString));

+  EmptyString.Size  = sizeof (ZeroString);

+  EmptyString.Str   = ZeroString;

+  //

+  // Process each language, then each string for each langage

+  //

+  ZeroString[0] = 0;

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    //

+    // If we have a language list, then make sure this language is in that

+    // list.

+    //

+    LanguageOk  = TRUE;

+    LangName    = Lang->LanguageName;

+    if (LanguagesOfInterest != NULL) {

+      LanguageOk = FALSE;

+      for (LOIPtr = LanguagesOfInterest; LOIPtr != NULL; LOIPtr = LOIPtr->Next) {

+        if (StrnCmp (LOIPtr->Str, Lang->LanguageName, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) {

+          LangName    = LOIPtr->Str;

+          LanguageOk  = TRUE;

+          break;

+        }

+      }

+    }

+

+    if (!LanguageOk) {

+      continue;

+    }

+    //

+    // Process each string for this language. We have to make 3 passes on the strings:

+    //   Pass1: computes sizes and fill in the string pack header

+    //   Pass2: write the array of offsets

+    //   Pass3: write the strings

+    //

+    //

+    // PASS 1: Fill in and print the HII string pack header

+    //

+    // Compute the size for this language package and write

+    // the header out. Each string package contains:

+    //   Header

+    //   Offset[]  -- an array of offsets to strings, of type RELOFST each

+    //   String[]  -- the actual strings themselves

+    //

+    AsciiSPrint ( Line, sizeof(Line),

+      "\n//******************************************************************************"

+      "\n// Start of string definitions for %s/%s",

+      Lang->LanguageName,

+      Lang->PrintableLanguageName

+      );

+    fprintf (Fptr, "%s", Line);

+    memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));

+    StringPack.Header.Type        = EFI_HII_STRING;

+    StringPack.NumStringPointers  = (UINT16) mDBData.NumStringIdentifiersReferenced;

+    //

+    // First string is the language name. If we're printing all languages, then

+    // it's just the "spa". If we were given a list of languages to print, then it's

+    // the "spacat" string. Compute its offset and fill in

+    // the info in the header. Since we know the language name string's length,

+    // and the printable language name follows it, use that info to fill in the

+    // entry for the printable language name as well.

+    //

+    StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)));

+    StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR));

+    //

+    // Add up the size of all strings so we can fill in our header.

+    //

+    Len = 0;

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        Len += (StrLen (LangName) + 1) * sizeof (WCHAR);

+      } else {

+        //

+        // Find a string with this language.stringname

+        //

+        StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+        if (StringIdentifier == NULL) {

+          Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+          return STATUS_ERROR;

+        }

+        //

+        // Find a matching string if this string identifier was referenced

+        //

+        EmptyString.Flags = STRING_FLAGS_UNDEFINED;

+        CurrString        = NULL;

+        if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {

+          CurrString = StringDBFindString (

+                        Lang->LanguageName,

+                        StringIdentifier->StringName,

+                        NULL,

+                        LanguagesOfInterest,

+                        IndirectionList

+                        );

+          if (NULL == CurrString) {

+            //

+            // If string for Lang->LanguageName is not found, try to get an English version

+            //

+            CurrString = StringDBFindString (

+                          L"eng",

+                          StringIdentifier->StringName,

+                          NULL,

+                          LanguagesOfInterest,

+                          IndirectionList

+                          );

+          }

+        }

+

+        if (CurrString == NULL) {

+          CurrString = &EmptyString;

+          EmptyString.Flags |= StringIdentifier->Flags;

+        }

+

+        Len += CurrString->Size;

+      }

+    }

+    StringPack.Header.Length =    sizeof (EFI_HII_STRING_PACK) 

+                                + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) 

+                                + Len;

+    //

+    // Write out the header one byte at a time

+    //

+    Ptr = (UINT8 *) &StringPack;

+    for (TempIndex = 0; TempIndex < sizeof (EFI_HII_STRING_PACK); TempIndex++, Ptr++) {

+      if ((TempIndex & 0x07) == 0) {

+        fprintf (Fptr, "\n  ");

+      }

+

+      fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr);

+    }

+

+    fprintf (Fptr, "\n  // offset 0x%X\n", sizeof (StringPack));

+    //

+    // PASS2 : write the offsets

+    //

+    // Traverse the list of strings again and write the array of offsets. The

+    // offset to the first string is the size of the string pack header

+    // plus the size of the offsets array. The other strings follow it.

+    //

+    StringIndex = 0;

+    Offset      = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      //

+      // Write the offset, followed by a useful comment

+      //

+      fprintf (Fptr, "  ");

+      Ptr = (UINT8 *) &Offset;

+      for (TempIndex = 0; TempIndex < sizeof (STRING_OFFSET); TempIndex++) {

+        fprintf (Fptr, "0x%02X, ", (UINT32) Ptr[TempIndex]);

+      }

+      //

+      // Find the string name

+      //

+      StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+      if (StringIdentifier == NULL) {

+        Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+        return STATUS_ERROR;

+      }

+

+      AsciiSPrint (Line, sizeof(Line) , " // offset to string %s (0x%04X)", StringIdentifier->StringName, StringIndex);

+      fprintf (Fptr, "%s", Line);

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        Offset += (StrLen (LangName) + 1) * sizeof (WCHAR);

+        CurrString = StringDBFindString (

+                      Lang->LanguageName,

+                      StringIdentifier->StringName,

+                      NULL, // scope

+                      NULL,

+                      NULL

+                      );

+      } else {

+        //

+        // Find a matching string

+        //

+        CurrString = StringDBFindString (

+                      Lang->LanguageName,

+                      StringIdentifier->StringName,

+                      NULL,   // scope

+                      LanguagesOfInterest,

+                      IndirectionList

+                      );

+

+        if (NULL == CurrString) {

+          CurrString = StringDBFindString (

+                        L"eng",

+                        StringIdentifier->StringName,

+                        NULL, // scope

+                        LanguagesOfInterest,

+                        IndirectionList

+                        );

+        }

+

+        EmptyString.LanguageName = Lang->LanguageName;

+        if (CurrString == NULL) {

+          CurrString        = &EmptyString;

+          EmptyString.Flags = STRING_FLAGS_UNDEFINED;

+        } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {

+          CurrString        = &EmptyString;

+          EmptyString.Flags = 0;

+        }

+

+        Offset += CurrString->Size;

+      }

+      //

+      // Print useful info about this string

+      //

+      if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {

+        fprintf (Fptr, " - not referenced");

+      }

+

+      if (CurrString->Flags & STRING_FLAGS_UNDEFINED) {

+        fprintf (Fptr, " - not defined for this language");

+      } else if (StrCmp (CurrString->LanguageName, Lang->LanguageName) != 0) {

+        AsciiSPrint (

+          Line, sizeof(Line),

+          " - not defined for this language -- using secondary language %s definition",

+          CurrString->LanguageName

+          );

+        fprintf ( Fptr, "%s", Line);

+      }

+

+      fprintf (Fptr, "\n");

+    }

+    //

+    // For unreferenced string identifiers, print a message that they are not referenced anywhere

+    //

+    while (StringIndex < mDBData.NumStringIdentifiers) {

+      StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+      if (StringIdentifier != NULL) {

+        AsciiSPrint (Line, sizeof(Line), "  // %s not referenced\n", StringIdentifier->StringName);

+        fprintf (Fptr, "%s", Line);

+      }

+

+      StringIndex++;

+    }

+

+    //

+    // PASS 3: write the strings themselves.

+    // Keep track of how many bytes we write per line because some editors

+    // (Visual Studio for instance) can't handle too long of lines.

+    //

+    Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+      if (StringIdentifier == NULL) {

+        Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+        return STATUS_ERROR;

+      }

+

+      AsciiSPrint (Line, sizeof(Line), "  // string %s offset 0x%08X\n  ", StringIdentifier->StringName, Offset);

+      fprintf (Fptr, "%s", Line);

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        TempStringPtr = LangName;

+      } else {

+        //

+        // Find a matching string if this string identifier was referenced

+        //

+        CurrString = NULL;

+        if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {

+          CurrString = StringDBFindString (

+                        Lang->LanguageName,

+                        StringIdentifier->StringName,

+                        NULL,   // scope

+                        LanguagesOfInterest,

+                        IndirectionList

+                        );

+          if (NULL == CurrString) {

+            CurrString = StringDBFindString (

+                          L"eng",

+                          StringIdentifier->StringName,

+                          NULL, // scope

+                          LanguagesOfInterest,

+                          IndirectionList

+                          );

+          }

+        }

+

+        if (CurrString == NULL) {

+          CurrString = &EmptyString;

+        }

+

+        TempStringPtr = CurrString->Str;

+      }

+

+      BytesThisLine = 0;

+      for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) {

+        fprintf (

+          Fptr,

+          "0x%02X, 0x%02X, ",

+          (UINT32) TempStringPtr[TempIndex] & 0xFF,

+          (UINT32) ((TempStringPtr[TempIndex] >> 8) & 0xFF)

+          );

+        BytesThisLine += 2;

+        Offset += 2;

+        //

+        // Let's say we only allow 14 per line

+        //

+        if (BytesThisLine > 14) {

+          fprintf (Fptr, "\n  ");

+          BytesThisLine = 0;

+        }

+      }

+      //

+      // Print NULL WCHAR at the end of this string.

+      //

+      fprintf (Fptr, "0x00, 0x00,\n");

+      Offset += 2;

+    }

+    //

+    // Sanity check the offset. Make sure our running offset is what we put in the

+    // string pack header.

+    //

+    if (StringPack.Header.Length != Offset) {

+      Error (

+        __FILE__,

+        __LINE__,

+        0,

+        "application error",

+        "stringpack size 0x%X does not match final size 0x%X",

+        StringPack.Header.Length,

+        Offset

+        );

+    }

+  }

+  //

+  // Print terminator string pack, closing brace and close the file.

+  // The size of 0 triggers to the consumer that this is the end.

+  //

+  memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));

+  StringPack.Header.Type  = EFI_HII_STRING;

+  Ptr                     = (UINT8 *) &StringPack;

+  fprintf (Fptr, "\n  // strings terminator pack");

+  for (TempIndex = 0; TempIndex < sizeof (StringPack); TempIndex++, Ptr++) {

+    if ((TempIndex & 0x0F) == 0) {

+      fprintf (Fptr, "\n  ");

+    }

+

+    fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr);

+  }

+

+  fprintf (Fptr, "\n};\n");

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Dump the #define string names

+

+Arguments:

+

+  FileName        - name of the output file to write 

+  BaseName        - used for the protection #ifndef/#endif 

+

+Returns:

+

+  STATUS

+

+--*/

+STATUS

+StringDBDumpStringDefines (

+  CHAR8 *FileName,

+  CHAR8 *BaseName

+  )

+{

+  FILE              *Fptr;

+  STRING_IDENTIFIER *Identifier;

+  CHAR8             CopyBaseName[100];

+  WCHAR             Line[200];

+  UINT32            Index;

+  const CHAR8       *StrDefHeader[] = {

+    "#ifndef _%s_STRINGS_DEFINE_H_\n",

+    "#define _%s_STRINGS_DEFINE_H_\n\n",

+    NULL

+  };

+

+  if ((Fptr = fopen (FileName, "w")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output string defines file");

+    return STATUS_ERROR;

+  }

+  //

+  // Get the base source filename and convert to uppercase.

+  //

+  if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) {

+    Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient");

+    return STATUS_ERROR;

+  }

+

+  strcpy (CopyBaseName, BaseName);

+  for (Index = 0; CopyBaseName[Index] != 0; Index++) {

+    if (islower (CopyBaseName[Index])) {

+      CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]);

+    }

+  }

+  //

+  // Assign index values to the string identifiers

+  //

+  StringDBAssignStringIndexes ();

+  //

+  // Write the standard header to the output file, and then the

+  // protective #ifndef.

+  //

+  StringDBWriteStandardFileHeader (Fptr);

+  for (Index = 0; StrDefHeader[Index] != NULL; Index++) {

+    fprintf (Fptr, StrDefHeader[Index], CopyBaseName);

+  }

+  //

+  // Print all the #defines for the string identifiers. Print identifiers

+  // whose names start with '$' as comments. Add comments for string

+  // identifiers not used as well.

+  //

+  Identifier = mDBData.StringIdentifier;

+  while (Identifier != NULL) {

+    if (Identifier->StringName[0] == L'$') {

+      fprintf (Fptr, "// ");

+    }

+

+    if (Identifier->Flags & STRING_FLAGS_REFERENCED) {

+      AsciiSPrint (Line, sizeof(Line), "#define %-40s 0x%04X\n", Identifier->StringName, Identifier->Index);

+      fprintf (Fptr, "%s", Line);

+    } else {

+      AsciiSPrint (Line, sizeof(Line), "//#define %-40s 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index);

+      fprintf (Fptr, "%s", Line);

+    }

+

+    Identifier = Identifier->Next;

+  }

+

+  fprintf (Fptr, "\n#endif\n");

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Add a string identifier to the database.

+

+Arguments:

+

+  StringName      - name of the string identifier. For example "STR_MY_STRING"

+  NewId           - if an ID has been assigned

+  Flags           - characteristics for the identifier

+

+Returns:

+

+  STATUS

+

+--*/

+STATUS

+StringDBAddStringIdentifier (

+  WCHAR     *StringName,

+  UINT16    *NewId,

+  UINT16    Flags

+  )

+{

+  STRING_IDENTIFIER *StringIdentifier;

+  STATUS            Status;

+  //

+  // If it was already used for some other language, then we don't

+  // need to add it. But set it to the current string identifier.

+  // The referenced bit is sticky.

+  //

+  Status            = STATUS_SUCCESS;

+  StringIdentifier  = StringDBFindStringIdentifierByName (StringName);

+  if (StringIdentifier != NULL) {

+    if (Flags & STRING_FLAGS_REFERENCED) {

+      StringIdentifier->Flags |= STRING_FLAGS_REFERENCED;

+    }

+

+    mDBData.CurrentStringIdentifier = StringIdentifier;

+    *NewId                          = (UINT16) StringIdentifier->Index;

+    return Status;

+  }

+

+  StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER));

+  if (StringIdentifier == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation error");

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER));

+  StringIdentifier->StringName = (WCHAR *) malloc ((StrLen (StringName) + 1) * sizeof (WCHAR));

+  if (StringIdentifier->StringName == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation error");

+    return STATUS_ERROR;

+  }

+

+  StrCpy (StringIdentifier->StringName, StringName);

+  if (*NewId != STRING_ID_INVALID) {

+    StringIdentifier->Index = *NewId;

+    StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED;

+    if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) {

+      mDBData.NumStringIdentifiers = StringIdentifier->Index + 1;

+    }

+  } else {

+    StringIdentifier->Index = mDBData.NumStringIdentifiers++;

+  }

+

+  StringIdentifier->Flags |= Flags;

+  //

+  // Add it to our list of string identifiers

+  //

+  if (mDBData.StringIdentifier == NULL) {

+    mDBData.StringIdentifier = StringIdentifier;

+  } else {

+    mDBData.LastStringIdentifier->Next = StringIdentifier;

+  }

+

+  mDBData.LastStringIdentifier    = StringIdentifier;

+  mDBData.CurrentStringIdentifier = StringIdentifier;

+  *NewId                          = (UINT16) StringIdentifier->Index;

+  return Status;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Add a new string to the database.

+

+Arguments:

+

+  LanguageName    - "eng" or "spa" language name

+  StringName      - "STR_MY_TEXT" string name

+  Scope           - from the #scope statements in the string file

+  Format          - if we should format the string

+  Flags           - characteristic flags for the string

+

+Returns:

+

+  STATUS

+

+Notes:

+

+  Several of the fields can be "inherited" from the previous calls to

+  our database functions. For example, if scope is NULL here, then

+  we'll use the previous setting.

+

+--*/

+STATUS

+StringDBAddString (

+  WCHAR   *LanguageName,

+  WCHAR   *StringName,

+  WCHAR   *Scope,

+  WCHAR   *String,

+  BOOLEAN Format,

+  UINT16  Flags

+  )

+{

+  LANGUAGE_LIST     *Lang;

+  UINT32            Size;

+  STRING_LIST       *Str;

+  UINT16            StringIndex;

+  WCHAR             TempLangName[4];

+  STRING_IDENTIFIER *StringIdentifier;

+

+  //

+  // Check that language name is exactly 3 characters, or emit an error.

+  // Truncate at 3 if it's longer, or make it 3 if it's shorter.

+  //

+  if (LanguageName != NULL) {

+    Size = StrLen (LanguageName);

+    if (Size != 3) {

+      ParserError (0, "invalid length for language name", "%S", LanguageName);

+      if (Size > 3) {

+        LanguageName[3] = 0;

+      } else {

+        //

+        // Make a local copy of the language name string, and extend to

+        // 3 characters since we make assumptions elsewhere in this program

+        // on the length.

+        //

+        StrCpy (TempLangName, LanguageName);

+        for (; Size < 3; Size++) {

+          TempLangName[Size] = L'?';

+        }

+

+        TempLangName[4] = 0;

+        LanguageName    = TempLangName;

+      }

+    }

+  }

+  //

+  // If they specified a language, make sure they've defined it already

+  // via a #langdef statement. Otherwise use the current default language.

+  //

+  if (LanguageName != NULL) {

+    Lang = StringDBFindLanguageList (LanguageName);

+    if (Lang == NULL) {

+      ParserError (0, "language not defined", "%S", LanguageName);

+      return STATUS_ERROR;

+    } else {

+      StringDBSetCurrentLanguage (LanguageName);

+    }

+  } else {

+    Lang = mDBData.CurrentLanguage;

+    if (Lang == NULL) {

+      //

+      // Have to call SetLanguage() first

+      //

+      ParserError (0, "no language defined", "%S", StringName);

+      return STATUS_ERROR;

+    }

+  }

+  //

+  // If they didn't define a string identifier, use the last string identifier

+  // added.

+  //

+  if (StringName == NULL) {

+    StringName = mDBData.CurrentStringIdentifier->StringName;

+    if (StringName == NULL) {

+      ParserError (0, "no string identifier previously specified", NULL);

+      return STATUS_ERROR;

+    }

+  }

+  //

+  // If scope was not specified, use the default setting

+  //

+  if (Scope != NULL) {

+    Scope = DuplicateString (Scope);

+  } else {

+    Scope = DuplicateString (mDBData.CurrentScope);

+  }

+  //

+  // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope);

+  //

+  // Check for duplicates for this Language.StringName.Scope. Allow multiple

+  // definitions of the language name and printable language name, since the

+  // user does not specifically define them.

+  //

+  if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) {

+    if ((StrCmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) &&

+        (StrCmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0)

+        ) {

+      ParserError (

+        0,

+        "string multiply defined",

+        "Language.Name.Scope = %S.%S.%S",

+        Lang->LanguageName,

+        StringName,

+        Scope

+        );

+      return STATUS_ERROR;

+    }

+  }

+

+  StringIndex = STRING_ID_INVALID;

+  if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  StringIdentifier = StringDBFindStringIdentifierByName (StringName);

+  //

+  // Add this string to the end of the strings for this language.

+  //

+  Str = (STRING_LIST *) malloc (sizeof (STRING_LIST));

+  if (Str == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation error");

+    return STATUS_ERROR;

+  }

+

+  memset ((char *) Str, 0, sizeof (STRING_LIST));

+  Size              = (StrLen (String) + 1) * sizeof (WCHAR);

+  Str->Flags        = Flags;

+  Str->Scope        = Scope;

+  Str->StringName   = StringIdentifier->StringName;

+  Str->LanguageName = DuplicateString (LanguageName);

+  Str->Str          = (WCHAR *) MALLOC (Size);

+  if (Str->Str == NULL) {

+    Error (NULL, 0, 0, NULL, "memory allocation error");

+    return STATUS_ERROR;

+  }

+  //

+  // If not formatting, just copy the string.

+  //

+  StrCpy (Str->Str, String);

+  if (Format) {

+    StringDBFormatString (Str->Str);

+  }

+  //

+  // Size may change after formatting. We set the size to

+  // the actual size of the string, including the null for

+  // easier processing later.

+  //

+  Str->Size = (StrLen (Str->Str) + 1) * sizeof (WCHAR);

+  if (Lang->String == NULL) {

+    Lang->String = Str;

+  } else {

+    Lang->LastString->Next = Str;

+  }

+

+  Lang->LastString = Str;

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Given a language name, see if a language list for it has been defined

+

+Arguments:

+

+  LanguageName    - like "eng"

+

+Returns:

+

+  A pointer to the language list

+

+--*/

+static

+LANGUAGE_LIST *

+StringDBFindLanguageList (

+  WCHAR *LanguageName

+  )

+{

+  LANGUAGE_LIST *Lang;

+

+  Lang = mDBData.LanguageList;

+  while (Lang != NULL) {

+    if (StrCmp (LanguageName, Lang->LanguageName) == 0) {

+      break;

+    }

+

+    Lang = Lang->Next;

+  }

+

+  return Lang;

+}

+

+/*****************************************************************************/

+STATUS

+StringDBSetCurrentLanguage (

+  WCHAR *LanguageName

+  )

+{

+  LANGUAGE_LIST *Lang;

+

+  Lang = StringDBFindLanguageList (LanguageName);

+  if (Lang == NULL) {

+    ParserError (0, "language not previously defined", "%S", LanguageName);

+    return STATUS_ERROR;

+  }

+

+  mDBData.CurrentLanguage = Lang;

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+STATUS

+StringDBAddLanguage (

+  WCHAR *LanguageName,

+  WCHAR *PrintableLanguageName

+  )

+{

+  LANGUAGE_LIST *Lang;

+  //

+  // Check for redefinitions

+  //

+  Lang = StringDBFindLanguageList (LanguageName);

+  if (Lang != NULL) {

+    //

+    // Better be the same printable name

+    //

+    if (StrCmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) {

+      ParserError (

+        0,

+        "language redefinition",

+        "%S:%S != %S:%S",

+        Lang->LanguageName,

+        Lang->PrintableLanguageName,

+        LanguageName,

+        PrintableLanguageName

+        );

+      return STATUS_ERROR;

+      //

+      //    } else {

+      //      ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName);

+      //      return STATUS_WARNING;

+      //

+    }

+  } else {

+    //

+    // Allocate memory to keep track of this new language

+    //

+    Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST));

+    if (Lang == NULL) {

+      Error (NULL, 0, 0, NULL, "memory allocation error");

+      return STATUS_ERROR;

+    }

+

+    memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST));

+    //

+    // Save the language name, then allocate memory to save the

+    // printable language name

+    //

+    StrCpy (Lang->LanguageName, LanguageName);

+    Lang->PrintableLanguageName = (WCHAR *) malloc ((StrLen (PrintableLanguageName) + 1) * sizeof (WCHAR));

+    if (Lang->PrintableLanguageName == NULL) {

+      Error (NULL, 0, 0, NULL, "memory allocation error");

+      return STATUS_ERROR;

+    }

+

+    StrCpy (Lang->PrintableLanguageName, PrintableLanguageName);

+

+    if (mDBData.LanguageList == NULL) {

+      mDBData.LanguageList = Lang;

+    } else {

+      mDBData.LastLanguageList->Next = Lang;

+    }

+

+    mDBData.LastLanguageList = Lang;

+  }

+  //

+  // Default is to make our active language this new one

+  //

+  StringDBSetCurrentLanguage (LanguageName);

+  //

+  // The first two strings for any language are the language name,

+  // followed by the printable language name. Add them and set them

+  // to referenced so they never get stripped out.

+  //

+  StringDBAddString (

+    LanguageName,

+    LANGUAGE_NAME_STRING_NAME,

+    NULL,

+    LanguageName,

+    FALSE,

+    STRING_FLAGS_REFERENCED

+    );

+  StringDBAddString (

+    LanguageName,

+    PRINTABLE_LANGUAGE_NAME_STRING_NAME,

+    NULL,

+    PrintableLanguageName,

+    FALSE,

+    STRING_FLAGS_REFERENCED

+    );

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+static

+STRING_IDENTIFIER *

+StringDBFindStringIdentifierByName (

+  WCHAR *StringName

+  )

+{

+  STRING_IDENTIFIER *Identifier;

+

+  Identifier = mDBData.StringIdentifier;

+  while (Identifier != NULL) {

+    if (StrCmp (StringName, Identifier->StringName) == 0) {

+      return Identifier;

+    }

+

+    Identifier = Identifier->Next;

+  }

+

+  return NULL;

+}

+

+static

+STRING_IDENTIFIER *

+StringDBFindStringIdentifierByIndex (

+  UINT32    StringIndex

+  )

+{

+  STRING_IDENTIFIER *Identifier;

+

+  Identifier = mDBData.StringIdentifier;

+  while (Identifier != NULL) {

+    if (Identifier->Index == StringIndex) {

+      return Identifier;

+    }

+

+    Identifier = Identifier->Next;

+  }

+

+  return NULL;

+}

+

+/*****************************************************************************/

+static

+void

+StringDBWriteStandardFileHeader (

+  FILE *OutFptr

+  )

+{

+  UINT32  TempIndex;

+  for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {

+    fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);

+  }

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+  

+  Given a Unicode string from an input file, reformat the string to replace

+  backslash control sequences with the appropriate encoding.

+

+Arguments:

+

+  String        - pointer to string to reformat

+

+Returns:

+

+  Nothing

+

+--*/

+void

+StringDBFormatString (

+  WCHAR   *String

+  )

+{

+  WCHAR *From;

+  WCHAR *To;

+  int   HexNibbles;

+  WCHAR HexValue;

+  //

+  // Go through the string and process any formatting characters

+  //

+  From  = String;

+  To    = String;

+  while (*From) {

+    if (*From == UNICODE_BACKSLASH) {

+      //

+      // First look for \wide and replace with the appropriate control character. Note that

+      // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is

+      // counted. Make adjustments for this. We advance From below, so subtract 2 each time.

+      //

+      if (StrnCmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) {

+        *To = WIDE_CHAR;

+        From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2;

+      } else if (StrnCmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) {

+        //

+        // Found: \narrow

+        //

+        *To = NARROW_CHAR;

+        From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2;

+      } else if (StrnCmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) {

+        //

+        // Found: \nbr

+        //

+        *To = NON_BREAKING_CHAR;

+        From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2;

+      } else if (StrnCmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) {

+        //

+        // Found: \br -- pass through untouched

+        //

+        *To = *From;

+      } else {

+        //

+        // Standard one-character control sequences such as \n, \r, \\, or \x

+        //

+        From++;

+        switch (*From) {

+        case ASCII_TO_UNICODE ('n'):

+          *To = UNICODE_CR;

+          To++;

+          *To = UNICODE_LF;

+          break;

+

+        //

+        // carriage return

+        //

+        case ASCII_TO_UNICODE ('r'):

+          *To = UNICODE_CR;

+          break;

+

+        //

+        // backslash

+        //

+        case UNICODE_BACKSLASH:

+          *To = UNICODE_BACKSLASH;

+          break;

+

+        //

+        // Tab

+        //

+        case ASCII_TO_UNICODE ('t'):

+          *To = UNICODE_TAB;

+          break;

+

+        //

+        // embedded double-quote

+        //

+        case UNICODE_DOUBLE_QUOTE:

+          *To = UNICODE_DOUBLE_QUOTE;

+          break;

+

+        //

+        // Hex Unicode character \x1234. We'll process up to 4 hex characters

+        //

+        case ASCII_TO_UNICODE ('x'):

+          HexValue = 0;

+          for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) {

+            if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) {

+              HexValue = (HexValue << 4) | (From[1] - UNICODE_0);

+            } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) {

+              HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a);

+            } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) {

+              HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A);

+            } else {

+              break;

+            }

+

+            From++;

+          }

+

+          if (HexNibbles == 0) {

+            ParserWarning (

+              0,

+              "expected at least one valid hex digit with \\x escaped character in string",

+              "\\%C",

+              *From

+              );

+          } else {

+            *To = HexValue;

+          }

+          break;

+

+        default:

+          *To = UNICODE_SPACE;

+          ParserWarning (0, "invalid escaped character in string", "\\%C", *From);

+          break;

+        }

+      }

+    } else {

+      *To = *From;

+    }

+

+    From++;

+    To++;

+  }

+

+  *To = 0;

+}

+

+/*****************************************************************************/

+STATUS

+StringDBReadDatabase (

+  CHAR8   *DBFileName,

+  BOOLEAN IgnoreIfNotExist,

+  BOOLEAN Verbose

+  )

+{

+  STRING_DB_HEADER    DbHeader;

+  STATUS              Status;

+  FILE                *DBFptr;

+  DB_DATA_ITEM_HEADER DataItemHeader;

+

+  Status  = STATUS_SUCCESS;

+  DBFptr  = NULL;

+  //

+  //  if (Verbose) {

+  //    fprintf (stdout, "Reading database file %s\n", DBFileName);

+  //  }

+  //

+  // Try to open the input file

+  //

+  if ((DBFptr = fopen (DBFileName, "rb")) == NULL) {

+    if (IgnoreIfNotExist) {

+      return STATUS_SUCCESS;

+    }

+

+    Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading");

+    return STATUS_ERROR;

+  }

+  //

+  // Read and verify the database header

+  //

+  if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, DBFileName, "failed to read header from database file");

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+

+  if (DbHeader.Key != STRING_DB_KEY) {

+    Error (NULL, 0, 0, DBFileName, "invalid header in database file");

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+

+  if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) {

+    Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean");

+    Status = STATUS_ERROR;

+    goto Finish;

+  }

+  //

+  // Read remaining items

+  //

+  while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) {

+    switch (DataItemHeader.DataType) {

+    case DB_DATA_TYPE_STRING_IDENTIFIER:

+      StringDBReadStringIdentifier (DBFptr);

+      break;

+

+    case DB_DATA_TYPE_LANGUAGE_DEFINITION:

+      StringDBReadLanguageDefinition (DBFptr);

+      break;

+

+    case DB_DATA_TYPE_STRING_DEFINITION:

+      StringDBReadString (DBFptr);

+      break;

+

+    default:

+      Error (

+        NULL,

+        0,

+        0,

+        "database corrupted",

+        "invalid data item type 0x%X at offset 0x%X",

+        (UINT32) DataItemHeader.DataType,

+        ftell (DBFptr) - sizeof (DataItemHeader)

+        );

+      Status = STATUS_ERROR;

+      goto Finish;

+    }

+  }

+

+Finish:

+  if (DBFptr != NULL) {

+    fclose (DBFptr);

+  }

+

+  return Status;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+  

+  Write everything we know to the output database file. Write:

+

+  Database header

+  String identifiers[]

+  StringPacks[]

+

+Arguments:

+

+  DBFileName    - name of the file to write to

+  Verbose       - for debug purposes, print info messages along the way.

+

+Returns:

+

+  STATUS

+

+--*/

+STATUS

+StringDBWriteDatabase (

+  CHAR8   *DBFileName,

+  BOOLEAN Verbose

+  )

+{

+  STRING_DB_HEADER  DbHeader;

+  UINT32            Counter;

+  UINT32            StrLength;

+  LANGUAGE_LIST     *Lang;

+  STRING_IDENTIFIER *StringIdentifier;

+  STRING_LIST       *StrList;

+  FILE              *DBFptr;

+

+  if (Verbose) {

+    fprintf (stdout, "Writing database %s\n", DBFileName);

+  }

+

+  if ((DBFptr = fopen (DBFileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing");

+    return STATUS_ERROR;

+  }

+  //

+  // Fill in and write the database header

+  //

+  memset (&DbHeader, 0, sizeof (STRING_DB_HEADER));

+  DbHeader.HeaderSize = sizeof (STRING_DB_HEADER);

+  DbHeader.Key        = STRING_DB_KEY;

+  DbHeader.Version    = STRING_DB_VERSION;

+  //

+  // Count the number of languages we have

+  //

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    DbHeader.NumLanguages++;

+  }

+  //

+  // Count up how many string identifiers we have, and total up the

+  // size of the names plus the size of the flags field we will

+  // write out too.

+  //

+  DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers;

+  StringIdentifier            = mDBData.StringIdentifier;

+  for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) {

+    StrLength = StrLen (StringIdentifier->StringName) + 1;

+    DbHeader.StringIdentifiersSize += StrLength * sizeof (WCHAR) + sizeof (StringIdentifier->Flags);

+    StringIdentifier = StringIdentifier->Next;

+  }

+

+  //

+  // Write the header

+  //

+  fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr);

+  if (Verbose) {

+    fprintf (stdout, "  Number of string identifiers  0x%04X\n", DbHeader.NumStringIdenfiers);

+    fprintf (stdout, "  Number of languages           %d\n", DbHeader.NumLanguages);

+  }

+  //

+  // Write the string identifiers

+  //

+  for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {

+    StringDBWriteStringIdentifier (

+      DBFptr,

+      (UINT16) StringIdentifier->Index,

+      StringIdentifier->Flags,

+      StringIdentifier->StringName

+      );

+  }

+  //

+  // Now write all the strings for each language

+  //

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName);

+    for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {

+      StringDBWriteString (

+        DBFptr,

+        StrList->Flags,

+        Lang->LanguageName,

+        StrList->StringName,

+        StrList->Scope,

+        StrList->Str

+        );

+    }

+  }

+

+  fclose (DBFptr);

+  return STATUS_SUCCESS;

+}

+

+STATUS

+StringDBSetStringReferenced (

+  CHAR8     *StringIdentifierName,

+  BOOLEAN   IgnoreNotFound

+  )

+{

+  STRING_IDENTIFIER *Id;

+  WCHAR             *WName;

+  STATUS            Status;

+  //

+  // See if it's already been defined.

+  //

+  Status  = STATUS_SUCCESS;

+  WName   = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR));

+  UnicodeSPrint (WName, (strlen (StringIdentifierName) + 1) * sizeof (WCHAR), L"%a", StringIdentifierName);

+  Id = StringDBFindStringIdentifierByName (WName);

+  if (Id != NULL) {

+    Id->Flags |= STRING_FLAGS_REFERENCED;

+  } else {

+    if (IgnoreNotFound == 0) {

+      ParserWarning (0, StringIdentifierName, "string identifier not found in database");

+      Status = STATUS_WARNING;

+    }

+  }

+

+  free (WName);

+  return Status;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Dump the contents of a database to an output unicode file.

+

+Arguments:

+

+  DBFileName        - name of the pre-existing database file to read

+  OutputFileName    - name of the file to dump the database contents to

+  Verbose           - for printing of additional info useful for debugging

+

+Returns:

+

+  STATUS

+

+Notes:

+

+  There's some issue with the unicode printing routines. Therefore to 

+  write to the output file properly, open it as binary and use fwrite.

+  Ideally we could open it with just L"w" and use fwprintf().

+

+--*/

+STATUS

+StringDBDumpDatabase (

+  CHAR8               *DBFileName,

+  CHAR8               *OutputFileName,

+  BOOLEAN             Verbose

+  )

+{

+  LANGUAGE_LIST     *Lang;

+  STRING_IDENTIFIER *StringIdentifier;

+  STRING_LIST       *StrList;

+  FILE              *OutFptr;

+  WCHAR             WChar;

+  WCHAR             CrLf[2];

+  WCHAR             Line[200];

+  WCHAR             *Scope;

+  //

+  // This function assumes the database has already been read, and

+  // we're just dumping our internal data structures to a unicode file.

+  //

+  if (Verbose) {

+    fprintf (stdout, "Dumping database file %s\n", DBFileName);

+  }

+

+  OutFptr         = fopen (OutputFileName, "wb");

+  if (OutFptr == NULL) {

+    Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");

+    return STATUS_ERROR;

+  }

+

+  WChar = UNICODE_FILE_START;

+  fwrite (&WChar, sizeof (WCHAR), 1, OutFptr);

+  CrLf[1] = UNICODE_LF;

+  CrLf[0] = UNICODE_CR;

+  //

+  // The default control character is '/'. Make it '#' by writing

+  // "/=#" to the output file.

+  //

+  UnicodeSPrint (Line, sizeof(Line), L"/=#");

+  fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+  fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+  fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+  //

+  // Dump all the string identifiers and their values

+  //

+  StringDBAssignStringIndexes ();

+  for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {

+    //

+    // Write the "#define " string

+    //

+    if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {

+      UnicodeSPrint (

+        Line,

+        sizeof(Line), L"%s %-60.60s 0x%04X",

+        DEFINE_STR,

+        StringIdentifier->StringName,

+        StringIdentifier->Index

+        );

+    } else {

+      UnicodeSPrint (

+        Line,

+        sizeof(Line), L"%s %-60.60s 0x%04X  // NOT REFERENCED",

+        DEFINE_STR,

+        StringIdentifier->StringName,

+        StringIdentifier->Index

+        );

+    }

+

+    fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+    fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+  }

+

+  fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+  //

+  // Now write all the strings for each language.

+  //

+  WChar = UNICODE_DOUBLE_QUOTE;

+  Scope = NULL;

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+    UnicodeSPrint (Line, sizeof(Line), L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName);

+    fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+    fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+    fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+    //

+    // Now the strings (in double-quotes) for this language. Write

+    // #string STR_NAME  #language eng "string"

+    //

+    for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {

+      //

+      // Print the internal flags for debug

+      //

+      UnicodeSPrint (Line, sizeof(Line), L"// flags=0x%02X", (UINT32) StrList->Flags);

+      fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+      fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+      //

+      // Print the scope if changed

+      //

+      if ((Scope == NULL) || (StrCmp (Scope, StrList->Scope) != 0)) {

+        UnicodeSPrint (Line, sizeof(Line), L"#scope %s", StrList->Scope);

+        fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+        fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+        Scope = StrList->Scope;

+      }

+

+      UnicodeSPrint (

+        Line,

+        sizeof(Line), L"#string %-50.50s #language %s \"",

+        StrList->StringName,

+        Lang->LanguageName

+        );

+      fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+      fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr);

+      UnicodeSPrint (Line, sizeof(Line), L"\"");

+      fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);

+      fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);

+    }

+  }

+

+  fclose (OutFptr);

+  return STATUS_SUCCESS;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Given a primary language, a string identifier number, and a list of

+  languages, find a secondary string.

+

+Arguments:

+

+  LanguageName      - primary language, like "spa"

+  StringId          - string index value

+  LanguageList      - linked list of "eng", "spa+cat",...

+

+Returns:

+

+  Pointer to a secondary string if found. NULL otherwise.

+

+Notes:

+ 

+  Given: LanguageName "spa"   and  LanguageList "spa+cat", match the

+  "spa" and extract the "cat" and see if there is a string defined

+  for "cat".StringId.

+

+--*/

+static

+STATUS

+StringDBWriteStringIdentifier (

+  FILE                *DBFptr,

+  UINT16              StringId,

+  UINT16              Flags,

+  WCHAR               *IdentifierName

+  )

+{

+  DB_DATA_ITEM_HEADER Hdr;

+  memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));

+  Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER;

+  if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string to output database file", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write StringId to output database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBReadStringIdentifier (

+  FILE                *DBFptr

+  )

+{

+  WCHAR   *IdentifierName;

+  UINT16  Flags;

+  UINT16  StringId;

+  UINT16  Size;

+

+  if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read StringId from database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read StringId flags from database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  StringDBAddStringIdentifier (IdentifierName, &StringId, Flags);

+  //

+  // printf ("STRID:  0x%04X %S\n", (UINT32)StringId, IdentifierName);

+  //

+  FREE (IdentifierName);

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBWriteString (

+  FILE            *DBFptr,

+  UINT16          Flags,

+  WCHAR           *Language,

+  WCHAR           *StringName,

+  WCHAR           *Scope,

+  WCHAR           *Str

+  )

+{

+  DB_DATA_ITEM_HEADER Hdr;

+  memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));

+  Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION;

+  if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string header to output database file", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string flags to output database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+  //

+  // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope);

+  //

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBReadString (

+  FILE            *DBFptr

+  )

+{

+  UINT16  Flags;

+  UINT16  Size;

+  WCHAR   *Language;

+  WCHAR   *StringName;

+  WCHAR   *Scope;

+  WCHAR   *Str;

+

+  if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read string flags from database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+  //

+  // If the first or second string (language name and printable language name),

+  // then skip them. They're added via language definitions data items in

+  // the database.

+  //

+  if (StringName[0] != L'$') {

+    StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags);

+  }

+  //

+  // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope);

+  //

+  FREE (Language);

+  FREE (StringName);

+  if (Str != NULL) {

+    FREE (Str);

+  }

+

+  if (Scope != NULL) {

+    FREE (Scope);

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBWriteLanguageDefinition (

+  FILE            *DBFptr,

+  WCHAR           *LanguageName,

+  WCHAR           *PrintableLanguageName

+  )

+{

+  DB_DATA_ITEM_HEADER Hdr;

+  memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));

+  Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION;

+  if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string to output database file", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBReadLanguageDefinition (

+  FILE            *DBFptr

+  )

+{

+  WCHAR   *LanguageName;

+  WCHAR   *PrintableLanguageName;

+  UINT16  Size;

+  STATUS  Status;

+

+  if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+

+  if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) {

+    return STATUS_ERROR;

+  }

+  //

+  // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName);

+  //

+  Status = StringDBAddLanguage (LanguageName, PrintableLanguageName);

+  FREE (LanguageName);

+  FREE (PrintableLanguageName);

+  return Status;

+}

+//

+// All unicode strings in the database consist of a UINT16 length

+// field, followed by the string itself. This routine reads one

+// of those and returns the info.

+//

+static

+STATUS

+StringDBReadGenericString (

+  FILE      *DBFptr,

+  UINT16    *Size,

+  WCHAR     **Str

+  )

+{

+  UINT16  LSize;

+  UINT16  Flags;

+  WCHAR   *LStr;

+

+  if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read a string length field from the database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL);

+    return STATUS_ERROR;

+  }

+

+  LStr = MALLOC (LSize);

+  if (LStr == NULL) {

+    Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) {

+    Error (NULL, 0, 0, "failed to read string from database", NULL);

+    Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr));

+    free (LStr);

+    return STATUS_ERROR;

+  }

+  //

+  // printf ("DBR: %S\n", LStr);

+  //

+  // If the flags field indicated we were asked to write a NULL string, then

+  // return them a NULL pointer.

+  //

+  if (Flags & STRING_FLAGS_UNDEFINED) {

+    *Size = 0;

+    *Str  = NULL;

+  } else {

+    *Size = LSize;

+    *Str  = LStr;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STATUS

+StringDBWriteGenericString (

+  FILE      *DBFptr,

+  WCHAR     *Str

+  )

+{

+  UINT16  Size;

+  UINT16  Flags;

+  WCHAR   ZeroString[1];

+  //

+  // Strings in the database consist of a size UINT16 followed

+  // by the string itself.

+  //

+  if (Str == NULL) {

+    ZeroString[0] = 0;

+    Str           = ZeroString;

+    Size          = sizeof (ZeroString);

+    Flags         = STRING_FLAGS_UNDEFINED;

+  } else {

+    Flags = 0;

+    Size  = (UINT16) ((StrLen (Str) + 1) * sizeof (WCHAR));

+  }

+

+  if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string size to database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {

+    Error (NULL, 0, 0, "failed to write string flags to database", NULL);

+    return STATUS_ERROR;

+  }

+

+  if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) {

+    Error (NULL, 0, 0, "failed to write string to database", NULL);

+    return STATUS_ERROR;

+  }

+

+  return STATUS_SUCCESS;

+}

+

+static

+STRING_LIST *

+StringDBFindString (

+  WCHAR                       *LanguageName,

+  WCHAR                       *StringName,

+  WCHAR                       *Scope,

+  WCHAR_STRING_LIST           *LanguagesOfInterest,

+  WCHAR_MATCHING_STRING_LIST  *IndirectionList

+  )

+{

+  LANGUAGE_LIST               *Lang;

+  STRING_LIST                 *CurrString;

+  WCHAR_MATCHING_STRING_LIST  *IndListPtr;

+  WCHAR                       TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1];

+  WCHAR                       *WCharPtr;

+

+  //

+  // If we were given an indirection list, then see if one was specified for this

+  // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope",

+  // then if this string name matches one in the list, then do a lookup with the

+  // specified scope and return that value.

+  //

+  if (IndirectionList != NULL) {

+    for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) {

+      if (StrCmp (StringName, IndListPtr->Str1) == 0) {

+        CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL);

+        if (CurrString != NULL) {

+          return CurrString;

+        }

+      }

+    }

+  }

+  //

+  // First look for exact match language.stringname

+  //

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    if (StrCmp (LanguageName, Lang->LanguageName) == 0) {

+      //

+      // Found language match. Try to find string name match

+      //

+      for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) {

+        if (StrCmp (StringName, CurrString->StringName) == 0) {

+          //

+          // Found a string name match. See if we're supposed to find

+          // a scope match.

+          //

+          if (Scope != NULL) {

+            if (StrCmp (CurrString->Scope, Scope) == 0) {

+              return CurrString;

+            }

+          } else {

+            return CurrString;

+          }

+        }

+      }

+    }

+  }

+  //

+  // If we got here, then we didn't find a match. Look for secondary string

+  // matches. That is to say, if we're processing "spa", and they requested

+  // "spa+cat", then recursively call with "cat"

+  //

+  while (LanguagesOfInterest != NULL) {

+    //

+    // If this is the language we're looking for, then process the

+    // languages of interest list for it.

+    //

+    if (StrnCmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) {

+      WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN;

+      while (*WCharPtr) {

+        //

+        // Double-check the length, though it should have been checked on the

+        // command line.

+        //

+        if (StrLen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) {

+          Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str);

+          return NULL;

+        }

+

+        StrnCpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN);

+        TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN]  = 0;

+        CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList);

+        if (CurrString != NULL) {

+          return CurrString;

+        }

+

+        WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN;

+      }

+    }

+

+    LanguagesOfInterest = LanguagesOfInterest->Next;

+  }

+

+  return NULL;

+}

+

+STATUS

+StringDBSetScope (

+  WCHAR   *Scope

+  )

+{

+  //

+  // Free up existing scope memory.

+  //

+  if (mDBData.CurrentScope != NULL) {

+    FREE (mDBData.CurrentScope);

+  }

+

+  mDBData.CurrentScope = DuplicateString (Scope);

+  return STATUS_SUCCESS;

+}

+//

+// We typically don't assign index values to string identifiers

+// until we're ready to write out files. To reduce the size of

+// the output file, re-order the string identifiers to move any

+// unreferenced ones to the end. Then we'll walk the list

+// again to assign string indexes, keeping track of the last

+// one referenced.

+//

+static

+void

+StringDBAssignStringIndexes (

+  VOID

+  )

+{

+  STRING_IDENTIFIER *StrId;

+  STRING_IDENTIFIER *FirstUsed;

+  STRING_IDENTIFIER *LastUsed;

+  STRING_IDENTIFIER *FirstUnused;

+  STRING_IDENTIFIER *LastUnused;

+  UINT32            Index;

+  UINT32            MaxReferenced;

+

+  //

+  // Create two lists -- used and unused. Then put them together with

+  // the unused ones on the end.

+  //

+  FirstUsed   = NULL;

+  LastUsed    = NULL;

+  FirstUnused = NULL;

+  LastUnused  = NULL;

+  StrId       = mDBData.StringIdentifier;

+  while (StrId != NULL) {

+    if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) {

+      //

+      // Put it on the unused list

+      //

+      if (FirstUnused == NULL) {

+        FirstUnused = StrId;

+      } else {

+        LastUnused->Next = StrId;

+      }

+

+      LastUnused        = StrId;

+      StrId             = StrId->Next;

+      LastUnused->Next  = NULL;

+    } else {

+      //

+      // Put it on the used list

+      //

+      if (FirstUsed == NULL) {

+        FirstUsed = StrId;

+      } else {

+        LastUsed->Next = StrId;

+      }

+

+      LastUsed        = StrId;

+      StrId           = StrId->Next;

+      LastUsed->Next  = NULL;

+    }

+  }

+  //

+  // Join the lists

+  //

+  if (FirstUsed != NULL) {

+    mDBData.StringIdentifier  = FirstUsed;

+    LastUsed->Next            = FirstUnused;

+  } else {

+    mDBData.StringIdentifier = FirstUnused;

+  }

+

+  MaxReferenced = 0;

+  Index         = 0;

+  for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) {

+    StrId->Index = Index;

+    Index++;

+    if (StrId->Flags & STRING_FLAGS_REFERENCED) {

+      mDBData.NumStringIdentifiersReferenced = Index;

+    }

+  }

+

+  mDBData.NumStringIdentifiers = Index;

+}

+

+static

+WCHAR *

+DuplicateString (

+  WCHAR   *Str

+  )

+{

+  WCHAR *NewStr;

+  if (Str == NULL) {

+    return NULL;

+  }

+

+  NewStr = MALLOC ((StrLen (Str) + 1) * sizeof (WCHAR));

+  if (NewStr == NULL) {

+    Error (NULL, 0, 0, "memory allocation failure", NULL);

+    return NULL;

+  }

+

+  StrCpy (NewStr, Str);

+  return NewStr;

+}

+

+static

+WCHAR *

+AsciiToWchar (

+  CHAR8 *Str

+  )

+{

+  UINT32  Len;

+  WCHAR   *NewStr;

+  WCHAR   *Ptr;

+

+  Len     = strlen (Str) + 1;

+  NewStr  = (WCHAR *) malloc (Len * sizeof (WCHAR));

+  for (Ptr = NewStr; *Str != 0; Str++, Ptr++) {

+    *Ptr = (UINT16) (UINT8) *Str;

+  }

+

+  *Ptr = 0;

+  return NewStr;

+}

+

+/*****************************************************************************/

+

+/*++

+

+Routine Description:

+

+  Create an HII export string pack for the strings in our database.

+

+Arguments:

+

+  FileName        - name of the output file to write 

+

+Returns:

+

+  STATUS

+

+

+--*/

+STATUS

+StringDBCreateHiiExportPack (

+  CHAR8                       *FileName

+  )

+{

+  FILE                        *Fptr;

+  LANGUAGE_LIST               *Lang;

+  STRING_LIST                 *CurrString;

+  STRING_LIST                 EmptyString;

+  UINT32                      Offset;

+  UINT32                      StringIndex;

+  UINT32                      TempIndex;

+  EFI_HII_STRING_PACK         StringPack;

+  UINT32                      Len;

+  WCHAR                       ZeroString[1];

+  WCHAR                       *TempStringPtr;

+  WCHAR                       *LangName;

+  STRING_IDENTIFIER           *StringIdentifier;

+

+  if ((Fptr = fopen (FileName, "wb")) == NULL) {

+    Error (NULL, 0, 0, FileName, "failed to open output HII export file");

+    return STATUS_ERROR;

+  }

+  //

+  // Assign index values to the string identifiers

+  //

+  StringDBAssignStringIndexes ();

+  //

+  // If a given string is not defined, then we'll use this one.

+  //

+  memset (&EmptyString, 0, sizeof (EmptyString));

+  EmptyString.Size  = sizeof (ZeroString);

+  EmptyString.Str   = ZeroString;

+  //

+  // Process each language, then each string for each langage

+  //

+  ZeroString[0] = 0;

+  for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {

+    //

+    // Process each string for this language. We have to make 3 passes on the strings:

+    //   Pass1: computes sizes and fill in the string pack header

+    //   Pass2: write the array of offsets

+    //   Pass3: write the strings

+    //

+    //

+    // PASS 1: Fill in and print the HII string pack header

+    //

+    // Compute the size for this language package and write

+    // the header out. Each string package contains:

+    //   Header

+    //   Offset[]  -- an array of offsets to strings, of type RELOFST each

+    //   String[]  -- the actual strings themselves

+    //

+    memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));

+    StringPack.Header.Type        = EFI_HII_STRING;

+    StringPack.NumStringPointers  = (UINT16) mDBData.NumStringIdentifiersReferenced;

+    LangName                      = Lang->LanguageName;

+    //

+    // First string is the language name. If we're printing all languages, then

+    // it's just the "spa". If we were given a list of languages to print, then it's

+    // the "spacat" string. Compute its offset and fill in

+    // the info in the header. Since we know the language name string's length,

+    // and the printable language name follows it, use that info to fill in the

+    // entry for the printable language name as well.

+    //

+    StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)));

+    StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR));

+    //

+    // Add up the size of all strings so we can fill in our header.

+    //

+    Len = 0;

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        Len += (StrLen (LangName) + 1) * sizeof (WCHAR);

+      } else {

+        //

+        // Find a string with this language.stringname

+        //

+        StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+        if (StringIdentifier == NULL) {

+          Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+          return STATUS_ERROR;

+        }

+        //

+        // Find a matching string if this string identifier was referenced

+        //

+        EmptyString.Flags = STRING_FLAGS_UNDEFINED;

+        CurrString        = NULL;

+        if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {

+          CurrString = StringDBFindString (

+                        Lang->LanguageName,

+                        StringIdentifier->StringName,

+                        NULL,

+                        NULL, // LanguagesOfInterest,

+                        NULL

+                        );

+          //

+          // IndirectionList);

+          //

+          if (NULL == CurrString) {

+            //

+            // If string for Lang->LanguageName is not found, try to get an English version

+            //

+            CurrString = StringDBFindString (

+                          L"eng",

+                          StringIdentifier->StringName,

+                          NULL,

+                          NULL, // LanguagesOfInterest,

+                          NULL

+                          );

+            //

+            // IndirectionList);

+            //

+          }

+        }

+

+        if (CurrString == NULL) {

+          CurrString = &EmptyString;

+          EmptyString.Flags |= StringIdentifier->Flags;

+        }

+

+        Len += CurrString->Size;

+      }

+    }

+    StringPack.Header.Length =    sizeof (EFI_HII_STRING_PACK) 

+                                + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) 

+                                + Len;

+    //

+    // Write out the string pack header

+    //

+    fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr);

+    //

+    // PASS2 : write the offsets

+    //

+    // Traverse the list of strings again and write the array of offsets. The

+    // offset to the first string is the size of the string pack header

+    // plus the size of the offsets array. The other strings follow it.

+    //

+    StringIndex = 0;

+    Offset      = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      //

+      // Write the offset

+      //

+      fwrite (&Offset, sizeof (STRING_OFFSET), 1, Fptr);

+      //

+      // Find the string name

+      //

+      StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+      if (StringIdentifier == NULL) {

+        Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+        return STATUS_ERROR;

+      }

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        Offset += (StrLen (LangName) + 1) * sizeof (WCHAR);

+        CurrString = StringDBFindString (

+                      Lang->LanguageName,

+                      StringIdentifier->StringName,

+                      NULL, // scope

+                      NULL,

+                      NULL

+                      );

+      } else {

+        //

+        // Find a matching string

+        //

+        CurrString = StringDBFindString (

+                      Lang->LanguageName,

+                      StringIdentifier->StringName,

+                      NULL, // scope

+                      NULL, // LanguagesOfInterest,

+                      NULL

+                      );

+        //

+        // IndirectionList);

+        //

+        if (NULL == CurrString) {

+          CurrString = StringDBFindString (

+                        L"eng",

+                        StringIdentifier->StringName,

+                        NULL, // scope

+                        NULL, // LanguagesOfInterest,

+                        NULL

+                        );

+          //

+          // IndirectionList);

+          //

+        }

+

+        EmptyString.LanguageName = Lang->LanguageName;

+        if (CurrString == NULL) {

+          CurrString        = &EmptyString;

+          EmptyString.Flags = STRING_FLAGS_UNDEFINED;

+        } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {

+          CurrString        = &EmptyString;

+          EmptyString.Flags = 0;

+        }

+

+        Offset += CurrString->Size;

+      }

+    }

+

+    //

+    // PASS 3: write the strings themselves.

+    //

+    Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);

+    for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {

+      StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);

+      if (StringIdentifier == NULL) {

+        Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);

+        return STATUS_ERROR;

+      }

+      //

+      // For the first string (language name), we print out the "spacat" if they

+      // requested it. We set LangName to point to the proper language name string above.

+      //

+      if (StringIndex == STRING_ID_LANGUAGE_NAME) {

+        TempStringPtr = LangName;

+      } else {

+        //

+        // Find a matching string if this string identifier was referenced

+        //

+        CurrString = NULL;

+        if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {

+          CurrString = StringDBFindString (

+                        Lang->LanguageName,

+                        StringIdentifier->StringName,

+                        NULL, // scope

+                        NULL, // LanguagesOfInterest,

+                        NULL

+                        );

+          //

+          // IndirectionList);

+          //

+          if (NULL == CurrString) {

+            CurrString = StringDBFindString (

+                          L"eng",

+                          StringIdentifier->StringName,

+                          NULL, // scope

+                          NULL, // LanguagesOfInterest,

+                          NULL

+                          );

+            //

+            // IndirectionList);

+            //

+          }

+        }

+

+        if (CurrString == NULL) {

+          CurrString = &EmptyString;

+        }

+

+        TempStringPtr = CurrString->Str;

+      }

+

+      for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) {

+        fwrite (&TempStringPtr[TempIndex], sizeof (CHAR16), 1, Fptr);

+        Offset += 2;

+      }

+      //

+      // Print NULL WCHAR at the end of this string.

+      //

+      TempIndex = 0;

+      fwrite (&TempIndex, sizeof (CHAR16), 1, Fptr);

+      Offset += 2;

+    }

+    //

+    // Sanity check the offset. Make sure our running offset is what we put in the

+    // string pack header.

+    //

+    if (StringPack.Header.Length != Offset) {

+      Error (

+        __FILE__,

+        __LINE__,

+        0,

+        "application error",

+        "stringpack size 0x%X does not match final size 0x%X",

+        StringPack.Header.Length,

+        Offset

+        );

+    }

+  }

+  //

+  // Print terminator string pack, closing brace and close the file.

+  // The size of 0 triggers to the consumer that this is the end.

+  //

+  memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));

+  StringPack.Header.Type = EFI_HII_STRING;

+  fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr);

+  fclose (Fptr);

+  return STATUS_SUCCESS;

+}

diff --git a/Source/StrGather/StringDB.h b/Source/StrGather/StringDB.h
new file mode 100644
index 0000000..c525731
--- /dev/null
+++ b/Source/StrGather/StringDB.h
@@ -0,0 +1,136 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  StringDB.h

+

+Abstract:

+

+  Common defines and prototypes for string database management

+  

+--*/

+

+#ifndef _STRING_DB_H_

+#define _STRING_DB_H_

+

+#define LANGUAGE_NAME_STRING_NAME           L"$LANGUAGE_NAME"

+#define PRINTABLE_LANGUAGE_NAME_STRING_NAME L"$PRINTABLE_LANGUAGE_NAME"

+

+void

+StringDBConstructor (

+  void

+  )

+;

+void

+StringDBDestructor (

+  void

+  )

+;

+

+STATUS

+StringDBAddString (

+  WCHAR   *LanguageName,

+  WCHAR   *StringIdentifier,

+  WCHAR   *Scope,

+  WCHAR   *String,

+  BOOLEAN Format,

+  UINT16  Flags

+  )

+;

+

+STATUS

+StringDBSetScope (

+  WCHAR   *Scope

+  )

+;

+

+#define STRING_FLAGS_REFERENCED           0x0001  // if referenced somewhere

+#define STRING_FLAGS_UNDEFINED            0x0002  // if we added it for padding purposes

+#define STRING_FLAGS_INDEX_ASSIGNED       0x0004  // so don't change the index value

+#define STRING_ID_INVALID                 0xFFFF

+#define STRING_ID_LANGUAGE_NAME           0x0000

+#define STRING_ID_PRINTABLE_LANGUAGE_NAME 0x0001

+

+STATUS

+StringDBAddStringIdentifier (

+  WCHAR     *StringIdentifier,

+  UINT16    *NewId,

+  UINT16    Flags

+  )

+;

+

+STATUS

+StringDBReadDatabase (

+  CHAR8   *DBFileName,

+  BOOLEAN IgnoreIfNotExist,

+  BOOLEAN Verbose

+  )

+;

+

+STATUS

+StringDBWriteDatabase (

+  CHAR8   *DBFileName,

+  BOOLEAN Verbose

+  )

+;

+

+STATUS

+StringDBDumpDatabase (

+  CHAR8               *DBFileName,

+  CHAR8               *OutputFileName,

+  BOOLEAN             Verbose

+  )

+;

+

+STATUS

+StringDBAddLanguage (

+  WCHAR *LanguageName,

+  WCHAR *PrintableLanguageName

+  )

+;

+

+STATUS

+StringDBDumpCStrings (

+  CHAR8                       *FileName,

+  CHAR8                       *BaseName,

+  WCHAR_STRING_LIST           *LanguagesOfInterest,

+  WCHAR_MATCHING_STRING_LIST  *IndirectionList

+  )

+;

+

+STATUS

+StringDBDumpStringDefines (

+  CHAR8               *FileName,

+  CHAR8               *BaseName

+  )

+;

+

+STATUS

+StringDBSetCurrentLanguage (

+  WCHAR *LanguageName

+  )

+;

+

+STATUS

+StringDBSetStringReferenced (

+  CHAR8     *StringIdentifierName,

+  BOOLEAN   IgnoreNotFound

+  )

+;

+

+void

+StringDBFormatString (

+  WCHAR   *String

+  )

+;

+

+#endif // #ifndef _STRING_DB_H_

diff --git a/Source/StrGather/build.xml b/Source/StrGather/build.xml
new file mode 100644
index 0000000..901b4a8
--- /dev/null
+++ b/Source/StrGather/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK StrGather Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="StrGather"/>

+  <property name="FileSet" value="*.c *.h"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <compilerarg value="-fshort-wchar" if="gcc"/>

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools String"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/String/PrintLib.c b/Source/String/PrintLib.c
new file mode 100644
index 0000000..eef3f4d
--- /dev/null
+++ b/Source/String/PrintLib.c
@@ -0,0 +1,674 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  PrintLib.c

+

+Abstract:

+

+  Print Library.

+

+--*/

+

+#include <Common/UefiBaseTypes.h>

+#include <Library/PrintLib.h>

+

+#include "CommonLib.h"

+#include "PrintLibInternal.h"

+

+typedef struct {

+  RETURN_STATUS  Status;

+  CHAR8          *String;

+} STATUS_LOOKUP_TABLE_ENTRY;

+

+static CONST STATUS_LOOKUP_TABLE_ENTRY  StatusString[] = {

+  { RETURN_SUCCESS,               "Success" },

+  { RETURN_LOAD_ERROR,            "Load Error" },

+  { RETURN_INVALID_PARAMETER,     "Invalid Parameter" },

+  { RETURN_UNSUPPORTED,           "Unsupported" },

+  { RETURN_BAD_BUFFER_SIZE,       "Bad Buffer Size" },

+  { RETURN_BUFFER_TOO_SMALL,      "Buffer Too Small" },

+  { RETURN_NOT_READY,             "Not Ready" },

+  { RETURN_DEVICE_ERROR,          "Device Error" },

+  { RETURN_WRITE_PROTECTED,       "Write Protected" },

+  { RETURN_OUT_OF_RESOURCES,      "Out of Resources" },

+  { RETURN_VOLUME_CORRUPTED,      "Volume Corrupt" },

+  { RETURN_VOLUME_FULL,           "Volume Full" },

+  { RETURN_NO_MEDIA,              "No Media" },

+  { RETURN_MEDIA_CHANGED,         "Media changed" },

+  { RETURN_NOT_FOUND,             "Not Found" },

+  { RETURN_ACCESS_DENIED,         "Access Denied" },

+  { RETURN_NO_RESPONSE,           "No Response" },

+  { RETURN_NO_MAPPING,            "No mapping" },

+  { RETURN_TIMEOUT,               "Time out" },

+  { RETURN_NOT_STARTED,           "Not started" },

+  { RETURN_ALREADY_STARTED,       "Already started" },

+  { RETURN_ABORTED,               "Aborted" },

+  { RETURN_ICMP_ERROR,            "ICMP Error" },

+  { RETURN_TFTP_ERROR,            "TFTP Error" },

+  { RETURN_PROTOCOL_ERROR,        "Protocol Error" },

+  { RETURN_WARN_UNKNOWN_GLYPH,    "Warning Unknown Glyph" },

+  { RETURN_WARN_DELETE_FAILURE,   "Warning Delete Failure" },

+  { RETURN_WARN_WRITE_FAILURE,    "Warning Write Failure" },

+  { RETURN_WARN_BUFFER_TOO_SMALL, "Warning Buffer Too Small" },

+  { 0,                              NULL                     }

+};

+

+

+/**

+  VSPrint function to process format and place the results in Buffer. Since a

+  VA_LIST is used this rountine allows the nesting of Vararg routines. Thus

+  this is the main print working routine

+

+  @param  StartOfBuffer Unicode buffer to print the results of the parsing of Format into.

+

+  @param  BufferSize Maximum number of characters to put into buffer. Zero means

+  no limit.

+

+  @param  Flags Intial flags value.  Can only have FORMAT_UNICODE and OUTPUT_UNICODE set

+

+  @param  FormatString Unicode format string see file header for more details.

+

+  @param  Marker Vararg list consumed by processing Format.

+

+  @return Number of characters printed.

+

+**/

+UINTN

+BasePrintLibVSPrint (

+  OUT CHAR8        *Buffer,

+  IN  UINTN        BufferSize,

+  IN  UINTN        Flags,

+  IN  CONST CHAR8  *Format,

+  IN  VA_LIST      Marker

+  )

+{

+  CHAR8           *OriginalBuffer;

+  CHAR8           ValueBuffer[MAXIMUM_VALUE_CHARACTERS];

+  UINTN           BytesPerOutputCharacter;

+  UINTN           BytesPerFormatCharacter;

+  UINTN           FormatMask;

+  UINTN           FormatCharacter;

+  UINTN           Width;

+  UINTN           Precision;

+  INT64           Value;

+  CHAR8           *ArgumentString;

+  UINTN           Character;

+  GUID            *TmpGuid;

+  TIME            *TmpTime;

+  UINTN           Count;

+  UINTN           ArgumentMask;

+  INTN            BytesPerArgumentCharacter;

+  UINTN           ArgumentCharacter;

+  BOOLEAN         Done;

+  UINTN           Index;

+  CHAR8           Prefix;

+  BOOLEAN         ZeroPad;

+  BOOLEAN         Comma;

+  UINTN           Digits;

+  UINTN           Radix;

+  RETURN_STATUS   Status;

+

+  OriginalBuffer = Buffer;

+

+  if ((Flags & OUTPUT_UNICODE) != 0) {

+    BytesPerOutputCharacter = 2;

+  } else {

+    BytesPerOutputCharacter = 1;

+  }

+  if ((Flags & FORMAT_UNICODE) != 0) {

+    BytesPerFormatCharacter = 2;

+    FormatMask = 0xffff;

+  } else {

+    BytesPerFormatCharacter = 1;

+    FormatMask = 0xff;

+  }

+

+  //

+  // Reserve space for the Null terminator.

+  // If BufferSize is 0, this will set BufferSize to the max unsigned value

+  //

+  BufferSize--;

+

+  //

+  // Get the first character from the format string

+  //

+  FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;

+

+  //

+  // Loop until the end of the format string is reached or the output buffer is full

+  //

+  while (FormatCharacter != 0 && BufferSize > 0) {

+    //

+    // Clear all the flag bits except those that may have been passed in

+    //

+    Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE);

+

+    //

+    // Set the default width to zero, and the default precision to 1

+    //

+    Width     = 0;

+    Precision = 1;

+    Prefix    = 0;

+    Comma     = FALSE;

+    ZeroPad   = FALSE;

+    Count     = 0;

+    Digits    = 0;

+

+    switch (FormatCharacter) {

+    case '%':

+      //

+      // Parse Flags and Width

+      //

+      for (Done = FALSE; !Done; ) {

+        Format += BytesPerFormatCharacter;

+        FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;

+        switch (FormatCharacter) {

+        case '.':

+          Flags |= PRECISION;

+          break;

+        case '-':

+          Flags |= LEFT_JUSTIFY;

+          break;

+        case '+':

+          Flags |= PREFIX_SIGN;

+          break;

+        case ' ':

+          Flags |= PREFIX_BLANK;

+          break;

+        case ',':

+          Flags |= COMMA_TYPE;

+          break;

+        case 'L':

+        case 'l':

+          Flags |= LONG_TYPE;

+          break;

+        case '*':

+          if ((Flags & PRECISION) == 0) {

+            Flags |= PAD_TO_WIDTH;

+            Width = VA_ARG (Marker, UINTN);

+          } else {

+            Precision = VA_ARG (Marker, UINTN);

+          }

+          break;

+        case '0':

+          if ((Flags & PRECISION) == 0) {

+            Flags |= PREFIX_ZERO;

+          }

+        case '1':

+        case '2':

+        case '3':

+        case '4':

+        case '5':

+        case '6':

+        case '7':

+        case '8':

+        case '9':

+          for (Count = 0; ((FormatCharacter >= '0') &&  (FormatCharacter <= '9')); ){

+            Count = (Count * 10) + FormatCharacter - '0';

+            Format += BytesPerFormatCharacter;

+            FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;

+          }

+          Format -= BytesPerFormatCharacter;

+          if ((Flags & PRECISION) == 0) {

+            Flags |= PAD_TO_WIDTH;

+            Width = Count;

+          } else {

+            Precision = Count;

+          }

+          break;

+        default:

+          Done = TRUE;

+          break;

+        }

+      }

+

+      //

+      // Limit the maximum field width to the remaining characters in the output buffer

+      //

+      if (Width > BufferSize) {

+        Width = BufferSize;

+      }

+

+      //

+      // Handle each argument type

+      //

+      switch (FormatCharacter) {

+      case 'X':

+        Flags |= PREFIX_ZERO;

+        //

+        // break skiped on purpose

+        //

+      case 'x':

+        Flags |= RADIX_HEX;

+        //

+        // break skiped on purpose

+        //

+      case 'd':

+        if ((Flags & LONG_TYPE) == 0) {

+          Value = (VA_ARG (Marker, INTN));

+        } else {

+          Value = VA_ARG (Marker, INT64);

+        }

+        if ((Flags & PREFIX_BLANK) != 0) {

+          Prefix = ' ';

+        }

+        if ((Flags & PREFIX_SIGN) != 0) {

+          Prefix = '+';

+        }

+        if ((Flags & COMMA_TYPE) != 0) {

+          Comma = TRUE;

+        }

+        if ((Flags & RADIX_HEX) == 0) {

+          Radix = 10;

+          if (Comma) {

+            Flags &= (~PREFIX_ZERO);

+            Precision = 1;

+          }

+          if (Value < 0) {

+            Flags |= PREFIX_SIGN;

+            Prefix = '-';

+            Value = -Value;

+          }

+        } else {

+          Radix = 16;

+          Comma = FALSE;

+          if ((Flags & LONG_TYPE) == 0 && Value < 0) {

+            Value = (UINTN)Value;

+          }

+        }

+        //

+        // Convert Value to a reversed string

+        //

+        Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);

+        if (Value == 0 && Precision == 0) {

+          Count = 0;

+        }

+        ArgumentString = (CHAR8 *)ValueBuffer + Count;

+        Digits = 3 - (Count % 3);

+        if (Comma && Count != 0) {

+          Count += ((Count - 1) / 3);

+        }

+        if (Prefix != 0) {

+          Count++;

+        }

+        Flags |= ARGUMENT_REVERSED;

+        ZeroPad = TRUE;

+        if ((Flags & PREFIX_ZERO) != 0) {

+          if ((Flags & PAD_TO_WIDTH) != 0) {

+            if ((Flags & PRECISION) == 0) {

+              Precision = Width;

+            }

+          }

+        }

+        break;

+

+      case 's':

+      case 'S':

+        Flags |= ARGUMENT_UNICODE;

+        //

+        // break skipped on purpose

+        //

+      case 'a':

+        ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);

+        if (ArgumentString == NULL) {

+          Flags &= (~ARGUMENT_UNICODE);

+          ArgumentString = "<null string>";

+        }

+        break;

+

+      case 'c':

+        Character = VA_ARG (Marker, UINTN) & 0xffff;

+        ArgumentString = (CHAR8 *)&Character;

+        Flags |= ARGUMENT_UNICODE;

+        break;

+

+      case 'g':

+        TmpGuid = VA_ARG (Marker, GUID *);

+        if (TmpGuid == NULL) {

+          ArgumentString = "<null guid>";

+        } else {

+          BasePrintLibSPrint (

+            ValueBuffer,

+            0,

+            0,

+            "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",

+            TmpGuid->Data1,

+            TmpGuid->Data2,

+            TmpGuid->Data3,

+            TmpGuid->Data4[0],

+            TmpGuid->Data4[1],

+            TmpGuid->Data4[2],

+            TmpGuid->Data4[3],

+            TmpGuid->Data4[4],

+            TmpGuid->Data4[5],

+            TmpGuid->Data4[6],

+            TmpGuid->Data4[7]

+            );

+          ArgumentString = ValueBuffer;

+        }

+        break;

+

+      case 't':

+        TmpTime = VA_ARG (Marker, TIME *);

+        if (TmpTime == NULL) {

+          ArgumentString = "<null time>";

+        } else {

+          BasePrintLibSPrint (

+            ValueBuffer,

+            0,

+            0,

+            "%02d/%02d/%04d  %02d:%02d",

+            TmpTime->Month,

+            TmpTime->Day,

+            TmpTime->Year,

+            TmpTime->Hour,

+            TmpTime->Minute

+            );

+          ArgumentString = ValueBuffer;

+        }

+        break;

+

+      case 'r':

+        Status = VA_ARG (Marker, RETURN_STATUS);

+        ArgumentString = ValueBuffer;

+        for (Index = 0; StatusString[Index].String != NULL; Index++) {

+          if (Status == StatusString[Index].Status) {

+            ArgumentString = StatusString[Index].String;

+          }

+        }

+        if (ArgumentString == ValueBuffer) {

+          BasePrintLibSPrint ((CHAR8 *) ValueBuffer, 0, 0, "%08X", Status);

+        }

+        break;

+

+      case '%':

+      default:

+        //

+        // if the type is '%' or unknown, then print it to the screen

+        //

+        ArgumentString = (CHAR8 *)&FormatCharacter;

+        Flags |= ARGUMENT_UNICODE;

+        break;

+      }

+      break;

+    case '\n':

+      ArgumentString = "\n";

+	  

+      break;

+    default:

+      ArgumentString = (CHAR8 *)&FormatCharacter;

+      Flags |= ARGUMENT_UNICODE;

+      break;

+    }

+

+    //

+    // Retrieve the ArgumentString attriubutes

+    //

+    if ((Flags & ARGUMENT_UNICODE) != 0) {

+      ArgumentMask = 0xffff;

+      BytesPerArgumentCharacter = 2;

+    } else {

+      ArgumentMask = 0xff;

+      BytesPerArgumentCharacter = 1;

+    }

+    if ((Flags & ARGUMENT_REVERSED) != 0) {

+      BytesPerArgumentCharacter = -BytesPerArgumentCharacter;

+    } else {

+      //

+      // Compute the number of characters in ArgumentString and store it in Count

+      // ArgumentString is either null-terminated, or it contains Precision characters

+      //

+      for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {

+        ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;

+        if (ArgumentCharacter == 0) {

+          break;

+        }

+      }

+    }

+

+    //

+    // Limit the length of the string to append to the remaining characters in the output buffer

+    //

+    if (Count > BufferSize) {

+      Count = BufferSize;

+    }

+    if (Precision < Count) {

+      Precision = Count;

+    }

+

+    //

+    // Pad before the string

+    //

+    if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {

+      Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);

+    }

+

+    if (ZeroPad) {

+      if (Prefix != 0) {

+        Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);

+      }

+      Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, '0', BytesPerOutputCharacter);

+    } else {

+      Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, ' ', BytesPerOutputCharacter);

+      if (Prefix != 0) {

+        Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);

+      }

+    }

+

+    //

+    // Output the Prefix character if it is present

+    //

+    Index = 0;

+    if (Prefix) {

+      Index++;

+    }

+

+    //

+    // Copy the string into the output buffer performing the required type conversions

+    //

+    while (Index < Count) {

+      ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;

+

+      Buffer = BasePrintLibFillBuffer (Buffer, 1, ArgumentCharacter, BytesPerOutputCharacter);

+      ArgumentString    += BytesPerArgumentCharacter;

+      Index++;

+      if (Comma) {

+        Digits++;

+        if (Digits == 3) {

+          Digits = 0;

+          Index++;

+          if (Index < Count) {

+            Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', BytesPerOutputCharacter);

+          }

+        }

+      }

+    }

+

+    //

+    // Pad after the string

+    //

+    if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {

+      Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);

+    }

+

+    //

+    // Reduce the number of characters

+    //

+    BufferSize -= Count;

+

+    //

+    // Get the next character from the format string

+    //

+    Format += BytesPerFormatCharacter;

+

+    //

+    // Get the next character from the format string

+    //

+    FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;

+  }

+

+  //

+  // Null terminate the Unicode or ASCII string

+  //

+  Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, BytesPerOutputCharacter);

+

+  return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);

+}

+

+UINTN

+BasePrintLibSPrint (

+  OUT CHAR8        *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  UINTN        Flags,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  )

+{

+  VA_LIST  Marker;

+

+  VA_START (Marker, FormatString);

+  return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+UnicodeVSPrint (

+  OUT CHAR16        *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  IN  VA_LIST       Marker

+  )

+{

+  return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+UnicodeSPrint (

+  OUT CHAR16        *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  ...

+  )

+{

+  VA_LIST Marker;

+

+  VA_START (Marker, FormatString);

+  return UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+UnicodeVSPrintAsciiFormat (

+  OUT CHAR16       *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  IN  VA_LIST      Marker

+  )

+{

+  return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE,FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+UnicodeSPrintAsciiFormat (

+  OUT CHAR16       *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  )

+{

+  VA_LIST Marker;

+

+  VA_START (Marker, FormatString);

+  return UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize >> 1, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+AsciiVSPrint (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR8   *FormatString,

+  IN  VA_LIST       Marker

+  )

+{

+  return BasePrintLibVSPrint (StartOfBuffer, BufferSize, 0, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+AsciiSPrint (

+  OUT CHAR8        *StartOfBuffer,

+  IN  UINTN        BufferSize,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  )

+{

+  VA_LIST Marker;

+

+  VA_START (Marker, FormatString);

+  return AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+AsciiVSPrintUnicodeFormat (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  IN  VA_LIST       Marker

+  )

+{

+  return BasePrintLibVSPrint (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+AsciiSPrintUnicodeFormat (

+  OUT CHAR8         *StartOfBuffer,

+  IN  UINTN         BufferSize,

+  IN  CONST CHAR16  *FormatString,

+  ...

+  )

+{

+  VA_LIST Marker;

+

+  VA_START (Marker, FormatString);

+  return AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker);

+}

+

+UINTN

+EFIAPI

+UnicodeValueToString (

+  IN OUT CHAR16  *Buffer,

+  IN UINTN       Flags,

+  IN INT64       Value,

+  IN UINTN       Width

+  )

+{

+  return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2);

+}

+

+UINTN

+EFIAPI

+AsciiValueToString (

+  IN OUT CHAR8  *Buffer,

+  IN UINTN      Flags,

+  IN INT64      Value,

+  IN UINTN      Width

+  )

+{

+  return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 1);

+}

diff --git a/Source/String/PrintLibInternal.c b/Source/String/PrintLibInternal.c
new file mode 100644
index 0000000..63d0c71
--- /dev/null
+++ b/Source/String/PrintLibInternal.c
@@ -0,0 +1,142 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  PrintLibInternal.c

+

+Abstract:

+

+  Print Library worker functions.

+

+--*/

+

+#include <Common/UefiBaseTypes.h>

+#include <Library/PrintLib.h>

+

+#include "CommonLib.h"

+#include "PrintLibInternal.h"

+

+static CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

+

+CHAR8 *

+BasePrintLibFillBuffer (

+  CHAR8   *Buffer,

+  INTN    Length,

+  UINTN   Character,

+  INTN    Increment

+  )

+{

+  INTN  Index;

+

+  for (Index = 0; Index < Length; Index++) {

+    *Buffer       =  (CHAR8) Character;

+    *(Buffer + 1) =  (CHAR8) (Character >> 8);

+    Buffer        += Increment;

+  }

+  return Buffer;

+}

+

+/**

+  Print worker function that prints a Value as a decimal number in Buffer.

+

+  @param  Buffer Location to place the Unicode or ASCII string of Value.

+

+  @param  Value Value to convert to a Decimal or Hexidecimal string in Buffer.

+

+  @param  Flags Flags to use in printing string, see file header for details.

+

+  @param  Precision Minimum number of digits to return in the ASCII string

+

+  @return Number of characters printed.

+

+**/

+UINTN

+EFIAPI

+BasePrintLibValueToString (

+  IN OUT CHAR8  *Buffer,

+  IN INT64      Value,

+  IN UINTN      Radix

+  )

+{

+  UINTN   Digits;

+  UINT32  Remainder;

+

+  //

+  // Loop to convert one digit at a time in reverse order

+  //

+  *(Buffer++) = 0;

+  Digits = 0;

+  do {

+    // Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);

+    Remainder = (UINT64)Value % (UINT32)Radix;

+    Value = (UINT64)Value / (UINT32)Radix;

+    *(Buffer++) = mHexStr[Remainder];

+    Digits++;

+  } while (Value != 0);

+  return Digits;

+}

+

+UINTN

+BasePrintLibConvertValueToString (

+  IN OUT CHAR8   *Buffer,

+  IN UINTN       Flags,

+  IN INT64       Value,

+  IN UINTN       Width,

+  IN UINTN       Increment

+  )

+{

+  CHAR8  *OriginalBuffer;

+  CHAR8  ValueBuffer[MAXIMUM_VALUE_CHARACTERS];

+  UINTN  Count;

+  UINTN  Digits;

+  UINTN  Index;

+

+  OriginalBuffer = Buffer;

+

+  if (Width == 0 || (Flags & COMMA_TYPE) != 0) {

+    Flags &= (~PREFIX_ZERO);

+  }

+

+  if (Width == 0 || Width > (MAXIMUM_VALUE_CHARACTERS - 1)) {

+    Width = MAXIMUM_VALUE_CHARACTERS - 1;

+  }

+

+  if (Value < 0) {

+    Value = -Value;

+    Buffer = BasePrintLibFillBuffer (Buffer, 1, '-', Increment);

+  }

+

+  Count = BasePrintLibValueToString (ValueBuffer, Value, 10);

+

+  if ((Flags & PREFIX_ZERO) != 0) {

+    Buffer = BasePrintLibFillBuffer (Buffer, Width - Count, '0', Increment);

+  }

+

+  Digits = 3 - (Count % 3);

+  for (Index = 0; Index < Count; Index++) {

+    Buffer = BasePrintLibFillBuffer (Buffer, 1, ValueBuffer[Count - Index], Increment);

+    if ((Flags & COMMA_TYPE) != 0) {

+      Digits++;

+      if (Digits == 3) {

+        Digits = 0;

+        if ((Index + 1) < Count) {

+          Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', Increment);

+        }

+      }

+    }

+  }

+

+  Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, Increment);

+

+  return ((Buffer - OriginalBuffer) / Increment);

+}

diff --git a/Source/String/PrintLibInternal.h b/Source/String/PrintLibInternal.h
new file mode 100644
index 0000000..87f0955e
--- /dev/null
+++ b/Source/String/PrintLibInternal.h
@@ -0,0 +1,101 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  PrintLibInternal.h

+

+Abstract:

+

+  Print Library.

+

+--*/

+

+

+

+//

+// Print primitives

+//

+//#define LEFT_JUSTIFY      0x01

+#define PREFIX_SIGN       0x02

+#define PREFIX_BLANK      0x04

+//#define COMMA_TYPE        0x08

+#define LONG_TYPE         0x10

+//#define PREFIX_ZERO       0x20

+#define OUTPUT_UNICODE    0x40

+#define RADIX_HEX         0x80

+#define FORMAT_UNICODE    0x100

+#define PAD_TO_WIDTH      0x200

+#define ARGUMENT_UNICODE  0x400

+#define PRECISION         0x800

+#define ARGUMENT_REVERSED 0x1000

+

+///

+/// Define the maximum number of characters that are required to encode

+/// a decimal, hexidecimal, GUID, or TIME value with a Nll terminator.

+///   Maximum Length Decimal String     = 28    "-9,223,372,036,854,775,808"

+///   Maximum Length Hexidecimal String = 17    "FFFFFFFFFFFFFFFF"

+///   Maximum Length GUID               = 37    "00000000-0000-0000-0000-000000000000"

+///   Maximum Length TIME               = 18    "12/12/2006  12:12"

+///

+#define MAXIMUM_VALUE_CHARACTERS  38

+

+//

+//

+//

+typedef struct {

+  UINT16  Year;

+  UINT8   Month;

+  UINT8   Day;

+  UINT8   Hour;

+  UINT8   Minute;

+  UINT8   Second;

+  UINT8   Pad1;

+  UINT32  Nanosecond;

+  INT16   TimeZone;

+  UINT8   Daylight;

+  UINT8   Pad2;

+} TIME;

+

+UINTN

+BasePrintLibSPrint (

+  OUT CHAR8        *Buffer,

+  IN  UINTN        BufferSize,

+  IN  UINTN        Flags,

+  IN  CONST CHAR8  *FormatString,

+  ...

+  );

+

+CHAR8 *

+BasePrintLibFillBuffer (

+  CHAR8   *Buffer,

+  INTN    Length,

+  UINTN   Character,

+  INTN    Increment

+  );

+

+UINTN

+EFIAPI

+BasePrintLibValueToString (

+  IN OUT CHAR8  *Buffer,

+  IN INT64      Value,

+  IN UINTN      Radix

+  );

+

+UINTN

+BasePrintLibConvertValueToString (

+  IN OUT CHAR8   *Buffer,

+  IN UINTN       Flags,

+  IN INT64       Value,

+  IN UINTN       Width,

+  IN UINTN       Increment

+  );

diff --git a/Source/String/String.c b/Source/String/String.c
new file mode 100644
index 0000000..78d0a59
--- /dev/null
+++ b/Source/String/String.c
@@ -0,0 +1,732 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  String.c

+

+Abstract:

+

+  Unicode and ASCII string primatives.

+

+--*/

+

+#include <assert.h>

+

+#include <Common/UefiBaseTypes.h>

+

+#include <string.h>

+

+#include "CommonLib.h"

+

+/**

+  Returns the length of a Null-terminated Unicode string.

+

+  This function returns the number of Unicode characters in the Null-terminated

+  Unicode string specified by String.

+

+  If String is NULL, then ASSERT().

+

+  @param  String  Pointer to a Null-terminated Unicode string.

+

+  @return The length of String.

+

+**/

+UINTN

+EFIAPI

+StrLen (

+  IN      CONST CHAR16              *String

+  )

+{

+  UINTN                             Length;

+

+  ASSERT (String != NULL);

+

+  for (Length = 0; *String != L'\0'; String++, Length++) {

+    ;

+  }

+  return Length;

+}

+

+/**

+  Returns the length of a Null-terminated ASCII string.

+

+  This function returns the number of ASCII characters in the Null-terminated

+  ASCII string specified by String.

+

+  If String is NULL, then ASSERT().

+

+  @param  String  Pointer to a Null-terminated ASCII string.

+

+  @return The length of String.

+

+**/

+UINTN

+EFIAPI

+AsciiStrLen (

+  IN      CONST CHAR8               *String

+  )

+{

+  UINTN                             Length;

+

+  ASSERT (String != NULL);

+

+  for (Length = 0; *String != '\0'; String++, Length++) {

+    ;

+  }

+  return Length;

+}

+

+/**

+  Copies one Null-terminated Unicode string to another Null-terminated Unicode

+  string and returns the new Unicode string.

+

+  This function copies the contents of the Unicode string Source to the Unicode

+  string Destination, and returns Destination. If Source and Destination

+  overlap, then the results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated Unicode string.

+  @param  Source      Pointer to a Null-terminated Unicode string.

+

+  @return Destiantion

+

+**/

+CHAR16 *

+EFIAPI

+StrCpy (

+  OUT     CHAR16                    *Destination,

+  IN      CONST CHAR16              *Source

+  )

+{

+  CHAR16                            *ReturnValue;

+

+  //

+  // Destination cannot be NULL

+  //

+  ASSERT (Destination != NULL);

+

+  //

+  // Destination and source cannot overlap

+  //

+  ASSERT ((UINTN)(Destination - Source) > StrLen (Source));

+  ASSERT ((UINTN)(Source - Destination) > StrLen (Source));

+

+  ReturnValue = Destination;

+  while (*Source) {

+    *(Destination++) = *(Source++);

+  }

+  *Destination = 0;

+  return ReturnValue;

+}

+

+/**

+  Copies one Null-terminated Unicode string with a maximum length to another

+  Null-terminated Unicode string with a maximum length and returns the new

+  Unicode string.

+

+  This function copies the contents of the Unicode string Source to the Unicode

+  string Destination, and returns Destination. At most, Length Unicode

+  characters are copied from Source to Destination. If Length is 0, then

+  Destination is returned unmodified. If Length is greater that the number of

+  Unicode characters in Source, then Destination is padded with Null Unicode

+  characters. If Source and Destination overlap, then the results are

+  undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated Unicode string.

+  @param  Source      Pointer to a Null-terminated Unicode string.

+  @param  Length      Maximum number of Unicode characters to copy.

+

+  @return Destination

+

+**/

+CHAR16 *

+EFIAPI

+StrnCpy (

+  OUT     CHAR16                    *Destination,

+  IN      CONST CHAR16              *Source,

+  IN      UINTN                     Length

+  )

+{

+  CHAR16                            *ReturnValue;

+

+  if (Length == 0) {

+    return Destination;

+  }

+

+  //

+  // Destination cannot be NULL if Length is not zero

+  //

+  ASSERT (Destination != NULL);

+

+  //

+  // Destination and source cannot overlap

+  // Q: Does Source have to be NULL-terminated?

+  //

+  ASSERT ((UINTN)(Destination - Source) > StrLen (Source));

+  ASSERT ((UINTN)(Source - Destination) >= Length);

+

+  ReturnValue = Destination;

+

+  while ((*Source != L'\0') && (Length > 0)) {

+    *(Destination++) = *(Source++);

+    Length--;

+  }

+

+  memset (Destination, 0, Length * sizeof (*Destination));

+  return ReturnValue;

+}

+

+/**

+  Returns the size of a Null-terminated Unicode string in bytes, including the

+  Null terminator.

+

+  This function returns the size, in bytes, of the Null-terminated Unicode

+  string specified by String.

+

+  If String is NULL, then ASSERT().

+

+  @param  String  Pointer to a Null-terminated Unicode string.

+

+  @return The size of String.

+

+**/

+UINTN

+EFIAPI

+StrSize (

+  IN      CONST CHAR16              *String

+  )

+{

+  return (StrLen (String) + 1) * sizeof (*String);

+}

+

+/**

+  Compares two Null-terminated Unicode strings, and returns the difference

+  between the first mismatched Unicode characters.

+

+  This function compares the Null-terminated Unicode string FirstString to the

+  Null-terminated Unicode string SecondString. If FirstString is identical to

+  SecondString, then 0 is returned. Otherwise, the value returned is the first

+  mismatched Unicode character in SecondString subtracted from the first

+  mismatched Unicode character in FirstString.

+

+  If FirstString is NULL, then ASSERT().

+  If SecondString is NULL, then ASSERT().

+

+  @param  FirstString   Pointer to a Null-terminated Unicode string.

+  @param  SecondString  Pointer to a Null-terminated Unicode string.

+

+  @retval 0   FirstString is identical to SecondString.

+  @retval !=0 FirstString is not identical to SecondString.

+

+**/

+INTN

+EFIAPI

+StrCmp (

+  IN      CONST CHAR16              *FirstString,

+  IN      CONST CHAR16              *SecondString

+  )

+{

+  //

+  // ASSERT both strings should never be zero

+  //

+  ASSERT (StrSize (FirstString) != 0);

+  ASSERT (StrSize (SecondString) != 0);

+

+  while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {

+    FirstString++;

+    SecondString++;

+  }

+  return *FirstString - *SecondString;

+}

+

+/**

+  Compares two Null-terminated Unicode strings with maximum lengths, and

+  returns the difference between the first mismatched Unicode characters.

+

+  This function compares the Null-terminated Unicode string FirstString to the

+  Null-terminated Unicode string SecondString. At most, Length Unicode

+  characters will be compared. If Length is 0, then 0 is returned. If

+  FirstString is identical to SecondString, then 0 is returned. Otherwise, the

+  value returned is the first mismatched Unicode character in SecondString

+  subtracted from the first mismatched Unicode character in FirstString.

+

+  If FirstString is NULL, then ASSERT().

+  If SecondString is NULL, then ASSERT().

+

+  @param  FirstString   Pointer to a Null-terminated Unicode string.

+  @param  SecondString  Pointer to a Null-terminated Unicode string.

+  @param  Length        Maximum number of Unicode characters to compare.

+

+  @retval 0   FirstString is identical to SecondString.

+  @retval !=0 FirstString is not identical to SecondString.

+

+**/

+INTN

+EFIAPI

+StrnCmp (

+  IN      CONST CHAR16              *FirstString,

+  IN      CONST CHAR16              *SecondString,

+  IN      UINTN                     Length

+  )

+{

+  if (Length == 0) {

+    return 0;

+  }

+

+  //

+  // ASSERT both strings should never be zero

+  //

+  ASSERT (StrSize (FirstString) != 0);

+  ASSERT (StrSize (SecondString) != 0);

+

+  while ((*FirstString != L'\0') &&

+         (*FirstString == *SecondString) &&

+         (Length > 1)) {

+    FirstString++;

+    SecondString++;

+    Length--;

+  }

+

+  return *FirstString - *SecondString;

+}

+

+/**

+  Concatenates one Null-terminated Unicode string to another Null-terminated

+  Unicode string, and returns the concatenated Unicode string.

+

+  This function concatenates two Null-terminated Unicode strings. The contents

+  of Null-terminated Unicode string Source are concatenated to the end of

+  Null-terminated Unicode string Destination. The Null-terminated concatenated

+  Unicode String is returned. If Source and Destination overlap, then the

+  results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated Unicode string.

+  @param  Source      Pointer to a Null-terminated Unicode string.

+

+  @return Destination

+

+**/

+CHAR16 *

+EFIAPI

+StrCat (

+  IN OUT  CHAR16                    *Destination,

+  IN      CONST CHAR16              *Source

+  )

+{

+  StrCpy (Destination + StrLen (Destination), Source);

+

+  //

+  // Size of the resulting string should never be zero.

+  //

+  ASSERT (StrSize (Destination) != 0);

+  return Destination;

+}

+

+/**

+  Concatenates one Null-terminated Unicode string with a maximum length to the

+  end of another Null-terminated Unicode string, and returns the concatenated

+  Unicode string.

+

+  This function concatenates two Null-terminated Unicode strings. The contents

+  of Null-terminated Unicode string Source are concatenated to the end of

+  Null-terminated Unicode string Destination, and Destination is returned. At

+  most, Length Unicode characters are concatenated from Source to the end of

+  Destination, and Destination is always Null-terminated. If Length is 0, then

+  Destination is returned unmodified. If Source and Destination overlap, then

+  the results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated Unicode string.

+  @param  Source      Pointer to a Null-terminated Unicode string.

+  @param  Length      Maximum number of Unicode characters to concatenate from

+                      Source.

+

+  @return Destination

+

+**/

+CHAR16 *

+EFIAPI

+StrnCat (

+  IN OUT  CHAR16                    *Destination,

+  IN      CONST CHAR16              *Source,

+  IN      UINTN                     Length

+  )

+{

+  StrnCpy (Destination + StrLen (Destination), Source, Length);

+

+  //

+  // Size of the resulting string should never be zero.

+  //

+  ASSERT (StrSize (Destination) != 0);

+  return Destination;

+}

+

+/**

+  Copies one Null-terminated ASCII string to another Null-terminated ASCII

+  string and returns the new ASCII string.

+

+  This function copies the contents of the ASCII string Source to the ASCII

+  string Destination, and returns Destination. If Source and Destination

+  overlap, then the results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated ASCII string.

+  @param  Source      Pointer to a Null-terminated ASCII string.

+

+  @return Destination

+

+**/

+CHAR8 *

+EFIAPI

+AsciiStrCpy (

+  OUT     CHAR8                     *Destination,

+  IN      CONST CHAR8               *Source

+  )

+{

+  CHAR8                             *ReturnValue;

+

+  //

+  // Destination cannot be NULL

+  //

+  ASSERT (Destination != NULL);

+

+  //

+  // Destination and source cannot overlap

+  //

+  ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));

+  ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source));

+

+  ReturnValue = Destination;

+  while (*Source) {

+    *(Destination++) = *(Source++);

+  }

+  *Destination = 0;

+  return ReturnValue;

+}

+

+/**

+  Copies one Null-terminated ASCII string with a maximum length to another

+  Null-terminated ASCII string with a maximum length and returns the new ASCII

+  string.

+

+  This function copies the contents of the ASCII string Source to the ASCII

+  string Destination, and returns Destination. At most, Length ASCII characters

+  are copied from Source to Destination. If Length is 0, then Destination is

+  returned unmodified. If Length is greater that the number of ASCII characters

+  in Source, then Destination is padded with Null ASCII characters. If Source

+  and Destination overlap, then the results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated ASCII string.

+  @param  Source      Pointer to a Null-terminated ASCII string.

+  @param  Length      Maximum number of ASCII characters to copy.

+

+  @return Destination

+

+**/

+CHAR8 *

+EFIAPI

+AsciiStrnCpy (

+  OUT     CHAR8                     *Destination,

+  IN      CONST CHAR8               *Source,

+  IN      UINTN                     Length

+  )

+{

+  CHAR8                             *ReturnValue;

+

+  if (Length == 0) {

+    return Destination;

+  }

+

+  //

+  // Destination cannot be NULL

+  //

+  ASSERT (Destination != NULL);

+

+  //

+  // Destination and source cannot overlap

+  //

+  ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));

+  ASSERT ((UINTN)(Source - Destination) >= Length);

+

+  ReturnValue = Destination;

+

+  while (*Source && Length > 0) {

+    *(Destination++) = *(Source++);

+    Length--;

+  }

+

+  // ZeroMem (Destination, Length * sizeof (*Destination));

+  memset (Destination, 0, Length * sizeof (*Destination));

+  return ReturnValue;

+}

+

+/**

+  Returns the size of a Null-terminated ASCII string in bytes, including the

+  Null terminator.

+

+  This function returns the size, in bytes, of the Null-terminated ASCII string

+  specified by String.

+

+  If String is NULL, then ASSERT().

+

+  @param  String  Pointer to a Null-terminated ASCII string.

+

+  @return The size of String.

+

+**/

+UINTN

+EFIAPI

+AsciiStrSize (

+  IN      CONST CHAR8               *String

+  )

+{

+  return (AsciiStrLen (String) + 1) * sizeof (*String);

+}

+

+/**

+  Compares two Null-terminated ASCII strings, and returns the difference

+  between the first mismatched ASCII characters.

+

+  This function compares the Null-terminated ASCII string FirstString to the

+  Null-terminated ASCII string SecondString. If FirstString is identical to

+  SecondString, then 0 is returned. Otherwise, the value returned is the first

+  mismatched ASCII character in SecondString subtracted from the first

+  mismatched ASCII character in FirstString.

+

+  If FirstString is NULL, then ASSERT().

+  If SecondString is NULL, then ASSERT().

+

+  @param  FirstString   Pointer to a Null-terminated ASCII string.

+  @param  SecondString  Pointer to a Null-terminated ASCII string.

+

+  @retval 0   FirstString is identical to SecondString.

+  @retval !=0 FirstString is not identical to SecondString.

+

+**/

+INTN

+EFIAPI

+AsciiStrCmp (

+  IN      CONST CHAR8               *FirstString,

+  IN      CONST CHAR8               *SecondString

+  )

+{

+  //

+  // ASSERT both strings should never be zero

+  //

+  ASSERT (AsciiStrSize (FirstString));

+  ASSERT (AsciiStrSize (SecondString));

+

+  while ((*FirstString != '\0') && (*FirstString == *SecondString)) {

+    FirstString++;

+    SecondString++;

+  }

+

+  return *FirstString - *SecondString;

+}

+

+STATIC

+CHAR8

+EFIAPI

+AsciiToUpper (

+  IN      CHAR8                     Chr

+  )

+{

+  return (Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr;

+}

+

+/**

+  Performs a case insensitive comparison of two Null-terminated ASCII strings,

+  and returns the difference between the first mismatched ASCII characters.

+

+  This function performs a case insensitive comparison of the Null-terminated

+  ASCII string FirstString to the Null-terminated ASCII string SecondString. If

+  FirstString is identical to SecondString, then 0 is returned. Otherwise, the

+  value returned is the first mismatched lower case ASCII character in

+  SecondString subtracted from the first mismatched lower case ASCII character

+  in FirstString.

+

+  If FirstString is NULL, then ASSERT().

+  If SecondString is NULL, then ASSERT().

+

+  @param  FirstString   Pointer to a Null-terminated ASCII string.

+  @param  SecondString  Pointer to a Null-terminated ASCII string.

+

+  @retval 0   FirstString is identical to SecondString using case insensitive

+              comparisons.

+  @retval !=0 FirstString is not identical to SecondString using case

+              insensitive comparisons.

+

+**/

+INTN

+EFIAPI

+AsciiStriCmp (

+  IN      CONST CHAR8               *FirstString,

+  IN      CONST CHAR8               *SecondString

+  )

+{

+  //

+  // ASSERT both strings should never be zero

+  //

+  ASSERT (AsciiStrSize (FirstString));

+  ASSERT (AsciiStrSize (SecondString));

+

+  while ((*FirstString != '\0') &&

+         (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString))) {

+    FirstString++;

+    SecondString++;

+  }

+

+  return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString);

+}

+

+/**

+  Compares two Null-terminated ASCII strings with maximum lengths, and returns

+  the difference between the first mismatched ASCII characters.

+

+  This function compares the Null-terminated ASCII string FirstString to the

+  Null-terminated ASCII  string SecondString. At most, Length ASCII characters

+  will be compared. If Length is 0, then 0 is returned. If FirstString is

+  identical to SecondString, then 0 is returned. Otherwise, the value returned

+  is the first mismatched ASCII character in SecondString subtracted from the

+  first mismatched ASCII character in FirstString.

+

+  If FirstString is NULL, then ASSERT().

+  If SecondString is NULL, then ASSERT().

+

+  @param  FirstString   Pointer to a Null-terminated ASCII string.

+  @param  SecondString  Pointer to a Null-terminated ASCII string.

+

+  @retval 0   FirstString is identical to SecondString.

+  @retval !=0 FirstString is not identical to SecondString.

+

+**/

+INTN

+EFIAPI

+AsciiStrnCmp (

+  IN      CONST CHAR8               *FirstString,

+  IN      CONST CHAR8               *SecondString,

+  IN      UINTN                     Length

+  )

+{

+  //

+  // ASSERT both strings should never be zero

+  //

+  ASSERT (AsciiStrSize (FirstString));

+  ASSERT (AsciiStrSize (SecondString));

+

+  while ((*FirstString != '\0') &&

+         (*FirstString == *SecondString) &&

+         (Length > 1)) {

+    FirstString++;

+    SecondString++;

+    Length--;

+  }

+  return *FirstString - *SecondString;

+}

+

+/**

+  Concatenates one Null-terminated ASCII string to another Null-terminated

+  ASCII string, and returns the concatenated ASCII string.

+

+  This function concatenates two Null-terminated ASCII strings. The contents of

+  Null-terminated ASCII string Source are concatenated to the end of Null-

+  terminated ASCII string Destination. The Null-terminated concatenated ASCII

+  String is returned.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated ASCII string.

+  @param  Source      Pointer to a Null-terminated ASCII string.

+

+  @return Destination

+

+**/

+CHAR8 *

+EFIAPI

+AsciiStrCat (

+  IN OUT CHAR8    *Destination,

+  IN CONST CHAR8  *Source

+  )

+{

+  AsciiStrCpy (Destination + AsciiStrLen (Destination), Source);

+

+  //

+  // Size of the resulting string should never be zero.

+  //

+  ASSERT (AsciiStrSize (Destination) != 0);

+  return Destination;

+}

+

+/**

+  Concatenates one Null-terminated ASCII string with a maximum length to the

+  end of another Null-terminated ASCII string, and returns the concatenated

+  ASCII string.

+

+  This function concatenates two Null-terminated ASCII strings. The contents

+  of Null-terminated ASCII string Source are concatenated to the end of Null-

+  terminated ASCII string Destination, and Destination is returned. At most,

+  Length ASCII characters are concatenated from Source to the end of

+  Destination, and Destination is always Null-terminated. If Length is 0, then

+  Destination is returned unmodified. If Source and Destination overlap, then

+  the results are undefined.

+

+  If Destination is NULL, then ASSERT().

+  If Source is NULL, then ASSERT().

+  If Source and Destination overlap, then ASSERT().

+

+  @param  Destination Pointer to a Null-terminated ASCII string.

+  @param  Source      Pointer to a Null-terminated ASCII string.

+  @param  Length      Maximum number of ASCII characters to concatenate from

+                      Source.

+

+  @return Destination

+

+**/

+CHAR8 *

+EFIAPI

+AsciiStrnCat (

+  IN OUT  CHAR8                     *Destination,

+  IN      CONST CHAR8               *Source,

+  IN      UINTN                     Length

+  )

+{

+  AsciiStrnCpy (Destination + AsciiStrLen (Destination), Source, Length);

+

+  //

+  // Size of the resulting string should never be zero.

+  //

+  ASSERT (AsciiStrSize (Destination) != 0);

+  return Destination;

+}

diff --git a/Source/String/build.xml b/Source/String/build.xml
new file mode 100644
index 0000000..b42504e
--- /dev/null
+++ b/Source/String/build.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK String

+  Copyright (c) 2006, Intel Corporation

+-->

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LibName" value="String"/>

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${LibName}/tmp"/>

+

+  <target name="GenTool" depends="init, String">

+    <echo message="The EDK Library: ${LibName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Library: ${LibName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+

+    <condition property="syslibdirs" value="">

+      <os family="mac"/>

+    </condition>

+    

+    <condition property="syslibs" value="">

+      <os family="mac"/>

+    </condition>

+    

+    <condition property="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs">

+      <os family="windows"/>

+    </condition>

+    

+    <condition property="syslibs" value="uuid">

+      <os family="windows"/>

+    </condition>

+    

+    <condition property="syslibdirs" value="/usr/lib">

+      <os name="Linux"/>

+    </condition>

+    

+    <condition property="syslibs" value="uuid">

+      <os name="Linux"/>

+    </condition>

+    

+  </target>

+

+  <target name="String" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${LIB_DIR}/${LibName}"

+        outtype="static"

+        debug="true"

+        optimize="speed">

+      <compilerarg value="${ExtraArgus}" if="ExtraArgus" />

+      <compilerarg value="-fshort-wchar" if="gcc"/>

+

+      <fileset dir="${basedir}/${LibName}" 

+        includes="*.c" />

+

+      <includepath path="${PACKAGE_DIR}/${LibName}"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>  

+    <delete dir="${PACKAGE_DIR}/${LibName}/tmp">

+    </delete>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/Strip/Strip.c b/Source/Strip/Strip.c
new file mode 100644
index 0000000..bccdffb
--- /dev/null
+++ b/Source/Strip/Strip.c
@@ -0,0 +1,105 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  Strip.c

+

+Abstract:

+

+  Quick Exe2Bin equivalent.

+

+--*/

+

+#include <stdio.h>

+#include <memory.h>

+#include <string.h>

+#include <stdlib.h>

+

+int

+main (

+  int  argc,

+  char *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Converts executable files to binary files.

+

+Arguments:

+

+  argc   - Number of command line arguments

+  argv[] - Array of pointers to the command line arguments

+

+Returns:

+

+  Zero     - Function completed successfully.

+  Non-zero - Function exited with errors.

+

+--*/

+{

+  FILE  *InFile;

+  FILE  *OutFile;

+  int   Index;

+  int   FileSize;

+  char  *Buffer;

+  char  *Ptrx;

+

+  if (argc < 3) {

+    printf ("Need more args, such as file name to convert and output name\n");

+    return -1;

+  }

+

+  InFile  = fopen (argv[1], "rb");

+  OutFile = fopen (argv[2], "wb");

+

+  if (!InFile) {

+    printf ("no file, exit\n");

+    return -1;

+  }

+

+  if (OutFile == NULL) {

+    printf ("Unable to open output file.\n");

+    return -1;

+  }

+

+  fseek (InFile, 0, SEEK_END);

+  FileSize = ftell (InFile);

+

+  if (FileSize < 0x200) {

+    printf ("%d is not a legal size, exit\n", FileSize);

+    return -1;

+  }

+

+  fseek (InFile, 0, SEEK_SET);

+

+  Buffer = (char *) malloc (FileSize);

+  if (Buffer == NULL) {

+    printf ("Error: Out of resources.\n");

+    return -1;

+  }

+

+  fread (Buffer, 1, FileSize, InFile);

+

+  Ptrx  = Buffer + 0x200;

+

+  Index = FileSize - 0x200;

+

+  fwrite (Ptrx, Index, 1, OutFile);

+

+  fclose (InFile);

+  fclose (OutFile);

+  free (Buffer);

+

+  return 0;

+}

diff --git a/Source/Strip/build.xml b/Source/Strip/build.xml
new file mode 100644
index 0000000..e079c7e
--- /dev/null
+++ b/Source/Strip/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK Strip Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="Strip"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed!"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/Ia32"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/TianoTools.msa b/Source/TianoTools.msa
new file mode 100644
index 0000000..2e4b27c
--- /dev/null
+++ b/Source/TianoTools.msa
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

+  <MsaHeader>

+    <ModuleName>Tiano C Tools</ModuleName>

+    <ModuleType>TOOL</ModuleType>

+    <GuidValue>A169C678-3F55-4b6a-80BF-FD8B8DCAB883</GuidValue>

+    <Version>2.0</Version>

+    <Abstract>This is the TianoTools Module</Abstract>

+    <Description>This Module provides the EFI/Tiano Tools that are used to create EFI/Tiano
+      Modules and Platform Binary Files (PBF)
+      These tools require compilation only once if the Developer Workstation and
+      the Developer's choice of HOST tool chain are stable.  If the developer
+      updates either the OS or the HOST tool chain, these tools should be rebuilt.</Description>

+    <Copyright>Copyright 2006, Intel Corporation</Copyright>

+    <License URL="http://opensource.org/licenses/bsd-license.php">All rights reserved.  This program and the accompanying materials
+are licensed and made available under the terms and conditions of the 
+BSD License which accompanies this distribution.  The full text of the 
+license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>

+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>

+  </MsaHeader>

+  <ModuleDefinitions>

+    <SupportedArchitectures>EBC IA32 X64 IPF</SupportedArchitectures>

+    <BinaryModule>false</BinaryModule>

+    <OutputFileBasename>NULL</OutputFileBasename>

+  </ModuleDefinitions>

+  <SourceFiles>

+    <Filename>build.xml</Filename>

+    <Filename>Common/build.xml</Filename>

+    <Filename>Common/CommonLib.c</Filename>

+    <Filename>Common/CommonLib.h</Filename>

+    <Filename>Common/Crc32.c</Filename>

+    <Filename>Common/Crc32.h</Filename>

+    <Filename>Common/EfiCompress.c</Filename>

+    <Filename>Common/EfiCompress.h</Filename>

+    <Filename>Common/EfiCustomizedCompress.h</Filename>

+    <Filename>Common/EfiDecompress.c</Filename>

+    <Filename>Common/EfiDecompress.h</Filename>

+    <Filename>Common/EfiUtilityMsgs.c</Filename>

+    <Filename>Common/EfiUtilityMsgs.h</Filename>

+    <Filename>Common/FvLib.c</Filename>

+    <Filename>Common/FvLib.h</Filename>

+    <Filename>Common/MyAlloc.c</Filename>

+    <Filename>Common/MyAlloc.h</Filename>

+    <Filename>Common/ParseInf.c</Filename>

+    <Filename>Common/ParseInf.h</Filename>

+    <Filename>Common/SimpleFileParsing.c</Filename>

+    <Filename>Common/SimpleFileParsing.h</Filename>

+    <Filename>Common/WinNtInclude.h</Filename>

+    <Filename>CompressDll/build.xml</Filename>

+    <Filename>CompressDll/CompressDll.c</Filename>

+    <Filename>CompressDll/CompressDll.h</Filename>

+    <Filename>CreateMtFile/build.xml</Filename>

+    <Filename>CreateMtFile/CreateMtFile.c</Filename>

+    <Filename>CustomizedCompress/build.xml</Filename>

+    <Filename>CustomizedCompress/CustomizedCompress.c</Filename>

+    <Filename>EfiCompress/build.xml</Filename>

+    <Filename>EfiCompress/EfiCompressMain.c</Filename>

+    <Filename>EfiCompress/makefile</Filename>

+    <Filename>EfiRom/build.xml</Filename>

+    <Filename>EfiRom/EfiRom.c</Filename>

+    <Filename>FlashMap/build.xml</Filename>

+    <Filename>FlashMap/FlashDefFile.c</Filename>

+    <Filename>FlashMap/FlashDefFile.h</Filename>

+    <Filename>FlashMap/FlashMap.c</Filename>

+    <Filename>FlashMap/Microcode.c</Filename>

+    <Filename>FlashMap/Microcode.h</Filename>

+    <Filename>FlashMap/Symbols.c</Filename>

+    <Filename>FlashMap/Symbols.h</Filename>

+    <Filename>FwImage/build.xml</Filename>

+    <Filename>FwImage/fwimage.c</Filename>

+    <Filename>GenAcpiTable/build.xml</Filename>

+    <Filename>GenAcpiTable/GenAcpiTable.c</Filename>

+    <Filename>GenCapsuleHdr/build.xml</Filename>

+    <Filename>GenCapsuleHdr/CreateGuid.c</Filename>

+    <Filename>GenCapsuleHdr/GenCapsuleHdr.c</Filename>

+    <Filename>GenCRC32Section/build.xml</Filename>

+    <Filename>GenCRC32Section/GenCRC32Section.c</Filename>

+    <Filename>GenCRC32Section/GenCRC32Section.h</Filename>

+    <Filename>GenDepex/build.xml</Filename>

+    <Filename>GenDepex/DepexParser.c</Filename>

+    <Filename>GenDepex/DepexParser.h</Filename>

+    <Filename>GenDepex/GenDepex.c</Filename>

+    <Filename>GenDepex/GenDepex.h</Filename>

+    <Filename>GenFfsFile/build.xml</Filename>

+    <Filename>GenFfsFile/GenFfsFile.c</Filename>

+    <Filename>GenFfsFile/GenFfsFile.h</Filename>

+    <Filename>GenFfsFile/SimpleFileParsing.c</Filename>

+    <Filename>GenFvImage/build.xml</Filename>

+    <Filename>GenFvImage/Ebc/PeCoffLoaderEx.c</Filename>

+    <Filename>GenFvImage/GenFvImageExe.c</Filename>

+    <Filename>GenFvImage/GenFvImageExe.h</Filename>

+    <Filename>GenFvImage/GenFvImageLib.c</Filename>

+    <Filename>GenFvImage/GenFvImageLib.h</Filename>

+    <Filename>GenFvImage/GenFvImageLibInternal.h</Filename>

+    <Filename>GenSection/build.xml</Filename>

+    <Filename>GenSection/GenSection.c</Filename>

+    <Filename>GenSection/GenSection.h</Filename>

+    <Filename>GenTEImage/build.xml</Filename>

+    <Filename>GenTEImage/GenTEImage.c</Filename>

+    <Filename>GuidChk/build.xml</Filename>

+    <Filename>GuidChk/CommonUtils.h</Filename>

+    <Filename>GuidChk/FileSearch.c</Filename>

+    <Filename>GuidChk/FileSearch.h</Filename>

+    <Filename>GuidChk/GuidChk.c</Filename>

+    <Filename>GuidChk/GuidList.c</Filename>

+    <Filename>GuidChk/UtilsMsgs.c</Filename>

+    <Filename>GuidChk/UtilsMsgs.h</Filename>

+    <Filename>Include/Common/BaseTypes.h</Filename>

+    <Filename>Include/Common/Capsule.h</Filename>

+    <Filename>Include/Common/Dependency.h</Filename>

+    <Filename>Include/Common/EfiImage.h</Filename>

+    <Filename>Include/Common/FirmwareFileSystem.h</Filename>

+    <Filename>Include/Common/FirmwareVolumeHeader.h</Filename>

+    <Filename>Include/Common/FirmwareVolumeImageFormat.h</Filename>

+    <Filename>Include/Common/InternalFormRepresentation.h</Filename>

+    <Filename>Include/Common/MultiPhase.h</Filename>

+    <Filename>Include/Common/UefiBaseTypes.h</Filename>

+    <Filename>Include/Common/Variable.h</Filename>

+    <Filename>Include/Common/WorkingBlockHeader.h</Filename>

+    <Filename>Include/Guid/AcpiTableStorage.h</Filename>

+    <Filename>Include/Guid/Apriori.h</Filename>

+    <Filename>Include/Guid/Capsule.h</Filename>

+    <Filename>Include/Guid/FirmwareFileSystem.h</Filename>

+    <Filename>Include/Ia32/ProcessorBind.h</Filename>

+    <Filename>Include/IndustryStandard/pci22.h</Filename>

+    <Filename>Include/Library/PeCoffLib.h</Filename>

+    <Filename>Include/Library/PrintLib.h</Filename>

+    <Filename>Include/Protocol/DevicePath.h</Filename>

+    <Filename>Include/Protocol/GuidedSectionExtraction.h</Filename>

+    <Filename>Include/Protocol/Hii.h</Filename>

+    <Filename>Include/Protocol/UgaDraw.h</Filename>

+    <Filename>MakeDeps/build.xml</Filename>

+    <Filename>MakeDeps/MakeDeps.c</Filename>

+    <Filename>ModifyInf/build.xml</Filename>

+    <Filename>ModifyInf/ModifyInf.c</Filename>

+    <Filename>Pccts/antlr/antlr.1</Filename>

+    <Filename>Pccts/antlr/antlr.c</Filename>

+    <Filename>Pccts/antlr/antlr.g</Filename>

+    <Filename>Pccts/antlr/antlr.ilk</Filename>

+    <Filename>Pccts/antlr/antlr.pdb</Filename>

+    <Filename>Pccts/antlr/antlr.r</Filename>

+    <Filename>Pccts/antlr/antlr1.txt</Filename>

+    <Filename>Pccts/antlr/AntlrMS.mak</Filename>

+    <Filename>Pccts/antlr/AntlrPPC.mak</Filename>

+    <Filename>Pccts/antlr/bits.c</Filename>

+    <Filename>Pccts/antlr/build.c</Filename>

+    <Filename>Pccts/antlr/build.xml</Filename>

+    <Filename>Pccts/antlr/dumpcycles.c</Filename>

+    <Filename>Pccts/antlr/dumpnode.c</Filename>

+    <Filename>Pccts/antlr/egman.c</Filename>

+    <Filename>Pccts/antlr/err.c</Filename>

+    <Filename>Pccts/antlr/fcache.c</Filename>

+    <Filename>Pccts/antlr/fset.c</Filename>

+    <Filename>Pccts/antlr/fset2.c</Filename>

+    <Filename>Pccts/antlr/gen.c</Filename>

+    <Filename>Pccts/antlr/generic.h</Filename>

+    <Filename>Pccts/antlr/globals.c</Filename>

+    <Filename>Pccts/antlr/hash.c</Filename>

+    <Filename>Pccts/antlr/hash.h</Filename>

+    <Filename>Pccts/antlr/lex.c</Filename>

+    <Filename>Pccts/antlr/main.c</Filename>

+    <Filename>Pccts/antlr/makefile</Filename>

+    <Filename>Pccts/antlr/makefile1</Filename>

+    <Filename>Pccts/antlr/misc.c</Filename>

+    <Filename>Pccts/antlr/mode.h</Filename>

+    <Filename>Pccts/antlr/mrhoist.c</Filename>

+    <Filename>Pccts/antlr/parser.dlg</Filename>

+    <Filename>Pccts/antlr/pred.c</Filename>

+    <Filename>Pccts/antlr/proto.h</Filename>

+    <Filename>Pccts/antlr/README</Filename>

+    <Filename>Pccts/antlr/scan.c</Filename>

+    <Filename>Pccts/antlr/stdpccts.h</Filename>

+    <Filename>Pccts/antlr/syn.h</Filename>

+    <Filename>Pccts/antlr/tokens.h</Filename>

+    <Filename>Pccts/antlr/vc70.pdb</Filename>

+    <Filename>Pccts/build.xml</Filename>

+    <Filename>Pccts/CHANGES_FROM_131.txt</Filename>

+    <Filename>Pccts/CHANGES_FROM_133.txt</Filename>

+    <Filename>Pccts/CHANGES_FROM_133_BEFORE_MR13.txt</Filename>

+    <Filename>Pccts/CHANGES_SUMMARY.txt</Filename>

+    <Filename>Pccts/dlg/automata.c</Filename>

+    <Filename>Pccts/dlg/build.xml</Filename>

+    <Filename>Pccts/dlg/dlg.1</Filename>

+    <Filename>Pccts/dlg/dlg.h</Filename>

+    <Filename>Pccts/dlg/dlg.r</Filename>

+    <Filename>Pccts/dlg/dlg1.txt</Filename>

+    <Filename>Pccts/dlg/dlg_a.c</Filename>

+    <Filename>Pccts/dlg/dlg_p.c</Filename>

+    <Filename>Pccts/dlg/dlg_p.g</Filename>

+    <Filename>Pccts/dlg/DlgMS.mak</Filename>

+    <Filename>Pccts/dlg/DlgPPC.mak</Filename>

+    <Filename>Pccts/dlg/err.c</Filename>

+    <Filename>Pccts/dlg/main.c</Filename>

+    <Filename>Pccts/dlg/makefile</Filename>

+    <Filename>Pccts/dlg/makefile1</Filename>

+    <Filename>Pccts/dlg/mode.h</Filename>

+    <Filename>Pccts/dlg/output.c</Filename>

+    <Filename>Pccts/dlg/parser.dlg</Filename>

+    <Filename>Pccts/dlg/relabel.c</Filename>

+    <Filename>Pccts/dlg/stdpccts.h</Filename>

+    <Filename>Pccts/dlg/support.c</Filename>

+    <Filename>Pccts/dlg/tokens.h</Filename>

+    <Filename>Pccts/h/antlr.h</Filename>

+    <Filename>Pccts/h/AParser.cpp</Filename>

+    <Filename>Pccts/h/AParser.h</Filename>

+    <Filename>Pccts/h/ast.c</Filename>

+    <Filename>Pccts/h/ast.h</Filename>

+    <Filename>Pccts/h/ASTBase.cpp</Filename>

+    <Filename>Pccts/h/ASTBase.h</Filename>

+    <Filename>Pccts/h/AToken.h</Filename>

+    <Filename>Pccts/h/ATokenBuffer.cpp</Filename>

+    <Filename>Pccts/h/ATokenBuffer.h</Filename>

+    <Filename>Pccts/h/ATokenStream.h</Filename>

+    <Filename>Pccts/h/ATokPtr.h</Filename>

+    <Filename>Pccts/h/ATokPtrImpl.h</Filename>

+    <Filename>Pccts/h/BufFileInput.cpp</Filename>

+    <Filename>Pccts/h/BufFileInput.h</Filename>

+    <Filename>Pccts/h/charbuf.h</Filename>

+    <Filename>Pccts/h/charptr.c</Filename>

+    <Filename>Pccts/h/charptr.h</Filename>

+    <Filename>Pccts/h/config.h</Filename>

+    <Filename>Pccts/h/DLexer.h</Filename>

+    <Filename>Pccts/h/DLexerBase.cpp</Filename>

+    <Filename>Pccts/h/DLexerBase.h</Filename>

+    <Filename>Pccts/h/DLG_stream_input.h</Filename>

+    <Filename>Pccts/h/dlgauto.h</Filename>

+    <Filename>Pccts/h/dlgdef.h</Filename>

+    <Filename>Pccts/h/err.h</Filename>

+    <Filename>Pccts/h/int.h</Filename>

+    <Filename>Pccts/h/PBlackBox.h</Filename>

+    <Filename>Pccts/h/pccts_assert.h</Filename>

+    <Filename>Pccts/h/pccts_iostream.h</Filename>

+    <Filename>Pccts/h/pccts_istream.h</Filename>

+    <Filename>Pccts/h/pccts_setjmp.h</Filename>

+    <Filename>Pccts/h/pccts_stdarg.h</Filename>

+    <Filename>Pccts/h/pccts_stdio.h</Filename>

+    <Filename>Pccts/h/pccts_stdlib.h</Filename>

+    <Filename>Pccts/h/pccts_string.h</Filename>

+    <Filename>Pccts/h/PCCTSAST.cpp</Filename>

+    <Filename>Pccts/h/PCCTSAST.h</Filename>

+    <Filename>Pccts/h/pcctscfg.h</Filename>

+    <Filename>Pccts/h/pcnames.bat</Filename>

+    <Filename>Pccts/h/slist.cpp</Filename>

+    <Filename>Pccts/h/SList.h</Filename>

+    <Filename>Pccts/history.ps</Filename>

+    <Filename>Pccts/history.txt</Filename>

+    <Filename>Pccts/KNOWN_PROBLEMS.txt</Filename>

+    <Filename>Pccts/makefile</Filename>

+    <Filename>Pccts/MPW_Read_Me</Filename>

+    <Filename>Pccts/NOTES.bcc</Filename>

+    <Filename>Pccts/NOTES.msvc</Filename>

+    <Filename>Pccts/README</Filename>

+    <Filename>Pccts/RIGHTS</Filename>

+    <Filename>Pccts/support/genmk/genmk.c</Filename>

+    <Filename>Pccts/support/genmk/genmk_old.c</Filename>

+    <Filename>Pccts/support/genmk/makefile</Filename>

+    <Filename>Pccts/support/rexpr/makefile</Filename>

+    <Filename>Pccts/support/rexpr/rexpr.c</Filename>

+    <Filename>Pccts/support/rexpr/rexpr.h</Filename>

+    <Filename>Pccts/support/rexpr/test.c</Filename>

+    <Filename>Pccts/support/set/set.c</Filename>

+    <Filename>Pccts/support/set/set.h</Filename>

+    <Filename>Pccts/support/sym/sym.c</Filename>

+    <Filename>Pccts/support/sym/template.h</Filename>

+    <Filename>PeCoffLoader/BasePeCoff.c</Filename>

+    <Filename>PeCoffLoader/build.xml</Filename>

+    <Filename>PeCoffLoader/Common/EfiImage.h</Filename>

+    <Filename>PeCoffLoader/Ia32/PeCoffLoaderEx.c</Filename>

+    <Filename>PeCoffLoader/Ipf/PeCoffLoaderEx.c</Filename>

+    <Filename>PeCoffLoader/X64/PeCoffLoaderEx.c</Filename>

+    <Filename>PeiRebase/build.xml</Filename>

+    <Filename>PeiRebase/makefile</Filename>

+    <Filename>PeiRebase/PeiRebaseExe.c</Filename>

+    <Filename>PeiRebase/PeiRebaseExe.h</Filename>

+    <Filename>SecApResetVectorFixup/build.xml</Filename>

+    <Filename>SecApResetVectorFixup/SecApResetVectorFixup.c</Filename>

+    <Filename>SecApResetVectorFixup/SecApResetVectorFixup.h</Filename>

+    <Filename>SecFixup/build.xml</Filename>

+    <Filename>SecFixup/SecFixup.c</Filename>

+    <Filename>SecFixup/SecFixup.h</Filename>

+    <Filename>SetStamp/build.xml</Filename>

+    <Filename>SetStamp/SetStamp.c</Filename>

+    <Filename>SplitFile/build.xml</Filename>

+    <Filename>SplitFile/SplitFile.c</Filename>

+    <Filename>StrGather/build.xml</Filename>

+    <Filename>StrGather/StrGather.c</Filename>

+    <Filename>StrGather/StrGather.h</Filename>

+    <Filename>StrGather/StringDB.c</Filename>

+    <Filename>StrGather/StringDB.h</Filename>

+    <Filename>String/build.xml</Filename>

+    <Filename>String/PrintLib.c</Filename>

+    <Filename>String/PrintLibInternal.c</Filename>

+    <Filename>String/PrintLibInternal.h</Filename>

+    <Filename>String/String.c</Filename>

+    <Filename>Strip/build.xml</Filename>

+    <Filename>Strip/Strip.c</Filename>

+    <Filename>VfrCompile/build.xml</Filename>

+    <Filename>VfrCompile/DLGLexer.cpp</Filename>

+    <Filename>VfrCompile/DLGLexer.h</Filename>

+    <Filename>VfrCompile/EfiVfr.h</Filename>

+    <Filename>VfrCompile/EfiVfrParser.cpp</Filename>

+    <Filename>VfrCompile/EfiVfrParser.h</Filename>

+    <Filename>VfrCompile/parser.dlg</Filename>

+    <Filename>VfrCompile/tokens.h</Filename>

+    <Filename>VfrCompile/VfrCompile.cpp</Filename>

+    <Filename>VfrCompile/VfrCompile.g</Filename>

+    <Filename>VfrCompile/VfrServices.cpp</Filename>

+    <Filename>VfrCompile/VfrServices.h</Filename>

+    <Filename>ZeroDebugData/build.xml</Filename>

+    <Filename>ZeroDebugData/ZeroDebugData.c</Filename>

+  </SourceFiles>

+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/Source/VfrCompile/EfiVfr.h b/Source/VfrCompile/EfiVfr.h
new file mode 100644
index 0000000..6419ad7
--- /dev/null
+++ b/Source/VfrCompile/EfiVfr.h
@@ -0,0 +1,181 @@
+/*++

+

+Copyright (c) 2004 - 2005, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiVfr.h

+

+Abstract:

+

+  Defines and prototypes for the EFI internal forms representation

+  setup protocol and drivers

+  

+--*/

+

+#ifndef _EFI_VFR_H_

+#define _EFI_VFR_H_

+

+#include <string.h>

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/InternalFormRepresentation.h>

+

+//

+// This number should be incremented with each change to the VFR compiler.

+// We write the version to the output list file for debug purposes.

+//

+#define VFR_COMPILER_VERSION  "1.88"

+

+//

+// Maximum file path for filenames

+//

+#ifndef MAX_PATH

+#define MAX_PATH        255

+#endif

+#define MAX_QUEUE_COUNT 255

+#define MAX_LINE_LEN    1024

+#define PROGRAM_NAME    "VfrCompile"

+

+//

+// We parse C-style structure definitions which can then be referenced

+// in VFR statements.

+// We need to define an internal structure that can be used to

+// track the fields in a structure definition, and another structure

+// to keep track of the structure name and subfields.

+//

+typedef struct _STRUCT_FIELD_DEFINITION {

+  struct _STRUCT_FIELD_DEFINITION *Next;

+  int                             DataSize;

+  int                             Offset;     // from the start of the structure

+  int                             ArrayLength;

+  char                            IsArray;

+  char                            *Name;

+} STRUCT_FIELD_DEFINITION;

+

+typedef struct _STRUCT_DEFINITION {

+  struct _STRUCT_DEFINITION *Next;

+  int                       Size;

+  int                       LineNum;          // line number where the structure was defined

+  int                       IsNonNV;          // if this is the non-NV data structure definition

+  int                       Referenced;       // if it's referenced anywhere in the VFR

+  int                       VarStoreIdValid;  // found a 'varstore' statement for it in the VFR

+  unsigned short            VarStoreId;       // key from a varstore IFR statement

+  int                       VarStoreLineNum;  // line number where VARSTORE was defined

+  char                      *Name;

+  STRUCT_FIELD_DEFINITION   *Field;

+  STRUCT_FIELD_DEFINITION   *LastField;

+} STRUCT_DEFINITION;

+

+//

+// For the IdEqValList variable list of UINT16's, keep track of them using

+// a linked list until we know how many there are.

+// We also use a linked list of these to keep track of labels used in

+// the VFR script so we can catch duplicates.

+// We'll also use it to keep track of defined varstore id's so we can

+// detect duplicate definitions.

+//

+typedef struct _UINT16_LIST {

+  struct _UINT16_LIST *Next;

+  UINT16              Value;

+  UINT32              LineNum;

+} UINT16_LIST;

+

+typedef struct _GOTO_REFERENCE {

+  struct _GOTO_REFERENCE  *Next;

+  UINT32                  RefLineNum; // line number of source file where referenced

+  UINT16                  Value;

+} GOTO_REFERENCE;

+

+typedef struct _FORM_ID_VALUE {

+  struct _FORM_ID_VALUE *Next;

+  UINT32                LineNum;

+  UINT16                Value;

+} FORM_ID_VALUE;

+

+//

+// We keep track in the parser of all "#line 4 "x.y"" strings so we

+// can cross-reference the line numbers in the preprocessor output .i file

+// to the original input files.

+//

+typedef struct _PARSER_LINE_DEFINITION {

+  struct _PARSER_LINE_DEFINITION  *Next;

+  UINT32                          HashLineNum;  // from the #line stmt

+  UINT32                          TokenLineNum; // line number in the .i file

+  CHAR8                           *FileName;    // from the #line stmt

+} PARSER_LINE_DEFINITION;

+

+extern PARSER_LINE_DEFINITION *gLineDefinition;

+extern PARSER_LINE_DEFINITION *gLastLineDefinition;

+

+extern

+char                          *

+ConvertLineNumber (

+  UINT32 *LineNum

+  )

+/*++

+

+Routine Description:

+  Given the line number in the preprocessor-output file, use the line number

+  information we've saved to determine the source file name and line number

+  where the code originally came from. This is required for error reporting.

+

+Arguments:

+  LineNum - the line number in the preprocessor-output file.

+

+Returns:

+  Returns a pointer to the source file name. Also returns the line number 

+  in the provided LineNum argument

+

+--*/

+;

+

+typedef struct _IFR_BYTE {

+  struct _IFR_BYTE  *Next;

+  UINT32            LineNum;

+  UINT8             OpcodeByte;

+  UINT8             KeyByte;

+} IFR_BYTE;

+

+typedef struct {

+  CHAR8 VfrFileName[MAX_PATH];

+  CHAR8 VfrListFileName[MAX_PATH];

+  INT8  CreateListFile;

+  INT8  CreateIfrBinFile;

+  CHAR8 IfrOutputFileName[MAX_PATH];

+  CHAR8 OutputDirectory[MAX_PATH];

+  CHAR8 PreprocessorOutputFileName[MAX_PATH];

+  CHAR8 VfrBaseFileName[MAX_PATH];  // name of input VFR file with no path or extension

+  CHAR8 *IncludePaths;

+  CHAR8 *CPreprocessorOptions;

+} OPTIONS;

+

+extern OPTIONS  gOptions;

+

+VOID

+WriteStandardFileHeader (

+  FILE *OutFptr

+  )

+/*++

+

+Routine Description:

+  This function is invoked to emit a standard header to an

+  output text file.

+  

+Arguments:

+  OutFptr - file to write the header to

+

+Returns:

+  None

+

+--*/

+;

+

+#endif // #ifndef _EFI_VFR_H_

diff --git a/Source/VfrCompile/VfrCompile.g b/Source/VfrCompile/VfrCompile.g
new file mode 100644
index 0000000..44820bc
--- /dev/null
+++ b/Source/VfrCompile/VfrCompile.g
@@ -0,0 +1,3529 @@
+/*++

+

+Copyright (c) 2004 - 2005, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  VfrCompile.g

+

+Abstract:

+

+  PCCTS parser and lexer definitions for the EFI VFR forms compiler

+  

+--*/  

+

+#header<<

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/MultiPhase.h>

+#include <Common/InternalFormRepresentation.h>

+#include <Protocol/UgaDraw.h>

+#include <Protocol/Hii.h>

+

+#include "CommonLib.h"

+#include "EfiUtilityMsgs.h"

+#include "EfiVfr.h"

+#include "VfrServices.h"

+

+#include <ctype.h>

+#ifndef __GNUC__

+#include <direct.h>

+#include <process.h> // for spawn functions

+#else

+#include <unistd.h>

+#endif

+

+>>

+

+<<

+

+//

+// Base info for DLG-generated scanner

+//

+#include "DLexerBase.h"    

+

+//

+// Include the scanner file generated by DLG

+//

+#include "DLGLexer.h"    

+

+class DLGLexerVfr : public DLGLexer

+{

+public:

+  DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};

+  INT32 errstd (char *Text) 

+  { 

+    printf ("unrecognized input '%s'\n", Text); 

+  }

+

+};

+

+//

+// Base token definitions for ANTLR

+//

+#include "AToken.h"

+

+//

+// This is how we invoke the C preprocessor on the VFR source file

+// to resolve #defines, #includes, etc. To make C source files

+// shareable between VFR and drivers, define VFRCOMPILE so that

+// #ifdefs can be used in shared .h files.

+//

+#ifdef __GNUC__

+#define PREPROCESSOR_COMMAND        "gcc "

+#define PREPROCESSOR_OPTIONS        "-x c -E -P -DVFRCOMPILE "

+#define FILE_SEP_CHAR '/'

+#define FILE_SEP_STRING "/"

+#else

+#define PREPROCESSOR_COMMAND        "cl.exe "

+#define PREPROCESSOR_OPTIONS        "/nologo /P /TC /DVFRCOMPILE "

+#define FILE_SEP_CHAR '/'

+#define FILE_SEP_STRING "/"

+#endif

+

+typedef ANTLRCommonToken ANTLRToken;

+

+//

+// Specify the filename extensions for the files we generate.

+//

+#define VFR_BINARY_FILENAME_EXTENSION       ".c"

+#define VFR_LIST_FILENAME_EXTENSION         ".lst"

+

+static 

+VOID 

+Usage ();

+

+static 

+STATUS 

+ProcessArgs (

+  int         Argc, 

+  char        *Argv[]

+  );

+

+static 

+VOID 

+Cleanup ();

+

+//

+// Globals

+//

+OPTIONS gOptions;

+

+int 

+main (

+  int   argc, 

+  char  **argv

+  )

+/*++

+

+Routine Description:

+  Application entry point function. Parse command-line arguments, 

+  invoke the parser, clean up, and return.

+

+Arguments:

+  argc - standard argc passed to main() per C conventions

+  argv - standard argv passed to main() per C conventions

+

+Returns:

+  STATUS_SUCCESS - program executed with no errors or warnings

+  STATUS_WARNING - program executed with warnings

+  STATUS_ERROR   - non-recoverable errors encountered while processing

+

+--*/

+{

+  FILE      *VfrFptr;

+  char      *Cmd;

+  char      *Cptr;

+  int       Len;

+  STATUS    Status;

+    

+  //

+  // Set our program name for the error printing routines.

+  // Then set printing limits.

+  //

+  SetUtilityName (PROGRAM_NAME);

+  SetPrintLimits (20, 20, 30);

+  //

+  // Process the command-line arguments

+  //

+  if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {

+    Usage ();

+    Cleanup();

+    return STATUS_ERROR;

+  }

+  VfrFptr = NULL;

+  //

+  // Verify the VFR script file exists

+  //

+  if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {

+    Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");

+    Cleanup();

+    return STATUS_ERROR;

+  }

+  //

+  // Now close the file and make a system call to run the preprocessor

+  // on it.

+  //

+  fclose (VfrFptr);

+  Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10;

+  if (gOptions.CPreprocessorOptions != NULL) {

+    Len += strlen (gOptions.CPreprocessorOptions) + 1;

+  }

+  if (gOptions.IncludePaths != NULL) {

+    Len += strlen (gOptions.IncludePaths) + 1;

+  }

+  Cmd = (char *)malloc (Len);

+  if (Cmd == NULL) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");

+    Cleanup();

+    return STATUS_ERROR;

+  }  

+  strcpy (Cmd, PREPROCESSOR_OPTIONS);

+  if (gOptions.IncludePaths != NULL) {

+    strcat (Cmd, gOptions.IncludePaths);

+    strcat (Cmd, " ");

+  }

+  if (gOptions.CPreprocessorOptions != NULL) {

+    strcat (Cmd, gOptions.CPreprocessorOptions);

+    strcat (Cmd, " ");

+  }

+  strcat (Cmd, gOptions.VfrFileName);

+#ifndef __GNUC__

+  Status = _spawnlp (_P_WAIT, PREPROCESSOR_COMMAND, Cmd, NULL);

+#else

+  {

+    char CommandLine[1000];

+    char *p;

+

+    //

+    // Lean the slashes forward.

+    //

+    for (p = gOptions.PreprocessorOutputFileName; *p; p++) {

+      if (*p=='\\') {

+        *p=FILE_SEP_CHAR;

+      }

+    }

+ 

+    //

+    // Lean the slashes forward.

+    //

+    for (p = Cmd; *p; p++) {

+      if (*p=='\\') {

+        *p=FILE_SEP_CHAR;

+      }

+    }

+ 

+    sprintf(CommandLine, "%s %s > %s", PREPROCESSOR_COMMAND, Cmd, gOptions.PreprocessorOutputFileName);

+    Status = system (CommandLine);

+  }

+#endif

+  if (Status != 0) {

+    Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");

+    printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);

+    Cleanup();

+    return STATUS_ERROR;

+  }

+  free (Cmd);

+  //

+  // Open the preprocessor output file

+  //

+  if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {

+    Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file", 

+      gOptions.PreprocessorOutputFileName);

+    Cleanup();

+    return STATUS_ERROR;

+  }

+  //

+  // Define input VFR file

+  //

+  DLGFileInput InputFile (VfrFptr);

+  //

+  // Define an instance of the scanner    

+  //

+  DLGLexerVfr Scanner (&InputFile);

+  //

+  // Define token buffer between scanner and parser

+  //

+  ANTLRTokenBuffer Pipe (&Scanner);    

+  //

+  // Create a token to use as a model

+  //

+  ANTLRToken Tok;     

+  //

+  // Tell the scanner what type the token is

+  //

+  Scanner.setToken (&Tok);    

+  //

+  // Create an instance of our parser

+  //

+  EfiVfrParser Parser (&Pipe);    

+  //

+  // Initialize the parser    

+  //

+  Parser.init ();

+  Status = GetUtilityStatus ();

+  if (Status != STATUS_SUCCESS) {

+    Cleanup();

+    return Status;

+  }  

+  //

+  // Start the first rule    

+  //

+  Parser.program ();

+  //

+  // Close the input script file

+  //

+  fclose (VfrFptr);

+  Parser.WriteIfrBytes ();

+  //

+  // Call cleanup, which does some extra checking of the script

+  //

+  Parser.Cleanup ();

+  Cleanup();

+  //

+  // If we had an error somewhere, delete our output files so that

+  // a subsequent build will rebuild them.

+  //

+  Status = GetUtilityStatus ();

+  if (Status == STATUS_ERROR) {

+    remove (gOptions.IfrOutputFileName);

+  }

+  return Status;

+}

+static

+VOID

+Cleanup ()

+/*++

+

+Routine Description:

+  Free up memory allocated during parsing.

+

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{

+  //

+  // Free up our string we allocated to track the include paths

+  //

+  if (gOptions.IncludePaths != NULL) {

+    free (gOptions.IncludePaths);

+    gOptions.IncludePaths = NULL;

+  }

+  //

+  // Free up our string we allocated to track preprocessor options

+  //

+  if (gOptions.CPreprocessorOptions != NULL) {

+    free (gOptions.CPreprocessorOptions);

+    gOptions.CPreprocessorOptions = NULL;

+  }

+}  

+

+static

+STATUS

+ProcessArgs (

+  int         Argc, 

+  char        *Argv[]

+  )

+/*++

+

+Routine Description:

+  Process the command-line arguments.

+

+Arguments:

+  Argc - standard argc passed to main()

+  Argv - standard argv passed to main()

+

+Returns:

+  STATUS_SUCCESS - program should continue (all args ok)

+

+--*/

+{

+  char    *IncludePaths;

+  char    *CPreprocessorOptions;

+  int     Len;  

+  char    CopyStr[MAX_PATH];

+  char    *Cptr;

+

+  //

+  // Put options in known state.

+  //

+  memset ((char *)&gOptions, 0, sizeof (OPTIONS));

+  //

+  // Go through all the arguments that start with '-'

+  //

+  Argc--;

+  Argv++;

+  while ((Argc > 0) && (Argv[0][0] == '-')) {

+    //

+    // -? or -h help option -- return an error for printing usage

+    //

+    if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {

+      return STATUS_ERROR;

+      break;

+    //

+    // -l to create a listing output file

+    //

+    } else if (stricmp (Argv[0], "-l") == 0) {

+      gOptions.CreateListFile = 1;

+    //

+    // -I include_path option for finding include files. We'll pass this

+    // to the preprocessor. Turn them all into a single include string.

+    //

+    } else if (stricmp (Argv[0], "-i") == 0) {

+      if ((Argc < 2) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument");

+        return STATUS_ERROR;

+      }

+      Argc--;

+      Argv++;

+      Len = strlen (" -I ");

+      Len += strlen (Argv[0]) + 2;

+      if (gOptions.IncludePaths != NULL) {

+        Len += strlen (gOptions.IncludePaths);

+      }

+      IncludePaths = (CHAR8 *)malloc (Len);

+      if (IncludePaths == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+      IncludePaths[0] = 0;

+      if (gOptions.IncludePaths != NULL) {

+        strcpy (IncludePaths, gOptions.IncludePaths);

+        free (gOptions.IncludePaths);

+      }

+      strcat (IncludePaths, " -I ");

+      strcat (IncludePaths, Argv[0]);

+      gOptions.IncludePaths = IncludePaths;

+    //

+    // -od OutputDirectory to define a common directory for output files

+    //

+    } else if (stricmp (Argv[0], "-od") == 0) {

+      if ((Argc < 2) || (Argv[1][0] == '-')) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");

+        return STATUS_ERROR;

+      }

+      Argc--;

+      Argv++;

+      strcpy (gOptions.OutputDirectory, Argv[0]);

+    } else if (stricmp (Argv[0], "-ibin") == 0) {

+      gOptions.CreateIfrBinFile = 1;

+    } else if (stricmp (Argv[0], "-nostrings") == 0) {

+      // deprecated option

+    //

+    // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.

+    // Turn them all into a single string.

+    //

+    } else if (stricmp (Argv[0], "-ppflag") == 0) {

+      if (Argc < 2) {

+        Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");

+        return STATUS_ERROR;

+      }

+      Argc--;

+      Argv++;

+      Len = strlen (Argv[0]) + 2;

+      if (gOptions.CPreprocessorOptions != NULL) {

+        Len += strlen (gOptions.CPreprocessorOptions);

+      }

+      CPreprocessorOptions = (CHAR8 *)malloc (Len);

+      if (CPreprocessorOptions == NULL) {

+        Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+        return STATUS_ERROR;

+      }

+      CPreprocessorOptions[0] = 0;

+      if (gOptions.CPreprocessorOptions != NULL) {

+        strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);

+        free (gOptions.CPreprocessorOptions);

+      }

+      strcat (CPreprocessorOptions, " ");

+      strcat (CPreprocessorOptions, Argv[0]);

+      gOptions.CPreprocessorOptions = CPreprocessorOptions;

+    } else {

+      Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");

+      return STATUS_ERROR;

+    }

+    Argc--;

+    Argv++;

+  }

+  //

+  // Must specify at least the vfr file name

+  //

+  if (Argc > 1) {

+    Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");

+    return STATUS_ERROR;

+  } else if (Argc < 1) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");

+    return STATUS_ERROR;

+  }

+  strcpy (gOptions.VfrFileName, Argv[0]);

+  //

+  // We run the preprocessor on the VFR file to manage #include statements.

+  // Unfortunately the preprocessor does not allow you to specify the

+  // output name or path of the resultant .i file, so we have to do

+  // some work. Here we'll extract the basename of the VFR file, then

+  // append .i on the end. 

+  //

+  strcpy (CopyStr, gOptions.VfrFileName);

+  Cptr = CopyStr + strlen (CopyStr) - 1;

+  for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':') && (*Cptr != '/'); Cptr--);

+  if (Cptr == CopyStr) {

+    strcpy (gOptions.PreprocessorOutputFileName, Cptr);

+    strcpy (gOptions.VfrBaseFileName, Cptr);

+  } else {

+    strcpy (gOptions.PreprocessorOutputFileName, Cptr+1);

+    strcpy (gOptions.VfrBaseFileName, Cptr+1);

+  }

+  for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++);

+  strcpy (Cptr, ".i");

+  //

+  // Terminate the vfr file basename at the extension

+  //

+  for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {

+  }

+  *Cptr = 0; 

+  //

+  // If they defined an output directory, prepend all output files

+  // with the working directory. Output files of interest:

+  //    VfrListFileName             -- list file

+  //    IfrOutputFileName           -- IFR bytes 

+  //    StringOutputFileName        -- string bytes

+  //    StringListFileName          -- not used

+  //    StringDefineFileName        -- #defines of string identifiers

+  //

+  // We have two cases:

+  //   1. Output directory (-od) not specified, in which case output files

+  //      go to the current working directory.

+  //   2. Output directory specified, in which case the output files

+  //      go directly to the specified directory.

+  //

+  if (gOptions.OutputDirectory[0] == 0) {

+    CopyStr[0] = 0;

+#ifndef __GNUC__

+    _getcwd (CopyStr, sizeof (CopyStr));

+#else

+    getcwd (CopyStr, sizeof (CopyStr));

+#endif

+    strcpy (gOptions.OutputDirectory, CopyStr);

+  }

+  //

+  // Make sure output directory has a trailing backslash

+  //

+  if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\' ||

+      gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '/') {

+    strcat (gOptions.OutputDirectory, FILE_SEP_STRING);

+  }

+  //

+  // Create the base output file name as: path\base, copy it to all the output

+  // filenames, and then add the appropriate extension to each.

+  //

+  strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);

+  strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);

+  strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);

+  strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);

+  strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);

+  //

+  // We set a default list file name, so if they do not

+  // want a list file, null out the name now.

+  //

+  if (gOptions.CreateListFile == 0) {

+    gOptions.VfrListFileName[0] = 0;

+  }

+  return STATUS_SUCCESS;

+}

+static 

+VOID 

+Usage ()

+/*++

+

+Routine Description:

+  Print utility usage instructions

+

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{

+  int Index;

+  const char *Help[] = {

+    " ", 

+    "VfrCompile version " VFR_COMPILER_VERSION,

+    " ",

+    "  Usage: VfrCompile {options} [VfrFile]",

+    " ",

+    "    where options include:",

+    "      -? or -h       prints this help",

+    "      -l             create an output IFR listing file",

+    "      -i IncPath     add IncPath to the search path for VFR included files",

+    "      -od OutputDir  deposit all output files to directory OutputDir (default=cwd)",

+    "      -ibin          create an IFR HII pack file",

+    "    where parameters include:",

+    "      VfrFile        name of the input VFR script file",

+    " ",

+    NULL

+    };

+  for (Index = 0; Help[Index] != NULL; Index++) {

+    fprintf (stdout, "%s\n", Help[Index]);

+  }

+}

+    

+>>

+

+

+#lexaction

+<<

+

+#include "EfiVfr.h"

+

+PARSER_LINE_DEFINITION  *gLineDefinition = NULL;

+PARSER_LINE_DEFINITION  *gLastLineDefinition = NULL;

+

+VOID

+AddFileLine (

+  char      *TokenString,

+  UINT32    TokenLine

+  )

+/*++

+

+Routine Description:

+  During the lexer phase, if we encounter a #line statement output by

+  the preprocessor, this function gets called. We'll save off the info 

+  for error reporting purposes. The preprocessor line information has the

+  form:

+    

+    #line 3 "FileName.c"  

+

+Arguments:

+  TokenString - the parsed string as shown above

+  TokenLine   - the line number in the preprocessed output file 

+  

+Returns:

+  NA

+

+--*/

+{

+  PARSER_LINE_DEFINITION  *LineDef;

+  CHAR8                   *Cptr;

+  

+  //

+  // Allocate a structure in which we can keep track of this line information.

+  //

+  LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));

+  memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));

+  LineDef->TokenLineNum = TokenLine;

+  LineDef->HashLineNum = atoi (TokenString + 6);

+  //

+  // Find the quotes in the filename, then allocate space in the line

+  // def structure for a copy of the filename. Finally, copy it without

+  // quotes to the line def.

+  //

+  for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);

+  if (*Cptr == '"') {

+    LineDef->FileName = (CHAR8 *)malloc (strlen (Cptr));

+    Cptr++;

+    strcpy (LineDef->FileName, Cptr);

+    for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);

+    *Cptr = 0;   

+    //

+    // Now add this new one to the list

+    //

+    if (gLineDefinition == NULL) {

+      gLineDefinition = LineDef;

+    } else {

+      gLastLineDefinition->Next = LineDef;

+    }

+    gLastLineDefinition = LineDef;

+  } else {

+    Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);

+    free (LineDef);

+    return;

+  }

+}

+char *

+ConvertLineNumber (

+  UINT32 *LineNum

+  )

+/*++

+

+Routine Description:

+  Given the line number in the preprocessor-output file, use the line number

+  information we've saved to determine the source file name and line number

+  where the code originally came from. This is required for error reporting.

+

+Arguments:

+  LineNum - the line number in the preprocessor-output file.

+

+Returns:

+  Returns a pointer to the source file name. Also returns the line number 

+  in the provided LineNum argument

+

+--*/

+{

+  PARSER_LINE_DEFINITION  *LineDef;

+  //

+  // Step through our linked list of #line information we saved off. 

+  // For each one, look at its line number, and the line number of the

+  // next record, and see if the passed-in line number is in the range.

+  // If it is, then convert the line number to the appropriate line number

+  // of the original source file.

+  //

+  for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {

+    //

+    // The given LineNum is the line number from the .i file.

+    // Find a line definition whose range includes this line number,

+    // convert the line number, and return the filename.

+    //

+    if (LineDef->TokenLineNum <= *LineNum) {

+      if (LineDef->Next != NULL) {

+        if (LineDef->Next->TokenLineNum > *LineNum) {

+          *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;

+          return LineDef->FileName;

+        }

+      } else {

+        //

+        // Last one in the list of line definitions, so has to be right

+        //

+        *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;

+        return LineDef->FileName;

+      }

+    }

+  }

+  return NULL;

+}

+

+>>

+

+//

+// Define a lexical class for parsing quoted strings. Basically

+// starts with a double quote, and ends with a double quote that

+// is not preceeded with a backslash.

+//

+#lexclass QUOTED_STRING

+#token TheString            "~[\"]*\"" << mode (START); >>     

+

+//

+// Define a lexical class for parsing "#pragma pack" statements. 

+// We do this just for convenience (since we skip them here) so

+// that users can include some minimal .h files.

+//

+#lexclass PRAGMA_PACK

+#token "pack"     << skip (); >>

+#token "[\ \t]"   << skip (); >> 

+#token "\("       << skip (); >>

+#token "[0-9]*"   << skip (); >>

+#token "\)"       << skip (); mode (START); >>

+

+//

+// Define a lexclass for skipping over C++ style comments

+//

+#lexclass CPP_COMMENT

+#token "~[\n]*"       << skip (); >>

+#token "\n"           << skip (); mode (START); newline (); >>

+

+//

+// Standard lexclass is START

+//

+#lexclass START

+

+//

+// Find start of C++ style comments

+//

+#token "//"     << skip (); mode (CPP_COMMENT); >>

+

+//

+// Skip whitespace

+//

+#token "[\ \t]"   << skip (); >> 

+

+//

+// Skip over newlines, but count them

+//

+#token "\n"       << skip (); newline (); >>

+

+//

+// Skip pragma pack statements

+//

+#token "\#pragma" << skip (); mode(PRAGMA_PACK); >>

+

+//

+// Skip over 'extern' in any included .H file

+//

+#token "extern"   << skip (); >>

+

+//

+// Tokens for the different keywords. Syntax is:

+// TokenName("ErrorMessageText")    "TokenString"

+//   where:

+//     TokenName is the token name (must be capitalized) that is used in the rules

+//     ErrorMessageText is the string the compiler emits when it detects a syntax error

+//     TokenString is the actual matching string used in the user script

+//

+#token LineDefinition                           "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>

+#token FormSet("formset")                       "formset"

+#token EndFormSet("endformset")                 "endformset"

+#token Title("title")                           "title"

+#token FormId("formid")                         "formid"

+#token OneOf("oneof")                           "oneof"

+#token Prompt("prompt")                         "prompt"

+#token OrderedList("orderedlist")               "orderedlist"

+#token EndList("endlist")                       "endlist"

+#token EndForm("endform")                       "endform"

+#token EndOneOf("endoneof")                     "endoneof"

+#token Form("form")                             "form"

+#token Subtitle("subtitle")                     "subtitle"

+#token Help("help")                             "help"

+#token VarId("varid")                           "varid"

+#token Text("text")                             "text"

+#token Option("option")                         "option"

+#token Value("value")                           "value"

+#token Flags("flags")                           "flags"

+#token Date("date")                             "date"

+#token EndDate("enddate")                       "enddate"

+#token Year("year")                             "year"

+#token Month("month")                           "month"

+#token Day("day")                               "day"

+#token Time("time")                             "time"

+#token EndTime("endtime")                       "endtime"

+#token Hour("hour")                             "hour"

+#token Minute("minute")                         "minute"

+#token Second("second")                         "second"

+#token AND("AND")                               "AND"

+#token OR("OR")                                 "OR"

+#token GrayOutIf("grayoutif")                   "grayoutif"

+#token NOT("NOT")                               "NOT"

+#token Label("label")                           "label"

+#token Timeout("timeout")                       "timeout"

+#token Inventory("inventory")                   "inventory"

+#token StringToken("STRING_TOKEN")              "STRING_TOKEN"

+#token NonNvDataMap("_NON_NV_DATA_MAP")         "_NON_NV_DATA_MAP"

+#token Struct("struct")                         "struct"

+#token Uint64("UINT64")                         "UINT64"

+#token Uint32("UINT32")                         "UINT32"

+#token Uint16("UINT16")                         "UINT16"

+#token Char16("CHAR16")                         "CHAR16"

+#token Uint8("UINT8")                           "UINT8"

+#token Guid("guid")                             "guid"

+#token CheckBox("checkbox")                     "checkbox"

+#token EndCheckBox("endcheckbox")               "endcheckbox"

+#token Numeric("numeric")                       "numeric"

+#token EndNumeric("endnumeric")                 "endnumeric"            

+#token Minimum("minimum")                       "minimum"         

+#token Maximum("maximum")                       "maximum"         

+#token Step("step")                             "step"      

+#token Default("default")                       "default"         

+#token Password("password")                     "password"          

+#token EndPassword("endpassword")               "endpassword"             

+#token String("string")                         "string"        

+#token EndString("endstring")                   "endstring"           

+#token MinSize("minsize")                       "minsize"         

+#token MaxSize("maxsize")                       "maxsize"         

+#token Encoding("encoding")                     "encoding"

+#token SuppressIf("suppressif")                 "suppressif"

+#token Hidden("hidden")                         "hidden"

+#token Goto("goto")                             "goto"

+#token InconsistentIf                           "inconsistentif"

+#token EndIf("endif")                           "endif"

+#token IdEqId("ideqid")                         "ideqid"

+#token IdEqVal("ideqval")                       "ideqval"

+#token VarEqVal("vareqval")                     "vareqval"

+#token Var("var")                               "var"

+#token IdEqValList("ideqvallist")               "ideqvallist"

+#token Length("length")                         "length"

+#token Values("values")                         "values"

+#token Key("key")                               "key"

+#token DefaultFlag("DEFAULT")                   "DEFAULT"

+#token ManufacturingFlag("MANUFACTURING")       "MANUFACTURING"

+#token InteractiveFlag("INTERACTIVE")           "INTERACTIVE"

+#token NVAccessFlag("NV_ACCESS")                "NV_ACCESS"

+#token ResetRequiredFlag("RESET_REQUIRED")      "RESET_REQUIRED"

+#token LateCheckFlag("LATE_CHECK")              "LATE_CHECK"

+#token Class("class")                           "class"

+#token Subclass("subclass")                     "subclass"

+#token TypeDef("typedef")                       "typedef"

+#token Restore("restore")                       "restore"

+#token Save("save")                             "save"

+#token Defaults("defaults")                     "defaults"

+#token Banner("banner")                         "banner"

+#token Align("align")                           "align"

+#token Left("left")                             "left"

+#token Right("right")                           "right"

+#token Center("center")                         "center"

+#token Line("line")                             "line"

+#token VarStore("varstore")                     "varstore"

+#token Name("name")                             "name"

+#token Oem("oem")                               "oem"

+#token True("TRUE")                             "TRUE"

+#token False("FALSE")                           "FALSE"

+#token GreaterThan(">")                         ">"

+#token GreaterEqual(">=")                       ">="

+#token LessThan("<")                          "<"

+#token LessEqual("<=")                        "<="

+

+//

+// Define the class and subclass tokens

+//

+#token ClassNonDevice("NONDEVICE")                        "NON_DEVICE"

+#token ClassDiskDevice("DISK_DEVICE")                     "DISK_DEVICE"

+#token ClassVideoDevice("VIDEO_DEVICE")                   "VIDEO_DEVICE"

+#token ClassNetworkDevice("NETWORK_DEVICE")               "NETWORK_DEVICE"

+#token ClassInputDevice("INPUT_DEVICE")                   "INPUT_DEVICE"

+#token ClassOnBoardDevice("ONBOARD_DEVICE")               "ONBOARD_DEVICE"

+#token ClassOtherDevice("OTHER_DEVICE")                   "OTHER_DEVICE"

+

+#token SubclassSetupApplication("SETUP_APPLICATION")      "SETUP_APPLICATION"

+#token SubclassGeneralApplication("GENERAL_APPLICATION")  "GENERAL_APPLICATION"

+#token SubclassFrontPage("FRONT_PAGE")                    "FRONT_PAGE"

+#token SubclassSingleUse("SINGLE_USE")                    "SINGLE_USE"

+

+#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]"   // 3 lowercase characters

+#token StringIdentifier("string identifier")    "[A-Za-z_][A-Za-z_0-9]*"

+#token Number("numeric value")                  "(0x[0-9A-Fa-f]+) | [0-9]+"

+#token OpenBrace("{")                           "\{"

+#token CloseBrace("}")                          "\}"

+#token OpenParen("(")                           "\("

+#token CloseParen(")")                          "\)"

+#token OpenBracket("[")                         "\["

+#token CloseBracket("]")                        "\]"

+

+//

+// Define all other invalid characters so that they get through the lexical phase

+// and we can catch them during the parse phase. We get much better error

+// messages then. 

+//

+#token InvalidCharacters("invalid characters")  "~[;:=,\.\|]"  

+

+//

+// This is the overall definition of a VFR form definition script.

+//

+program :

+  ( dataStructDefinition )*

+  formSetStatement   

+  ( vfrStatementVarStore )*

+  ( formDefinition )*

+  EFS:EndFormSet  ";"                   << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>

+  "@" // end of file

+  ;

+    

+formSetStatement :

+  FS:FormSet                            << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>

+  Guid "=" 

+  OpenBrace 

+  G1:Number ","

+  G2:Number ","

+  G3:Number ","

+  OpenBrace

+  G4:Number ","

+  G5:Number ","

+  G6:Number ","

+  G7:Number ","

+  G8:Number ","

+  G9:Number ","

+  G10:Number ","

+  G11:Number 

+  CloseBrace

+  CloseBrace                            << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),

+                                                           G4->getText (), G5->getText (), G6->getText (), G7->getText (),

+                                                           G8->getText (), G9->getText (), G10->getText (), G11->getText ()

+                                                          );

+                                         >>

+  ","

+  Title "=" getStringId ","

+  Help  "=" getStringId ","

+  //

+  // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)

+  //

+                                            << WriteDWord (0, 0); WriteDWord (0, 0); >>

+  Class "=" CVAL:classDefinition ","        << WriteClass (); >>

+  Subclass "=" SVAL:subclassDefinition ","  << WriteSubclass (); >>

+                                            << WriteWord (mNvDataStructSize); >>

+  ;  

+

+//

+// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C

+//

+classDefinition :

+  validClassNames ( "\|" validClassNames )*

+  ;

+  

+validClassNames :

+    CND:ClassNonDevice          << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>

+  | CDD:ClassDiskDevice         << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>

+  | CVD:ClassVideoDevice        << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>

+  | CNW:ClassNetworkDevice      << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>

+  | CID:ClassInputDevice        << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>

+  | COB:ClassOnBoardDevice      << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>

+  | COD:ClassOtherDevice        << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>

+  | CNUM:Number                 << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>

+  ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>

+

+//

+// A form can only be of one subclass type.

+//

+subclassDefinition :

+    SSA:SubclassSetupApplication    << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>

+  | SGA:SubclassGeneralApplication  << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>

+  | SFP:SubclassFrontPage           << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>

+  | SSU:SubclassSingleUse           << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>

+  | SNUM:Number                     << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>

+  ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>

+

+//

+// Parse a C type data structure for storing VFR setup data. Allow:

+//  typedef struct _XXX_ {

+//     (fields)

+//  } MY_NV_DATA;

+//

+dataStructDefinition :

+  << int IsNonNV = 0; >>

+  { TypeDef } 

+  S:Struct                          

+  (

+    NonNvDataMap                    << IsNonNV = 1; >>

+  |

+    { StringIdentifier }

+  )                                 << StartStructDefinition (IsNonNV, S->getLine()); >>

+  OpenBrace 

+  dataStructFields 

+  CloseBrace NAME:StringIdentifier  << EndStructDefinition (NAME->getText(), NAME->getLine()); >>

+  ";"

+  ;

+

+//

+// Parse a C type data structure for defining data that is not stored in NV.

+//  typedef struct _NON_NV_DATA_MAP {

+//     (fields)

+//  } NON_NV_DATA_MAP;

+//

+nonNvDataStructDefinition :

+  { TypeDef } 

+  Struct NonNvDataMap

+  { StringIdentifier }

+  OpenBrace 

+  dataStructFields 

+  CloseBrace NAME:StringIdentifier        << AddStructField (NAME->getText(), NAME->getLine(), 0, 0, 0); >>

+  ";"                                             

+  ;

+

+dataStructFields :

+  ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   UINT64 Name[4];

+//   UINT64 Name;

+//

+// Used while parsing the NV data map structures.

+//

+dataStructField64 :

+  << int ArrayLength = 1; char IsArray = 0; >>

+  "UINT64" 

+  NAME:StringIdentifier 

+  ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) 

+                                                    << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   UINT32 Name[4];

+//   UINT32 Name;

+//

+// Used while parsing the NV data map structures.

+//

+dataStructField32 :

+  << int ArrayLength = 1; char IsArray = 0; >>

+  "UINT32" 

+  NAME:StringIdentifier 

+  ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )  

+                                                    << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   UINT16 Name[4];

+//   UINT16 Name;

+//

+// Used while parsing the NV data map structures.

+//

+dataStructField16 :

+  << int ArrayLength = 1; char IsArray = 0; >>

+  ( "UINT16" | "CHAR16" )

+  NAME:StringIdentifier 

+  ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) 

+                                                    << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   UINT8 Name[4];

+//   UINT8 Name;

+//

+// Used while parsing the NV data map structures.

+//

+dataStructField8 :

+  << int ArrayLength = 1; char IsArray = 0; >>

+  "UINT8" 

+  NAME:StringIdentifier 

+  ( ";" | OpenBracket IVal:Number CloseBracket ";"  << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) 

+                                                    << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//    form formid = 1,

+//      title  = STRING_TOKEN(STR_FORM_TITLE);

+//      -- form statements --

+//    endform;

+//

+//  The Form ID cannot be 0

+//

+formDefinition :

+  FRM:Form FormId                << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >> 

+  "=" 

+  VAL:Number                     << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>

+  ","

+  Title "=" getStringId ";"      // writes string identifier

+  ( vfrStatements )*

+  ENDF:EndForm  ";"              << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>

+  ;

+

+//

+// VFR statements in a formset

+//

+vfrStatements :

+  vfrStatementSubTitle        | 

+  vfrStatementOneOf           |

+  vfrStatementTextText        |

+  vfrStatementCheckBox        |

+  vfrStatementNumeric         |

+  vfrStatementDate            |

+  vfrStatementTime            |

+  vfrStatementPassword        |

+  vfrStatementString          |

+  vfrStatementSuppressIf      |

+  vfrStatementHidden          |

+  vfrStatementGoto            | 

+  vfrStatementGrayOutIf       |

+  vfrStatementInconsistentIf  |

+  vfrStatementLabel           |

+  vfrStatementBanner          |

+  vfrStatementInventory       |

+  vfrStatementOrderedList     |

+  vfrStatementOem             |

+  vfrStatementSaveRestoreDefaults

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   label 100;

+//

+vfrStatementLabel :

+  OPID:Label                              << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>

+  VAL:Number                              << 

+                                              WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); 

+                                              AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());

+                                          >>

+  ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   oem 0x12, 0x34, 0x56;

+//

+vfrStatementOem :

+  OPID:Oem                              << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>

+  ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )

+  ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*

+  ";"

+  ;

+  

+//*****************************************************************************

+//

+// PARSE:

+//   inconsistentif NOT .... AND NOT .... OR ... endif;

+//

+vfrStatementInconsistentIf : 

+  << ResetFlags (); >>

+  IIFOP:InconsistentIf                  << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>

+  Prompt "=" getStringId ","

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* "," 

+  }

+  << WriteFlags (); >> //  write the flags field

+  vfrBooleanExpression

+  EOP:EndIf ";"                         << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>

+  ;

+

+//*****************************************************************************

+// 

+// PARSE:

+//   TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR 

+//               ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND

+//            (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR

+//               vareqval var(VAR_EQ_TEST_NAME) == 0x1)

+//

+// For supporting complex express, divide the vfrBooleanExpression to two parts

+// so that pred-LL(k) parser can parse incrementally.

+//

+vfrBooleanExpression :

+  leftPartVfrBooleanExp { rightPartVfrBooleanExp }

+  ;

+  

+leftPartVfrBooleanExp :

+  OpenParen vfrBooleanExpression CloseParen                                                        |

+  (ideqval | ideqid | ideqvallist | vareqval | truefalse)                                          |

+  NOPID:NOT leftPartVfrBooleanExp           << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>

+  ;

+

+rightPartVfrBooleanExp :

+  AOPID:AND vfrBooleanExpression            << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >>  |

+  OOPID:OR vfrBooleanExpression             << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   TRUE

+//

+truefalse :

+  TOPID:True                                << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |

+  FOPID:False                               << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};

+//

+vfrStatementVarStore : 

+  OP:VarStore                           << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>

+  STRUCT_NAME:StringIdentifier ","

+  Key   "=" KNUM:Number ","

+  Name  "=" VAR_NAME:StringIdentifier ","  

+  Guid "=" 

+  OpenBrace 

+  G1:Number ","

+  G2:Number ","

+  G3:Number ","

+  OpenBrace

+  G4:Number ","

+  G5:Number ","

+  G6:Number ","

+  G7:Number ","

+  G8:Number ","

+  G9:Number ","

+  G10:Number ","

+  G11:Number 

+  CloseBrace

+  CloseBrace                            << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),

+                                                           G4->getText (), G5->getText (), G6->getText (), G7->getText (),

+                                                           G8->getText (), G9->getText (), G10->getText (), G11->getText ()

+                                                          );

+                                           WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2)); 

+                                           AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());

+                                         >>

+  

+  ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:  

+//   vareqval var(0x100) == 0x20

+//

+vareqval : 

+  OPID:VarEqVal                           << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>

+  Var OpenParen 

+  VAR:Number                              << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>

+  CloseParen

+  compareNumber

+  ;

+

+ideqval : 

+  OPID:IdEqVal                            << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>

+  vfrStructFieldName[0]

+  compareNumber

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   ideqid MyNVData3.Field16A == MyNVData3.Field16B

+//

+// NOTE: Before processing the second variable store in the ideqid statement, set a global flag

+//       so that when we parse the second variable we set the secondary variable store id.

+//

+ideqid : 

+  OPID:IdEqId                             << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP);  >>

+  vfrStructFieldName[0]

+  compareVfrStructFieldNameNL0

+  ;

+

+//*****************************************************************************

+//

+// compareNumber is the combination of compare operation and Number

+//

+compareNumber :

+  (

+  "=="

+  VAL1:Number                             << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>

+  ) |

+  (

+  GTOPID:GreaterThan

+  VAL2:Number                             << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));

+                                             WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>

+  ) |

+  (

+  GEOPID:GreaterEqual

+  VAL3:Number                             << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));

+                                             WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>

+  ) |

+  (

+  LTOPID:LessThan

+  VAL4:Number                             << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));

+                                             WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);

+                                             WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>

+  ) |

+  (

+  LEOPID:LessEqual

+  VAL5:Number                             << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));

+                                             WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);

+                                             WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>

+  )

+  ;

+

+//*****************************************************************************

+//

+// compareVfrStructFieldNameNL0 is the combination of compare operation and  vfrStructFieldNameNL[0]

+//

+compareVfrStructFieldNameNL0 :

+  (

+  "=="                                    << mIdEqIdStmt = 1; >>

+  vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0; >>

+  ) |

+  (

+  GTOPID:GreaterThan                      << mIdEqIdStmt = 1; >>

+  vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;

+                                             WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>

+  ) |

+  (

+  GEOPID:GreaterEqual                     << mIdEqIdStmt = 1; >>

+  vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;

+                                             WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>

+  ) |

+  (

+  LTOPID:LessThan                       << mIdEqIdStmt = 1; >>

+  vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;

+                                             WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);

+                                             WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>

+  ) |

+  (

+  LEOPID:LessEqual                      << mIdEqIdStmt = 1; >>

+  vfrStructFieldNameNL[0]                 << mIdEqIdStmt = 0;

+                                             WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);

+                                             WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>

+  )

+  ;

+  

+

+ideqvallist : 

+  OPID:IdEqValList                        << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>

+  vfrStructFieldName[0] 

+  "=="

+  ( VAL:Number                            << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +

+                                          << FlushQueueIdEqValList(); >>

+  ;

+    

+vfrStatementGoto : 

+  << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>

+  IDG:Goto                          << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>

+  VAL:Number  ","                   << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); 

+                                       AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());

+                                    >>

+  KP:Prompt   "=" getStringId ","   << LineNum = KP->getLine();  >>

+  Help        "=" getStringId

+  { 

+    "," 

+    FF:Flags  "=" flagsField ( "\|" flagsField )*  << LineNum = FF->getLine(); >>

+  }

+  {

+    "," Key   "=" KNUM:Number       << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>

+  }

+                                    << WriteFlagsKey (KeyValue, LineNum); >>

+  ";"

+  ;

+    

+vfrStatementHidden : 

+  IDH:Hidden                  << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>

+  Value "="

+  VAL:Number ","              << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>

+  Key "="

+  KVAL:Number                 << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>

+  ";"

+  ;    

+

+//*****************************************************************************

+//

+// PARSE:

+//   suppressif <boolean_expression> { grayoutif } <statements>+ endif;

+// Note:

+//   You can have: suppressif:grayoutif:statements:endif

+//                 suppressif:grayoutif:endif                  -- serves no purpose

+//                 suppressif:statements:endif

+//                 suppressif:endif                            -- serves no purpose

+//

+vfrStatementSuppressIf : 

+  << ResetFlags (); >>

+  OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* ","

+  }

+  << WriteFlags (); >> //  write the flags field 

+  vfrBooleanExpression

+  ";"

+  { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+

+  ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>

+  ;

+

+//

+// This is the form for a grayoutif nested in a suppressif statement

+//

+suppressIfGrayOutIf :

+  << ResetFlags (); >>

+  OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* "," 

+  }

+  << WriteFlags (); >> //  write the flags field

+  vfrBooleanExpression

+  ";"

+  ; 

+

+//*****************************************************************************

+//

+// PARSE:

+//   grayoutif { flags = n, } <boolean_expression> endif;

+// Note:

+//   You can have: grayoutif:suppressif:statements:endif

+//                 grayoutif:statements:endif

+//

+//

+vfrStatementGrayOutIf :

+  << ResetFlags (); >>

+  OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* "," 

+  }

+  << WriteFlags (); >> //  write the flags field

+  vfrBooleanExpression

+  ";"

+  { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+ 

+  ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>

+  ;

+

+//

+// This is the format for a suppressif nested in a grayoutif

+//

+grayoutIfSuppressIf : 

+  << ResetFlags (); >>

+  OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* ","

+  }

+  << WriteFlags (); >> //  write the flags field

+  vfrBooleanExpression

+  ";"

+  ;

+

+//

+// These are the VFR statements that are valid inside a suppressif or grayoutif statement.

+//

+suppressIfAndGrayoutIfSubstatements :

+  vfrStatementOneOf           |

+  vfrStatementTextText        |

+  vfrStatementCheckBox        |

+  vfrStatementNumeric         |

+  vfrStatementDate            |

+  vfrStatementTime            |

+  vfrStatementPassword        |

+  vfrStatementString          |

+  vfrStatementHidden          |

+  vfrStatementGoto            | 

+  vfrStatementLabel           |

+  vfrStatementInventory       |

+  vfrStatementOrderedList     |

+  vfrStatementSaveRestoreDefaults

+  ; 

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//    password  varid    = MyNvData.Password,

+//              prompt   = STRING_TOKEN(STR_PASSWORD_PROMPT),

+//              help     = STRING_TOKEN(STR_PASSWORD_HELP),

+//              minsize  = 6,

+//              maxsize  = 20,

+//              encoding = 1,

+//    endpassword; 

+  

+vfrStatementPassword : 

+  << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>

+  IDPW:Password                       << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>

+  VarId       "=" vfrStructFieldNameArray[0] ","

+  Prompt      "=" getStringId ","

+  KH:Help     "=" getStringId ","    << LineNum = KH->getLine(); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* ","  << LineNum = FF->getLine(); >>

+  }

+  {

+    Key "=" KNUM:Number ","           << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>

+  }

+                                      << WriteFlagsKey (KeyValue, LineNum); >>

+  MinSize   "=" MIN:Number ","        << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>

+  MaxSize   "=" MAX:Number ","        << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>

+  Encoding  "=" ENC:Number ","        << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>

+  EndPassword  ";"              

+  ;

+

+//*****************************************************************************

+//

+//  PARSE:

+//

+//    string    varid    = MyNv.String,

+//              prompt   = STRING_TOKEN(STR_STRING_PROMPT),

+//              help     = STRING_TOKEN(STR_STRING_HELP),

+//              flags    = INTERACTIVE,

+//              key      = 0x1234,

+//              minsize  = 6,

+//              maxsize  = 0x14,

+//    endstring; 

+//

+// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error

+// reporting we save the line number of the "help" keyword.

+//

+vfrStatementString : 

+  << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>

+  IDS:String                                << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>

+  VarId     "=" vfrStructFieldNameArray[0] ","

+  Prompt    "=" getStringId ","

+  KH:Help   "=" getStringId ","             << LineNum = KH->getLine(); >>

+  { 

+    FF:Flags "=" 

+    flagsField ( "\|" flagsField )*         << LineNum = FF->getLine(); >>

+    "," 

+  }

+  {

+    Key "=" KNUM:Number ","                 << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>

+  }

+                                            << WriteFlagsKey (KeyValue, LineNum); >>

+  MinSize   "=" MIN:Number ","              << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0);  >>

+  MaxSize   "=" MAX:Number ","              << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>

+  EndString  ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//    numeric varid   = MyIfrNVData.HowOldAreYouInYears, 

+//            prompt  = STRING_TOKEN(STR_NUMERIC_PROMPT),

+//            help    = STRING_TOKEN(STR_NUMERIC_HELP),

+//            flags   = INTERACTIVE,  // flags is optional

+//            key     = 0x1234,       // key is optional if (flags & INTERACTIVE = 0)

+//            minimum = 0x0,

+//            maximum = 0xf0,

+//            step    = 1,            // step is option, and step=1 if not specified

+//            default = 0;            // default is optional, and default=minimum if not specified

+//    endnumeric;

+//

+// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.

+// That check is done in WriteFlagsKey() function.

+//

+vfrStatementNumeric :  

+  << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>

+  IDN:Numeric                         << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>

+  VarId     "=" vfrStructFieldName[2] ","

+  Prompt    "=" getStringId ","

+  KH:Help   "=" getStringId ","       << LineNum = KH->getLine(); >>

+  { 

+    FF:Flags "=" flagsField ( "\|" flagsField )* ","     << LineNum = FF->getLine (); >>

+  }

+  {

+    Key "=" KNUM:Number  ","          << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>

+  }

+                                      << WriteFlagsKey (KeyValue, LineNum); >>

+  minMaxStepDefault                   

+  EndNumeric ";"                      << WriteMinMaxStepDefault (); >>

+  ;

+

+//

+// Parse minimum/maximum/step/default statements. Special cases:

+//   - if step not specified, then the value is 1

+//   - if default not specified, then the value is the min value specified

+//   - if max < min, print a warning and swap the values (changes default too)

+//

+minMaxStepDefault :

+  << InitMinMaxStepDefault (); >>

+  Minimum   "=" MIN:Number ","        << SetMinMaxStepDefault (GetNumber (MIN->getText(),  MIN->getLine(), 2), 0, MIN->getLine()); >>

+  Maximum   "=" MAX:Number ","        << SetMinMaxStepDefault (GetNumber (MAX->getText(),  MAX->getLine(), 2), 1, MAX->getLine()); >>

+  { Step    "=" STEP:Number ","       << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }

+  { Default "=" DEF:Number ","        << SetMinMaxStepDefault (GetNumber (DEF->getText(),  DEF->getLine(), 2), 3, DEF->getLine()); >> }

+  ;

+

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//    date    year varid  = Date.Year,                        // "Date.Year" is a special case we recognize

+//            prompt      = STRING_TOKEN(STR_DATE_PROMPT),

+//            help        = STRING_TOKEN(STR_DATE_YEAR_HELP),

+//            minimum     = 1939,

+//            maximum     = 2101,

+//            step        = 1,

+//            default     = 1964,

+//

+//            month varid = Date.Month,    

+//            prompt      = STRING_TOKEN(STR_DATE_PROMPT),

+//            help        = STRING_TOKEN(STR_DATE_MONTH_HELP),

+//            minimum     = 1,

+//            maximum     = 12,

+//            step        = 1,

+//            default     = 1,

+//

+//            day varid   = Date.Day,

+//            prompt      = STRING_TOKEN(STR_DATE_PROMPT),

+//            help        = STRING_TOKEN(STR_DATE_DAY_HELP),

+//            minimum     = 1,

+//            maximum     = 31,

+//            step        = 0x1,

+//            default     = 1,

+//

+//    enddate;

+//  

+vfrStatementDate :  

+  Date                            

+  IDY:Year VarId "="                  << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>

+  vfrStructFieldName[2] "," 

+  dateTimeSubStatement                    

+  IDM:Month VarId "="                 << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>

+  vfrStructFieldName[2] "," 

+  dateTimeSubStatement                    

+  IDD:Day VarId "="                   << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >> 

+  vfrStructFieldName[2] ","  

+  dateTimeSubStatement    

+  EndDate ";"

+  ;

+  

+vfrStatementTime :  

+  Time                            

+  IDH:Hour VarId "="                  << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>

+  vfrStructFieldName[2] ","  

+  dateTimeSubStatement                    

+  IDM:Minute VarId "="                << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>

+  vfrStructFieldName[2] "," 

+  dateTimeSubStatement                    

+  IDS:Second VarId "="                << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>

+  vfrStructFieldName[2] "," 

+  dateTimeSubStatement

+  EndTime ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   text  text = STRING_ID;

+//   text  text = STRING_ID, text = STRING_ID;

+//   text  text = STRING_ID, text = STRING_ID, flags = x, key = y;

+//

+vfrStatementTextText :

+  << ResetFlags (); >>

+  IDT:Text                            << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>

+  Help "=" getStringId ","

+  Text "=" 

+  getStringId                         // writes string identifier

+  { "," Text "=" getStringId

+    "," Flags "=" flagsField ( "\|" flagsField )*  << WriteFlags (); >>

+    "," 

+    Key "=" KNUM:Number               << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>

+  }

+  ";" 

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   inventory help = ID, text = ID;

+//   inventory help = ID, text = id, text = ID;

+//

+vfrStatementInventory :

+  IDI:Inventory                        << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>

+  Help        "=" getStringId ","

+  Text        "=" getStringId                 // writes string identifier

+  { "," Text  "=" getStringId

+  }

+  ";" 

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//    restore defaults,

+//      formid  = 4,

+//      prompt  = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),

+//      help    = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),

+//      flags   = 0,

+//      key     = 0;

+//

+//    save defaults,

+//      formid  = 4,

+//      prompt  = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),

+//      help    = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),

+//      flags   = 0,

+//      key     = 0;

+//

+vfrStatementSaveRestoreDefaults : 

+  << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>

+  ( IDS:Save                            << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>

+  | IDR:Restore                         << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>

+  )

+  Defaults ","

+  FormId    "=" FRMID:Number  ","       << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2)); 

+                                           AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());

+                                        >>

+  Prompt    "=" getStringId ","

+  KH:Help   "=" getStringId             << LineNum = KH->getLine(); >>

+  { 

+    "," FF:Flags "=" flagsField ( "\|" flagsField )*  << LineNum = FF->getLine(); >>

+  }

+  {

+    "," Key "=" KNUM:Number             << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>

+  }

+                                        << WriteFlagsKey (KeyValue, LineNum); >>

+  ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK

+//

+// 

+flagsField :

+  VAL:Number                          << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>

+  | IF:InteractiveFlag                << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine());    >>

+  | MF:ManufacturingFlag              << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine());  >>

+  | DF:DefaultFlag                    << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine());        >>

+  | NV:NVAccessFlag                   << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine());      >>

+  | RR:ResetRequiredFlag              << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>

+  | LC:LateCheckFlag                  << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine());     >>

+  ;

+

+dateTimeSubStatement :

+  Prompt  "=" getStringId ","

+  Help    "=" getStringId ","

+                                      << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key

+  minMaxStepDefault                   << WriteMinMaxStepDefault (); >>

+  ;

+  

+vfrStatementCheckBox :  

+  << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>

+  IDCB:CheckBox                       << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>

+  VarId     "=" vfrStructFieldName[1] ","

+  Prompt    "=" getStringId ","

+  Help      "=" getStringId ","

+  FF:Flags  "=" flagsField ( "\|" flagsField )*  "," << LineNum = FF->getLine(); >>

+  { 

+    Key "=" KV:Number  ","           << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>

+  }

+                                     << WriteFlagsKey (KeyValue, LineNum); >>

+  EndCheckBox ";"

+  ;

+     

+vfrStatementSubTitle :

+  IDS:Subtitle Text "="               << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>

+  getStringId                         // writes string indentifier

+  ";"

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//    banner 

+//      title = STRING_TOKEN(STR_BANNER_TITLE),

+//      line  1,

+//      align center;     // or left or right

+//

+//    banner, 

+//      title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;

+//

+vfrStatementBanner :

+  IDB:Banner { "," }                    << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>

+  Title "=" getStringId ","

+  ( 

+    Line VAL:Number ","                 << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>

+    Align 

+    ( Left                              << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>

+    | Center                            << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>

+    | Right                             << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>

+    ) ";"

+  |

+    Timeout "=" TO:Number ";"           << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>

+                                        << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>

+  )

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   oneof  varid       = MyNv.OneOfData,

+//          prompt      = STRING_TOKEN(STR_ONE_OF_PROMPT),

+//          help        = STRING_TOKEN(STR_ONE_OF_HELP),

+//          option text = STRING_TOKEN(STR_ONE_OF_TEXT), 

+//          value       = 0, 

+//          flags       = DEFAULT | INTERACTIVE;

+//

+// supressif/grayoutif are supported inside oneof stmt.

+// We do not restrict the number of oneOfOptionText to >=2, but >=1.

+// The situation that all oneOfOptionText are suppressed is also possiable.

+//

+vfrStatementOneOf :

+  << ResetFlags (); >>

+  IDOO:OneOf                              << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>

+  VarId   "=" vfrStructFieldName[2] ","       

+  Prompt  "=" getStringId  ","           // writes string identifier

+  Help    "=" getStringId  ","           // writes string identifier

+  ( oneOfOptionText )+                   // there must be at least 1 option to be choosed, not 2.

+  IDEOO:EndOneOf   ";"                    << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//  

+//   orderedlist  varid       = MyNv.OrderedListData,

+//                prompt      = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),

+//                help        = STRING_TOKEN(STR_ORDERED_LIST_HELP),  

+//                option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;

+//                -- additional option text -- 

+//   endlist;

+//

+vfrStatementOrderedList :

+  << ResetFlags (); InitOrderedList(); >>

+  IDOL:OrderedList                       << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>

+  VarId   "=" vfrStructFieldNameArray[1] ","       

+  Prompt  "=" getStringId  ","           // writes string identifier

+  Help    "=" getStringId  ","           // writes string identifier

+  orderedListOptionText ( orderedListOptionText )+

+  IDEOL:EndList   ";"                    << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;

+//

+// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to

+// be set, and value cannot be 0.

+//

+orderedListOptionText :

+  << UINT32 KeyValue = 0; >>

+  IDO:Option                          << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>

+  Text      "=" getStringId ","       // writes string identifier

+  Value     "=" WVAL:Number ","       << 

+                                          if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {

+                                            PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL); 

+                                          } else {

+                                            WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2)); 

+                                          }

+                                      >>

+  FF:Flags  "=" orderedListFlagsField  

+                ("\|" orderedListFlagsField )*                   

+  { 

+    "," Key "=" KV:Number             << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> 

+  }

+                                      << WriteFlagsKey (KeyValue, FF->getLine()); >>

+  ";"                                 << mOptionCount++; >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK

+//

+// The ordered list flags field cannot have a default.

+//

+orderedListFlagsField :

+  VAL:Number                          << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>

+  | IF:InteractiveFlag                << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine());    >>

+  | MF:ManufacturingFlag              << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine());  >>

+  | NV:NVAccessFlag                   << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine());      >>

+  | RR:ResetRequiredFlag              << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>

+  | LC:LateCheckFlag                  << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine());     >>

+  | DF:DefaultFlag                    << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>

+  ;

+

+//

+// Parse references to VFR structure field names of form "MyNvStructure.Field". 

+// This implementation is specific to strings, passwords, and references in an 

+// ordered list statement because we want to specify the size of the entire 

+// field, rather than just one element. Then call a function to write out its 

+// offset and length.

+//

+vfrStructFieldNameArray[int FieldWidth] :

+  << int ArrayIndex = 1; char IsArrayIndex = 0; >>

+  SName:StringIdentifier 

+  "." 

+  SFieldName:StringIdentifier 

+  { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }

+            << 

+                WriteFieldOffset (1, 

+                                  SName->getText(), 

+                                  SName->getLine(), 

+                                  SFieldName->getText(), 

+                                  SFieldName->getLine(),

+                                  ArrayIndex, 

+                                  IsArrayIndex,

+                                  FieldWidth,

+                                  1

+                                  ); 

+            >>

+  ;

+

+//

+// Parse references to VFR structure field names of form "MyNvStructure.Field",

+// then call a function to write out its offset and length.

+//

+vfrStructFieldName[int FieldWidth] :

+  << int ArrayIndex = 1; char IsArrayIndex = 0; >>

+  SName:StringIdentifier 

+  "." 

+  SFieldName:StringIdentifier 

+  { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }

+            << 

+                WriteFieldOffset (1, 

+                                  SName->getText(), 

+                                  SName->getLine(), 

+                                  SFieldName->getText(), 

+                                  SFieldName->getLine(),

+                                  ArrayIndex, 

+                                  IsArrayIndex,

+                                  FieldWidth,

+                                  0

+                                  ); 

+            >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//

+//   MyNvStructure.FieldName[4]

+//

+// Parse references to VFR structure field names of form "MyNvStructure.Field",

+// then call a function to write out the offset with no length.

+//

+vfrStructFieldNameNL[int FieldWidth] :

+  << int ArrayIndex = 1; char IsArrayIndex = 0; >>

+  SName:StringIdentifier 

+  "." 

+  SFieldName:StringIdentifier 

+  { OpenBracket AIndex:Number CloseBracket   << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }

+            << 

+                WriteFieldOffset (0, 

+                                  SName->getText(), 

+                                  SName->getLine(), 

+                                  SFieldName->getText(), 

+                                  SFieldName->getLine(),

+                                  ArrayIndex, 

+                                  IsArrayIndex,

+                                  FieldWidth,

+                                  0

+                                  ); 

+            >>

+  ;

+

+//*****************************************************************************

+//

+// PARSE:

+//   suppressif TRUE OR FALSE;

+//   grayoutif FALSE OR TRUE;

+//     option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;

+//     option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;

+//   endif;

+//

+oneOfOptionText :

+  suppressIfOptionText    |

+  grayOutIfOptionText     |

+  commonOptionText

+  ;

+

+suppressIfOptionText : 

+  << ResetFlags (); >>

+  OPID:SuppressIf                     << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* ","

+  }

+  << WriteFlags (); >> //  write the flags field 

+  vfrBooleanExpression

+  ";"

+  { suppressIfGrayOutIf } ( commonOptionText )+

+  ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>

+  ;

+

+grayOutIfOptionText :

+  << ResetFlags (); >>

+  OPID:GrayOutIf                      << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>

+  { 

+    FF:Flags  "=" flagsField ( "\|" flagsField )* "," 

+  }

+  << WriteFlags (); >> //  write the flags field

+  vfrBooleanExpression

+  ";"

+  { grayoutIfSuppressIf } ( commonOptionText )+ 

+  ENDOP:EndIf ";"                     << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>

+  ;

+

+commonOptionText : 

+  << UINT32 KeyValue = 0; >>

+  IDO:Option                      << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>

+  Text      "=" getStringId ","   // writes string identifier

+  Value     "=" WVal:Number ","   << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>

+  FF:Flags  "=" flagsField  ("\|" flagsField )*                   

+  { 

+    "," Key "=" KV:Number         << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> 

+  }

+                                  << WriteFlagsKey (KeyValue, FF->getLine()); >>

+  ";"                             << mOptionCount++; >>

+  ;

+

+//

+// Gets a string identifier. It must be a numeric value of form:

+// 

+//   STRING_TOKEN(100)

+//

+getStringId :

+  << unsigned short StrId; >>

+  StringToken OpenParen

+  IdVal:Number             << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >> 

+  CloseParen

+  ;

+

+//******************************************************************************

+//

+// Parser class definition. 

+//  

+class EfiVfrParser {

+<<

+//

+// Parser definitions go here    

+//

+private:

+  STRUCT_DEFINITION   *mFirstStructDefinition;

+  STRUCT_DEFINITION   *mLastStructDefinition;

+  INT32               mNvDataStructSize;                    

+  INT32               mNonNvDataStructSize;

+  //

+  // Flag to indicate that we're processing a ideqid VFR statement so that

+  // we can do late checks on the statement.

+  //

+  INT32               mIdEqIdStmt;

+  INT32               mLastNVVariableDataSize;

+  GOTO_REFERENCE      *mGotoReferences;

+  FORM_ID_VALUE       *mFormIdValues;

+  VfrOpcodeHandler    mOpcodeHandler;

+  UINT16_LIST         *mUint16List;

+  UINT16_LIST         *mLastUint16;

+  UINT16_LIST         *mDefinedLabels;

+  UINT16_LIST         *mDefinedVarStoreId;

+  UINT16_LIST         *mLastDefinedVarStoreId;

+  UINT32              mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;

+  UINT32              mStmtFlags;

+  UINT32              mSubStmtFlags;

+  UINT32              mSubStmtFlagsLineNum;

+  EFI_GUID            mFormSetGuid;

+  UINT8               mNvDataStructDefined;

+  UINT16              mClass, mSubclass;

+  UINT32              mIfStart;

+  UINT32              mOptionCount;  // how many "option" fields in a given statement

+  UINT32              mLastVarIdSize;

+  UINT8               mOutput;

+public:        

+

+VOID 

+EfiVfrParser::SetIfStart (

+  UINT32 LineNum

+  )

+/*++

+

+Routine Description:

+  Invoked during VFR parsing when an "if" is encountered. Save the

+  source line number so we can point to it if we don't find a 

+  corresponding endif later.

+

+Arguments:

+  LineNum - source line number where the "if" was parsed.

+

+Returns:

+  None

+

+--*/

+{

+  mIfStart = LineNum;

+}

+VOID 

+EfiVfrParser::SetClass (

+  UINT32 LineNum, 

+  UINT32 Value

+  ) 

+/*++

+

+Routine Description:

+  Invoked during VFR parsing when a "class" statement is found. Check the

+  range on the class value and save it for later.

+

+Arguments:

+  LineNum - source line number where the class statement was parsed.

+  Value   - the class value

+

+Returns:

+  None

+

+--*/

+{

+  if (Value & 0xFFFF0000) {

+    PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");

+  }

+  mClass |= (UINT16)Value;

+}

+VOID 

+EfiVfrParser::SetSubclass (

+  UINT32 LineNum, 

+  UINT32 Value

+  ) 

+/*++

+

+Routine Description:

+  Invoked during VFR parsing when a subclass statement is found. Check the

+  range on the value and save it for later.

+

+Arguments:

+  LineNum - source line number where the class statement was parsed.

+  Value   - the subclass value from the VFR statement

+

+Returns:

+  None

+

+--*/

+{

+  if (Value & 0xFFFF0000) {

+    PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");

+  }

+  mSubclass |= (UINT16)Value;

+}

+VOID EfiVfrParser::WriteClass ()

+{

+  WriteWord (mClass);

+  mClass = 0;

+}

+VOID EfiVfrParser::WriteSubclass ()

+{

+  WriteWord (mSubclass);

+  mSubclass = 0;

+}

+VOID EfiVfrParser::WriteIfrBytes ()

+{

+  mOpcodeHandler.WriteIfrBytes ();

+}

+VOID 

+EfiVfrParser::WriteFlagsKey (

+  UINT32 KeyValue, 

+  UINT32 LineNum

+  ) 

+/*++

+

+Routine Description:

+  Write out the flags and key values from the previous VFR statement.

+  Many statements take a flags/key pair. If not specified, then 0

+  values are written out. However do not allow an interactive flags field

+  to be specified if no key value is specified. Also, if NV_ACCESS flag

+  is set but INTERACTIVE is not, then set interactive and issue a warning.

+

+Arguments:

+  KeyValue  - the key value from the VFR statement

+  LineNum   - source line number where the statement was parsed

+

+Returns:

+  None

+

+--*/

+{

+  if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {

+    PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");

+  }

+  if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {

+    PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");

+    mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;

+  }

+  WriteFlags ();

+  WriteWord (KeyValue);

+}

+VOID 

+EfiVfrParser::InitOrderedList ()

+{

+  mOptionCount = 0;

+}  

+VOID 

+EfiVfrParser::EndOrderedList (

+  UINT32 LineNum

+  )

+{

+  if (mLastVarIdSize < mOptionCount) {

+    PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");

+  }

+}

+VOID 

+EfiVfrParser::ResetFlags ()

+/*++

+

+Routine Description:

+

+  Flags are set for each substatement in a given one-of statement.

+  To make sure there are no conflicts, for example setting DEFAULT on

+  more than one substatement, we keep track of the flags at a statement

+  level and a substatement level. This function resets the flags so 

+  we get a fresh start.

+

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{

+  mStmtFlags = 0;

+  mSubStmtFlagsLineNum = 0;

+  mSubStmtFlags = 0;

+}

+//

+// Test validity of flags value for a one-of statement.

+//

+VOID 

+EfiVfrParser::TestOneOfFlags (

+  UINT32 LineNum

+  ) 

+{

+  //

+  // One of the fields must have had the default bit set

+  //

+  if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {

+    PrintWarningMessage (LineNum, "default value must be specified", NULL);

+  }

+}

+VOID 

+EfiVfrParser::SetFlags (

+  UINT32 Flags, 

+  UINT32 LineNum

+  ) 

+{

+  //

+  // Check for redefinitions and invalid combinations

+  //

+  if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {

+    PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");

+  }

+  if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {

+    PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");

+  }

+  mSubStmtFlags |= Flags;

+  mSubStmtFlagsLineNum = LineNum;

+}

+VOID 

+EfiVfrParser::WriteFlags ()

+{

+  //

+  // Check value for validity

+  //

+  if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT | 

+                        EFI_IFR_FLAG_MANUFACTURING | 

+                        EFI_IFR_FLAG_INTERACTIVE | 

+                        EFI_IFR_FLAG_NV_ACCESS | 

+                        EFI_IFR_FLAG_RESET_REQUIRED | 

+                        EFI_IFR_FLAG_LATE_CHECK )) {

+    PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);

+  }

+  WriteByte ((UINT8)mSubStmtFlags, 'F');

+  //

+  // We can now clear the substatement flags

+  //

+  mStmtFlags |= mSubStmtFlags;

+  mSubStmtFlags = 0;

+}

+//

+// When we parse a min/max/step/default sequence, save off the values for

+// later use. Call this first to init the values.

+//

+VOID 

+EfiVfrParser::InitMinMaxStepDefault ()

+{

+  mMinimumValue         = 0;

+  mMaximumValue         = 0;

+  mStepValue            = 1;

+  mDefaultValue         = 0;

+}  

+VOID 

+EfiVfrParser::WriteMinMaxStepDefault ()

+{

+  WriteWord (mMinimumValue);

+  WriteWord (mMaximumValue);

+  WriteWord (mStepValue);

+  WriteWord (mDefaultValue);

+}  

+VOID 

+EfiVfrParser::SetMinMaxStepDefault (

+  UINT16  Value, 

+  INT32   MMSD, 

+  INT32   LineNum

+  ) 

+{

+  UINT16 TempValue;

+  //

+  // Min specified

+  //

+  if (MMSD == 0) {

+    mMinimumValue = Value;

+    mDefaultValue = Value;

+  //

+  // Max specified

+  //

+  } else if (MMSD == 1) {

+    mMaximumValue = Value;

+    //

+    // If min > max, then swap the values. That includes resetting the default

+    // value as well.

+    //

+    if (mMinimumValue > mMaximumValue) {

+      PrintWarningMessage (LineNum, NULL, "maximum < minimum");      

+      TempValue = Value;

+      mMaximumValue = mMinimumValue;

+      mMinimumValue = TempValue;

+      mDefaultValue = mMinimumValue;

+    }

+  //

+  // Step specified

+  //

+  } else if (MMSD == 2) { 

+    mStepValue = Value;

+  //

+  // Default specified. Make sure min <= default <= max.

+  //

+  } else if (MMSD == 3) {

+    mDefaultValue = Value;

+    if (mMinimumValue > Value) {

+      PrintErrorMessage (LineNum, NULL, "default value < minimum value");

+    } else if (Value > mMaximumValue) {

+      PrintErrorMessage (LineNum, NULL, "default value > maximum value");

+    }

+  } else {

+    PrintErrorMessage (LineNum, "application error", "internal MMSD error");    

+  }

+}

+VOID 

+EfiVfrParser::AddLabel (

+  UINT32 LabelNumber, 

+  UINT32 LineNum

+  ) 

+{

+  UINT16_LIST *Label;

+

+  //

+  // Added a label from the user VFR script. Make sure they haven't already 

+  // defined the same label elsewhere

+  //

+  for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {

+    if (Label->Value == LabelNumber) {

+      PrintErrorMessage (LineNum, NULL, "label already defined");

+      PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");

+      break;

+    }

+  }

+  Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));

+  if (Label == NULL) {

+    PrintErrorMessage (0, NULL, "memory allocation error");

+    return;

+  }

+  memset ((char *)Label, 0, sizeof (UINT16_LIST));

+  Label->Value = LabelNumber;

+  Label->LineNum = LineNum;

+  Label->Next = mDefinedLabels;

+  mDefinedLabels = Label;

+}

+VOID 

+EfiVfrParser::QueueIdEqValList (

+  UINT16 Value

+  )

+{

+  UINT16_LIST   *U16;

+  

+  U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));

+  if (U16 == NULL) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");

+  } else {

+    memset ((char *)U16, 0, sizeof (UINT16_LIST));

+    U16->Value = Value;

+    if (mUint16List == NULL) {

+      mUint16List = U16;

+    } else {

+      mLastUint16->Next = U16;

+    } 

+    mLastUint16 = U16;

+  }

+}    

+VOID 

+EfiVfrParser::FlushQueueIdEqValList ()

+{

+  UINT32 Count;

+  

+  //

+  // We queued up a list of IdEqValList items. The IFR requires a count

+  // followed by the actual values. Do it.

+  //

+  Count = 0;

+  mLastUint16 = mUint16List;

+  while (mLastUint16 != NULL) {

+    Count++;

+    mLastUint16 = mLastUint16->Next;

+  }

+  // BUGBUG -- check for more than 16K items?

+  WriteWord (Count);

+  //

+  // Now write the values.

+  //

+  mLastUint16 = mUint16List;

+  while (mLastUint16 != NULL) {

+    WriteWord ((UINT32)mLastUint16->Value);

+    mLastUint16 = mLastUint16->Next;

+  }

+  //

+  // Free up the list

+  //  

+  mLastUint16 = mUint16List;

+  while (mUint16List != NULL) {

+    mLastUint16 = mUint16List->Next;

+    free (mUint16List);

+    mUint16List = mLastUint16;

+  }

+}

+VOID 

+EfiVfrParser::PrintErrorMessage (

+  UINT32              LineNum,

+  CHAR8               *Msg1,

+  CHAR8               *Msg2

+  )

+{

+  char *FileName;

+  

+  if (LineNum != 0) {

+    FileName = ConvertLineNumber ((UINT32 *)&LineNum);

+    Error (FileName, LineNum, 0, Msg1, Msg2);

+  } else {

+    Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);

+  }

+}

+VOID 

+EfiVfrParser::PrintWarningMessage (

+  UINT32              LineNum,

+  CHAR8               *Msg1,

+  CHAR8               *Msg2

+  )

+{

+  char *FileName;

+  

+  if (LineNum != 0) {

+    FileName = ConvertLineNumber ((UINT32 *)&LineNum);

+    Warning (FileName, LineNum, 0, Msg1, Msg2);

+  } else {

+    Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);

+  }

+}

+VOID 

+EfiVfrParser::syn (

+  ANTLRAbstractToken  *Tok, 

+  ANTLRChar           *Egroup, 

+  SetWordType         *Eset, 

+  ANTLRTokenType      ETok, 

+  INT32               Huh

+  )

+/*++

+

+Routine Description:

+  Called by the parser base class as a result of parse syntax errors.

+

+Arguments:

+  Tok     - token that caused the error

+  Egroup  - not sure

+  Eset    - index in token table of the expected token

+  Huh     - not sure

+

+Returns:

+  NA

+

+--*/

+{

+  char    *FileName;

+  UINT32  LineNum;

+  

+  LineNum = Tok->getLine ();

+  FileName = ConvertLineNumber ((UINT32 *)&LineNum);

+  //

+  // Sometimes the token number is 0, in which case I don't know what to

+  // print.

+  //

+  if (ETok == 0) {

+    Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");

+  } else {

+    //

+    // If we were expecting an endif, then report the line where the corresponding

+    // IF began.

+    //

+    if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {

+      LineNum = mIfStart;

+      FileName = ConvertLineNumber (&LineNum);

+      Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);

+    } else {

+      Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);

+    }

+  }

+}

+

+VOID 

+EfiVfrParser::init()        

+/*++

+

+Routine Description:

+  Initializations function for our parser.

+

+Arguments:

+  None.

+

+Returns:

+  None.

+

+--*/

+{

+  ANTLRParser::init();

+

+  //

+  // Used for queuing a variable list of UINT16's

+  //

+  mUint16List               = NULL;

+  mLastUint16               = NULL;

+  mFirstStructDefinition    = NULL;

+  mLastStructDefinition     = NULL;

+  mNvDataStructSize         = 0;

+  mNonNvDataStructSize      = 0;

+  mNvDataStructDefined      = 0;

+  mGotoReferences           = NULL;

+  mFormIdValues             = NULL;

+  mDefinedLabels            = NULL;

+  mClass                    = 0;

+  mSubclass                 = 0;

+  mIfStart                  = 0;

+  mDefinedVarStoreId        = NULL;

+  mLastDefinedVarStoreId    = NULL;

+  mIdEqIdStmt               = 0;

+  mLastNVVariableDataSize   = 0;

+    

+  memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));

+}

+//

+// Destructor for the parser.

+//

+EfiVfrParser::~EfiVfrParser(VOID)

+{

+  Cleanup();

+}

+VOID

+EfiVfrParser::Cleanup (VOID)

+/*++

+

+Routine Description:

+  Free memory allocated during parsing

+

+Arguments:

+  None.

+

+Returns:

+  None.

+

+--*/

+{

+  STRUCT_DEFINITION         *NextStruct;

+  STRUCT_FIELD_DEFINITION   *NextField;

+  UINT8                     Buff[6];

+  UINT16_LIST               *NextU16List;

+  

+  //

+  // Free up the structure definitions if any

+  //

+  while (mFirstStructDefinition != NULL) {

+    //

+    // Free up all the fields for this struct

+    //

+    while (mFirstStructDefinition->Field != NULL) {

+      NextField = mFirstStructDefinition->Field->Next;

+      free (mFirstStructDefinition->Field->Name);

+      free (mFirstStructDefinition->Field);

+      mFirstStructDefinition->Field = NextField;

+    }

+    NextStruct = mFirstStructDefinition->Next;

+    free (mFirstStructDefinition->Name);

+    free (mFirstStructDefinition);

+    mFirstStructDefinition = NextStruct;

+  }

+  //

+  // Free up the goto references and form id defines

+  //

+  FreeGotoReferences ();

+  //

+  // Free up label list

+  //

+  while (mDefinedLabels != NULL) {

+    NextU16List = mDefinedLabels->Next;

+    delete (mDefinedLabels);

+    mDefinedLabels = NextU16List;

+  }

+  //

+  // Free up the list of defined variable storage IDs

+  //

+  while (mDefinedVarStoreId != NULL) {

+    NextU16List = mDefinedVarStoreId->Next;

+    delete (mDefinedVarStoreId);

+    mDefinedVarStoreId = NextU16List;

+  }

+}

+

+INT32 

+EfiVfrParser::AtoX (

+  CHAR8   *HexString, 

+  INT32   NumBytes, 

+  UINT32  *HexValue

+  )

+/*++

+

+Routine Description:

+  Given a pointer to a ascii hex string, convert to a number with the given

+  number of bytes.

+

+Arguments:

+  HexString   - pointer to a string of format 30BCA

+  Size        - number of bytes to convert

+  HexValue    - return result

+

+Returns:

+  The number of bytes converted.

+

+--*/

+{

+  INT32 Count;

+  INT32 Value;

+

+  *HexValue = 0;

+  Count = 0;

+  while (Count < NumBytes) {

+    if ((*HexString >= '0') && (*HexString <= '9')) {

+      Value = *HexString - '0';

+    } else if ((*HexString >= 'a') && (*HexString <= 'f')) {

+      Value = *HexString - 'a' + 10;

+    } else if ((*HexString >= 'A') && (*HexString <= 'F')) {

+      Value = *HexString - 'A' + 10;

+    } else {

+      return Count;

+    }

+    HexString++;

+    *HexValue = (*HexValue << 4) | Value;

+    if ((*HexString >= '0') && (*HexString <= '9')) {

+      Value = *HexString - '0';

+    } else if ((*HexString >= 'a') && (*HexString <= 'f')) {

+      Value = *HexString - 'a' + 10;

+    } else if ((*HexString >= 'A') && (*HexString <= 'F')) {

+      Value = *HexString - 'A' + 10;

+    } else {

+      return Count;

+    }

+    *HexValue = (*HexValue << 4) | Value;

+    HexString++;

+    Count++;

+  }

+  return Count;

+}

+VOID 

+EfiVfrParser::WriteGuidValue (

+  UINT32       TokenLineNum,

+  CHAR8        *G1, 

+  CHAR8        *G2,

+  CHAR8        *G3,

+  CHAR8        *G4,

+  CHAR8        *G5,

+  CHAR8        *G6,

+  CHAR8        *G7,

+  CHAR8        *G8,

+  CHAR8        *G9,

+  CHAR8        *G10,

+  CHAR8        *G11

+  )

+/*++

+

+Routine Description:

+  A Guid was parsed, likely of format:

+  #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }

+

+  Write out the value.

+

+Arguments:

+  TokenLineNum   - line number where the guid was used

+  G1-G11         - the 11 fields of the guid value

+

+Returns:

+  None.

+

+--*/

+{

+  UINT32        Value;

+  INT32         Loop;

+

+  mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);

+  mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);

+  mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);

+  mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);

+  mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);

+  mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);

+  mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);

+  mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);

+  mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);

+  mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);

+  mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);

+  

+  WriteDWord (mFormSetGuid.Data1, 'G');

+  WriteWord (mFormSetGuid.Data2);

+  WriteWord (mFormSetGuid.Data3);

+  WriteByte (mFormSetGuid.Data4[0], 0);

+  WriteByte (mFormSetGuid.Data4[1], 0);

+  WriteByte (mFormSetGuid.Data4[2], 0);

+  WriteByte (mFormSetGuid.Data4[3], 0);

+  WriteByte (mFormSetGuid.Data4[4], 0);

+  WriteByte (mFormSetGuid.Data4[5], 0);

+  WriteByte (mFormSetGuid.Data4[6], 0);

+  WriteByte (mFormSetGuid.Data4[7], 0);

+}

+VOID 

+EfiVfrParser::WriteFieldOffset (

+  INT8    WriteLength,

+  CHAR8   *StructName, 

+  INT32   LineNum1, 

+  CHAR8   *FieldName, 

+  INT32   LineNum2,

+  INT32   ArrayIndex,

+  INT8    IsArrayIndex,

+  INT32   FieldWidth,

+  INT8    WriteArraySize

+  ) 

+/*++

+

+Routine Description:

+  A VFR script referenced the NV store structure. Given the structure's name

+  and the field's name, write the offset of the field to the output file.

+

+Arguments:

+  WriteLength     - write the field length byte out

+  StructName      - name of the NV store structure

+  LineNum1        - line number in the VFR where we are (for error printing)

+  FieldName       - the name of the field within the NV store structure

+  LineNum2        - line number in the VFR where FieldName is referenced 

+  ArrayIndex      - the index specified, for example NV_DATA.Field[ArrayIndex]

+  IsArrayIndex    - non-zero if an array index was specified

+  FieldWidth      - expected size for the Field (1 byte? 2 bytes?)

+  WriteArraySize  - write the size of the entire field, not the size of a single element

+

+Returns:

+  None.

+

+--*/

+{

+  STRUCT_DEFINITION         *StructDef;

+  STRUCT_FIELD_DEFINITION   *FieldDef;

+  UINT32                    Offset;

+  UINT32                    VarSize;

+  CHAR8                     Msg[100];

+  //

+  // If we're writing an array size, then they better have referenced the field without an

+  // index. 

+  //

+  if (WriteArraySize && IsArrayIndex) {

+    sprintf (Msg, "array index specified where an array is required");

+    PrintErrorMessage (LineNum2, FieldName, Msg);

+    return;

+  }

+  //

+  // Look through our list of known structures for a match

+  //

+  for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {

+    //

+    // Check for matching structure name

+    //

+    if (strcmp (StructDef->Name, StructName) == 0) {

+      //

+      // Mark it as referenced (for debug purposes only). Check the

+      // flag that indicates that we have already found a varstore VFR

+      // statement for it.

+      //

+      StructDef->Referenced++;

+      if (StructDef->VarStoreIdValid == 0) {

+        //

+        // Set it valid so we don't flag it multiple times, then emit the error

+        //

+        StructDef->VarStoreIdValid = 1;

+        PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");

+      }

+      //

+      // Let the opcode-handler know which variable storage we're now using

+      //

+      if (mIdEqIdStmt) {

+        mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);

+      } else {

+        mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);

+      }

+      //

+      // Found matching structure name. Now find the matching field name

+      //

+      for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {

+        if (strcmp (FieldDef->Name, FieldName) == 0) {

+          //

+          // Make sure the variable size is valid

+          //

+          if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {

+            sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');

+            PrintErrorMessage (LineNum2, FieldName, Msg);

+          }

+          //

+          // If they specified an index (MyVfrData.FieldX[10]), then make sure that the

+          // data structure was declared as an array, and that the index is in bounds.

+          // If they did not specify an index, then we'll assume 0. This is required for

+          // strings.

+          //

+          if (IsArrayIndex) {

+            VarSize = FieldDef->DataSize;

+            if (FieldDef->IsArray == 0) {

+              PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");

+              return;

+            }

+            if (FieldDef->ArrayLength < ArrayIndex) {

+              PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");

+              return;

+            }

+          } else {

+            if (FieldDef->IsArray) {

+              VarSize = FieldDef->DataSize * FieldDef->ArrayLength;

+            } else {

+              VarSize = FieldDef->DataSize;

+            }

+          }

+          //

+          // If we're in the middle of a ideqid VFR statement, then this is the second

+          // variable ID that we're now processing. Make sure that its size is the same

+          // as the first variable.

+          // 

+          if (mIdEqIdStmt) {

+            if (mLastVarIdSize != VarSize) {

+              PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");

+              return;

+            }

+          }

+          mLastVarIdSize = VarSize;

+          //

+          // If we're supposed to write an array size, then require it to be an array

+          //

+          if (WriteArraySize && !FieldDef->IsArray) {

+            PrintErrorMessage (LineNum2, FieldName, "array required");

+            return;

+          }

+          //

+          // Write the variable offset and size. If we're in the non-NV structure, then

+          // set the offset beyond the NV data structure size.

+          //

+          Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);

+          if (StructDef->IsNonNV) Offset += mNvDataStructSize; 

+          WriteWord (Offset);

+          if (WriteLength) {

+            if (WriteArraySize) {

+              if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {

+                PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");

+                return;

+              }

+              WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);

+            } else {

+              WriteByte (FieldDef->DataSize, 0);

+            }

+          }

+          return;

+        }

+      }

+      sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);

+      PrintErrorMessage (LineNum2, Msg, NULL);

+      PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);

+      return;

+    }

+  }

+  //

+  // The structure was not found in the defined list. See if it's the "Date" structure

+  //

+  if (strcmp (StructName, "Date") == 0) {

+    //

+    // BUGBUG -- remove support for Date and Time as valid structure 

+    // names. They should use the NON_NV_DATA_MAP structure for this.

+    //

+    // Someone specified Date.Years|Months|Days

+    // BUGBUG -- define some constants for the IDs used here

+    // Length == 0 implies that this is not user NV data storage.

+    //

+    if (strcmp (FieldName, "Year") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else if (strcmp (FieldName, "Month") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else if (strcmp (FieldName, "Day") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else {

+      PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");

+    }

+    return;

+  } else if (strcmp (StructName, "Time") == 0) {

+    //

+    // Someone specified Time.Hours|Minutes|Seconds

+    // BUGBUG -- define some constants for the IDs used here

+    //

+    if (strcmp (FieldName, "Hours") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else if (strcmp (FieldName, "Minutes") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else if (strcmp (FieldName, "Seconds") == 0) {

+      //

+      // Write ID (offset), ID, and size

+      //

+      WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);

+      if (WriteLength) {

+        WriteByte (0, 0);

+      }

+    } else {

+      PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");

+    }

+    return;

+  } else {

+    PrintErrorMessage (LineNum1, StructName, "undefined structure");

+    return;

+  }

+}

+VOID

+EfiVfrParser::StartStructDefinition (

+  INT32  IsNonNV,

+  INT32  LineNum

+  )

+/*++

+

+Routine Description:

+  Called when we encounter a new "struct _MY_STRUCT..." statement while parsing. 

+  Initialize internal data and structures for parsing the fields of the structure.

+

+Arguments:

+  LineNum  - line number in the source file (for error reporting purposes)

+  IsNonNv  - flag indicating (if nonzero) that the variable referred to is not in

+             the standard NV store.

+Returns:

+  None

+

+--*/

+{

+  STRUCT_DEFINITION *StructDef;

+  //

+  // Allocate memory for the structure record

+  //

+  StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));

+  memset (StructDef, 0, sizeof (STRUCT_DEFINITION));

+  StructDef->LineNum = LineNum;

+  //

+  // Set flag indicating non-NV data structure or not

+  //

+  StructDef->IsNonNV = IsNonNV;

+  //

+  // Add it to the end of our linked list. If it's the first one

+  // defined, then it's the default varstore ID, so set it valid.

+  //

+  if (mFirstStructDefinition == NULL) {

+    mFirstStructDefinition = StructDef;

+    StructDef->VarStoreIdValid = 1;

+  } else {

+    mLastStructDefinition->Next = StructDef;

+  }

+  mLastStructDefinition = StructDef;

+}

+VOID

+EfiVfrParser::EndStructDefinition (

+  CHAR8  *StructName,

+  INT32  LineNum

+  )

+{

+  STRUCT_DEFINITION         *StructDef;

+  STRUCT_FIELD_DEFINITION   *FieldDef;

+  UINT32                    Offset;

+  //

+  // Make sure they have not already defined a structure with this name

+  //

+  for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {

+    if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {

+      PrintErrorMessage (LineNum, StructName, "structure with this name already defined");

+      //

+      // Fall through and fill in the rest of the structure information. We do

+      // this because the structure has already been added to our global list,

+      // so will be used elsewhere, so we want it to contain valid fields.

+      //

+    }

+  }    

+  //

+  // Allocate memory for the structure name 

+  //

+  mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);

+  strcpy (mLastStructDefinition->Name, StructName);

+  //

+  // Compute the structure size, and the offsets to each field

+  //

+  Offset = 0;

+  for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {

+    FieldDef->Offset = Offset;

+    Offset += FieldDef->ArrayLength * FieldDef->DataSize;

+  }

+  mLastStructDefinition->Size = Offset;

+  //

+  // Go through all the structure we have so far and figure out (if we can)

+  // the size of the non-NV storage. We also assume that the first structure

+  // definition is the primary/default storage for the VFR form.

+  //

+  if (mNonNvDataStructSize == 0) {

+    for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {

+      if (StructDef->IsNonNV) {

+        mNonNvDataStructSize = StructDef->Size;

+        break;

+      }

+    }

+  }

+  if (mNvDataStructSize == 0) {

+    for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {

+      if (StructDef->IsNonNV == 0) {

+        mNvDataStructSize = StructDef->Size;

+        break;

+      }

+    }

+  }

+}

+VOID 

+EfiVfrParser::AddStructField (

+  CHAR8   *FieldName, 

+  INT32   LineNum, 

+  INT32   DataSize,

+  INT32   ArrayLength,

+  INT8    IsArray

+  ) 

+/*++

+

+Routine Description:

+  We're parsing the VFR structure definition. Add another defined field to 

+  our definition.

+

+Arguments:

+  FieldName   - name of the field in the structure.

+  LineNum     - the line number from the input (preprocessor output) file

+  DataSize    - the size of the field (1, 2, or 4 bytes)

+  ArrayLength - the number of elements (for array)

+  IsArray     - non-zero if the field is an array

+

+Returns:

+  None.

+

+--*/

+{

+  STRUCT_FIELD_DEFINITION *FieldDef;

+  STRUCT_FIELD_DEFINITION *Temp;

+  //

+  // Make sure we don't already have a field of this name in our structure

+  //

+  for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {

+    if (strcmp (FieldDef->Name, FieldName) == 0) {

+      PrintErrorMessage (LineNum, FieldName, "field with this name already defined");

+      return;

+    }

+  } 

+  //

+  // If it's an array, then they better not have a size of 0. For example:

+  //   UINT8 MyBytes[0];

+  //

+  if (IsArray && (ArrayLength <= 0)) {

+    PrintErrorMessage (LineNum, FieldName, "invalid array size");

+    return;

+  }    

+  //

+  // Allocate memory for a new structure field definition

+  //    

+  FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));

+  memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));

+  FieldDef->ArrayLength  = ArrayLength;

+  FieldDef->DataSize     = DataSize;

+  FieldDef->IsArray      = IsArray;

+  FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);

+  strcpy (FieldDef->Name, FieldName);

+  //

+  // Add it to the end of the field list for the currently active structure

+  //

+  if (mLastStructDefinition->Field == NULL) {

+    mLastStructDefinition->Field = FieldDef;

+  } else {

+    mLastStructDefinition->LastField->Next = FieldDef;

+  }

+  mLastStructDefinition->LastField = FieldDef;

+}

+VOID

+EfiVfrParser::AddVarStore (

+  CHAR8  *StructName,       // actual name of the structure

+  CHAR8  *VarName,          // actual NV variable name

+  UINT16 VarStoreId,        // key value

+  INT32  LineNum            // parse line number (for error reporting)

+  )

+/*++

+

+Routine Description:

+  Called while parsing a varstore statement. Add the variable store 

+  to our linked list.

+

+Arguments:

+  StructName    - the name of the typedef'ed structure to use

+  VarName       - the NV variable name as specified in the varstore statement

+  VarStoreId    - the variable store ID as specified in the varstore statememt

+  LineNum       - the line number from the input (preprocessor output) file

+

+Returns:

+  None.

+

+--*/

+{

+  STRUCT_DEFINITION *StructDef;

+  UINT16_LIST       *L16Ptr;

+  //

+  // Go through our list of previously-defined variable store IDs and

+  // make sure this one is not a duplicate in name or key value.

+  //

+  for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {

+    if (L16Ptr->Value == VarStoreId) {

+      PrintErrorMessage (LineNum, "variable storage key already used", NULL);

+      PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);

+    }

+  }

+  // 

+  // Key value of 0 is invalid since that's assigned by default to the default

+  // variable store (the first structure parsed).

+  //

+  if (VarStoreId == 0) {

+    PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);

+  }

+  //

+  // Create a new element to add to the list

+  //

+  L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));

+  memset (L16Ptr, 0, sizeof (UINT16_LIST));

+  L16Ptr->LineNum = LineNum;

+  L16Ptr->Value = VarStoreId;

+  if (mDefinedVarStoreId == NULL) {

+    mDefinedVarStoreId = L16Ptr;

+  } else {

+    mLastDefinedVarStoreId->Next = L16Ptr;

+  }

+  mLastDefinedVarStoreId = L16Ptr;

+  //

+  // Find the structure definition with this name

+  //

+  for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {

+    if (strcmp (StructDef->Name, StructName) == 0) {

+      //

+      // Make sure they did not already define a variable storage ID 

+      // for this structure.

+      //

+      if (StructDef->VarStoreId != 0) {

+        PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");

+        PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");

+      }

+      StructDef->VarStoreId       = VarStoreId;

+      StructDef->VarStoreIdValid  = 1;

+      StructDef->VarStoreLineNum  = LineNum;

+      WriteWord (StructDef->Size);

+      while (*VarName) {

+        WriteByte(*VarName, 0);

+        VarName++;

+      }

+      WriteByte(0,0);

+      return;

+    }

+  }    

+  PrintErrorMessage (LineNum, StructName, "structure with this name not defined");

+}

+VOID 

+EfiVfrParser::WriteDWord (

+  UINT32    Value, 

+  UINT8     KeyByte

+  )

+/*++

+

+Routine Description:

+  During parsing, we came upon some code that requires a 32-bit value be

+  written to the VFR binary file. Queue up the 4 bytes.

+

+Arguments:

+  Value   - the 32-bit value to write

+  KeyByte - a single character which gets written out beside the first byte.

+            This is used to tag the data in the output file so that during 

+            debug you have an idea what the value is.

+

+Returns:

+  None.

+

+--*/

+{

+  //

+  // Write 4 bytes, little endian. Specify a key byte only on the first one

+  //

+  mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);

+  Value \>>= 8;

+  mOpcodeHandler.AddByte ((UINT8)Value, 0);

+  Value \>>= 8;

+  mOpcodeHandler.AddByte ((UINT8)Value, 0);

+  Value \>>= 8;

+  mOpcodeHandler.AddByte ((UINT8)Value, 0);

+}

+VOID 

+EfiVfrParser::WriteOpByte (

+  UINT32    LineNum,

+  UINT8     ByteValue

+  )

+/*++

+

+Routine Description:

+  

+  During parsing, we came upon a new VFR opcode. At this point we flush

+  the output queue and then queue up this byte (with 'O' for opcode tag).

+

+Arguments:

+

+  ByteValue   - opcode value

+

+Returns:

+

+  None.

+

+--*/

+{

+  mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);

+}

+VOID 

+EfiVfrParser::WriteByte (

+  UINT8   ByteValue, 

+  UINT8   Key

+  )

+/*++

+

+Routine Description:

+  

+  During parsing of the VFR we spoonfeed this function with bytes to write to

+  the output VFR binary file. This function simply queues up the bytes, and

+  the queue gets flushed each time a new VFR opcode is encountered.

+

+Arguments:

+

+  ByteValue   - raw byte to write

+  Key         - character to tag the byte with when we write ByteValue to the

+                output file.

+

+Returns:

+

+  None.

+

+--*/

+{

+  mOpcodeHandler.AddByte (ByteValue, Key);

+}

+VOID 

+EfiVfrParser::WriteWord (

+  UINT32  Value

+  )

+/*++

+

+Routine Description:

+  During VFR parsing we came upon a case where we need to write out a 

+  16-bit value. Queue it up.

+

+Arguments:

+  Value - value to write.

+

+Returns:

+  None.

+

+--*/

+{

+  mOpcodeHandler.AddByte ((UINT8)Value, 0);

+  mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);

+}

+VOID 

+EfiVfrParser::WriteStringIdWord (

+  UINT16 WordValue

+  )

+{

+  mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');

+  mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);

+}

+VOID

+EfiVfrParser::FreeGotoReferences ()

+/*++

+

+Routine Description:

+  Called during cleanup to free up the memory we allocated when

+  keeping track of VFR goto statements.

+

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{

+  GOTO_REFERENCE  *CurrRef;

+  GOTO_REFERENCE  *NextRef;

+  FORM_ID_VALUE   *CurrFormId;

+  FORM_ID_VALUE   *NextFormId;

+  UINT8           Found;

+  CHAR8           Name[20];

+

+  //

+  // Go through all the "goto" references and make sure there was a 

+  // form ID of that value defined.

+  //

+  for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {

+    Found = 0;

+    for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {

+      if (CurrRef->Value == CurrFormId->Value) {

+        Found = 1;

+        break;

+      }

+    }

+    if (!Found) {

+      sprintf (Name, "%d", (UINT32)CurrRef->Value);

+      PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");

+    }  

+  }  

+  //

+  // Now free up the form id and goto references

+  //

+  CurrFormId = mFormIdValues;

+  while (CurrFormId != NULL) {

+    NextFormId = CurrFormId->Next;

+    free (CurrFormId);

+    CurrFormId = NextFormId;

+  }

+  mFormIdValues = NULL;

+  CurrRef = mGotoReferences;

+  while (CurrRef != NULL) {

+    NextRef = CurrRef->Next;

+    free (CurrRef);

+    CurrRef = NextRef;

+  }  

+  mGotoReferences = NULL;

+}

+VOID

+EfiVfrParser::AddGotoReference (

+  UINT32  GotoNumber,

+  UINT32  LineNum

+  )

+/*++

+

+Routine Description:

+  During VFR parsing we came upon a goto statement. Since we support

+  forward references, save the referenced label and at the end of parsing

+  we'll check that the label was actually defined somewhere.

+

+Arguments:

+  GotoNumber  - the label number referenced

+  LineNum     - the line number where the reference was made (used for

+                error reporting)

+

+Returns:

+  None

+

+--*/

+{

+  GOTO_REFERENCE *NewRef;

+  

+  NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));

+  if (NewRef == NULL) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+    return;

+  }

+  memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));

+  NewRef->Value = (UINT16)GotoNumber;

+  NewRef->RefLineNum = LineNum;

+  NewRef->Next = mGotoReferences;

+  mGotoReferences = NewRef;

+}

+VOID

+EfiVfrParser::AddFormId (

+  INT32   FormIdValue,

+  UINT32  LineNum

+  )

+/*++

+

+Routine Description:

+  This function is called when we parse "form formid = 3" statements.

+  We save the form ID valud so we can verify that duplicates are not

+  defined. Also, these are the targets of goto statements, so when we're

+  done parsing the script we also go through all the goto statements to

+  check that there was a target FormId defined as referenced by each

+  goto statement.

+  

+  Note that formid = 0 is invalid.

+

+Arguments:

+  FormIdValue  - the parsed value for the Form ID

+  LineNum      - line number of the source file we're parsing

+

+Returns:

+  NA

+

+--*/

+{

+  FORM_ID_VALUE *NewFormId;

+  char          *FileName;

+  char          *FileName2;

+  UINT32        LineNum2;  

+  //

+  // Verify that FormId != 0

+  //

+  if (FormIdValue == 0) {

+    FileName = ConvertLineNumber (&LineNum);

+    Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);

+    return;

+  }

+  //

+  // First go through all previously defined form IDs and make sure they have not defined

+  // duplicates.

+  //

+  for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {

+    if ((UINT16)FormIdValue == NewFormId->Value) {

+      FileName = ConvertLineNumber (&LineNum);

+      LineNum2 = NewFormId->LineNum;

+      FileName2 = ConvertLineNumber (&LineNum2);

+      Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);

+      Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);

+      return;

+    }

+  }

+  //

+  // Allocate memory for a new one 

+  //

+  NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));

+  if (NewFormId == NULL) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");

+    return;

+  }

+  memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));

+  NewFormId->LineNum = LineNum;

+  NewFormId->Next = mFormIdValues;

+  NewFormId->Value = (UINT16)FormIdValue;

+  mFormIdValues = NewFormId;

+}

+UINT32

+EfiVfrParser::GetNumber (

+  CHAR8   *NumStr,

+  UINT32  LineNum,

+  UINT32  NumBytes

+  )

+{

+  UINT32 Value;

+  

+  if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {

+    AtoX (NumStr + 2, 4, &Value);

+  } else {

+    Value = (UINT32)atoi (NumStr);

+  }

+  //

+  // Check range

+  //

+  if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {

+    PrintErrorMessage (LineNum, NumStr, "value out of range");

+    return 0;

+  }

+  return Value;

+}

+

+>>

+

+} // end grammar class

+

diff --git a/Source/VfrCompile/VfrServices.cpp b/Source/VfrCompile/VfrServices.cpp
new file mode 100644
index 0000000..359256a
--- /dev/null
+++ b/Source/VfrCompile/VfrServices.cpp
@@ -0,0 +1,758 @@
+/*++

+

+Copyright (c) 2004 - 2005, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  VfrServices.cpp

+

+Abstract:

+

+  Support routines for the VFR compiler

+  

+--*/  

+

+#include <stdio.h>    // for FILE routines

+#include <stdlib.h>   // for malloc() and free()

+

+#include <Common/UefiBaseTypes.h>

+#include <Common/MultiPhase.h>

+#include <Common/InternalFormRepresentation.h>

+#include <Protocol/UgaDraw.h>  // for EFI_UGA_PIXEL definition

+#include <Protocol/Hii.h>

+

+#include "EfiUtilityMsgs.h"

+#include "EfiVfr.h"

+#include "VfrServices.h"

+

+

+static const char *mSourceFileHeader[] = {

+  "//",

+  "//  DO NOT EDIT -- auto-generated file",

+  "//",

+  "//  This file is generated by the VFR compiler.",

+  "//",

+  NULL

+};

+

+typedef struct {

+   CHAR8    *Name;

+   INT32    Size;

+} IFR_OPCODE_SIZES;

+

+//

+// Create a table that can be used to do internal checking on the IFR

+// bytes we emit.

+//

+static const IFR_OPCODE_SIZES mOpcodeSizes[] = {

+  { 0, 0 },     // invalid

+  { "EFI_IFR_FORM",                       sizeof (EFI_IFR_FORM) },

+  { "EFI_IFR_SUBTITLE",                   sizeof (EFI_IFR_SUBTITLE) }, 

+  { "EFI_IFR_TEXT",                       -6 }, //sizeof (EFI_IFR_TEXT) }, 

+  { "unused 0x04 opcode",                 0 }, // EFI_IFR_GRAPHIC_OP

+  { "EFI_IFR_ONE_OF",                     sizeof (EFI_IFR_ONE_OF) }, 

+  { "EFI_IFR_CHECKBOX",                   sizeof (EFI_IFR_CHECKBOX) }, 

+  { "EFI_IFR_NUMERIC",                    sizeof (EFI_IFR_NUMERIC) }, 

+  { "EFI_IFR_PASSWORD",                   sizeof (EFI_IFR_PASSWORD) }, 

+  { "EFI_IFR_ONE_OF_OPTION",              sizeof (EFI_IFR_ONE_OF_OPTION) }, 

+  { "EFI_IFR_SUPPRESS",                   sizeof (EFI_IFR_SUPPRESS) }, 

+  { "EFI_IFR_END_FORM",                   sizeof (EFI_IFR_END_FORM) }, 

+  { "EFI_IFR_HIDDEN",                     sizeof (EFI_IFR_HIDDEN) }, 

+  { "EFI_IFR_END_FORM_SET",               sizeof (EFI_IFR_END_FORM_SET) }, 

+  { "EFI_IFR_FORM_SET",                   sizeof (EFI_IFR_FORM_SET) }, 

+  { "EFI_IFR_REF",                        sizeof (EFI_IFR_REF) }, 

+  { "EFI_IFR_END_ONE_OF",                 sizeof (EFI_IFR_END_ONE_OF) }, 

+  { "EFI_IFR_INCONSISTENT",               sizeof (EFI_IFR_INCONSISTENT) }, 

+  { "EFI_IFR_EQ_ID_VAL",                  sizeof (EFI_IFR_EQ_ID_VAL) }, 

+  { "EFI_IFR_EQ_ID_ID",                   sizeof (EFI_IFR_EQ_ID_ID) }, 

+  { "EFI_IFR_EQ_ID_LIST",                 -sizeof (EFI_IFR_EQ_ID_LIST) }, 

+  { "EFI_IFR_AND",                        sizeof (EFI_IFR_AND) }, 

+  { "EFI_IFR_OR",                         sizeof (EFI_IFR_OR) }, 

+  { "EFI_IFR_NOT",                        sizeof (EFI_IFR_NOT) }, 

+  { "EFI_IFR_END_EXPR",                   sizeof (EFI_IFR_END_EXPR) }, 

+  { "EFI_IFR_GRAY_OUT",                   sizeof (EFI_IFR_GRAY_OUT) }, 

+  { "EFI_IFR_DATE",                       sizeof (EFI_IFR_DATE) / 3 }, 

+  { "EFI_IFR_TIME",                       sizeof (EFI_IFR_TIME) / 3 }, 

+  { "EFI_IFR_STRING",                     sizeof (EFI_IFR_STRING) }, 

+  { "EFI_IFR_LABEL",                      sizeof (EFI_IFR_LABEL) }, 

+  { "EFI_IFR_SAVE_DEFAULTS",              sizeof (EFI_IFR_SAVE_DEFAULTS) }, 

+  { "EFI_IFR_RESTORE_DEFAULTS",           sizeof (EFI_IFR_RESTORE_DEFAULTS) }, 

+  { "EFI_IFR_BANNER",                     sizeof (EFI_IFR_BANNER) },

+  { "EFI_IFR_INVENTORY",                  sizeof (EFI_IFR_INVENTORY) },

+  { "EFI_IFR_EQ_VAR_VAL_OP",              sizeof (EFI_IFR_EQ_VAR_VAL) },

+  { "EFI_IFR_ORDERED_LIST_OP",            sizeof (EFI_IFR_ORDERED_LIST) },

+  { "EFI_IFR_VARSTORE_OP",                -sizeof (EFI_IFR_VARSTORE) },

+  { "EFI_IFR_VARSTORE_SELECT_OP",         sizeof (EFI_IFR_VARSTORE_SELECT) },

+  { "EFI_IFR_VARSTORE_SELECT_PAIR_OP",    sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },

+  { "EFI_IFR_TRUE",                       sizeof (EFI_IFR_TRUE)},

+  { "EFI_IFR_FALSE",                      sizeof (EFI_IFR_FALSE)},

+  { "EFI_IFR_GT",                         sizeof (EFI_IFR_GT)},

+  { "EFI_IFR_GE",                         sizeof (EFI_IFR_GE)},

+  { "EFI_IFR_OEM_DEFINED_OP",             -2 },

+};

+

+

+VfrOpcodeHandler::VfrOpcodeHandler (

+  ) 

+/*++

+

+Routine Description:

+  Constructor for the VFR opcode handling class.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{ 

+  mIfrBytes                       = NULL; 

+  mLastIfrByte                    = NULL;

+  mBytesWritten                   = 0;

+  mQueuedByteCount                = 0;

+  mQueuedOpcodeByteValid          = 0;

+  mPrimaryVarStoreId              = 0;

+  mSecondaryVarStoreId            = 0;

+  mSecondaryVarStoreIdSet         = 0;

+  mPrimaryVarStoreIdSet           = 0;

+  mDefaultVarStoreId              = 0;

+}

+

+VOID 

+VfrOpcodeHandler::SetVarStoreId (

+  UINT16 VarStoreId

+  )

+/*++

+

+Routine Description:

+  This function is invoked by the parser when a variable is referenced in the 

+  VFR. Save the variable store (and set a flag) so that we can later determine 

+  if we need to emit a varstore-select or varstore-select-pair opcode.

+  

+Arguments:

+  VarStoreId - ID of the variable store referenced in the VFR

+

+Returns:

+  None

+

+--*/

+{

+  mPrimaryVarStoreId    = VarStoreId;

+  mPrimaryVarStoreIdSet = 1;

+}

+

+VOID 

+VfrOpcodeHandler::SetSecondaryVarStoreId (

+  UINT16 VarStoreId

+  )

+/*++

+

+Routine Description:

+  This function is invoked by the parser when a secondary variable is 

+  referenced in the VFR. Save the variable store (and set a flag) so 

+  that we can later determine if we need to emit a varstore-select or 

+  varstore-pair opcode.

+  

+Arguments:

+  VarStoreId - ID of the variable store referenced in the VFR

+

+Returns:

+  None

+

+--*/

+{

+  mSecondaryVarStoreId    = VarStoreId;

+  mSecondaryVarStoreIdSet = 1;

+}

+

+VOID 

+VfrOpcodeHandler::WriteIfrBytes (

+  ) 

+/*++

+

+Routine Description:

+  This function is invoked at the end of parsing. Its purpose

+  is to write out all the IFR bytes that were queued up while

+  parsing.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{ 

+  IFR_BYTE                  *Curr;

+  IFR_BYTE                  *Next;

+  UINT32                    Count;

+  UINT32                    LineCount;

+  UINT32                    PoundLines;

+  UINT32                    ByteCount;

+  CHAR8                     Line[MAX_LINE_LEN];

+  CHAR8                     *Cptr;

+  FILE                      *InFptr;

+  FILE                      *OutFptr;

+  UINT32                    ListFile;

+  EFI_HII_IFR_PACK_HEADER   IfrHeader;

+  UINT8                     *Ptr;

+  FILE                      *IfrBinFptr;

+  UINT32                    BytesLeftThisOpcode;

+  //

+  // If someone added a new opcode and didn't update our opcode sizes structure, error out.

+  //

+  if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {

+    Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");

+    return;

+  }

+  //

+  // Flush the queue

+  //

+  FlushQueue ();    

+  //

+  // If there have been any errors to this point, then skip dumping the IFR

+  // binary data. This way doing an nmake again will try to build it again, and

+  // the build will fail if they did not fix the problem.

+  //

+  if (GetUtilityStatus () != STATUS_ERROR) {

+    if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {

+      Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");

+      return;

+    }

+    //

+    // Write the standard file header to the output file

+    //

+    WriteStandardFileHeader (IfrBinFptr);

+    //

+    // Write the structure header

+    //

+    fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);

+    //

+    // Write the header

+    //

+    memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));

+    IfrHeader.Header.Type = EFI_HII_IFR;

+    IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);    

+    Ptr = (UINT8 *)&IfrHeader;

+    for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {

+      if ((Count & 0x03) == 0) {

+        fprintf (IfrBinFptr, "\n  ");

+      }

+      fprintf (IfrBinFptr, "0x%02X, ", *Ptr);      

+    }

+    //

+    //

+    // Write all the IFR bytes

+    //

+    fprintf (IfrBinFptr, "\n  // start of IFR data");

+    Curr = mIfrBytes;

+    Count = 0;

+    while (Curr != NULL) {

+      if ((Count & 0x0F) == 0) {

+        fprintf (IfrBinFptr, "\n  ");

+      }

+      if (Curr->KeyByte != 0) {

+        fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);

+      }

+      fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);

+      Count++;

+      Curr = Curr->Next;

+    }

+    fprintf (IfrBinFptr, "\n};\n\n");

+    //

+    //

+    // Close the file

+    //

+    fclose (IfrBinFptr); 

+    IfrBinFptr = NULL;

+  }

+  //

+  // Write the bytes as binary data if the user specified to do so

+  //

+  if ((GetUtilityStatus () != STATUS_ERROR) &&  (gOptions.CreateIfrBinFile != 0)) {

+    //

+    // Use the Ifr output file name with a ".hpk" extension.

+    //

+    for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;

+         (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');

+         Cptr--) {

+      //

+      // do nothing

+      //

+    }

+    if (*Cptr == '.') {

+      strcpy (Cptr, ".hpk");

+    } else {

+      strcat (gOptions.IfrOutputFileName, ".hpk");

+    }

+    if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {

+      Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");

+      return;

+    }

+    //

+    // Write the structure header

+    //

+    memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));

+    IfrHeader.Header.Type = EFI_HII_IFR;

+    IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);    

+    Ptr = (UINT8 *)&IfrHeader;

+    for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {

+      fwrite (Ptr, 1, 1, IfrBinFptr);

+    }

+    //

+    //

+    // Write all the IFR bytes

+    //

+    Curr = mIfrBytes;

+    Count = 0;

+    while (Curr != NULL) {

+      fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);

+      Curr = Curr->Next;

+    }

+    //

+    //

+    // Close the file

+    //

+    fclose (IfrBinFptr); 

+    IfrBinFptr = NULL;

+  }

+  //

+  // If creating a listing file, then open the input and output files

+  //

+  ListFile = 0;

+  if (gOptions.CreateListFile) {

+    //

+    // Open the input VFR file and the output list file

+    //

+    if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {

+      Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");

+    } else {

+      if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {

+        Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");

+        fclose (InFptr);

+        InFptr = NULL;

+      } else {

+        LineCount   = 0;

+        ListFile    = 1;

+        PoundLines  = 0;

+        ByteCount   = 0;

+      }

+    }

+  }

+  //

+  // Write the list file

+  //

+  if (ListFile) {

+    //

+    // Write out the VFR compiler version

+    //

+    fprintf (OutFptr, "//\n//  VFR compiler version " VFR_COMPILER_VERSION "\n//\n");

+    Curr = mIfrBytes;

+    while (Curr != NULL) {

+      //

+      // Print lines until we reach the line of the current opcode

+      //

+      while (LineCount < PoundLines + Curr->LineNum) {

+        if (fgets (Line, sizeof (Line), InFptr) != NULL) {

+          //

+          // We should check for line length exceeded on the fgets(). Otherwise it

+          // throws the listing file output off. Future enhancement perhaps.

+          //

+          fprintf (OutFptr, "%s", Line);

+          if (strncmp (Line, "#line", 5) == 0) {

+            PoundLines++;

+          }

+        }

+        LineCount++;

+      }

+      //

+      // Print all opcodes with line numbers less than where we are now

+      //

+      BytesLeftThisOpcode = 0;

+      while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {

+        if (BytesLeftThisOpcode == 0) {

+          fprintf (OutFptr, ">%08X: ", ByteCount);

+          if (Curr->Next != NULL) {

+            BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;

+          }

+        }

+        fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);

+        ByteCount++;

+        BytesLeftThisOpcode--;

+        if (BytesLeftThisOpcode == 0) {

+          fprintf (OutFptr, "\n");

+        }

+        Curr = Curr->Next;

+      }

+    }

+    //

+    // Dump any remaining lines from the input file

+    //

+    while (fgets (Line, sizeof (Line), InFptr) != NULL) {

+      fprintf (OutFptr, "%s", Line);

+    }

+    fclose (InFptr);

+    fclose (OutFptr);

+  }

+  //

+  // Debug code to make sure that each opcode we write out has as many

+  // bytes as the IFR structure requires. If there were errors, then

+  // don't do this step.

+  //

+  if (GetUtilityStatus () != STATUS_ERROR) {

+    Curr = mIfrBytes;

+    ByteCount = 0;

+    while (Curr != NULL) {

+      //

+      // First byte is the opcode, second byte is the length

+      //

+      if (Curr->Next == NULL) {

+        Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");

+        break;

+      }

+      Count = (UINT32)Curr->Next->OpcodeByte;

+      if (Count == 0) {

+        Error (

+          __FILE__, 

+          __LINE__, 

+          0, 

+          "application error", 

+          "opcode with 0 length specified in output at offset 0x%X", 

+          ByteCount

+          );

+        break;

+      }

+      //

+      // Check the length

+      //

+      if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {

+        Error (

+          __FILE__, 

+          __LINE__, 

+          0, 

+          "application error", 

+          "invalid opcode 0x%X in output at offset 0x%X", 

+          (UINT32) Curr->OpcodeByte, ByteCount

+          );

+      } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {

+        //

+        // For those cases where the length is variable, the size is negative, and indicates

+        // the miniumum size.

+        //

+        if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {

+          Error (

+            __FILE__, 

+            __LINE__, 

+            0, 

+            "application error", 

+            "insufficient number of bytes written for %s at offset 0x%X",

+            mOpcodeSizes[Curr->OpcodeByte].Name, 

+            ByteCount

+            );

+        }

+      } else {

+        //

+        // Check for gaps

+        //

+        if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {

+          Error (

+            __FILE__, 

+            __LINE__, 

+            0, 

+            "application error", 

+            "invalid opcode 0x%X in output at offset 0x%X", 

+            (UINT32)Curr->OpcodeByte, 

+            ByteCount

+            );

+        } else {

+          //

+          // Check size

+          //

+          if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {

+            Error (

+              __FILE__, 

+              __LINE__, 

+              0, 

+              "application error", 

+              "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",

+              Count, 

+              mOpcodeSizes[Curr->OpcodeByte].Size, 

+              mOpcodeSizes[Curr->OpcodeByte].Name, 

+              ByteCount

+              );

+          }

+        }

+      }

+      //

+      // Skip to next opcode

+      //

+      while (Count > 0) {

+        ByteCount++;

+        if (Curr == NULL) {

+          Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");

+          break;

+        }

+        Curr = Curr->Next;

+        Count--;

+      }

+    }

+  }

+}

+

+VfrOpcodeHandler::~VfrOpcodeHandler(

+  ) 

+/*++

+

+Routine Description:

+  Destructor for the VFR opcode handler. Free up memory allocated

+  while parsing the VFR script.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+{

+  IFR_BYTE    *Curr;

+  IFR_BYTE    *Next;

+  //

+  // Free up the IFR bytes

+  //

+  Curr = mIfrBytes;

+  while (Curr != NULL) {

+    Next = Curr->Next;

+    free (Curr);

+    Curr = Next;

+  }

+}

+

+int 

+VfrOpcodeHandler::AddOpcodeByte (

+  UINT8 OpcodeByte, 

+  UINT32 LineNum

+  ) 

+/*++

+

+Routine Description:

+  This function is invoked by the parser when a new IFR

+  opcode should be emitted.

+  

+Arguments:

+  OpcodeByte  - the IFR opcode

+  LineNum     - the line number from the source file that resulted

+                in the opcode being emitted.

+

+Returns:

+  0 always

+

+--*/

+{

+  UINT32 Count;

+

+  FlushQueue();

+  //

+  // Now add this new byte

+  //

+  mQueuedOpcodeByte       = OpcodeByte;

+  mQueuedLineNum          = LineNum;

+  mQueuedOpcodeByteValid  = 1;

+  return 0;

+}

+

+VOID 

+VfrOpcodeHandler::AddByte (

+  UINT8 ByteVal, 

+  UINT8 KeyByte

+  )

+/*++

+

+Routine Description:

+  This function is invoked by the parser when it determines

+  that more raw IFR bytes should be emitted to the output stream.

+  Here we just queue them up into an output buffer.

+  

+Arguments:

+  ByteVal   - the raw byte to emit to the output IFR stream

+  KeyByte   - a value that can be used for debug. 

+

+Returns:

+  None

+

+--*/

+{

+  //

+  // Check for buffer overflow

+  //

+  if (mQueuedByteCount > MAX_QUEUE_COUNT) {

+    Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");

+  } else {

+    mQueuedBytes[mQueuedByteCount]    = ByteVal;

+    mQueuedKeyBytes[mQueuedByteCount] = KeyByte;

+    mQueuedByteCount++;

+  }

+}

+

+int 

+VfrOpcodeHandler::FlushQueue (

+  )

+/*++

+

+Routine Description:

+  This function is invoked to flush the internal IFR buffer.

+  

+Arguments:

+  None

+

+Returns:

+  0 always

+

+--*/

+{

+  UINT32 Count;

+  UINT32 EmitNoneOnePair;

+

+  EmitNoneOnePair = 0;

+  //

+  // If the secondary varstore was specified, then we have to emit

+  // a varstore-select-pair opcode, which only applies to the following

+  // statement. 

+  //

+  if (mSecondaryVarStoreIdSet) {

+    mSecondaryVarStoreIdSet = 0;

+    //

+    // If primary and secondary are the same as the current default

+    // varstore, then we don't have to do anything.

+    // Note that the varstore-select-pair only applies to the following

+    // opcode.

+    //

+    if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {

+      IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);

+      IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);

+      IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);

+      IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);

+      IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);

+      IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);

+    }

+  } else if (mPrimaryVarStoreIdSet != 0) {

+    mPrimaryVarStoreIdSet = 0;

+    if (mDefaultVarStoreId != mPrimaryVarStoreId) {

+      //

+      // The VFR statement referenced a different variable store 

+      // than the last one we reported. Insert a new varstore select 

+      // statement. 

+      //

+      IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);

+      IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);

+      IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);

+      IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);

+      mDefaultVarStoreId = mPrimaryVarStoreId;

+    }

+  }

+  //

+  // Likely a new opcode is being added. Since each opcode item in the IFR has 

+  // a header that specifies the size of the opcode item (which we don't

+  // know until we find the next opcode in the VFR), we queue up bytes

+  // until we know the size. Then we write them out. So flush the queue

+  // now.

+  //

+  if (mQueuedOpcodeByteValid != 0) {

+    // 

+    // Add the previous opcode byte, the length byte, and the binary

+    // data.

+    //

+    IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);

+    IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);

+    for (Count = 0; Count < mQueuedByteCount; Count++) {

+      IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);          

+    }

+    mQueuedByteCount = 0;

+    mQueuedOpcodeByteValid = 0;

+  }    

+  return 0;

+}

+

+int 

+VfrOpcodeHandler::IAddByte (

+  UINT8   ByteVal, 

+  UINT8   KeyByte, 

+  UINT32  LineNum

+  )

+/*++

+

+Routine Description:

+  This internal function is used to add actual IFR bytes to

+  the output stream. Most other functions queue up the bytes

+  in an internal buffer. Once they come here, there's no

+  going back.

+

+  

+Arguments:

+  ByteVal   - value to write to output 

+  KeyByte   - key value tied to the byte -- useful for debug

+  LineNum   - line number from source file the byte resulted from

+

+Returns:

+  0 - if successful

+  1 - failed due to memory allocation failure

+

+--*/

+{

+  IFR_BYTE    *NewByte;

+  NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));

+  if (NewByte == NULL) {

+    return 1;

+  }

+  memset ((char *)NewByte, 0, sizeof (IFR_BYTE));

+  NewByte->OpcodeByte = ByteVal;

+  NewByte->KeyByte = KeyByte;

+  NewByte->LineNum = LineNum;

+  //

+  // Add to the list

+  //

+  if (mIfrBytes == NULL) {

+    mIfrBytes = NewByte;

+  } else {

+    mLastIfrByte->Next = NewByte;

+  } 

+  mLastIfrByte = NewByte;

+  mBytesWritten++;

+  return 0;

+}

+

+VOID 

+WriteStandardFileHeader (

+  FILE *OutFptr

+  ) 

+/*++

+

+Routine Description:

+  This function is invoked to emit a standard header to an

+  output text file.

+  

+Arguments:

+  OutFptr - file to write the header to

+

+Returns:

+  None

+

+--*/

+{

+  UINT32 TempIndex;

+  for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {

+    fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);

+  }

+  //

+  // Write out the VFR compiler version

+  //

+  fprintf (OutFptr, "//  VFR compiler version " VFR_COMPILER_VERSION "\n//\n");

+}

diff --git a/Source/VfrCompile/VfrServices.h b/Source/VfrCompile/VfrServices.h
new file mode 100644
index 0000000..6b8c560
--- /dev/null
+++ b/Source/VfrCompile/VfrServices.h
@@ -0,0 +1,227 @@
+/*++

+

+Copyright (c) 2004, Intel Corporation                                                         

+All rights reserved. This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  VfrServices.h

+

+Abstract:

+

+  Prototypes and defines for routines and classes used by the

+  EFI VFR compiler.

+  

+--*/

+

+#ifndef _VFR_SERVICES_H_

+#define _VFR_SERVICES_H_

+

+class VfrOpcodeHandler

+{

+public:

+  VfrOpcodeHandler (

+    VOID

+    )

+  /*++

+

+Routine Description:

+  Constructor for the VFR opcode handling class.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+  ;

+  ~VfrOpcodeHandler (

+    VOID

+    )

+  /*++

+

+Routine Description:

+  Destructor for the VFR opcode handler. Free up memory allocated

+  while parsing the VFR script.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+  ;

+  void

+  WriteIfrBytes (

+    VOID

+    )

+  /*++

+

+Routine Description:

+  This function is invoked at the end of parsing. Its purpose

+  is to write out all the IFR bytes that were queued up while

+  parsing.

+  

+Arguments:

+  None

+

+Returns:

+  None

+

+--*/

+  ;

+  int

+  AddOpcodeByte (

+    UINT8  OpcodeByte,

+    UINT32 LineNum

+    )

+  /*++

+

+Routine Description:

+  This function is invoked by the parser when a new IFR

+  opcode should be emitted.

+  

+Arguments:

+  OpcodeByte  - the IFR opcode

+  LineNum     - the line number from the source file that resulted

+                in the opcode being emitted.

+

+Returns:

+  0 always

+

+--*/

+  ;

+  void

+  AddByte (

+    UINT8 ByteVal,

+    UINT8 KeyByte

+    )

+  /*++

+

+Routine Description:

+  This function is invoked by the parser when it determines

+  that more raw IFR bytes should be emitted to the output stream.

+  Here we just queue them up into an output buffer.

+  

+Arguments:

+  ByteVal   - the raw byte to emit to the output IFR stream

+  KeyByte   - a value that can be used for debug. 

+

+Returns:

+  None

+

+--*/

+  ;

+  void

+  SetVarStoreId (

+    UINT16 VarStoreId

+    )

+  /*++

+

+Routine Description:

+  This function is invoked by the parser when a variable is referenced in the 

+  VFR. Save the variable store (and set a flag) so that we can later determine 

+  if we need to emit a varstore-select or varstore-select-pair opcode.

+  

+Arguments:

+  VarStoreId - ID of the variable store referenced in the VFR

+

+Returns:

+  None

+

+--*/

+  ;

+  void

+  SetSecondaryVarStoreId (

+    UINT16 VarStoreId

+    )

+  /*++

+

+Routine Description:

+  This function is invoked by the parser when a secondary variable is 

+  referenced in the VFR. Save the variable store (and set a flag) so 

+  that we can later determine if we need to emit a varstore-select or 

+  varstore-pair opcode.

+  

+Arguments:

+  VarStoreId - ID of the variable store referenced in the VFR

+

+Returns:

+  None

+

+--*/

+  ;

+

+/* */

+private:

+  int

+  FlushQueue (

+    VOID

+    )

+  /*++

+

+Routine Description:

+  This function is invoked to flush the internal IFR buffer.

+  

+Arguments:

+  None

+

+Returns:

+  0 always

+

+--*/

+  ;

+  int

+  IAddByte (

+    UINT8  ByteVal,

+    UINT8  KeyByte,

+    UINT32 LineNum

+    )

+  /*++

+

+Routine Description:

+  This internal function is used to add actual IFR bytes to

+  the output stream. Most other functions queue up the bytes

+  in an internal buffer. Once they come here, there's no

+  going back.

+

+  

+Arguments:

+  ByteVal   - value to write to output 

+  KeyByte   - key value tied to the byte -- useful for debug

+  LineNum   - line number from source file the byte resulted from

+

+Returns:

+  0 - if successful

+  1 - failed due to memory allocation failure

+

+--*/

+  ;

+

+/* */

+private:

+  IFR_BYTE  *mIfrBytes;

+  IFR_BYTE  *mLastIfrByte;

+  UINT32    mQueuedByteCount;

+  UINT32    mBytesWritten;

+  UINT32    mQueuedLineNum;

+  UINT8     mQueuedBytes[MAX_QUEUE_COUNT];

+  UINT8     mQueuedKeyBytes[MAX_QUEUE_COUNT];

+  UINT8     mQueuedOpcodeByte;

+  UINT32    mQueuedOpcodeByteValid;

+  UINT16    mPrimaryVarStoreId;

+  UINT8     mPrimaryVarStoreIdSet;

+  UINT16    mSecondaryVarStoreId;

+  UINT8     mSecondaryVarStoreIdSet;

+  UINT16    mDefaultVarStoreId;

+};

+

+#endif // #ifndef _VFR_SERVICES_H_

diff --git a/Source/VfrCompile/build.xml b/Source/VfrCompile/build.xml
new file mode 100644
index 0000000..51770d8
--- /dev/null
+++ b/Source/VfrCompile/build.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir="." name="VfrCompile">

+<!--

+    EDK VfrCompile Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="VfrCompile"/>

+  <property name="FileSet" value="*.cpp"/>

+  <property name="FileSetPccts" value="ATokenBuffer.cpp DLexerBase.cpp AParser.cpp"/>

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Antlr, Dlg, Tool">

+    <echo message="The EDK Tool: ${ToolName} build has completed"/>

+  </target>

+

+  <target name="init">

+

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+

+    <condition property="AntlrDepends">

+      <uptodate targetfile="${PACKAGE_DIR}/VfrCompile/parser.dlg" srcfile="${PACKAGE_DIR}/VfrCompile/VfrCompile.g" value="true"/>

+    </condition>

+

+    <condition property="DlgDepends">

+      <uptodate targetfile="${PACKAGE_DIR}/VfrCompile/DLGLexer.cpp" srcfile="${PACKAGE_DIR}/VfrCompile/parser.dlg" value="true"/>

+    </condition>

+

+    <condition property="CheckDepends">

+      <or>

+        <isset property="AntlrDepends"/>

+        <isset property="DlgDepends"/>

+      </or>

+    </condition>

+

+    <condition property="gxx_extra_libs" value="stdc++ System gcc_s.10.4 gcc">

+      <os family="mac"/>

+    </condition>

+    

+    <condition property="gxx_extra_libs" value="stdc++">

+      <os name="linux"/>

+    </condition>

+    

+    <condition property="gxx_extra_libs" value="stdc++">

+      <os family="windows"/>

+    </condition>

+    

+  </target>

+

+  <target name="Antlr" depends="init" unless="AntlrDepends">

+    <echo message="Executing ANTLR"/>

+    <exec dir="${basedir}/${ToolName}" executable="${env.FRAMEWORK_TOOLS_PATH}/antlr" failonerror="TRUE">

+      <arg line="-CC -e3 -ck 3 -o . VfrCompile.g"/>

+    </exec>

+  </target>

+

+  <target name="Dlg" depends="Antlr" unless="DlgDepends">

+    <echo message="Executing DLG"/>

+    <exec dir="${basedir}/${ToolName}" executable="${env.FRAMEWORK_TOOLS_PATH}/dlg" failonerror="TRUE">

+      <arg line="-C2 -i -CC -o . parser.dlg"/>

+    </exec>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        debug="true"

+        optimize="speed">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" />

+

+      <fileset dir="${basedir}/Pccts/h" 

+        includes="${FileSetPccts}" />

+

+      <includepath path="${PACKAGE_DIR}/Pccts/h"/>

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+      <libset dir="${LIB_DIR}" libs="CommonTools"/>

+      <syslibset libs="${gxx_extra_libs}" if="gcc"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>

+    <delete>

+      <fileset dir="${BUILD_DIR}" includes="*.obj"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${basedir}/${ToolName}/DLGLexer.cpp"/>

+      <fileset file="${basedir}/${ToolName}/DLGLexer.h"/>

+      <fileset file="${basedir}/${ToolName}/EfiVfrParser.cpp"/>

+      <fileset file="${basedir}/${ToolName}/EfiVfrParser.h"/>

+      <fileset file="${basedir}/${ToolName}/parser.dlg"/>

+      <fileset file="${basedir}/${ToolName}/tokens.h"/>

+      <fileset file="${basedir}/${ToolName}/VfrCompile.cpp"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/ZeroDebugData/ZeroDebugData.c b/Source/ZeroDebugData/ZeroDebugData.c
new file mode 100644
index 0000000..caf129b
--- /dev/null
+++ b/Source/ZeroDebugData/ZeroDebugData.c
@@ -0,0 +1,391 @@
+/*++

+

+Copyright (c)  2004-2006 Intel Corporation. All rights reserved

+This program and the accompanying materials are licensed and made available

+under the terms and conditions of the BSD License which accompanies this

+distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+

+Module Name:

+

+  ZeroDebugData.c

+

+Abstract:

+

+  Zero the Debug Data Fields of Portable Executable (PE) format file.

+

+--*/

+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+

+void

+PrintUsage (

+  void

+  )

+/*++

+Routine Description:

+  print usage of ZeroDebugData command

+

+Arguments:

+  None

+

+Returns:

+  None

+--*/

+// GC_TODO:    void - add argument and description to function comment

+{

+  //

+  // print usage of command

+  //

+  printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");

+}

+

+int

+ReadFromFile (

+  FILE      *fp,

+  long      offset,

+  void      *buffer,

+  int       size

+  )

+/*++

+Routine Description:

+  read data from a specified location of file

+

+Arguments:

+  fp              - file pointer

+  offset          - number of bytes from beginning of file

+  buffer          - buffer used to store data

+  size            - size of buffer

+

+Returns:

+  =  0            - Success

+  = -1            - Failed

+--*/

+{

+  //

+  // set file pointer to the specified location of file

+  //

+  if (fseek (fp, offset, SEEK_SET) != 0) {

+    printf ("Error: Cannot move the current location of the file.\n");

+    return -1;

+  }

+  //

+  // read data from the file

+  //

+  if (fread (buffer, size, 1, fp) != 1) {

+    printf ("Error: Cannot read data from the file.\n");

+    return -1;

+  }

+

+  return 0;

+}

+

+int

+ZeroDebugData (

+  FILE      *fp,

+  FILE      *fpData

+  )

+/*++

+

+Routine Description:

+

+  Zero the debug data fields of the file

+

+Arguments:

+

+  fp              - file pointer

+  fpData          - pointer to output file that ZeroDebugData progress is written to

+

+Returns:

+

+  =  0            - Success

+  = -1            - Failed

+

+--*/

+{

+  unsigned char header[4];

+  unsigned long offset;

+  unsigned long NumberOfRvaAndSizes;

+  unsigned int  nvalue;

+  unsigned long lvalue;

+  unsigned long Size;

+  unsigned long Pointer;

+  unsigned char *Buffer;

+  unsigned long Index;

+

+  //

+  // read the header of file

+  //

+  if (ReadFromFile (fp, 0, header, 2) != 0) {

+    printf ("Error: open image file\n");

+    return -1;

+  }

+  //

+  // "MZ" -- the header of image file (PE)

+  //

+  if (strncmp ((char *) header, "MZ", 2) != 0) {

+    printf ("Error: Invalid Image file.\n");

+    return -1;

+  }

+  //

+  // At location 0x3C, the stub has the file offset to the

+  // PE signature.

+  //

+  if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {

+    return -1;

+  }

+  //

+  // read the header of optional

+  //

+  if (ReadFromFile (fp, offset, header, 4) != 0) {

+    return -1;

+  }

+  //

+  // "PE\0\0" -- the signature of optional header

+  //

+  if (strncmp ((char *) header, "PE\0\0", 4) != 0) {

+    printf ("Error: Invalid PE format file.\n");

+    return -1;

+  }

+  //

+  // Add 16 to skip COFF file header, and get to optional header.

+  //

+  offset += 24;

+

+  //

+  // Check the magic field, 0x10B for PE32 and 0x20B for PE32+

+  //

+  if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {

+    return -1;

+  }

+  //

+  // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.

+  // Else it is 108.

+  //

+  switch (nvalue & 0xFFFF) {

+  case 0x10B:

+    offset += 92;

+    printf ("Info: Image is PE32. ");

+    break;

+

+  case 0x20B:

+    offset += 108;

+    printf ("Info: Image is PE32+. ");

+    break;

+

+  default:

+    printf ("Error: Magic value is unknown.\n");

+    return -1;

+  }

+  //

+  // get the value of NumberOfRvaAndSizes

+  //

+  if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {

+    printf ("Error: read NumberOfRvaAndSizes error.\n");

+    return -1;

+  }

+  //

+  // printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes);

+  //

+  //

+  // Finding Debug Table, offset of Debug Table

+  // is 4 + 6 * 8 = 52.

+  //

+  if (NumberOfRvaAndSizes >= 7) {

+    if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {

+      return -1;

+    }

+    //

+    // Read the SizeOfData(16) and PointerToRawData(24)

+    //

+    if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) {

+      printf ("error: Size = %d\n", Size);

+      return -1;

+    }

+

+    printf ("Debug data: size = %xh, ", Size);

+    fprintf (fpData, "Debug data: size = %xh, ", Size);

+

+    if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) {

+      printf ("error: LoadOffset = %xh\n", Pointer);

+      return -1;

+    }

+    //

+    // printf ("LoadOffset = %xh, ", Pointer);

+    //

+    fprintf (fpData, "LoadOffset = %xh, ", Pointer);

+

+    if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) {

+      printf ("error: FileOffset = %xh\n", Pointer);

+      return -1;

+    }

+

+    printf ("FileOffset = %xh, ", Pointer);

+    fprintf (fpData, "FileOffset = %xh, \n", Pointer);

+

+    if ((lvalue != 0) && (Pointer != 0)) {

+      //

+      // prepare buffer

+      //

+      Buffer = malloc (Size + 1);

+      if (Buffer == NULL) {

+        printf ("Error: Cannot allocate memory.\n");

+        return -1;

+      }

+      //

+      // set file pointer to the specified location of file

+      //

+      if (fseek (fp, Pointer, SEEK_SET) != 0) {

+        printf ("Error: Cannot move the current location of the file.\n");

+        free (Buffer);

+        return -1;

+      }

+      //

+      // read data from PE file

+      //

+      if (fread (Buffer, Size, 1, fp) != 1) {

+        printf ("Error: Cannot read data from the file.\n");

+        free (Buffer);

+        return -1;

+      }

+      //

+      // write to data file

+      //

+      for (Index = 0; Index < Size;) {

+        fprintf (fpData, "%02x ", Buffer[Index]);

+

+        Index++;

+        if (Index % 8 == 0) {

+          fprintf (fpData, "\n");

+        }

+      }

+

+      fprintf (fpData, "\n");

+

+      //

+      // zero buffer and write back to PE file

+      //

+      if (fseek (fp, Pointer, SEEK_SET) != 0) {

+        printf ("Error: Cannot move the current location of the file.\n");

+        free (Buffer);

+        return -1;

+      }

+

+      memset (Buffer, 0, Size);

+      if (fwrite (Buffer, Size, 1, fp) != 1) {

+        perror ("Error: Cannot write zero to the file.\n");

+        free (Buffer);

+        return -1;

+      }

+      //

+      // set file pointer to the specified location of file

+      //

+      if (fseek (fp, lvalue + 4, SEEK_SET) != 0) {

+        printf ("Error: Cannot move the current location of the file.\n");

+        free (Buffer);

+        return -1;

+      }

+

+      if (fwrite (Buffer, 4, 1, fp) != 1) {

+        perror ("Error: Cannot write zero to the file.\n");

+        free (Buffer);

+        return -1;

+      }

+

+      free (Buffer);

+    }

+  }

+

+  return 0;

+}

+

+int

+main (

+  int       argc,

+  char      *argv[]

+  )

+/*++

+

+Routine Description:

+

+  Prints the zero debug data of the PE file to the DebugData file.

+  Executes the ZeroDebugData function.

+

+Arguments:

+

+  argc   - Standard C argument, number of command line arguments.

+  argv[] - Standard C argument, array of pointers to the input files,

+           such as the PE and DebugData files.

+

+Returns:

+

+  zero    - success

+  nonzero - failure

+

+--*/

+{

+  FILE  *fp;

+  FILE  *fpData;

+  char  DataFile[1024] = "";

+

+  //

+  // check the number of parameters

+  //

+  if (argc < 2) {

+    printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");

+    return -1;

+  }

+  //

+  // open the DebugData file, if not exists, return

+  //

+  if (argc >= 3) {

+    strcpy (DataFile, argv[2]);

+  } else {

+    strcpy (DataFile, "DebugData.dat");

+  }

+

+  fpData = fopen (DataFile, "a+");

+  if (fpData == NULL) {

+    fpData = fopen (DataFile, "w");

+    if (fpData == NULL) {

+      printf ("Error: Cannot open the data file!\n");

+      return -1;

+    }

+  }

+  //

+  // open the PE file

+  //

+  fp = fopen (argv[1], "r+b");

+  if (fp == NULL) {

+    printf ("Error: Cannot open the PE file!\n");

+    return -1;

+  }

+  //

+  // Zero the Debug Data to the PE file

+  //

+  printf ("Zero Debug Data to file %s:\n", argv[1]);

+  fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]);

+  if ((int *) ZeroDebugData (fp, fpData) != 0) {

+    printf ("Error: Zero Debug Data PE file\n");

+    fclose (fp);

+    return -1;

+  }

+

+  printf (" success\n");

+

+  //

+  // close the PE file

+  //

+  fflush (fpData);

+  fflush (fp);

+  fclose (fpData);

+  fclose (fp);

+

+  return 0;

+}

diff --git a/Source/ZeroDebugData/build.xml b/Source/ZeroDebugData/build.xml
new file mode 100644
index 0000000..194afc8
--- /dev/null
+++ b/Source/ZeroDebugData/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="GenTool" basedir=".">

+<!--

+    EDK ZeroDebugData Tool

+  Copyright (c) 2006, Intel Corporation

+-->

+  <property name="ToolName" value="ZeroDebugData"/>

+  <property name="FileSet" value="*.c"/>

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="LINK_OUTPUT_TYPE" value="static"/>

+  <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>

+

+  <target name="GenTool" depends="init, Tool">

+    <echo message="The EDK Tool: ${ToolName} build  has completed"/>

+  </target>

+

+  <target name="init">

+    <echo message="Building the EDK Tool: ${ToolName}"/>

+    <mkdir dir="${BUILD_DIR}"/>

+  </target>

+

+  <target name="Tool" depends="init">

+    <cc name="${ToolChain}" objdir="${BUILD_DIR}" 

+        outfile="${BIN_DIR}/${ToolName}"

+        outtype="executable"

+        optimize="speed" 

+        debug="true">

+

+      <fileset dir="${basedir}/${ToolName}" 

+        includes="${FileSet}" 

+        defaultexcludes="TRUE" 

+        excludes="*.xml *.inf"/>

+

+      <includepath path="${PACKAGE_DIR}/Include"/>

+      <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>

+      <includepath path="${PACKAGE_DIR}/Common"/>

+    </cc>

+  </target>

+

+  <target name="clean">

+    <echo message="Removing Intermediate Files Only"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+    </delete>

+  </target>

+

+  <target name="cleanall">

+    <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>  

+    <delete failonerror="false" quiet="true" includeEmptyDirs="true">

+      <fileset dir="${BUILD_DIR}"/>

+      <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>

+      <fileset file="${BIN_DIR}/${ToolName}.pdb"/>

+    </delete>

+  </target>

+

+</project>

diff --git a/Source/build.xml b/Source/build.xml
new file mode 100644
index 0000000..f222b4a
--- /dev/null
+++ b/Source/build.xml
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="utf-8" ?> 

+<!--

+Copyright (c) 2006, Intel Corporation

+All rights reserved. This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+-->

+<project default="all" basedir="." name="C_Code">

+<!-- Copyright (c) 2006, Intel Corporation -->

+<!-- Filename: Tools/Source/build.xml -->

+

+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>

+

+  <property name="ReallyVerbose" value="false"/>

+  <property environment="env" />

+

+  <property name="WORKSPACE" value="${env.WORKSPACE}" />

+  <property name="WORKSPACE_DIR" value="${WORKSPACE}" />

+  <property name="PACKAGE" value="Tools" />

+  <property name="PACKAGE_DIR" value="${WORKSPACE}/Tools/CCode/Source" />

+  <property name="LIB_DIR" value="${PACKAGE_DIR}/Library" />

+  <property name="BIN_DIR" value="${WORKSPACE}/Tools/bin" />

+  <property name="BUILD_MODE" value="PACKAGE" />

+  <property name="Libs" 

+    value="Common/build.xml CustomizedCompress/build.xml PeCoffLoader/build.xml String/build.xml"/>

+

+  <import file="${WORKSPACE_DIR}/Tools/Conf/BuildMacro.xml" />

+

+  <path id="classpath">

+    <fileset dir="${WORKSPACE}/Tools/Jars" includes="*.jar"/>

+    <fileset dir="${env.XMLBEANS_HOME}/lib" includes="*.jar"/>

+  </path>

+

+  <taskdef classpathref="classpath" resource="net/sf/antcontrib/antlib.xml" />

+

+

+  <target name="all" depends="initArch, init, Tools">

+    <echo message="The EDK II C Tools build complete!"/>

+  </target>

+  

+  <target name="init">

+    <echo message="EDK C Code Tools, build initialization"/>

+    <taskdef classpathref="classpath" resource="GenBuild.tasks" />

+    <taskdef classpathref="classpath" resource="cpptasks.tasks"/>

+    <typedef classpathref="classpath" resource="cpptasks.types"/>

+    <mkdir dir="${BIN_DIR}" />

+    <mkdir dir="${LIB_DIR}" />

+

+  </target>

+

+  <target name="initArch">

+    <condition property="HostArch" value="X64">

+      <os arch="amd64"/>

+    </condition>

+    <condition property="HostArch" value="Ia32">

+      <or>

+        <os arch="x86"/>

+        <os arch="i386"/>

+      </or>

+    </condition>

+    <condition property="HostArch" value="Ia32">

+      <os arch="i386"/>

+    </condition> 

+

+    <if>

+      <os family="unix" />

+      <then>

+        <echo message="OS Family UNIX, ${HostArch}" />

+      </then>

+      <elseif>

+        <os family="dos" />

+        <then>

+          <echo message="OS Family DOS, ${HostArch}" />

+        </then>

+      </elseif>

+      <elseif>

+        <os family="mac" />

+        <then>

+          <echo message="OS Family OS X, ${HostArch}" />

+        </then>

+      </elseif>

+      <else>

+        <fail message="OS Family Unsupported, ${HostArch}" />

+      </else>

+    </if>

+

+    <if>

+      <not>

+        <isset property="ToolChain" />

+      </not>

+      <then>

+        <if>

+          <isset property="env.TOOL_CHAIN" />

+          <then>

+            <property name="ToolChain" value="${env.TOOL_CHAIN}"/>

+          </then>

+          <else>

+            <!-- Default Tool Chain is Microsoft Visual Studio -->

+            <property name="ToolChain" value="msvc"/>

+          </else>

+        </if>

+      </then>

+    </if>

+    

+    <if>

+      <equals arg1="${ToolChain}" arg2="gcc" />

+      <then>

+        <exec executable="gcc" outputproperty="host.gcc.ver">

+          <arg line="-E" />

+          <arg line="-P" />

+          <arg line="-x c" />

+          <arg line="gcc.ver" />

+        </exec>

+        <if>

+          <contains string="${host.gcc.ver}" substring="4" />

+          <then>

+            <property name="ExtraArgus" value="-Wno-pointer-sign" />

+          </then>

+        </if>

+      </then>

+    </if>

+

+    <condition property="linux" value="true">

+      <os name="Linux"/>

+    </condition>

+    

+    <condition property="intel_win">

+      <and>

+        <os family="dos"/>

+        <equals arg1="${ToolChain}" arg2="intel"/>

+      </and>

+    </condition>

+    

+    <condition property="intel_linux">

+      <and>

+        <os name="Linux"/>

+        <equals arg1="${ToolChain}" arg2="intel"/>

+      </and>

+    </condition>

+    

+    <condition property="intel_mac">

+      <and>

+        <os family="mac"/>

+        <equals arg1="${ToolChain}" arg2="intel"/>

+      </and>

+    </condition>

+    

+    <condition property="gcc">

+      <and>

+        <equals arg1="${ToolChain}" arg2="gcc"/>

+      </and>

+    </condition>

+

+    <condition property="cygwin">

+      <and>

+        <os family="dos"/>

+        <equals arg1="${ToolChain}" arg2="gcc"/>

+      </and>

+    </condition>

+    

+    <condition property="x86_64_linux">

+      <and>

+        <os name="Linux"/>

+        <equals arg1="${HostArch}" arg2="X64"/>

+      </and>

+    </condition>

+    

+    <condition property="windows" value="true">

+      <os family="Windows"/>

+    </condition>

+    

+    <condition property="OSX" value="true">

+      <os family="Mac"/>

+    </condition>

+

+    <condition property="cyglinux">

+      <or>

+        <istrue value="${linux}"/>

+        <istrue value="${cygwin}"/>

+      </or>

+    </condition>

+

+    <!-- msft is a family, used by both Microsoft and Intel Windows compiler tool chains -->

+    <condition property="msft">

+      <isfalse value="${gcc}"/>

+    </condition>

+

+    <if>

+      <istrue value="${ReallyVerbose}"/>

+      <then>

+        <echo message="Test property msvc:         ${msvc}"/> 

+        <echo message="Test property gcc:          ${gcc}"/> 

+        <echo message="Test property intel_win:    ${intel_win}"/> 

+        <echo message="Test property intel_linux:  ${intel_linux}"/> 

+        <echo message="Test property intel_mac:    ${intel_mac}"/> 

+        <echo message="Test property msft:         ${msft}"/> 

+        <echo message="Test property cygwin:       ${cygwin}"/> 

+        <echo message="Test property cyglinux:     ${cyglinux}"/> 

+        <echo message="Test property windows:      ${windows}"/> 

+        <echo message="Test property linux:        ${linux}"/> 

+        <echo message="Test property OSX:          ${OSX}"/> 

+        <echo message="Test property x86_64_linux: ${x86_64_linux}"/> 

+       </then>

+    </if>

+

+    <property name="haveLibtool" value="false"/>

+    <if>

+      <and>

+        <not>

+          <isset property="env.CYGWIN_HOME"/>

+        </not>

+          <isset property="cygwin"/>

+      </and>

+      <then>

+        <fail message="You must set the environment variable: CYGWIN_HOME"/>

+      </then>

+    </if>

+

+    <if>

+        <istrue value="${gcc}"/>

+      <then>

+        <property name="ext_static" value=".a"/>

+        <property name="ext_dynamic" value=".so"/>

+        <if>

+          <istrue value="${cygwin}"/>

+          <then>

+            <property name="ext_exe" value=".exe"/>

+          </then>

+          <else>

+            <property name="ext_exe" value=""/>

+          </else>

+        </if>

+      </then>

+      <else>

+        <property name="ext_static" value=".lib"/>

+        <property name="ext_dynamic" value=".dll"/>

+        <property name="ext_exe" value=".exe"/>

+      </else>

+    </if>

+  </target>

+

+  <target name="Libraries" depends="initArch, init">

+    <subant target="" inheritall="true">

+      <fileset dir="${PACKAGE_DIR}" 

+        includes="${Libs}"/>

+    </subant>

+  </target>

+

+  <target name="Tools" depends="Libraries">

+    <subant target="" inheritall="true">

+      <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"

+        excludes="${Libs}"/>

+    </subant>

+  </target>

+

+  <target name="clean" depends="initArch">

+    <subant target="clean" inheritall="true">

+      <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"/>

+    </subant>

+  </target>

+

+  <target name="cleanall" depends="initArch">

+    <subant target="cleanall" inheritall="true">

+      <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"/>

+    </subant>

+    <delete dir="${LIB_DIR}"/>

+  </target>

+</project>