/*
* autogen.h
* $Id: autogen.h,v 4.31 2007/07/07 01:04:11 bkorb Exp $
*
* Time-stamp: "2007-07-06 11:23:43 bkorb"
* Last Committed: $Date: 2007/07/07 01:04:11 $
*
* Global header file for AutoGen
*
* This file is part of AutoGen.
* AutoGen copyright (c) 1992-2007 by Bruce Korb - all rights reserved
*
* AutoGen is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, 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 this program. If not, see .
*/
#ifndef AUTOGEN_BUILD
#define AUTOGEN_BUILD 1
#include "config.h"
#include "compat/compat.h"
#include REGEX_HEADER
#include
#include
#include "opts.h"
#include "directive.h"
#include "snprintfv/printf.h"
#ifndef STR
# define _STR(s) #s
# define STR(s) _STR(s)
#endif
#define ISNAMECHAR( c ) (isalnum(c) || ((c) == '_') || ((c) == '-'))
#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
#define ag_offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
/*
* 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;
#define NOPROCESS ((pid_t)-1)
#define NULLPROCESS ((pid_t)0)
typedef unsigned char* tpChar;
#include "expr.h"
#include "autoopts/autoopts.h"
#include "cgi-fsm.h"
#include "defParse-fsm.h"
typedef union {
tpChar pzStr;
char ch;
} def_token_u_t;
#define STATE_TABLE /* set up `atexit' and load Guile */ \
_State_( INIT ) /* processing command line options */ \
_State_( OPTIONS ) /* Loading guile at option time */ \
_State_( GUILE_PRELOAD ) /* Loading value definitions */ \
_State_( LOAD_DEFS ) /* Loading library template */ \
_State_( LIB_LOAD ) /* Loading primary template */ \
_State_( LOAD_TPL ) /* processing templates */ \
_State_( EMITTING ) /* loading an included template */ \
_State_( INCLUDING ) /* end of processing before exit() */ \
_State_( CLEANUP ) /* Clean up code in error response */ \
_State_( ABORTING ) /* `exit' has been called */ \
_State_( DONE )
#define _State_(n) PROC_STATE_ ## n,
typedef enum { STATE_TABLE COUNT_PROC_STATE } teProcState;
#undef _State_
#define EXPORT
typedef struct fpStack tFpStack;
typedef struct outSpec tOutSpec;
typedef struct scanContext tScanCtx;
typedef struct defEntry tDefEntry;
typedef struct macro_desc tMacro;
typedef struct template_desc tTemplate;
typedef struct for_info tForInfo;
typedef struct for_state tForState;
typedef struct template_lib_marker tTlibMark;
#define MAX_SUFFIX_LEN 8 /* maximum length of a file name suffix */
#define MAX_HEREMARK_LEN 64 /* max length of a here mark */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Template Library Layout
*
* Procedure for loading a template function
*/
typedef tMacro* (tLoadProc)( tTemplate*, tMacro*, char const** ppzScan );
typedef tLoadProc* tpLoadProc;
typedef void (tUnloadProc)( tMacro* );
typedef tUnloadProc* tpUnloadProc;
/*
* Procedure for handling a template function
* during the text emission phase.
*/
typedef tMacro* (tHdlrProc)( tTemplate*, tMacro* );
typedef tHdlrProc* tpHdlrProc;
/*
* This must be included after the function prototypes
* (the prototypes are used in the generated tables),
* but before the macro descriptor structure (the function
* enumeration is generated here).
*/
#include "functions.h"
#define TEMPLATE_REVISION 1
#define TEMPLATE_MAGIC_MARKER {{{'A', 'G', 'L', 'B'}}, \
TEMPLATE_REVISION, FUNCTION_CKSUM }
struct template_lib_marker {
union {
unsigned char str[4]; /* {'A', 'G', 'L', 'B'} */
unsigned int i[1];
} magic;
unsigned short revision; /* TEMPLATE_REVISION */
unsigned short funcSum; /* FUNCTION_CKSUM */
};
/*
* Defines for conditional expressions.
* The first four are an enumeration that appear in the
* low four bits and the next-to-lowest four bits.
* "PRIMARY_TYPE" and "SECONDARY_TYPE" are masks for
* extracting this enumeration. The rest are flags.
*/
#define EMIT_VALUE 0x0000 /* emit value of variable */
#define EMIT_EXPRESSION 0x0001 /* Emit Scheme result */
#define EMIT_SHELL 0x0002 /* emit shell output */
#define EMIT_STRING 0x0003 /* emit content of expr */
#define EMIT_PRIMARY_TYPE 0x0007
#define EMIT_SECONDARY_TYPE 0x0070
#define EMIT_SECONDARY_SHIFT 4
#define EMIT_IF_ABSENT 0x0100
#define EMIT_ALWAYS 0x0200 /* emit one of two exprs */
#define EMIT_FORMATTED 0x0400 /* format, if val present */
#define EMIT_NO_DEFINE 0x0800 /* don't get defined value */
struct macro_desc {
teFuncType funcCode; /* Macro function */
int lineNo; /* of macro def */
int endIndex; /* End of block macro */
int sibIndex; /* Sibling macro (ELIF or SELECT) */
uintptr_t ozName; /* macro name (sometimes) */
uintptr_t ozText; /* associated text */
long res; /* some sort of result */
void* funcPrivate;
};
struct template_desc {
tTlibMark magic; /* TEMPLATE_MAGIC_MARKER */
size_t descSize; /* Structure Size */
char* pNext; /* Next Pointer */
int macroCt; /* Count of Macros */
tCC* pzTplFile; /* Name of template file */
char* pzTplName; /* Defined Macro Name */
char* pzTemplText; /* offset of the text */
char zStartMac[MAX_SUFFIX_LEN];
char zEndMac[MAX_SUFFIX_LEN];
tMacro aMacros[1]; /* Array of Macros */
/* char text[...]; * strings at end of macros */
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Name/Value Definitions Layout
*/
typedef enum {
VALTYP_UNKNOWN = 0,
VALTYP_TEXT,
VALTYP_BLOCK
} teValType;
#define NO_INDEX ((short)0x80DEAD)
typedef struct sDefCtx tDefCtx;
struct sDefCtx {
tDefEntry* pDefs; /* ptr to current def set */
tDefCtx* pPrev; /* ptr to previous def set */
};
typedef union {
tDefEntry* pDefEntry;
char* pzText;
} uDefValue;
struct defEntry {
tDefEntry* pNext; /* next member of same level */
tDefEntry* pTwin; /* next member with same name */
tDefEntry* pPrevTwin; /* previous memb. of level */
tDefEntry* pEndTwin; /* head of chain to end ptr */
char* pzDefName; /* name of this member */
long index; /* index among twins */
uDefValue val; /* string or list of children */
char* pzSrcFile; /* definition file name */
int srcLineNum; /* def file source line */
teValType valType; /* text/block/not defined yet */
};
struct scanContext {
tScanCtx* pCtx;
char* pzScan;
tCC* pzCtxFname;
char* pzData;
int lineNo;
};
struct outSpec {
tOutSpec* pNext;
char const* pzFileFmt;
char zSuffix[ 1 ];
};
#define FPF_FREE 0x0001 /* free the fp structure */
#define FPF_UNLINK 0x0002 /* unlink file (temp file) */
#define FPF_NOUNLINK 0x0004 /* do not unlink file */
#define FPF_STATIC_NM 0x0008 /* name statically alloced */
#define FPF_NOCHMOD 0x0010 /* do not chmod(2) file */
struct fpStack {
int flags;
tFpStack* pPrev;
FILE* pFile;
tCC* pzOutName;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* FOR loop processing state
*/
struct for_info {
int fi_depth;
int fi_alloc;
tForState* fi_data;
};
struct for_state {
ag_bool for_loading;
int for_from;
int for_to;
int for_by;
int for_index;
char* for_pzSep;
char* for_pzName;
ag_bool for_lastFor;
ag_bool for_firstFor;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Parsing stuff
*/
typedef struct {
int entryCt;
int allocCt;
char* entries[1];
} tList;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* GLOBAL VARIABLES
*
* General Processing Globals
*/
#define pzProg autogenOptions.pzProgName
MODE teProcState procState VALUE( PROC_STATE_INIT );
MODE tTemplate* pNamedTplList VALUE( NULL );
MODE tCC* pzOopsPrefix VALUE( "" );
/*
* Template Processing Globals
*/
MODE tCC* pzCurSfx VALUE( NULL );
MODE time_t outTime VALUE( 0 );
MODE tFpStack* pCurFp VALUE( NULL );
MODE tOutSpec* pOutSpecList VALUE( NULL );
MODE jmp_buf fileAbort;
MODE char* pzCurStart VALUE( NULL );
MODE uintptr_t curStartOff VALUE( 0 );
MODE tForInfo forInfo VALUE( { 0 } );
MODE FILE* pfTrace VALUE( NULL );
MODE char* pzTmpStderr VALUE( NULL );
MODE tCC* serverArgs[2] VALUE( { NULL } );
MODE tCC* pzShellProgram VALUE( NULL );
/*
* AutoGen definiton and template context
*
* currDefCtx is the current, active list of name/value pairs.
* Points to its parent list for full search resolution.
*
* pCurTemplate the template (and DEFINE macro) from which
* the current set of macros is being extracted.
*
* These are set in exactly ONE place:
* On entry to the dispatch routine (generateBlock)
* Two routines, however, must restore the values: mFunc_Define
* and mFunc_For. They are the only routines that dynamically
* push name/value pairs on the definition stack.
*/
MODE tDefCtx currDefCtx VALUE( { NULL } );
MODE tDefCtx rootDefCtx VALUE( { NULL } );
MODE tTemplate* pCurTemplate VALUE( NULL );
MODE tCC* pzLastScheme VALUE( NULL );
#ifdef DAEMON_ENABLED
/*
* When operating as a daemon, autogen can be told to reload
* its options the next time it wakes up (send it a SIGHUP).
*/
MODE ag_bool redoOptions VALUE( AG_TRUE );
#endif
/*
* Current Macro
*
* This may be set in exactly three places:
* 1. The dispatch routine (generateBlock) that steps through
* a list of macros
* 2. mFunc_If may transfer to one of its 'ELIF' or 'ELSE'
* alternation macros
* 3. mFunc_Case may transfer to one of its selection clauses.
*/
MODE tMacro* pCurMacro VALUE( NULL );
/*
* Template Parsing Globals
*/
MODE int templLineNo VALUE( 1 );
MODE tScanCtx* pBaseCtx VALUE( NULL );
MODE tScanCtx* pCurCtx VALUE( NULL );
MODE tScanCtx* pDoneCtx VALUE( NULL );
MODE size_t endMacLen VALUE( 0 );
MODE char zEndMac[ 8 ] VALUE( "" );
MODE size_t startMacLen VALUE( 0 );
MODE char zStartMac[ 8 ] VALUE( "" );
MODE int guileFailure VALUE( 0 );
/*
* Definition Parsing Globals
*/
MODE char* pzDefineData VALUE( NULL );
MODE char* pz_token VALUE( NULL );
MODE te_dp_event lastToken VALUE( DP_EV_INVALID );
MODE int stackDepth VALUE( 0 );
MODE int stackSize VALUE( 16 );
MODE tDefEntry* parseStack[16] VALUE( { 0 } );
MODE tDefEntry** ppParseStack VALUE( parseStack );
MODE tDefEntry* pCurrentEntry VALUE( NULL );
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* GLOBAL STRINGS
*/
#define MKSTRING( name, val ) \
MODE char const z ## name[ sizeof( val )] VALUE( val )
MKSTRING( AllocWhat, "Could not allocate a %d byte %s\n" );
MKSTRING( AllocErr, "Allocation Failure" );
MKSTRING( Cannot, "fserr %d: cannot %s %s: %s\n" );
MKSTRING( TplWarn, "Warning in template %s, line %d\n\t%s\n" );
MKSTRING( FileLine, "\tfrom %s line %d\n" );
MKSTRING( ShDone, "ShElL-OuTpUt-HaS-bEeN-cOmPlEtEd" );
MKSTRING( NotStr, "ERROR: %s is not a string\n" );
MKSTRING( DevNull, "/dev/null" );
MKSTRING( ShellEnv, "SHELL" );
MKSTRING( Format, "format" );
MKSTRING( FileFormat, "%s%s\0%s.%s" );
MKSTRING( Nil, "" );
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* GLOBAL PROCEDURES
*/
#ifndef HAVE_STRLCPY
extern size_t strlcpy( char* dest, char const* src, size_t n );
#endif
#ifdef ENABLE_FMEMOPEN
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* IF we have fopencookie or funopen, then we also have our own fmemopen
*/
extern FILE * ag_fmemopen (void *buf, ssize_t len, char const *mode);
#endif
#include "proto.h"
typedef union {
const void* cp;
void* p;
} v2c_t;
MODE v2c_t p2p VALUE( { NULL } );
#ifdef DEBUG_ENABLED
# define AG_ABEND(s) ag_abend_at(s,__FILE__,__LINE__)
#else
# define AG_ABEND(s) ag_abend_at(s)
#endif
#ifdef DEBUG_FSM
# define DEBUG
#else
# undef DEBUG
#endif
#define AG_ABEND_IN(t,m,s) \
STMTS( pCurTemplate=(t); pCurMacro=(m); AG_ABEND(s);)
extern void ag_scmStrings_init( void );
extern void ag_scmStrings_deinit( void );
extern void ag_scmStrings_free( void );
extern char* ag_scribble( size_t size );
#if defined(DEBUG_ENABLED)
extern void manageAllocatedData( void* pd );
#else
# define manageAllocatedData(_ptr)
#endif
/*
* Code variations based on the version of Guile:
*/
#if GUILE_VERSION < 107000 /* pre-Guile 1.7.x */
#if GUILE_VERSION < 106000 /* Guile 1.4 */
# define AG_SCM_STRING_P(_s) gh_string_p(_s)
# define AG_SCM_BOOL_P(_b) gh_boolean_p(_b)
# define AG_SCM_SYM_P(_s) gh_symbol_p(_s)
# define AG_SCM_IS_PROC(_p) gh_procedure_p(_p)
# define AG_SCM_CHAR_P(_c) gh_char_p(_c)
# define AG_SCM_VEC_P(_v) gh_vector_p(_v)
# define AG_SCM_PAIR_P(_p) gh_pair_p(_p)
# define AG_SCM_NUM_P(_n) gh_number_p(_n)
# define AG_SCM_LIST_P(_l) gh_list_p(_l)
# define AG_SCM_STR2SCM(_st,_sz) gh_str2scm(_st,_sz)
# define AG_SCM_STR02SCM(_s) gh_str02scm(_s)
#else /* Guile 1.6.x */
# define AG_SCM_STRING_P(_s) SCM_STRINGP(_s)
# define AG_SCM_BOOL_P(_b) SCM_BOOLP(_b)
# define AG_SCM_SYM_P(_s) SCM_SYMBOLP(_s)
# define AG_SCM_IS_PROC(_p) SCM_NFALSEP( scm_procedure_p(_p))
# define AG_SCM_CHAR_P(_c) SCM_CHARP(_c)
# define AG_SCM_VEC_P(_v) SCM_VECTORP(_v)
# define AG_SCM_PAIR_P(_p) SCM_NFALSEP( scm_pair_p(_p))
# define AG_SCM_NUM_P(_n) SCM_NUMBERP(_n)
# define AG_SCM_LIST_P(_l) SCM_NFALSEP( scm_list_p(_l))
# define AG_SCM_STR2SCM(_st,_sz) scm_mem2string(_st,_sz)
# define AG_SCM_STR02SCM(_s) scm_makfrom0str(_s)
#endif
static inline char* ag_scm2zchars( SCM s, tCC* type )
{
if (! AG_SCM_STRING_P( s ))
AG_ABEND( aprf( zNotStr, type ));
if (SCM_SUBSTRP(s))
s = scm_makfromstr( SCM_CHARS(s), SCM_LENGTH(s), 0 );
return SCM_CHARS(s);
}
# define AG_SCM_STRLEN(_s) SCM_LENGTH(_s)
# define AG_SCM_CHARS(_s) SCM_CHARS(_s)
#else /* Guile 1.7 and following */
extern char* ag_scm2zchars( SCM s, tCC* type );
# if GUILE_VERSION < 108000
# define AG_SCM_STRLEN(_s) SCM_STRING_LENGTH(_s)
# define AG_SCM_CHARS(_s) SCM_STRING_CHARS(_s)
# define AG_SCM_VEC_P(_v) SCM_VECTORP(_v)
# else
# define AG_SCM_STRLEN(_s) scm_c_string_length(_s)
# define AG_SCM_CHARS(_s) scm_i_string_chars(_s)
# define AG_SCM_VEC_P(_v) scm_is_vector(_v)
# endif
# define AG_SCM_STRING_P(_s) scm_is_string(_s)
# define AG_SCM_BOOL_P(_b) SCM_BOOLP(_b)
# define AG_SCM_SYM_P(_s) SCM_SYMBOLP(_s)
# define AG_SCM_IS_PROC(_p) scm_is_true( scm_procedure_p(_p))
# define AG_SCM_CHAR_P(_c) SCM_CHARP(_c)
# define AG_SCM_PAIR_P(_p) scm_is_true( scm_pair_p(_p))
# define AG_SCM_NUM_P(_n) scm_is_number(_n)
# define AG_SCM_LIST_P(_l) SCM_NFALSEP( scm_list_p(_l))
# define AG_SCM_STR2SCM(_st,_sz) scm_from_locale_stringn(_st,_sz)
# define AG_SCM_STR02SCM(_s) scm_from_locale_string(_s)
#endif /* pre-1.7 / 1.7 and following */
/*
* Guile version invariant!!
*/
#define AG_SCM_INT2SCM(_i) gh_int2scm(_i)
#define AG_SCM_SCM2INT(_i) gh_scm2int(_i)
#define AG_SCM_LONG2SCM(_i) gh_long2scm(_i)
#define AG_SCM_SCM2LONG(_i) gh_scm2long(_i)
static inline SCM ag_eval( tCC* pzStr )
{
SCM res;
tCC* pzSaveScheme = pzLastScheme; /* Watch for nested calls */
pzLastScheme = pzStr;
res = ag_scm_c_eval_string_from_file_line(
pzStr, pCurTemplate->pzTplFile, pCurMacro->lineNo );
pzLastScheme = pzSaveScheme;
return res;
}
#endif /* AUTOGEN_BUILD */
/*
* Local Variables:
* mode: C
* c-file-style: "stroustrup"
* indent-tabs-mode: nil
* End:
* end of agen5/autogen.h */