
/*
 *  autogen.h
 *  $Id: autogen.h,v 2.13 1999/07/07 19:30:52 bkorb Exp $
 *  Global header file for AutoGen
 */

/*
 *  AutoGen copyright 1992-1999 Bruce Korb
 *
 *  AutoGen is free software.
 *  You may redistribute it and/or modify it under the terms of the
 *  GNU General Public License, as published by the Free Software
 *  Foundation; either version 2, or (at your option) any later version.
 *
 *  AutoGen is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with AutoGen.  See the file "COPYING".  If not,
 *  write to:  The Free Software Foundation, Inc.,
 *             59 Temple Place - Suite 330,
 *             Boston,  MA  02111-1307, USA.
 */

#ifndef AUTOGEN_HDR
#define AUTOGEN_HDR

/* Pre-processor magic - slurps in common headers */
#include "config.h"
#include "compat/compat.h"

#include <time.h>
#include <utime.h>
#include <ctype.h>
#include <sys/mman.h>

#include "config.h"

#include "opts.h"
#include "tokenize.h"
#include "snprintfv/snprintfv.h"

/*
 *  Maximum number of tokens in a macro invocation
 */
#ifndef MAX_TKN
#   define MAX_TKN  2048
#endif

/*
 *  Maximum number of elements in a stack expression.
 *  This may be larger than "MAX_TKN" because the "_stack"
 *  function may push many elements onto the stack.
 */
#ifndef MAX_STK
#  define MAX_STK  2048
#endif

#ifndef STR
#  define _STR(s) #s
#  define STR(s)  _STR(s)
#endif

#undef  IS_LOW
#define IS_LOW(c)  (((c) <= 'z') && ((c) >= 'a'))
#undef  IS_HI
#define IS_HI(c)   (((c) <= 'Z') && ((c) >= 'A'))

#ifndef _toupper
#  ifdef __toupper
#    define _toupper(c)     __toupper(c)
#    define _tolower(c)     __tolower(c)
#  else
#    define _toupper(c)     toupper(c)
#    define _tolower(c)     tolower(c)
#  endif
#endif

#define PTRUP(p) STMTS(if(IS_LOW(*(p)))*(p)=_toupper(*(p));(p)++)
#define PTRDN(p) STMTS(if(IS_HI( *(p)))*(p)=_tolower(*(p));(p)++)

/*
 *  Procedure success codes
 *
 *  USAGE:  define procedures to return "tSuccess".  Test their results
 *          with the SUCCEEDED, FAILED and HADGLITCH macros.
 */
#define SUCCESS  ((tSuccess) 0)
#define FAILURE  ((tSuccess)-1)
#define PROBLEM  ((tSuccess) 1)

typedef int tSuccess;

#define SUCCEEDED( p )     ((p) == SUCCESS)
#define SUCCESSFUL( p )    SUCCEEDED( p )
#define FAILED( p )        ((p) <  SUCCESS)
#define HADGLITCH( p )     ((p) >  SUCCESS)

#ifndef NUL
#  define NUL '\0'
#endif

#undef STATIC

#ifdef DEBUG
#  define STATIC
#else
#  define STATIC static
#endif

#define STRSIZE( s )  (sizeof(s)-1)

#ifdef DEFINING
#  define VALUE( s )  = s
#  define MODE
#else
#  define VALUE( s )
#  define MODE extern
#endif

#define YYSTYPE t_word

typedef struct macro         tMacro;
typedef struct fpStack       tFpStack;
typedef struct scanContext   tScanCtx;
typedef struct defEntry      tDefEntry;
typedef struct outSpec       tOutSpec;
typedef struct templDir      tTemplDir;
typedef struct templ_file    tTemplFile;
typedef struct valStack      tValStack;
typedef struct defList       tDefList;

typedef enum { VT_NONE,  VT_STK_MARK,
               VT_VALUE, VT_STRING,   VT_ALLOC_STR,
               VT_STACK } teValType;

typedef union value tuValue;

union value {
    t_word     val;
    char*      pz;
};

struct valStack {
    teValType  valType;
    tuValue    val;
};

struct defList {
    char*      pzName;
    char*      pzValue;
};

/*
 *  Dual pipe opening of a child process
 */

typedef struct {
    int     readFd;
    int     writeFd;
}  tFdPair;

typedef struct {
    FILE*   pfRead;  /* parent read fp  */
    FILE*   pfWrite; /* parent write fp */
}  tpfPair;

typedef char* tpChar;

/*
 *  Procedure for loading a template function
 */
typedef tMacro* (tLoadProc)( tMacro* pTpl, char** ppzScan );
typedef tLoadProc* tpLoadProc;

/*
 *  Procedure for handling a template function
 *  during the text emission phase.
 */
typedef tMacro* (tHdlrProc)( tMacro* pTpl, tDefEntry* pCurDef );
typedef tHdlrProc* tpHdlrProc;

#include "agfunc.h"

struct templDir {
    tTemplDir*  pNext;
    char        zDirName[2];
};

struct outSpec {
    tOutSpec*   pNext;
    const char* pzFileFmt;
    char        zSuffix[ 1 ];
};


typedef enum { MACTYP_UNKNOWN = 0,
               MACTYP_TEXT,
               MACTYP_BLOCK } teMacType;


#define NO_INDEX ((short)0x80FF)

struct defEntry {
    tDefEntry* pDad;         /* pointer to parent          */
    tDefEntry* pNext;        /* next member of same parent */
    tDefEntry* pTwin;        /* next member with same name */
    tDefEntry* pPrevTwin;    /* previous memb. of parent   */
    tDefEntry* pEndTwin;     /* head of chain to end ptr   */
    char*      pzName;       /* name of this member        */
    teMacType  macType;      /* text/block/not defined yet */
    long       index;        /* index among twins          */
    char*      pzValue;      /* string or list of children */
};

struct scanContext {
    tScanCtx*   pCtx;
    char*       pzScan;
    char*       pzFileName;
    char*       pzData;
    int         lineNo;
};

struct fpStack {
    tFpStack*   pPrev;
    FILE*       pFile;
    char*       pzName;
};


struct macro {
    teFuncType  funcCode;  /* Macro function         */
    tMacro*     pEnd;      /* End of block macro     */
    tMacro*     pSibling;  /* Sibling macro (ELIF or SELECT) */
    int         tknCt;     /* count of arguments     */

    char**      ppTkns;    /* ptr to list of tokens  */
    char*       pzText;    /* associated text        */
    int         lineNo;    /* of macro def           */
    void*       evalRes;   /* Result of an eval      */
};


struct templ_file {
    char*       pzText;
    int         macCt;
    tMacro*     pMacros;
    char        zName[1];
};

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  Expression Evaluation Stuff
 */
#define ISSPACETAB( c )  (((c) == ' ') || ((c) == '\t'))

typedef enum { CC_UPPER = 1, CC_lower = 2, CC_Cap, CC_NONE,
               CC_ALL_UP,    CC_all_low,   CC_All_Cap } teCaseType;



typedef enum { REL_NONE,
               REL_EQ, REL_NE, REL_GT, REL_LT, REL_GE, REL_LE,
               REL_NOT   = (unsigned)'!' /* 041  */,
               REL_MOD   = (unsigned)'%' /* 045  */,
               REL_AND   = (unsigned)'&' /* 046  */,
               REL_MULT  = (unsigned)'*' /* 052  */,
               REL_PLUS  = (unsigned)'+' /* 053  */,
               REL_MINUS = (unsigned)'-' /* 055  */,
               REL_DIV   = (unsigned)'/' /* 057  */,
               REL_XOR   = (unsigned)'^' /* 0136 */,
               REL_OR    = (unsigned)'|' /* 0174 */,
               REL_MATCH = (unsigned)'~' /* 0176 */
             } teRel;


#define NOPROCESS   ((pid_t)-1)
#define NULLPROCESS ((pid_t)0)

typedef enum { PROC_STATE_INIT,
               PROC_STATE_OPTIONS,
               PROC_STATE_LOAD_DEFS,
               PROC_STATE_LOAD_TPL,
               PROC_STATE_EMITTING
} teProcState;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  GLOBAL VARIABLES
 */
#define pzProg   AutoGenOptions.pzProgName
MODE const char* pzCurSfx        VALUE( (char*)NULL );
MODE int         curIndex        VALUE( 0 );
MODE time_t      outTime         VALUE( 0 );
MODE int         templLineNo     VALUE( 0 );
MODE tFpStack*   pCurFp          VALUE( (tFpStack*)NULL );

MODE tOutSpec*   pOutSpecList    VALUE( (tOutSpec*)NULL );
MODE jmp_buf     fileAbort       VALUE( { 0 } );
MODE char*       pzCurStart      VALUE( (char*)NULL );
MODE off_t       curStartOff     VALUE( 0 );
MODE int         forLoopDepth    VALUE( 0 );
MODE ag_bool     lastForCycle    VALUE( AG_FALSE );
MODE ag_bool     firstForCycle   VALUE( AG_FALSE );
MODE teProcState procState       VALUE( PROC_STATE_INIT );

MODE tDefEntry   rootEntry;
MODE tScanCtx*   pBaseCtx        VALUE( (tScanCtx*)NULL );
MODE tScanCtx*   pCurCtx         VALUE( (tScanCtx*)NULL );
MODE tScanCtx*   pDoneCtx        VALUE( (tScanCtx*)NULL );

MODE int         endMacLen       VALUE( 0  );
MODE char        zEndMac[  16 ]  VALUE( "" );

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  GLOBAL STRINGS
 */
MODE char*     pzTemplFileName   VALUE( (char*)NULL );

#define ZALLOCERR   "%s ERROR:  Couldn't allocate a %d byte %s\n"
#define ZCANNOT     "%s ERROR %d: cannot %s %s:  %s\n"
#define ZSHDONE     "ShElL-OuTpUt-HaS-bEeN-cOmPlEtEd"
#define ZTPLERR     "Error in template %s, line %d\n\t%s\n"
#define ZTOKENLIST  "token list"

MODE const char zAllocErr[   sizeof( ZALLOCERR  )] VALUE( ZALLOCERR );
MODE const char zCannot[     sizeof( ZCANNOT    )] VALUE( ZCANNOT );
MODE const char zShDone[     sizeof( ZSHDONE    )] VALUE( ZSHDONE );
MODE const char zTplErr[     sizeof( ZTPLERR    )] VALUE( ZTPLERR );
MODE const char zTokenList[  sizeof( ZTOKENLIST )] VALUE( ZTOKENLIST );

MODE char*  pzDefineFileName VALUE( (char*)NULL );
MODE char*  pzDefineData     VALUE( (char*)NULL );
MODE size_t defineDataSize   VALUE( 0 );

#define LOAD_ABORT STMTS( if (procState<PROC_STATE_EMITTING) \
                          exit(EXIT_FAILURE); \
                          longjmp( fileAbort, FAILURE ))

#ifdef MEMDEBUG

typedef struct mem_mgmt tMemMgmt;
struct mem_mgmt {
    tMemMgmt*   pNext;
    tMemMgmt*   pPrev;
    char*       pEnd;
    const char* pzWhence;
};

#  ifdef strdup
#    undef strdup
#  endif
#  define strdup(s) dupString((s), __FILE__ " at " STR( __LINE__ ))

   extern char* dupString( const char* pz, const char* pzDupFrom );

   extern void* ag_alloc( size_t, const char* );
   extern void* ag_realloc( void*, size_t, const char* );
   extern void  ag_free( void* );

#  define AGALOC( c )      ag_alloc( c, __FILE__ " at " STR( __LINE__ ))
#  define AGREALOC( p, c)  ag_realloc( p, c, __FILE__ " at " STR( __LINE__ ))
#  define AGFREE( p )      ag_free( p )
#  define AGDUPSTR( p, s ) STMTS( \
                           tSCC z[] = "strdup in " __FILE__ " at " \
                                  STR( __LINE__ );\
                           p = dupString( s, z ))
#  define TAGMEM( m, t )   STMTS( tMemMgmt* p  = ((tMemMgmt*)m)-1; \
                           tSCC z[] = t " in " __FILE__ " at " \
                                  STR( __LINE__ ); \
                           p->pzWhence = z )
#else
#  define AGALOC( c )      malloc( c )
#  define AGREALOC( p, c)  realloc( p, c )
#  define AGFREE( p )      free( p )
#  define AGDUPSTR( p, s ) p = strdup( s )
#  define TAGMEM( m, t )
#endif

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  GLOBAL PROCEDURES
 */
#include "proto.h"
#endif /* AUTOGEN_HDR */
/* end of autogen.h */
