%e 2000
%{
#undef NDEBUG
#include "GR_config.h"
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef YY_START
#define MY_YY_START YY_START
#else
#ifdef YYSTATE
#define MY_YY_START YYSTATE
#else
#define MY_YY_START yy_start
#endif
#endif

#define TWO_D 22
#define SURFACE 23
#define THREE_D 33
 
#if (defined(dim2))
#define TYPE TWO_D
#define MeshInput "                \"2d mesh input\");\n"
#elif (defined(surf))
#define TYPE SURFACE
#define MeshInput "                \"surface mesh input\");\n"
#elif (defined(dim3))
#define TYPE THREE_D
#define MeshInput "                \"3d mesh input\");\n"
#else
#error Must define either dim2, surf, or dim3
#endif

#define TOPO_DIM (TYPE / 10)
#define SPACE_DIM (TYPE % 10)
 
static const char * const pstrTopOfSource[] = {
  "#include \"GR_config.h\"",
  "#include <stdio.h>",
  "#include <stdlib.h>",
  "#include \"GR_misc.h\"",
  "#include \"GR_VarArrayBase.h\"",
#if (TYPE == TWO_D)
  "#define TOPO_DIM 2",
  "#define SPACE_DIM 2",
  "#include \"GR_Mesh2D.h\"",
  "void vReadFile_Mesh2D(",
#elif (TYPE == SURFACE)
  "#define TOPO_DIM 2",
  "#define SPACE_DIM 3",
  "#include \"GR_SurfMesh.h\"",
  "void vReadFile_Surface(",
#else
  "#define TOPO_DIM 3",
  "#define SPACE_DIM 3",
  "#include \"GR_VolMesh.h\"",
  "void vReadFile_VolMesh(",
#endif
  "                       const char * const strBaseFileName,",
  "                       int& iNumVerts,",
  "                       int& iNumFaces,",
  "                       int& iNumCells,",
#if (TYPE != SURFACE)
  "                       int& iNumBdryFaces,",
#endif
  "                       int& iNumIntBdryFaces,",
  "                       bool& qFaceVert,",
  "                       bool& qCellVert,",
  "                       bool& qFaceCell,",
  "                       bool& qCellFace,",
  "                       bool& qCellRegion,",
#if (TYPE != SURFACE)
  "                       bool& qBFaceFace,",
  "                       bool& qBFaceVert,",
  "                       bool& qBFaceBC,",
#endif
  "                       bool& qIntBFaceFace,",
  "                       bool& qIntBFaceVert,",
  "                       bool& qIntBFaceBC,",
  "                       VAVertex& VAVerts,",
  "                       int (*&a2iFaceVert)[TOPO_DIM],",
  "                       int (*&a2iFaceCell)[2],",
  "                       int (*&a2iCellVert)[TOPO_DIM+1],",
  "                       int (*&a2iCellFace)[TOPO_DIM+1],",
  "                       int *&aiCellRegion,",
#if (TYPE != SURFACE)
  "                       int *&aiBFaceFace,",
  "                       int *&aiBFaceBC,",
  "                       int (*&a2iBFaceVert)[TOPO_DIM],",
#endif
  "                       int (*&a2iIntBFaceFace)[2],",
  "                       int *&aiIntBFaceBC,",
  "                       int (*&a2iIntBFaceVert)[TOPO_DIM]",
  "                       )",
  "{",
  "  iNumVerts = 0;",
  "  iNumFaces = 0;",
  "  iNumCells = 0;",
  "  iNumIntBdryFaces = 0;",
#if (TYPE != SURFACE)
  "  iNumBdryFaces = 0;",
#endif
  "  qFaceVert = false;",
  "  qCellVert = false;",
  "  qFaceCell = false;",
  "  qCellFace = false;",
  "  qCellRegion = false;",
  "  a2iFaceCell = reinterpret_cast<int(*)[2]> (NULL);",
  "  a2iFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);",
  "  a2iCellVert = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);",
  "  a2iCellFace = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);",
  "  aiCellRegion = reinterpret_cast<int *> (NULL);",
#if (TYPE != SURFACE)
  "  qBFaceVert = false;",
  "  qBFaceFace = false;",
  "  qBFaceBC = false;",
  "  aiBFaceFace = reinterpret_cast<int *> (NULL);",
  "  aiBFaceBC   = reinterpret_cast<int *> (NULL);",
  "  a2iBFaceVert= reinterpret_cast<int(*)[TOPO_DIM]> (NULL);",
#endif
  "  qIntBFaceFace = false;",
  "  qIntBFaceVert = false;",
  "  qIntBFaceBC   = false;",
  "  a2iIntBFaceFace = reinterpret_cast<int(*)[2]> (NULL);",
  "  aiIntBFaceBC    = reinterpret_cast<int *> (NULL);",
  "  a2iIntBFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);",
  " ",
  "  int iVertOffset = 0, iFaceOffset = 0;",
  "  int iCellOffset = 0, iBFaceOffset = 1;",
  "  FILE *pFInFile = fopen(\"/dev/zero\", \"r\");",
  "  char strFileName[1024];",
  ""
};
 
static void vAppendToString(char strIn[], int * const piLen,
			    const int iMaxLen, const char strApp[]) 
{
  int iAppLen = strlen(strApp);
  assert(strlen(strIn) == *piLen);
  if (iAppLen + *piLen > iMaxLen) exit(1);
  sprintf(&(strIn[*piLen]), "%s", strApp);
  *piLen = *piLen + iAppLen;
  assert(strlen(strIn) == *piLen);
}

static void vClearString(char strIn[], const int iSize)
{
  int ii;
  for (ii = 0; ii < iSize; ii++)
    strIn[ii] = '\0';
}

#define vUserIntInput(strArgs, piArgsLen, strInput, piInputLen, strCallString)\
  { \
    vAppendToString(strArgs, piArgsLen, 1024, strCallString); \
    vAppendToString(strInput, piInputLen, 1024, yytext); \
    iPrevContext = MY_YY_START; \
    BEGIN(USER_INT_SIZE); \
  }

#define vDefaultIntInput(strFormat, piFormatLen, strArgs, piArgsLen, strInput, piInputLen, strCallString)\
  {\
    vAppendToString(strFormat, piFormatLen, 1024, "%d");\
    vAppendToString(strArgs, piArgsLen, 1024, strCallString);\
    vAppendToString(strInput, piInputLen, 1024, yytext);\
  }


#define vUserCoordInput(strArgs, piArgsLen, strInput, piInputLen, strCallString)\
  {\
    char strDummy[1024];\
    sprintf(strDummy, ", %s", strCallString);\
    vAppendToString(strArgs, piArgsLen, 1024, strDummy);\
    vAppendToString(strInput, piInputLen, 1024, yytext);\
    iPrevContext = MY_YY_START;\
    BEGIN(USER_FLOAT_SIZE);\
  }

#define vDefaultCoordInput(strFormat, piFormatLen, strArgs, piArgsLen, strInput, piInputLen, strCallString)\
  {\
    char strDummy[1024];\
    sprintf(strDummy, ", %s", strCallString);\
    vAppendToString(strFormat, piFormatLen, 1024, "%lf");\
    vAppendToString(strArgs, piArgsLen, 1024, strDummy);\
    vAppendToString(strInput, piInputLen, 1024, yytext);\
  }
  
%}

%s USER_INT_SIZE USER_FLOAT_SIZE QUOTE VERTEX_LINE FORTRAN_LINE
%s CELL_LINE FACE_LINE BFACE_LINE INT_BFACE_LINE

%%
%{
  char strFormat[1024], strArgs[1024];
  char strInput[1024];
  int iFormatLen = 0, iArgsLen = 0, iInputLen = 0;
  int iPrevContext;
  bool qXRead, qYRead;
  bool qVertIndexRead = false, qFaceIndexRead = false, qCellIndexRead = false;
  bool qFortranVerts = false, qFortranFaces = false, qFortranCells = false;
  bool qVertCountRead = false, qFaceCountRead = false;
  bool qCellCountRead = false, qCellRegionRead = false;
  bool qBFaceCountRead = false, qBFaceIndexRead = false;
  bool qIntBFaceCountRead = false, qIntBFaceIndexRead = false;
  bool qVertARead, qVertBRead, qVertCRead;
  bool qCellARead, qCellBRead;
  bool qFaceARead, qFaceBRead, qFaceCRead;
  bool qFaceRead, qBCRead;
#if (SPACE_DIM == 3)
  bool qZRead;
#endif
#if (TOPO_DIM == 3)
  bool qVertDRead, qFaceDRead;
#endif
  vClearString(strInput, 1024);
  vClearString(strFormat, 1024);
  vClearString(strArgs, 1024);
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
%}

<INITIAL>^#.* {  /* comments are swallowed */ }

<INITIAL,FACE_LINE,VERTEX_LINE,CELL_LINE,BFACE_LINE,INT_BFACE_LINE>% {
  vAppendToString(strInput, &iInputLen, 1024, "%");
  vAppendToString(strFormat, &iFormatLen, 1024, "%%");
}

<INITIAL,FACE_LINE,VERTEX_LINE,CELL_LINE,BFACE_LINE,INT_BFACE_LINE>\" {
  vAppendToString(strInput, &iInputLen, 1024, "\"");
  iPrevContext = MY_YY_START; 
  BEGIN(QUOTE);
}

<QUOTE>\" {
  vAppendToString(strInput, &iInputLen, 1024, "\"");
  BEGIN(iPrevContext);
}

<QUOTE>\\\" {
  vAppendToString(strInput, &iInputLen, 1024, "\\\"");
  vAppendToString(strFormat, &iFormatLen, 1024, "\\\"");
}

<QUOTE>[^\\\"]* {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  vAppendToString(strFormat, &iFormatLen, 1024, yytext);
}

drop_int {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  vAppendToString(strFormat, &iFormatLen, 1024, "%*d");
}

drop_double {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  vAppendToString(strFormat, &iFormatLen, 1024, "%*f");
}

<INITIAL>^fortran[ \t]*\n {
  printf("    /* fortran */\n");
  printf("  iVertOffset = 1;\n");
  printf("  iFaceOffset = 1;\n");
  printf("  iCellOffset = 1;\n");
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  qFortranVerts = true;
  qFortranCells = true;
  qFortranFaces = true;
}

<INITIAL>^fortran {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  BEGIN(FORTRAN_LINE);
}

<FORTRAN_LINE>verts {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  qFortranVerts = true;
}

<FORTRAN_LINE>cells {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  qFortranCells = true;
}

<FORTRAN_LINE>faces {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  qFortranFaces = true;
}

<FORTRAN_LINE>\n {
  printf("    /*%s*/\n", strInput);
  if (qFortranVerts)
    printf("  iVertOffset = 1;\n");
  if (qFortranFaces)
    printf("  iFaceOffset = 1;\n");
  if (qFortranCells)
    printf("  iCellOffset = 1;\n");
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}

<INITIAL>^newfile[ \t]+.* {
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  {
    int iLow = 7, iHi;
    while (isspace(yytext[iLow])) iLow++;
    iHi = iLow;
    while (!isspace(yytext[iHi])) iHi++;
    printf("  char strTemp[1024];\n");
    printf("  snprintf(strTemp, 1024, \"%.*s\");\n", iHi - iLow, &(yytext[iLow]));
    printf("  char *pcWhere = strstr(strBaseFileName, strTemp);\n");
    printf("  if (pcWhere) {\n");
    printf("    snprintf(strFileName, 1024, \"%%s\", strBaseFileName);\n");
    printf("  } else {\n");
    printf("    snprintf(strFileName, 1024, \"%%s.%.*s\", strBaseFileName);\n",
	     iHi - iLow, &(yytext[iLow]));
    printf("  }\n");
  }
  printf("\n");
  printf("  /*%s*/\n", strInput);
  printf("  printf(\"Opening input file %%s\\n\", strFileName);\n");
  printf("  if (pFInFile) fclose(pFInFile);\n");
  printf("  pFInFile = fopen(strFileName, \"r\");\n");
  printf("  if (NULL == pFInFile)\n");
  printf("    vFatalError(\"Couldn't open input file for reading\",\n");
  printf(MeshInput);
  printf("\n");
}

<USER_INT_SIZE>[0-9]+ {
  char strMiniFormat[16];
  sprintf(strMiniFormat, "%%%sd", yytext);
  vAppendToString(strFormat, &iFormatLen, 1024, strMiniFormat);
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  BEGIN(iPrevContext);
}

<USER_FLOAT_SIZE>[0-9]+[.]?[0-9]* {
  char strMiniFormat[16];
  sprintf(strMiniFormat, "%%%slf", yytext);
  vAppendToString(strFormat, &iFormatLen, 1024, strMiniFormat);
  vAppendToString(strInput, &iInputLen, 1024, yytext);
  BEGIN(iPrevContext);
}

<INITIAL>nverts[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iNumVerts"); 
  qVertCountRead = true;
}

<INITIAL>nverts	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iNumVerts");
  qVertCountRead = true;
}

<INITIAL>nfaces[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iNumFaces"); 
  qFaceCountRead = true;
}

<INITIAL>nfaces	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iNumFaces");
  qFaceCountRead = true;
}

<INITIAL>ncells[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iNumCells"); 
  qCellCountRead = true;
}

<INITIAL>ncells	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iNumCells"); 
  qCellCountRead = true;
}

%{
#if (TYPE != SURFACE)
%}
<INITIAL>nbfaces[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iNumBdryFaces");
  qBFaceCountRead = true;
}

<INITIAL>nbfaces	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iNumBdryFaces"); 
  qBFaceCountRead = true;
}
%{
#endif
%}

<INITIAL>nintbfaces[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iNumIntBdryFaces");
  qBFaceCountRead = true;
}

<INITIAL>nintbfaces	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iNumIntBdryFaces"); 
  qIntBFaceCountRead = true;
}
<INITIAL>\n {
  if (iFormatLen != 1) {
    vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
    printf("  /*%s*/\n", strInput);
    printf("  fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
  }
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
}

[ \t]+	{
  strFormat[iFormatLen++] = ' ';
  vAppendToString(strInput, &iInputLen, 1024, yytext);
}

<INITIAL>^verts:[ \t]* {
  assert(qVertCountRead);
  qXRead = false, qYRead = false, qVertIndexRead = false;
  printf("\n");
  BEGIN(VERTEX_LINE);
  printf("  if (iNumVerts == 0)\n");
  printf("    vFatalError(\"Tried to read vertex data without specifying number of vertices\",\n");
  printf(MeshInput);
  printf("  VAVerts.vSetup(iNumVerts);\n");
  printf("  for (int iV = 0; iV < iNumVerts; iV++) {\n");
  printf("    int iRealVert = iV;\n");
  printf("    double dXX, dYY;\n");
#if (SPACE_DIM == 3)
  printf("    double dZZ;\n");
#endif
  vAppendToString(strInput, &iInputLen, 1024, "verts: ");
}

<VERTEX_LINE>index[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iRealVert");
  qVertIndexRead = true;
}

<VERTEX_LINE>index	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ",  &iRealVert"); 
  qVertIndexRead = true;
}

<VERTEX_LINE>coords {
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dXX"); 
  yytext[0] = '\0';
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dYY");
  qXRead = qYRead = true;
#if (SPACE_DIM == 3)
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dZZ");
  qZRead = true;
#endif
}

<VERTEX_LINE>x[ \t]*[0-9]*\.*[0-9]* {
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dXX"); 
  qXRead = true;
}

<VERTEX_LINE>y[ \t]*[0-9]*\.*[0-9]* {
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dYY"); 
  qYRead = true;
}

%{
#if (SPACE_DIM == 3)
%}
<VERTEX_LINE>z[ \t]*[0-9]*\.*[0-9]* {
  vDefaultCoordInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		     strInput, &iInputLen, "&dZZ"); 
  qZRead = true;
}
%{
#endif 
%}

<VERTEX_LINE>\n {
  assert(qXRead && qYRead);
#if (SPACE_DIM == 3)
  assert(qZRead);
#endif 
  vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
  printf("    /*%s*/\n", strInput);
  printf("    fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
  printf("    {\n");
#if (SPACE_DIM == 3)
  printf("      double adCoord[] = {dXX, dYY, dZZ};\n");
#else 
  printf("      double adCoord[] = {dXX, dYY};\n");
#endif 
  if (qVertIndexRead) {
    printf("      /* Remove an offset from the index if it exists. */\n");
    printf("      iRealVert -= iVertOffset;\n");
    printf("      if (iRealVert < 0 || iRealVert >= iNumVerts)\n");
    printf("        vFatalError(\"Invalid vertex index\",\n");
    printf(MeshInput);
  }
  printf("      (VAVerts.pTEntry(iRealVert))->vSetCoords(SPACE_DIM, adCoord);\n");
  printf("    }\n");
  printf("  }\n");
  printf("\n");
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}

<INITIAL>^faces:[ \t]* {
  assert(qFaceCountRead);
  BEGIN(FACE_LINE);
  qVertARead = qVertBRead = qCellARead = qCellBRead = false;
  qFaceIndexRead = false;
#if (TOPO_DIM == 3)
  qVertCRead = false;
#endif 
  printf("\n");
  printf("  if (iNumFaces == 0)\n");
  printf("    vFatalError(\"Tried to read face data without specifying number of faces\",\n");
  printf(MeshInput);
  printf("  /* Allocate both the face-vert and face-cell arrays if they haven't been.\n");
  printf("     One or both may have to be deleted later. */\n");
  printf("  if (! a2iFaceVert)\n");
  printf("    a2iFaceVert = new int[iNumFaces][TOPO_DIM];\n");
  printf("  if (! a2iFaceCell)\n");
  printf("    a2iFaceCell = new int[iNumFaces][2];\n");
  printf("  if (iNumVerts == 0)\n");
  printf("    vWarning(\"Number of verts unknown while reading faces; sanity checking may be crippled.\");\n");
  printf("  if (iNumCells == 0)\n");
  printf("    vWarning(\"Number of cells unknown while reading faces; sanity checking may be crippled.\");\n");
  printf("  for (int iF = 0; iF < iNumFaces; iF++) {\n");
  printf("    int iRealFace = iF;\n");
  printf("    int iCellA = iNumCells, iCellB = iNumCells;\n");
  printf("    int iVertA = -1, iVertB = -1;\n");
#if (TOPO_DIM == 3)
  printf("    int iVertC = -1;\n");
#endif 
  vAppendToString(strInput, &iInputLen, 1024, "faces: ");
}

<FACE_LINE>index[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iRealFace");
  qFaceIndexRead = true;
}

<FACE_LINE>index	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iRealFace"); 
  qFaceIndexRead = true;
}

<FACE_LINE>cells {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iCellA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iCellB");
  qCellARead = qCellBRead = true;
}

<FACE_LINE>cella[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iCellA"); 
  qCellARead = true;
}

<FACE_LINE>cella {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iCellA");
  qCellARead = true;
}

<FACE_LINE>cellb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iCellB");
  qCellBRead = true;
}

<FACE_LINE>cellb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iCellB");
  qCellBRead = true;
}

<FACE_LINE>verts {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertB");
  qVertARead = qVertBRead = true;
#if (TOPO_DIM == 3)
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertC");
  qVertCRead = true;
#endif 
}

<FACE_LINE>verta[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertA");
  qVertARead = true;
}

<FACE_LINE>verta {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertA");
  qVertARead = true;
}

<FACE_LINE>vertb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertB");
  qVertBRead = true;
}

<FACE_LINE>vertb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertB");
  qVertBRead = true;
}

%{
#if (TOPO_DIM == 3)
%}
<FACE_LINE>vertc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertC");
  qVertCRead = true;
}

<FACE_LINE>vertc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertC");
  qVertCRead = true;
}

%{
#endif 
%}
<FACE_LINE>\n {
  vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
  printf("    /*%s*/\n", strInput);
  printf("    fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
#if (TOPO_DIM == 2)
  if (qVertARead || qVertBRead)
#else
    if (qVertARead || qVertBRead || qVertCRead)
#endif 
      {
#if (TOPO_DIM == 2)
	assert(qVertARead && qVertBRead);
#else
	assert(qVertARead && qVertBRead && qVertCRead);
#endif
	if (qFaceIndexRead) {
	  printf("      /* Remove an offset from the index if it exists. */\n");
	  printf("      iRealFace -= iFaceOffset;\n");
	  printf("      if (iRealFace < 0 || iRealFace >= iNumFaces)\n");
	  printf("        vFatalError(\"Invalid face index\",\n");
	  printf(MeshInput);
	}
	printf("    /* Remove an offset from the vertex indices if needed. */\n");
	printf("    iVertA -= iVertOffset;\n");
	printf("    iVertB -= iVertOffset;\n");
#if (TOPO_DIM == 3)
	printf("    iVertC -= iVertOffset;\n");
#endif
	printf("    if ( iVertA < 0 || iVertB < 0 ||\n");
#if (TOPO_DIM == 3)
	printf("         iVertC < 0 || \n");
#endif 
	printf("         ((iNumVerts > 0) && \n");
	printf("          (iVertA >= iNumVerts || \n");
#if (TOPO_DIM == 3)
	printf("           iVertC >= iNumVerts || \n");
#endif
	printf("           iVertB >= iNumVerts) ) ) \n");
	printf("      vFatalError(\"Vertex index out of range\",\n");
	printf(MeshInput);
	printf("    (a2iFaceVert)[iRealFace][0] = iVertA;\n");
	printf("    (a2iFaceVert)[iRealFace][1] = iVertB;\n");
#if (TOPO_DIM == 3)
	printf("    (a2iFaceVert)[iRealFace][2] = iVertC;\n");
#endif 
	printf("\n");
      }
  if (qCellARead || qCellBRead) {
    assert(qCellARead && qCellBRead);
    printf("    /* Remove an offset from the vertex indices if needed. */\n");
    printf("    if (iCellA >= 0) iCellA -= iCellOffset;\n");
    printf("    if (iCellB >= 0) iCellB -= iCellOffset;\n");
    printf("    /* Can not check cell index for out-of-range low, */\n");
    printf("    /* because BC's have a negative index. */\n");
    printf("    if ( iNumCells > 0 && \n");
    printf("         (iCellA >= iNumCells || \n");
    printf("          iCellB >= iNumCells) ) \n");
    printf("      vFatalError(\"Cell index out of range\",\n");
    printf(MeshInput);
    printf("    (a2iFaceCell)[iRealFace][0] = iCellA;\n");
    printf("    (a2iFaceCell)[iRealFace][1] = iCellB;\n");
  }
  printf("  }\n");
  printf("\n");
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead) 
#else 
  if (qVertARead || qVertBRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead);
#else 
    assert(qVertARead && qVertBRead);
#endif
    printf("  qFaceVert = true;\n");
  }
  if (qCellARead || qCellBRead) {
    assert(qCellARead && qCellBRead);
    printf("  qFaceCell = true;\n");
  }
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}

<INITIAL>^cells:[ \t]* {
  assert(qCellCountRead);
  BEGIN(CELL_LINE);
  qVertARead = qVertBRead = qVertCRead = false;
  qFaceARead = qFaceBRead = qFaceCRead = false;
#if (TOPO_DIM == 3)
  qVertDRead = qFaceDRead = false;
#endif 
  printf("  if (iNumCells == 0)\n");
  printf("    vFatalError(\"Tried to read cell data without specifying number of cells\",\n");
  printf(MeshInput);
  printf("  /* Allocate both the cell-vert and cell-face arrays if they haven't been.\n");
  printf("     One or both may have to be deleted later. */\n");
  printf("  if (! a2iCellVert) \n");
  printf("    a2iCellVert = new int[iNumCells][TOPO_DIM+1];\n");
  printf("  if (! a2iCellFace) \n");
  printf("    a2iCellFace = new int[iNumCells][TOPO_DIM+1];\n");
  printf("  if (! aiCellRegion) \n");
  printf("    aiCellRegion = new int[iNumCells];\n");
  printf("  if (iNumVerts == 0)\n");
  printf("    vWarning(\"Number of verts unknown while reading cells; sanity checking may be crippled.\");\n");
  printf("  if (iNumFaces == 0)\n");
  printf("    vWarning(\"Number of faces unknown while reading cells; sanity checking may be crippled.\");\n");
  printf("  for (int iC = 0; iC < iNumCells; iC++) {\n");
  printf("    int iRealCell = iC;\n");
  printf("    int iFaceA = iNumFaces, iFaceB = iNumFaces;\n");
  printf("    int iFaceC = iNumFaces;\n");
  printf("    int iVertA = -1, iVertB = -1, iVertC = -1;\n");
  printf("    int iReg = 0;\n");
#if (TOPO_DIM == 3)
  printf("    int iFaceD = iNumFaces, iVertD = -1;\n");
#endif 
  vAppendToString(strInput, &iInputLen, 1024, "cells: ");
}

<CELL_LINE>index[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iRealCell"); 
  qCellIndexRead = true;
}

<CELL_LINE>index	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iRealCell");
  qCellIndexRead = true;
}

<CELL_LINE>region[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iReg");
  qCellRegionRead = true;
}

<CELL_LINE>region {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iReg");
  qCellRegionRead = true;
}

<CELL_LINE>faces {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceA");
  vAppendToString(strInput, &iInputLen, 1024, " ");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceB");
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceC");
  qFaceARead = qFaceBRead = qFaceCRead = true;
#if (TOPO_DIM == 3)
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceD");
  qFaceDRead = true;
#endif 
}

<CELL_LINE>facea[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceA"); 
  qFaceARead = true;
}

<CELL_LINE>facea {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceA");
  qFaceARead = true;
}

<CELL_LINE>faceb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceB"); 
  qFaceBRead = true;
}

<CELL_LINE>faceb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceB");
  qFaceBRead = true;
}

<CELL_LINE>facec[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceC");
  qFaceCRead = true;
}

<CELL_LINE>facec {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceC");
  qFaceCRead = true;
}

%{
#if (TOPO_DIM == 3)
%}
<CELL_LINE>faced[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceD");
  qFaceDRead = true;
}

<CELL_LINE>faced {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceD");
  qFaceDRead = true;
}

%{
#endif 
%}

<CELL_LINE>verts {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertB");
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertC");
  qVertARead = qVertBRead = qVertCRead = true;
#if (TOPO_DIM == 3)
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertD");
  qVertDRead = true;
#endif 
}

<CELL_LINE>verta[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertA");
  qVertARead = true;
}

<CELL_LINE>verta {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertA");
  qVertARead = true;
}

<CELL_LINE>vertb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertB");
  qVertBRead = true;
}

<CELL_LINE>vertb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertB");
  qVertBRead = true;
}

<CELL_LINE>vertc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertC");
  qVertCRead = true;
}

<CELL_LINE>vertc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertC");
  qVertCRead = true;
}

%{
#if (TOPO_DIM == 3)
%}
<CELL_LINE>vertd[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertD");
  qVertDRead = true;
}

<CELL_LINE>vertd {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertD");
  qVertDRead = true;
}

%{
#endif 
%}
<CELL_LINE>\n {
  vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
  printf("    /*%s*/\n", strInput);
  printf("    fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
  if (qCellIndexRead) {
    printf("    /* Remove any offset from the cell index */\n");
    printf("    iRealCell -= iCellOffset;\n");
    printf("    if (iRealCell < 0 || iRealCell >= iNumCells)\n");
    printf("      vFatalError(\"Invalid cell index\",\n");
    printf(MeshInput);
  }
  if (qCellRegionRead) {
    printf("    /* Store the region that the cell belongs to. */\n");
    printf("    if (iReg <= 0 || iReg >= 32)\n");
    printf("      vFatalError(\"Cell tagged with invalid region.\",\n");
    printf(MeshInput);
    printf("    (aiCellRegion)[iRealCell] = iReg;\n");
  }
  else {
    printf("    /* Dummy line to prevent compiler complaints. */\n");
    printf("    iReg++;\n");
  }
  printf("    /* The following (possibly) extra work happens to get rid */\n");
  printf("    /* of compiler complaints about unused variables. */\n");
  printf("    /* Remove offset from the vertex indices */\n");
  printf("    iVertA -= iVertOffset;\n");
  printf("    iVertB -= iVertOffset;\n");
  printf("    iVertC -= iVertOffset;\n");
#if (TOPO_DIM == 3)
  printf("    iVertD -= iVertOffset;\n");
#endif
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead || qVertDRead) 
#else 
  if (qVertARead || qVertBRead || qVertCRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead && qVertDRead);
#else 
    assert(qVertARead && qVertBRead && qVertCRead);
#endif
    printf("    if ( iVertA < 0 || iVertB < 0 || iVertC < 0 ||\n");
#if (TOPO_DIM == 3)
    printf("         iVertD < 0 || \n");
#endif 
    printf("         ((iNumVerts > 0) && \n");
    printf("          (iVertA >= iNumVerts || \n");
    printf("           iVertB >= iNumVerts || \n");
#if (TOPO_DIM == 3)
    printf("           iVertD >= iNumVerts || \n");
#endif
    printf("           iVertC >= iNumVerts) ) ) \n");
    printf("      vFatalError(\"Vertex index out of range\",\n");
    printf(MeshInput);
    printf("    (a2iCellVert)[iRealCell][0] = iVertA;\n");
    printf("    (a2iCellVert)[iRealCell][1] = iVertB;\n");
    printf("    (a2iCellVert)[iRealCell][2] = iVertC;\n");
#if (TOPO_DIM == 3)
    printf("    (a2iCellVert)[iRealCell][3] = iVertD;\n");
#endif 
    printf("\n");
  }
  printf("    /* The following (possibly) extra work happens to get rid */\n");
  printf("    /* of compiler complaints about unused variables. */\n");
  printf("    /* Remove offset from the face indices */\n");
  printf("    iFaceA -= iFaceOffset;\n");
  printf("    iFaceB -= iFaceOffset;\n");
  printf("    iFaceC -= iFaceOffset;\n");
#if (TOPO_DIM == 3)
  printf("    iFaceD -= iFaceOffset;\n");
#endif
#if (TOPO_DIM == 3)
  if (qFaceARead || qFaceBRead || qFaceCRead || qFaceDRead) 
#else 
  if (qFaceARead || qFaceBRead || qFaceCRead)
#endif
  {
#if (TOPO_DIM == 3)
    assert(qFaceARead && qFaceBRead && qFaceCRead && qFaceDRead);
#else 
    assert(qFaceARead && qFaceBRead && qFaceCRead);
#endif 
    printf("    if ( iFaceA < 0 || iFaceB < 0 || iFaceC < 0 ||\n");
#if (TOPO_DIM == 3)
    printf("         iFaceD < 0 ||\n");
#endif
    printf("         ((iNumFaces > 0) && \n");
    printf("          (iFaceA >= iNumFaces || \n");
    printf("           iFaceB >= iNumFaces || \n");
#if (TOPO_DIM == 3)
    printf("           iFaceD >= iNumFaces || \n");
#endif
    printf("           iFaceC >= iNumFaces) ) ) \n");
    printf("      vFatalError(\"Face index out of range\",\n");
    printf(MeshInput);
    printf("    (a2iCellFace)[iRealCell][0] = iFaceA;\n");
    printf("    (a2iCellFace)[iRealCell][1] = iFaceB;\n");
    printf("    (a2iCellFace)[iRealCell][2] = iFaceC;\n");
#if (TOPO_DIM == 3)
    printf("    (a2iCellFace)[iRealCell][3] = iFaceD;\n");
#endif 
  }
  printf("  }\n");
  printf("\n");
  if (qCellRegionRead)
    printf("  qCellRegion = true;\n");
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead || qVertDRead) 
#else 
  if (qVertARead || qVertBRead || qVertCRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead && qVertDRead);
#else 
    assert(qVertARead && qVertBRead && qVertCRead);
#endif
    printf("  qCellVert = true;\n");
  }

#if (TOPO_DIM == 3)
  if (qFaceARead || qFaceBRead || qFaceCRead || qFaceDRead) 
#else 
  if (qFaceARead || qFaceBRead || qFaceCRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qFaceARead && qFaceBRead && qFaceCRead && qFaceDRead);
#else 
    assert(qFaceARead && qFaceBRead && qFaceCRead);
#endif
    printf("  qCellFace = true;\n");
  }
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}

<INITIAL>^intbdryfaces:[ \t]* {
  assert(qIntBFaceCountRead);
  BEGIN(INT_BFACE_LINE);
  qVertARead = qVertBRead = qFaceARead = qFaceBRead = qBCRead = false;
#if (TOPO_DIM == 3)
  qVertCRead = false;
#endif 
  printf("\n");
  printf("  if (iNumBdryFaces == 0)\n");
  printf("    vFatalError(\"Tried to read internal bdry face data without specifying number of bdry faces\",\n");
  printf(MeshInput);
  printf("  /* Allocate the bface-face, bface-vert, and bface-BC arrays. */\n");
  printf("  /* One or more may have to be deleted later. */\n");
  printf("  if (! a2iIntBFaceFace) \n");
  printf("    a2iIntBFaceFace = new int[iNumIntBdryFaces][2];\n");
  printf("  if (! (aiIntBFaceBC)) \n");
  printf("    aiIntBFaceBC    = new int[iNumIntBdryFaces];\n");
  printf("  if (! a2iIntBFaceVert) \n");
  printf("    a2iIntBFaceVert = new int[iNumIntBdryFaces][TOPO_DIM];\n");
  printf("  if (iNumVerts == 0)\n");
  printf("    vWarning(\"# of verts unknown while reading bdry faces; sanity checking may be crippled.\");\n");
  printf("  if (iNumFaces == 0)\n");
  printf("    vWarning(\"# of faces unknown while reading bdry faces; sanity checking may be crippled.\");\n");
  printf("  for (int iBF = 0; iBF < iNumIntBdryFaces; iBF++) {\n");
  printf("    int iRealBFace = iBF;\n");
  printf("    int iFaceA = iNumFaces, iFaceB = iNumFaces, iBC = -100;\n");
  printf("    int iVertA = -1, iVertB = -1;\n");
#if (TOPO_DIM == 3)
  printf("    int iVertC = -1;\n");
#endif 
  vAppendToString(strInput, &iInputLen, 1024, "intbdryfaces: ");
}

<INT_BFACE_LINE>index[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iRealBFace");
  qIntBFaceIndexRead = true;
}

<INT_BFACE_LINE>index	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iRealBFace"); 
  qIntBFaceIndexRead = true;
}

<INT_BFACE_LINE>bc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iBC");
  qBCRead = true;
}

<INT_BFACE_LINE>bc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iBC");
  qBCRead = true;
}

<INT_BFACE_LINE>facea[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceA");
  qFaceARead = true;
}

<INT_BFACE_LINE>facea {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceA");
  qFaceARead = true;
}

<INT_BFACE_LINE>faceb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFaceB");
  qFaceBRead = true;
}

<INT_BFACE_LINE>faceb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceB");
  qFaceBRead = true;
}

<INT_BFACE_LINE>faces {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFaceB");
  qFaceARead = qFaceBRead = true;
}

<INT_BFACE_LINE>verts {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertB");
  qVertARead = qVertBRead = true;
#if (TOPO_DIM == 3)
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertC");
  qVertCRead = true;
#endif 
}

<INT_BFACE_LINE>verta[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertA");
  qVertARead = true;
}

<INT_BFACE_LINE>verta {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertA");
  qVertARead = true;
}

<INT_BFACE_LINE>vertb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertB");
  qVertBRead = true;
}

<INT_BFACE_LINE>vertb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,", &iVertB");
  qVertBRead = true;
}

%{
#if (TOPO_DIM == 3)
%}
<INT_BFACE_LINE>vertc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertC");
  qVertCRead = true;
}

<INT_BFACE_LINE>vertc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,", &iVertC");
  qVertCRead = true;
}

%{
#endif
%}

<INT_BFACE_LINE>\n {
  vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
  printf("    /*%s*/\n", strInput);
  printf("    fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
  if (qIntBFaceIndexRead) {
    printf("    /* Remove any offset from the cell index */\n");
    printf("    iRealBFace -= iBFaceOffset;\n");
    printf("    if (iRealBFace < 0 || iRealBFace >= iNumBdryFaces)\n");
    printf("      vFatalError(\"Invalid boundary face index\",\n");
    printf(MeshInput);
  }
    
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead) 
#else 
  if (qVertARead || qVertBRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead);
#else
    assert(qVertARead && qVertBRead);
#endif
    printf("    /* Remove offset from the vertex indices */\n");
    printf("    iVertA -= iVertOffset;\n");
    printf("    iVertB -= iVertOffset;\n");
#if (TOPO_DIM == 3)
    printf("    iVertC -= iVertOffset;\n");
#endif
    printf("    if ( iVertA < 0 || iVertB < 0 ||\n");
#if (TOPO_DIM == 3)
    printf("         iVertC < 0 ||\n");
#endif
    printf("         ((iNumVerts > 0) && \n");
    printf("          (iVertA >= iNumVerts || \n");
#if (TOPO_DIM == 3)
	printf("           iVertC >= iNumVerts || \n");
#endif 
	printf("           iVertB >= iNumVerts) ) ) \n");
	printf("      vFatalError(\"Vertex index out of range\",\n");
	printf(MeshInput);
	printf("    (a2iIntBFaceVert)[iRealBFace][0] = iVertA;\n");
	printf("    (a2iIntBFaceVert)[iRealBFace][1] = iVertB;\n");
#if (TOPO_DIM == 3)
	printf("    (a2iIntBFaceVert)[iRealBFace][2] = iVertC;\n\n");
#endif 
	printf("\n");
      }
  if (qFaceARead) {
    assert(qFaceBRead);
    printf("    /* Remove offset from face index */ \n");
    printf("    iFaceA -= iFaceOffset;\n");
    printf("    iFaceB -= iFaceOffset;\n");
    printf("    if ( iFaceA < 0 ||\n");
    printf("         iFaceB < 0 ||\n");
    printf("         ((iNumFaces > 0) && \n");
    printf("          (iFaceA >= iNumFaces) || \n");
    printf("          (iFaceB >= iNumFaces) ) ) \n");
    printf("      vFatalError(\"Face index out of range\",\n");
    printf(MeshInput);
    printf("    (a2iIntBFaceFace)[iRealBFace][0] = iFaceA;\n");
    printf("    (a2iIntBFaceFace)[iRealBFace][1] = iFaceB;\n");
  }
  if (qBCRead) {
    printf("    if ( iBC <= 0 )\n");
    printf("      vFatalError(\"Boundary condition out of range\",\n");
    printf(MeshInput);
    printf("    (aiIntBFaceBC)[iRealBFace] = iBC;\n");
  }
  printf("  }\n");
  printf("\n");
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead) 
#else 
  if (qVertARead || qVertBRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead);
#else 
    assert(qVertARead && qVertBRead);
#endif
    printf("  qIntBFaceVert = true;\n");
  }  
  assert(qFaceARead);
  assert(qFaceBRead);
  printf("  qIntBFaceFace = true;\n");
  if (qBCRead) {
    printf("  qIntBFaceBC = true;\n");
  }
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}

%{
#if (TYPE != SURFACE)
%}
<INITIAL>^bdryfaces:[ \t]* {
  assert(qBFaceCountRead);
  BEGIN(BFACE_LINE);
  qVertARead = qVertBRead = qFaceRead = qBCRead = false;
#if (TOPO_DIM == 3)
  qVertCRead = false;
#endif 
  printf("\n");
  printf("  if (iNumBdryFaces == 0)\n");
  printf("    vFatalError(\"Tried to read bdry face data without specifying number of bdry faces\",\n");
  printf(MeshInput);
  printf("  /* Allocate the bface-face, bface-vert, and bface-BC arrays. */\n");
  printf("  /* One or more may have to be deleted later. */\n");
  printf("  if (! aiBFaceFace) \n");
  printf("    aiBFaceFace = new int[iNumBdryFaces];\n");
  printf("  if (! aiBFaceBC) \n");
  printf("    aiBFaceBC   = new int[iNumBdryFaces];\n");
  printf("  if (! a2iBFaceVert) \n");
  printf("    a2iBFaceVert= new int[iNumBdryFaces][TOPO_DIM];\n");
  printf("  if (iNumVerts == 0)\n");
  printf("    vWarning(\"# of verts unknown while reading bdry faces; sanity checking may be crippled.\");\n");
  printf("  if (iNumFaces == 0)\n");
  printf("    vWarning(\"# of faces unknown while reading bdry faces; sanity checking may be crippled.\");\n");
  printf("  for (int iBF = 0; iBF < iNumBdryFaces; iBF++) {\n");
  printf("    int iRealBFace = iBF;\n");
  printf("    int iFace = iNumFaces, iBC = -100;\n");
  printf("    int iVertA = -1, iVertB = -1;\n");
#if (TOPO_DIM == 3)
  printf("    int iVertC = -1;\n");
#endif 
  vAppendToString(strInput, &iInputLen, 1024, "bdryfaces: ");
}

<BFACE_LINE>index[ \t]*/[0-9]+	{
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen, ", &iRealBFace");
  qBFaceIndexRead = true;
}

<BFACE_LINE>index	{
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iRealBFace"); 
  qBFaceIndexRead = true;
}

<BFACE_LINE>bc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iBC");
  qBCRead = true;
}

<BFACE_LINE>bc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iBC");
  qBCRead = true;
}

<BFACE_LINE>face[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iFace");
  qFaceRead = true;
}

<BFACE_LINE>face {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iFace");
  qFaceRead = true;
}

<BFACE_LINE>verts {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,
		   ", &iVertA");
  yytext[0] = '\0';
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertB");
  qVertARead = qVertBRead = true;
#if (TOPO_DIM == 3)
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertC");
  qVertCRead = true;
#endif 
}

<BFACE_LINE>verta[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertA");
  qVertARead = true;
}

<BFACE_LINE>verta {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen, ", &iVertA");
  qVertARead = true;
}

<BFACE_LINE>vertb[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertB");
  qVertBRead = true;
}

<BFACE_LINE>vertb {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,", &iVertB");
  qVertBRead = true;
}

%{
#if (TOPO_DIM == 3)
%}
<BFACE_LINE>vertc[ \t]*/[0-9]+ {
  vUserIntInput(strArgs, &iArgsLen, strInput, &iInputLen,
		", &iVertC");
  qVertCRead = true;
}

<BFACE_LINE>vertc {
  vDefaultIntInput(strFormat, &iFormatLen, strArgs, &iArgsLen,
		   strInput, &iInputLen,", &iVertC");
  qVertCRead = true;
}

%{
#endif
%}

<BFACE_LINE>\n {
  vAppendToString(strFormat, &iFormatLen, 1024, "\\n\"");
  printf("    /*%s*/\n", strInput);
  printf("    fscanf(pFInFile, %s%s);\n", strFormat, strArgs);
  if (qBFaceIndexRead) {
    printf("    /* Remove any offset from the cell index */\n");
    printf("    iRealBFace -= iBFaceOffset;\n");
    printf("    if (iRealBFace < 0 || iRealBFace >= iNumBdryFaces)\n");
    printf("      vFatalError(\"Invalid boundary face index\",\n");
    printf(MeshInput);
  }
    
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead) 
#else 
  if (qVertARead || qVertBRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead);
#else
    assert(qVertARead && qVertBRead);
#endif
    printf("    /* Remove offset from the vertex indices */\n");
    printf("    iVertA -= iVertOffset;\n");
    printf("    iVertB -= iVertOffset;\n");
#if (TOPO_DIM == 3)
    printf("    iVertC -= iVertOffset;\n");
#endif
    printf("    if ( iVertA < 0 || iVertB < 0 ||\n");
#if (TOPO_DIM == 3)
    printf("         iVertC < 0 ||\n");
#endif
    printf("         ((iNumVerts > 0) && \n");
    printf("          (iVertA >= iNumVerts || \n");
#if (TOPO_DIM == 3)
	printf("           iVertC >= iNumVerts || \n");
#endif 
	printf("           iVertB >= iNumVerts) ) ) \n");
	printf("      vFatalError(\"Vertex index out of range\",\n");
	printf(MeshInput);
	printf("    (a2iBFaceVert)[iRealBFace][0] = iVertA;\n");
	printf("    (a2iBFaceVert)[iRealBFace][1] = iVertB;\n");
#if (TOPO_DIM == 3)
	printf("    (a2iBFaceVert)[iRealBFace][2] = iVertC;\n\n");
#endif 
	printf("\n");
      }
  if (qFaceRead) {
    printf("    /* Remove offset from face index */ \n");
    printf("    iFace -= iFaceOffset;\n");
    printf("    if ( iFace < 0 ||\n");
    printf("         ((iNumFaces > 0) && \n");
    printf("          (iFace >= iNumFaces) ) ) \n");
    printf("      vFatalError(\"Face index out of range\",\n");
    printf(MeshInput);
    printf("    (aiBFaceFace)[iRealBFace] = iFace;\n");
  }
  if (qBCRead) {
    printf("    if ( iBC <= 0 )\n");
    printf("      vFatalError(\"Boundary condition out of range\",\n");
    printf(MeshInput);
    printf("    (aiBFaceBC)[iRealBFace] = iBC;\n");
  }
  printf("  }\n");
  printf("\n");
#if (TOPO_DIM == 3)
  if (qVertARead || qVertBRead || qVertCRead) 
#else 
  if (qVertARead || qVertBRead) 
#endif
  {
#if (TOPO_DIM == 3)
    assert(qVertARead && qVertBRead && qVertCRead);
#else 
    assert(qVertARead && qVertBRead);
#endif
    printf("  qBFaceVert = true;\n");
  }  
  if (qFaceRead) {
    printf("  qBFaceFace = true;\n");
  }
  else 
  if (qBCRead) {
    printf("  qBFaceBC = true;\n");
  }
  vClearString(strInput, 1024);
  iInputLen = 0;
  vClearString(strFormat, 1024);
  iFormatLen = 0;
  vAppendToString(strFormat, &iFormatLen, 1024, "\"");
  vClearString(strArgs, 1024);
  iArgsLen = 0;
  BEGIN(INITIAL);
}
%{
#endif
%}

discard_integer {
  vAppendToString(strInput, &iInputLen, 1024, "discard_integer ");
  vAppendToString(strFormat, &iFormatLen, 1024, "%*d");
}

discard_float {
  vAppendToString(strInput, &iInputLen, 1024, "discard_float ");
  vAppendToString(strFormat, &iFormatLen, 1024, "%*f");
}

discard_string {
  vAppendToString(strInput, &iInputLen, 1024, "discard_string ");
  vAppendToString(strFormat, &iFormatLen, 1024, "%*s");
}

<INITIAL>discard_line {
  vAppendToString(strInput, &iInputLen, 1024, "discard_line ");
  vAppendToString(strFormat, &iFormatLen, 1024, "%*[^\\n]");
}

<INITIAL,FACE_LINE,VERTEX_LINE,CELL_LINE,INT_BFACE_LINE>.	{
  strFormat[iFormatLen++] = yytext[0];
  vAppendToString(strInput, &iInputLen, 1024, yytext);
} /* LAST RULE */

%%

int main(void)
{
  /* Write the header for the file that reads/writes the mesh */
  int ii = 0;
  while (strlen(pstrTopOfSource[ii]) != 0)
    printf("%s\n", pstrTopOfSource[ii++]);

  /* Parse the template and generate code. */
  yylex();

  /* Write the footer for the file that reads/writes the mesh */

  printf("  /* Get rid of the face-vert array if it isn't used. */\n");
  printf("  if (!(qFaceVert) && a2iFaceVert) {\n");
  printf("    delete [] a2iFaceVert;\n");
  printf("    a2iFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the face-cell array if it isn't used. */\n");
  printf("  if (!(qFaceCell) && (a2iFaceCell)){\n");
  printf("    delete [] a2iFaceCell;\n");
  printf("    a2iFaceCell = reinterpret_cast<int(*)[2]> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the cell-vert array if it isn't used. */\n");
  printf("  if (!(qCellVert) && (a2iCellVert)) {\n");
  printf("    delete [] a2iCellVert;\n");
  printf("    a2iCellVert = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the cell-face array if it isn't used. */\n");
  printf("  if (!(qCellFace) && (a2iCellFace)) {\n");
  printf("    delete [] a2iCellFace;\n");
  printf("    a2iCellFace = reinterpret_cast<int(*)[TOPO_DIM+1]> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the cell-region array if it isn't used. */\n");
  printf("  if (!(qCellRegion) && (aiCellRegion)) {\n");
  printf("    delete [] aiCellRegion;\n");
  printf("    aiCellRegion = reinterpret_cast<int *> (NULL);\n");
  printf("  }\n\n");
#if (TYPE != SURFACE)  
  printf("  /* Get rid of the bface-face array if it isn't used. */\n");
  printf("  if (!(qBFaceFace) && (aiBFaceFace)){\n");
  printf("    delete [] aiBFaceFace;\n");
  printf("    aiBFaceFace = reinterpret_cast<int *> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the bface-BC array if it isn't used. */\n");
  printf("  if (!(qBFaceBC) && (aiBFaceBC)){\n");
  printf("    delete [] aiBFaceBC;\n");
  printf("    aiBFaceBC = reinterpret_cast<int *> (NULL);\n");
  printf("  }\n\n");
  printf("  /* Get rid of the bface-vert array if it isn't used. */\n");
  printf("  if (!(qBFaceVert) && (a2iBFaceVert)) {\n");
  printf("    delete [] a2iBFaceVert;\n");
  printf("    a2iBFaceVert = reinterpret_cast<int(*)[TOPO_DIM]> (NULL);\n");
  printf("  }\n\n");
#endif
  printf("  /* The following lines prevent compiler complaints. */\n");
  printf("  iBFaceOffset++;\n");
  printf("  iFaceOffset++;\n");
  printf("  iCellOffset++;\n");
  printf("  iVertOffset++;\n");
  printf("  fclose(pFInFile);\n");
  printf("}\n");
  exit(0);
}
