Exemplo n.º 1
0
/**
 *  Starting with the current directory, search the directory
 *  list trying to find the base template file name.
 */
LOCAL tTemplate *
loadTemplate(char const * pzFileName, char const * referrer)
{
    static tmap_info_t mapInfo;
    static char        zRealFile[ AG_PATH_MAX ];

    /*
     *  Find the template file somewhere
     */
    {
        static char const * const apzSfx[] = { "tpl", "agl", NULL };
        if (! SUCCESSFUL(findFile(pzFileName, zRealFile, apzSfx, referrer))) {
            errno = ENOENT;
            AG_CANT("map data file", pzFileName);
        }
    }

    /*
     *  Make sure the specified file is a regular file.
     *  Make sure the output time stamp is at least as recent.
     */
    {
        struct stat stbf;
        if (stat(zRealFile, &stbf) != 0)
            AG_CANT("stat file", pzFileName);

        if (! S_ISREG(stbf.st_mode)) {
            errno = EINVAL;
            AG_CANT("not regular file", pzFileName);
        }

        if (outTime <= stbf.st_mtime)
            outTime = stbf.st_mtime + 1;
    }

    text_mmap(zRealFile, PROT_READ|PROT_WRITE, MAP_PRIVATE, &mapInfo);
    if (TEXT_MMAP_FAILED_ADDR(mapInfo.txt_data))
        AG_ABEND(aprf("Could not open template '%s'", zRealFile));

    if (pfDepends != NULL)
        append_source_name(zRealFile);

    /*
     *  Process the leading pseudo-macro.  The template proper
     *  starts immediately after it.
     */
    {
        tMacro    * pSaveMac = pCurMacro;
        tTemplate * pRes;
        pCurMacro = NULL;

        pRes = digest_pseudo_macro(&mapInfo, zRealFile);
        pCurMacro = pSaveMac;
        text_munmap(&mapInfo);

        return pRes;
    }
}
Exemplo n.º 2
0
/**
 *  This directive will insert definitions from another file into
 *  the current collection.  If the file name is adorned with
 *  double quotes or angle brackets (as in a C program), then the
 *  include is ignored.
 */
char *
doDir_include(directive_enum_t id, char const * dir, char * scan_next)
{
    static char const * const apzSfx[] = { DIRECT_INC_DEF_SFX, NULL };
    scan_ctx_t * new_ctx;
    size_t     inc_sz;
    char       full_name[ AG_PATH_MAX + 1 ];
    (void)id;

    dir = SPN_WHITESPACE_CHARS(dir);
    /*
     *  Ignore C-style includes.  This allows "C" files to be processed
     *  for their "#define"s.
     */
    if ((*dir == '"') || (*dir == '<'))
        return scan_next;

    if (! SUCCESSFUL(
            find_file(dir, full_name, apzSfx, cctx->scx_fname))) {
        errno = ENOENT;
        fswarn("search for", cctx->scx_fname);
        return scan_next;
    }

    /*
     *  Make sure the specified file is a regular file and we can get
     *  the correct size for it.
     */
    inc_sz = file_size(full_name);
    if (inc_sz == 0)
        return scan_next;

    /*
     *  Get the space for the output data and for context overhead.
     *  This is an extra allocation and copy, but easier than rewriting
     *  'loadData()' for this special context.
     */
    {
        size_t sz = sizeof(scan_ctx_t) + 4 + inc_sz;
        new_ctx = (scan_ctx_t *)AGALOC(sz, "inc def head");

        memset(VOIDP(new_ctx), 0, sz);
        new_ctx->scx_line = 1;
    }

    /*
     *  Link it into the context stack
     */
    cctx->scx_scan     = scan_next;
    new_ctx->scx_next  = cctx;
    cctx               = new_ctx;
    AGDUPSTR(new_ctx->scx_fname, full_name, "def file");

    new_ctx->scx_scan  =
    new_ctx->scx_data  =
    scan_next          = (char *)(new_ctx + 1);

    /*
     *  Read all the data.  Usually in a single read, but loop
     *  in case multiple passes are required.
     */
    {
        FILE * fp = fopen(full_name, "r" FOPEN_TEXT_FLAG);
        char * pz = scan_next;

        if (fp == NULL)
            AG_CANT(DIRECT_INC_CANNOT_OPEN, full_name);

        if (dep_fp != NULL)
            add_source_file(full_name);

        do  {
            size_t rdct = fread(VOIDP(pz), (size_t)1, inc_sz, fp);

            if (rdct == 0)
                AG_CANT(DIRECT_INC_CANNOT_READ, full_name);

            pz += rdct;
            inc_sz -= rdct;
        } while (inc_sz > 0);

        fclose(fp);
        *pz = NUL;
    }

    return scan_next;
}
Exemplo n.º 3
0
/**
 * Prepare the raft of environment variables.
 * This runs before Guile starts and grabs the value for LD_LIBRARY_PATH.
 * Guile likes to fiddle that.  When we run initialize(), we will force it
 * to match what we currently have.  Additionally, force our environment
 * to be "C" and export all the variables that describe our system.
 */
LOCAL void
prep_env(void)
{
    /*
     *  as of 2.0.2, Guile will fiddle with strings all on its own accord.
     *  Coerce the environment into being POSIX ASCII strings so it keeps
     *  its bloody stinking nose out of our data.
     */
    putenv(C(char *, LC_ALL_IS_C));

    /*
     *  If GUILE_WARN_DEPRECATED has not been defined, then likely we are
     *  not in a development environment and likely we don't want to give
     *  our users any angst.
     */
    if (getenv(GUILE_WARN_DEP_STR) == NULL)
        putenv(C(char *, GUILE_WARN_NO_ENV));

    ld_lib_path = getenv(LD_LIB_PATH_STR);
    if (ld_lib_path == NULL) {
        ld_lib_path = LD_LIB_PATH_PFX;

    } else {
        size_t psz = strlen(ld_lib_path) + 1;
        char * p = AGALOC(LD_LIB_PATH_PFX_LEN + psz, "lp");
        memcpy(p, LD_LIB_PATH_PFX, LD_LIB_PATH_PFX_LEN);
        memcpy(p + LD_LIB_PATH_PFX_LEN, ld_lib_path, psz);
        ld_lib_path = p;
    }

    /*
     *  Set the last resort search directories first (lowest priority)
     *  The lowest of the low is the config time install data dir.
     *  Next is the *current* directory of this executable.
     *  Last (highest priority) of the low priority is the library data dir.
     */
    SET_OPT_TEMPL_DIRS(DFT_TPL_DIR_DATA);
    SET_OPT_TEMPL_DIRS(DFT_TPL_DIR_RELATIVE);
    SET_OPT_TEMPL_DIRS(LIBDATADIR);

    {
        char z[ SCRIBBLE_SIZE+8 ] = "__autogen__";
#if defined(HAVE_SOLARIS_SYSINFO)
        static const int nm[] = {
            SI_SYSNAME, SI_HOSTNAME, SI_ARCHITECTURE, SI_HW_PROVIDER,
#ifdef      SI_PLATFORM
            SI_PLATFORM,
#endif
            SI_MACHINE };
        int  ix;
        long sz;

        add_sys_env(z);
        for (ix = 0; ix < sizeof(nm)/sizeof(nm[0]); ix++) {
            sz = sysinfo(nm[ix], z+2, sizeof(z) - 2);
            if (sz > 0) {
                sz += 2;
                while (z[sz-1] == NUL)  sz--;
                strcpy(z + sz, ADD_ENV_VARS_SUFFIX_FMT+2);
                add_sys_env(z);
            }
        }

#elif defined(HAVE_UNAME_SYSCALL)
        struct utsname unm;

        add_sys_env(z);
        if (uname(&unm) != 0)
            AG_CANT(UNAME_CALL_NAME, SYSCALL_NAME);

        if (snprintf(z+2, SCRIBBLE_SIZE, ADD_ENV_VARS_SUFFIX_FMT, unm.sysname)
            <= SCRIBBLE_SIZE)
            add_sys_env(z);

        if (snprintf(z+2, SCRIBBLE_SIZE, ADD_ENV_VARS_SUFFIX_FMT, unm.machine)
            <= SCRIBBLE_SIZE)
            add_sys_env(z);

        if (snprintf(z+2, SCRIBBLE_SIZE, ADD_ENV_VARS_SUFFIX_FMT, unm.nodename)
            <= SCRIBBLE_SIZE)
            add_sys_env(z);
#else

        add_sys_env(z);
#endif
    }
}
Exemplo n.º 4
0
/*=directive include
 *
 *  arg:  unadorned-file-name
 *
 *  text:
 *  This directive will insert definitions from another file into
 *  the current collection.  If the file name is adorned with
 *  double quotes or angle brackets (as in a C program), then the
 *  include is ignored.
=*/
static char*
doDir_include(char* pzArg, char* pzScan)
{
    static char const * apzSfx[] = { "def", NULL };
    tScanCtx*  pCtx;
    size_t     inclSize;
    char       zFullName[ AG_PATH_MAX + 1 ];

    /*
     *  Ignore C-style includes.  This allows "C" files to be processed
     *  for their "#define"s.
     */
    if ((*pzArg == '"') || (*pzArg == '<'))
        return pzScan;
    pCurCtx->pzScan  = pzScan;

    if (! SUCCESSFUL(
                findFile(pzArg, zFullName, apzSfx, pCurCtx->pzCtxFname))) {
        fprintf(pfTrace, "WARNING:  cannot find `%s' definitions file\n",
                pzArg);
        return pzScan;
    }

    /*
     *  Make sure the specified file is a regular file and we can get
     *  the correct size for it.
     */
    {
        struct stat stbf;
        if (stat(zFullName, &stbf) != 0) {
            fprintf(pfTrace, "WARNING %d (%s):  cannot stat `%s' "
                    "for include\n", errno, strerror(errno), zFullName);
            return pzScan;
        }
        if (! S_ISREG(stbf.st_mode)) {
            fprintf(pfTrace, "WARNING:  `%s' must be regular file to "
                    "include\n", zFullName);
            return pzScan;
        }
        inclSize = stbf.st_size;
        if (outTime <= stbf.st_mtime)
            outTime = stbf.st_mtime + 1;
    }

    if (inclSize == 0)
        return pzScan;

    /*
     *  Get the space for the output data and for context overhead.
     *  This is an extra allocation and copy, but easier than rewriting
     *  'loadData()' for this special context.
     */
    {
        size_t sz = sizeof(tScanCtx) + 4 + inclSize;
        pCtx = (tScanCtx*)AGALOC(sz, "include def header");

        memset((void*)pCtx, 0, sz);
        pCtx->lineNo = 1;
    }

    /*
     *  Link it into the context stack
     */
    pCtx->pCtx       = pCurCtx;
    pCurCtx          = pCtx;
    AGDUPSTR(pCtx->pzCtxFname, zFullName, "def file name");

    pCtx->pzScan     =
        pCtx->pzData     =
            pzScan           = (char*)(pCtx + 1);

    /*
     *  Read all the data.  Usually in a single read, but loop
     *  in case multiple passes are required.
     */
    {
        FILE*  fp = fopen(zFullName, "r" FOPEN_TEXT_FLAG);
        char*  pz = pzScan;

        if (fp == NULL)
            AG_CANT("open file", zFullName);

        if (pfDepends != NULL)
            append_source_name(zFullName);

        do  {
            size_t rdct = fread((void*)pz, (size_t)1, inclSize, fp);

            if (rdct == 0)
                AG_CANT("read file", zFullName);

            pz += rdct;
            inclSize -= rdct;
        } while (inclSize > 0);

        fclose(fp);
        *pz = NUL;
    }

    return pzScan;
}
Exemplo n.º 5
0
/**
 *  Suck in the entire definitions file and parse it.
 */
LOCAL void
readDefines(void)
{
    char const *  pzDefFile;
    char *        pzData;
    size_t        dataSize;
    size_t        sizeLeft;
    FILE *        fp;
    def_input_mode_t in_mode = ready_input(&pzDefFile, &dataSize);

    if (in_mode == INPUT_DONE)
        return;

    /*
     *  Allocate the space we need for our definitions.
     */
    sizeLeft = dataSize+4+sizeof(*pBaseCtx);
    pBaseCtx = (tScanCtx*)AGALOC(sizeLeft, "file buffer");
    memset((void*)pBaseCtx, 0, sizeLeft);
    pBaseCtx->lineNo = 1;
    sizeLeft = dataSize;

    /*
     *  Our base context will have its currency pointer set to this
     *  input.  It is also a scanning pointer, but since this buffer
     *  is never deallocated, we do not have to remember the initial
     *  value.  (It may get reallocated here in this routine, tho...)
     */
    pzData =
        pBaseCtx->pzScan =
            pBaseCtx->pzData = (char*)(pBaseCtx+1);
    pBaseCtx->pCtx = NULL;

    /*
     *  Set the input file pointer, as needed
     */
    if (in_mode == INPUT_STDIN)
        fp = stdin;

    else {
        fp = fopen(pzDefFile, "r" FOPEN_TEXT_FLAG);
        if (fp == NULL)
            AG_CANT("open", pzDefFile);

        if (pfDepends != NULL)
            append_source_name(pzDefFile);
    }

    /*
     *  Read until done...
     */
    for (;;) {
        size_t rdct = fread((void*)pzData, (size_t)1, sizeLeft, fp);

        /*
         *  IF we are done,
         */
        if (rdct == 0) {
            /*
             *  IF it is because we are at EOF, then break out
             *  ELSE abend.
             */
            if (feof(fp) || (in_mode == INPUT_STDIN))
                break;

            AG_CANT("read", pzDefFile);
        }

        /*
         *  Advance input pointer, decrease remaining count
         */
        pzData   += rdct;
        sizeLeft -= rdct;

        /*
         *  See if there is any space left
         */
        if (sizeLeft == 0) {
            tScanCtx* p;
            off_t dataOff;

            /*
             *  IF it is a regular file, then we are done
             */
            if (in_mode != INPUT_STDIN)
                break;

            /*
             *  We have more data and we are out of space.
             *  Try to reallocate our input buffer.
             */
            dataSize += (sizeLeft = 0x1000);
            dataOff = pzData - pBaseCtx->pzData;
            p = AGREALOC((void*)pBaseCtx, dataSize+4+sizeof(*pBaseCtx),
                         "expanded file buffer");

            /*
             *  The buffer may have moved.  Set the data pointer at an
             *  offset within the new buffer and make sure our base pointer
             *  has been corrected as well.
             */
            if (p != pBaseCtx) {
                p->pzScan = \
                            p->pzData = (char*)(p+1);
                pzData = p->pzData + dataOff;
                pBaseCtx = p;
            }
        }
    }

    if (pzData == pBaseCtx->pzData)
        AG_ABEND("No definition data were read");

    *pzData = NUL;
    AGDUPSTR(pBaseCtx->pzCtxFname, pzDefFile, "def file name");
    manageAllocatedData(pBaseCtx);
    manageAllocatedData((void*)pBaseCtx->pzCtxFname);

    /*
     *  Close the input file, parse the data
     *  and alphabetically sort the definition tree contents.
     */
    if (in_mode != INPUT_STDIN)
        fclose(fp);

    pCurCtx = pBaseCtx;
    dp_run_fsm();
}
Exemplo n.º 6
0
/**
 * figure out which file descriptor to use for reading definitions.
 */
static def_input_mode_t
ready_input(char const ** ppzfile, size_t * psz)
{
    struct stat stbf;

    if (! ENABLED_OPT(DEFINITIONS)) {
        pBaseCtx = (tScanCtx*)AGALOC(sizeof(tScanCtx), "scan context");
        memset((void*)pBaseCtx, 0, sizeof(tScanCtx));
        pBaseCtx->lineNo     = 1;
        pBaseCtx->pzCtxFname = "@@ No-Definitions @@";
        manageAllocatedData(pBaseCtx);

        if (! ENABLED_OPT(SOURCE_TIME))
            outTime = time(NULL);
        return INPUT_DONE;
    }

    *ppzfile = OPT_ARG(DEFINITIONS);

    if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
        fprintf(pfTrace, "Definition Load:\n");

    /*
     *  Check for stdin as the input file.  We use the current time
     *  as the modification time for stdin.  We also note it so we
     *  do not try to open it and we try to allocate more memory if
     *  the stdin input exceeds our initial allocation of 16K.
     */
    if (strcmp(*ppzfile, "-") == 0) {
        *ppzfile = OPT_ARG(DEFINITIONS) = "stdin";
        if (getenv("REQUEST_METHOD") != NULL) {
            loadCgi();
            pCurCtx = pBaseCtx;
            dp_run_fsm();
            return INPUT_DONE;
        }

accept_fifo:
        outTime  = time(NULL);
        *psz = 0x4000 - (4+sizeof(*pBaseCtx));
        return INPUT_STDIN;
    }

    /*
     *  This, then, must be a regular file.  Make sure of that and
     *  find out how big it was and when it was last modified.
     */
    if (stat(*ppzfile, &stbf) != 0)
        AG_CANT("stat", *ppzfile);

    if (! S_ISREG(stbf.st_mode)) {
        if (S_ISFIFO(stbf.st_mode))
            goto accept_fifo;

        errno = EINVAL;
        AG_CANT("open non-regular file", *ppzfile);
    }

    /*
     *  IF the source-time option has been enabled, then
     *  our output file mod time will start as one second after
     *  the mod time on this file.  If any of the template files
     *  are more recent, then it will be adjusted.
     */
    *psz = stbf.st_size;

    if (ENABLED_OPT(SOURCE_TIME))
        outTime = stbf.st_mtime + 1;
    else outTime = time(NULL);

    return INPUT_FILE;
}