コード例 #1
0
/*=gfunc find_file
 *
 * what:   locate a file in the search path
 * exparg: file-name,  name of file with text
 * exparg: @suffix  @  file suffix to try, too   @ opt @
 *
 * doc:
 *
 * AutoGen has a search path that it uses to locate template and definition
 * files.  This function will search the same list for @file{file-name}, both
 * with and without the @file{.suffix}, if provided.
=*/
SCM
ag_scm_find_file(SCM file, SCM suffix)
{
    SCM res = SCM_UNDEFINED;

    if (! AG_SCM_STRING_P(file))
        scm_wrong_type_arg(FIND_FILE_NAME, 1, file);

    {
        char z[ AG_PATH_MAX+1 ];
        char const * pz = ag_scm2zchars(file, "file-name");

        /*
         *  The suffix is optional.  If provided, it will be a string.
         */
        if (AG_SCM_STRING_P(suffix)) {
            char* apz[2];
            apz[0] = (char *)ag_scm2zchars(suffix, "file suffix");
            apz[1] = NULL;
            if (SUCCESSFUL(findFile(pz, z, (char const **)apz, NULL)))
                res = AG_SCM_STR02SCM(z);

        } else if (SUCCESSFUL(findFile(pz, z, NULL, NULL)))
            res = AG_SCM_STR02SCM(z);
    }

    return res;
}
コード例 #2
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc tpl_file
 *
 * what:   get the template file name
 *
 * exparg: full_path, include full path to file, optonal
 *
 * doc:  Returns the name of the current template file.
 *       If @code{#t} is passed in as an argument, then the template
 *       file is hunted for in the template search path.  Otherwise,
 *       just the unadorned name.
=*/
SCM
ag_scm_tpl_file(SCM full)
{
    if (AG_SCM_BOOL_P(full) && AG_SCM_NFALSEP(full)) {
        static char const * const sfx[] = { "tpl", NULL };

        char z[AG_PATH_MAX];
        if (SUCCESSFUL(findFile(pzTemplFileName, z, sfx, NULL)))
            return AG_SCM_STR02SCM(z);
    }

    return AG_SCM_STR02SCM((char*)(void*)pzTemplFileName);
}
コード例 #3
0
ファイル: expString.c プロジェクト: Distrotech/autogen
/*=gfunc stack
 *
 * what:  make list of AutoGen values
 *
 * exparg: ag-name, AutoGen value name
 *
 * doc:  Create a scheme list of all the strings that are associated
 *       with a name.  They must all be text values or we choke.
=*/
SCM
ag_scm_stack(SCM obj)
{
    SCM          res;
    SCM *        pos = &res;
    def_ent_t ** ppDE;
    def_ent_t *  pDE;
    SCM          str;

    res = SCM_EOL;

    ppDE = find_def_ent_list(ag_scm2zchars(obj, "AG Object"));
    if (ppDE == NULL)
        return SCM_EOL;

    for (;;) {
        pDE = *(ppDE++);

        if (pDE == NULL)
            break;

        if (pDE->de_type != VALTYP_TEXT)
            return SCM_UNDEFINED;

        str  = AG_SCM_STR02SCM(pDE->de_val.dvu_text);
        *pos = scm_cons(str, SCM_EOL);
        pos  = SCM_CDRLOC(*pos);
    }

    return res;
}
コード例 #4
0
/*=gfunc stack
 *
 * what:  make list of AutoGen values
 *
 * exparg: ag-name, AutoGen value name
 *
 * doc:  Create a scheme list of all the strings that are associated
 *       with a name.  They must all be text values or we choke.
=*/
SCM
ag_scm_stack(SCM obj)
{
    SCM         res;
    SCM *       pos = &res;
    tDefEntry** ppDE;
    tDefEntry*  pDE;
    SCM         str;

    res = SCM_EOL;

    ppDE = findEntryList(ag_scm2zchars(obj, "AG Object"));
    if (ppDE == NULL)
        return SCM_EOL;

    for (;;) {
        pDE = *(ppDE++);

        if (pDE == NULL)
            break;

        if (pDE->valType != VALTYP_TEXT)
            return SCM_UNDEFINED;

        str  = AG_SCM_STR02SCM(pDE->val.pzText);
        *pos = scm_cons(str, SCM_EOL);
        pos  = SCM_CDRLOC(*pos);
    }

    return res;
}
コード例 #5
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc get
 *
 * what:   get named value
 *
 * exparg: ag-name, name of AutoGen value
 * exparg: alt-val, value if not present, optional
 *
 * doc:
 *  Get the first string value associated with the name.
 *  It will either return the associated string value (if
 *  the name resolves), the alternate value (if one is provided),
 *  or else the empty string.
=*/
SCM
ag_scm_get(SCM agName, SCM altVal)
{
    tDefEntry*  pE;
    ag_bool     x;

    if (! AG_SCM_STRING_P(agName))
         pE = NULL;
    else pE = findDefEntry(ag_scm2zchars(agName, "ag value"), &x);

    if ((pE == NULL) || (pE->valType != VALTYP_TEXT)) {
        if (AG_SCM_STRING_P(altVal))
            return altVal;
        return AG_SCM_STR02SCM(zNil);
    }

    return AG_SCM_STR02SCM(pE->val.pzText);
}
コード例 #6
0
ファイル: expString.c プロジェクト: Distrotech/autogen
/*=gfunc c_string
 *
 * what:  emit string for ANSI C
 * general_use:
 *
 * exparg: string, string to reformat
 *
 * doc:
 *  Reform a string so that, when printed, the C compiler will be able to
 *  compile the data and construct a string that contains exactly what the
 *  current string contains.  Many non-printing characters are replaced with
 *  escape sequences.  Newlines are replaced with a backslash, an @code{n}, a
 *  closing quote, a newline, seven spaces and another re-opening quote.  The
 *  compiler will implicitly concatenate them.  The reader will see line
 *  breaks.
 *
 *  A K&R compiler will choke.  Use @code{kr-string} for that compiler.
 *
=*/
SCM
ag_scm_c_string(SCM str)
{
    char const * pz = ag_scm2zchars(str, "cstr");
    SCM res;
    pz  = optionQuoteString(pz, C_STRING_NEWLINE);
    res = AG_SCM_STR02SCM(pz);
    AGFREE(pz);
    return res;
}
コード例 #7
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/**
 * guts of the template file/line functions
 */
static SCM
do_tpl_file_line(int line_delta, char const * fmt)
{
    void * args[2] = {
        [0] = (void*)pCurTemplate->pzTplFile,
        [1] = (void*)((long)pCurMacro->lineNo + line_delta)
    };
    char * buf = strrchr(args[0], DIRCH);
    if (buf != NULL)
        args[0] = buf + 1;

    {
        size_t sz = strlen(fmt) + strlen(args[0]) + 24;
        buf = ag_scribble(sz);
    }

    sprintfv(buf, fmt, (snv_constpointer*)args);
    return AG_SCM_STR02SCM(buf);
}
コード例 #8
0
/**
 *  Could not find the file or could not find the markers.
 *  Either way, emit an empty enclosure.
 */
static SCM
mk_empty_text(char const* pzStart, char const* pzEnd, SCM def)
{
    size_t mlen = strlen(pzStart) + strlen(pzEnd) + 3;
    char* pzOut;

    if (! AG_SCM_STRING_P(def)) {
        pzOut = ag_scribble(mlen);
        sprintf(pzOut, LINE_CONCAT3_FMT+3, pzStart, pzEnd);

    } else {
        char const * pzDef = ag_scm2zchars(def, "dft extr str");
        mlen += AG_SCM_STRLEN(def) + 1;
        pzOut = ag_scribble(mlen);
        sprintf(pzOut, LINE_CONCAT3_FMT, pzStart, pzDef, pzEnd);
    }

    return AG_SCM_STR02SCM(pzOut);
}
コード例 #9
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc def_file_line
 *
 * what:   get a definition file+line number
 *
 * exparg: ag-name, name of AutoGen value
 * exparg: msg-fmt, formatting for line message, optional
 *
 * doc:
 *  Returns the file and line number of a AutoGen defined value, using
 *  either the default format, "from %s line %d", or else the format you
 *  supply.  For example, if you want to insert a "C" language file-line
 *  directive, you would supply the format "# %2$d \"%1$s\"", but that
 *  is also already supplied with the scheme variable
 *  @xref{SCM c-file-line-fmt}.  You may use it thus:
 *
 *  @example
 *  (def-file-line "ag-def-name" c-file-line-fmt)
 *  @end example
 *
 *  It is also safe to use the formatting string, "%2$d".  AutoGen uses
 *  an argument vector version of printf: @xref{snprintfv}.
=*/
SCM
ag_scm_def_file_line(SCM obj, SCM fmt)
{
    static char const zFmt[]  = "from %s line %d";
    char const * pzFmt = zFmt;
    char * buf;
    ag_bool     x;

    tDefEntry * pE = findDefEntry(ag_scm2zchars(obj, "ag value"), &x);

    /*
     *  IF we did not find the entry we are looking for
     *  THEN return UNDEFINED
     */
    if (pE == NULL)
        return SCM_UNDEFINED;

    if (AG_SCM_STRING_P(fmt))
        pzFmt = ag_scm2zchars(fmt, "file/line format");

    {
        void * args[2] = {
            (void*)pE->pzSrcFile,
            (void*)(long)pE->srcLineNum
        };
        size_t maxlen;

        buf = strrchr(args[0], DIRCH);
        if (buf != NULL)
            args[0] = buf + 1;

        maxlen = strlen(args[0]) + strlen(pzFmt) + LOG10_2to32 + 1;
        buf = ag_scribble(maxlen);
        sprintfv(buf, pzFmt, (snv_constpointer*)args);
    }

    return AG_SCM_STR02SCM(buf);
}
コード例 #10
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc suffix
 *
 * what:   get the current suffix
 *
 * doc:
 *  Returns the current active suffix (@pxref{pseudo macro}).
=*/
SCM
ag_scm_suffix(void)
{
    return AG_SCM_STR02SCM((char*)pzCurSfx);
}
コード例 #11
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc def_file
 *
 * what:   definitions file name
 *
 * doc:  Get the name of the definitions file.
 *       Returns the name of the source file containing the AutoGen
 *       definitions.
=*/
SCM
ag_scm_def_file(void)
{
    return AG_SCM_STR02SCM((char*)(void*)pBaseCtx->pzCtxFname);
}
コード例 #12
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/*=gfunc base_name
 *
 * what:   base output name
 *
 * doc:  Returns a string containing the base name of the output file(s).
 *       Generally, this is also the base name of the definitions file.
=*/
SCM
ag_scm_base_name(void)
{
    return AG_SCM_STR02SCM((char*)(void*)OPT_ARG(BASE_NAME));
}
コード例 #13
0
ファイル: expState.c プロジェクト: pexip/os-autogen
/**
 * Find a definition with a specific value
 */
static SCM
find_entry_value(SCM op, SCM obj, SCM test)
{
    static char const zFailed[] = "failed\n";
    static char const zSucc[]   = "SUCCESS\n";

    ag_bool     isIndexed;
    tDefEntry*  pE;
    char*       pzField;

    {
        char * name = ag_scm2zchars(obj, "find name");

        if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
            fprintf(pfTrace, " in \"%s\" -- ", name);

        pzField = strchr(name, name_sep_ch);
        if (pzField != NULL)
            *(pzField++) = NUL;

        pE = findDefEntry(name, &isIndexed);
    }

    /*
     *  No such entry?  return FALSE
     */
    if (pE == NULL) {
        if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
            fputs(zFailed, pfTrace);
        return SCM_BOOL_F;
    }

    /*
     *  No subfield?  Check the values
     */
    if (pzField == NULL) {
        SCM result;
        SCM field;
        if (pE->valType != VALTYP_TEXT) {
            if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
                fputs(zFailed, pfTrace);
            return SCM_BOOL_F; /* Cannot match string -- not a text value */
        }

        field  = AG_SCM_STR02SCM(pE->val.pzText);
        result = AG_SCM_APPLY2(op, field, test);
        if (! isIndexed)
            while (result == SCM_BOOL_F) {

                pE = pE->pTwin;
                if (pE == NULL)
                    break;

                field = AG_SCM_STR02SCM(pE->val.pzText);
                result = AG_SCM_APPLY2(op, field, test);
            }

        if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
            fputs((result == SCM_BOOL_T) ? zSucc : zFailed, pfTrace);
        return result;
    }

    /*
     *  a subfield for a text macro?  return FALSE
     */
    if (pE->valType == VALTYP_TEXT) {
        if (OPT_VALUE_TRACE >= TRACE_EXPRESSIONS)
            fputs(zFailed, pfTrace);
        return SCM_BOOL_F;
    }

    /*
     *  Search the members for what we want.
     */
    pzField[-1] = name_sep_ch;
    {
        SCM field   = AG_SCM_STR02SCM(pzField);
        SCM result;
        tDefCtx ctx = currDefCtx;

        currDefCtx.pPrev = &ctx;
        currDefCtx.pDefs = pE->val.pDefEntry;

        result = find_entry_value(op, field, test);

        if (! isIndexed)
            while (result == SCM_BOOL_F) {

                pE = pE->pTwin;
                if (pE == NULL)
                    break;

                currDefCtx.pDefs = pE->val.pDefEntry;
                result = find_entry_value(op, field, test);
            }

        currDefCtx = ctx;
        return result;
    }
}
コード例 #14
0
ファイル: expString.c プロジェクト: Distrotech/autogen
/*=gfunc raw_shell_str
 *
 * what:  single quote shell string
 * general_use:
 *
 * exparg: string, string to transform
 *
 * doc:
 *  Convert the text of the string into a singly quoted string
 *  that a normal shell will process into the original string.
 *  (It will not do macro expansion later, either.)
 *  Contained single quotes become tripled, with the middle quote
 *  escaped with a backslash.  Normal shells will reconstitute the
 *  original string.
 *
 *  @strong{Notice}:  some shells will not correctly handle unusual
 *  non-printing characters.  This routine works for most reasonably
 *  conventional ASCII strings.
=*/
SCM
ag_scm_raw_shell_str(SCM obj)
{
    char * data;
    char * pz;
    char * pzFree;

    data = ag_scm2zchars(obj, "AG Object");

    {
        size_t dtaSize = AG_SCM_STRLEN(obj) + 3; /* NUL + 2 quotes */
        pz = data-1;
        for (;;) {
            pz = strchr(pz+1, '\'');
            if (pz == NULL)
                break;
            dtaSize += 3; /* '\'' -> 3 additional chars */
        }

        pzFree = pz = AGALOC(dtaSize + 2, "raw string");
    }

    /*
     *  Handle leading single quotes before starting the first quote.
     */
    while (*data == '\'') {
        *(pz++) = '\\';
        *(pz++) = '\'';

        /*
         *  IF pure single quotes, then we're done.
         */
        if (*++data == NUL) {
            *pz = NUL;
            goto returnString;
        }
    }

    /*
     *  Start quoting.  If the string is empty, we wind up with two quotes.
     */
    *(pz++) = '\'';

    for (;;) {
        switch (*(pz++) = *(data++)) {
        case NUL:
            goto loopDone;

        case '\'':
            /*
             *  We've inserted a single quote, which ends the quoting session.
             *  Now, insert escaped quotes for every quote char we find, then
             *  restart the quoting.
             */
            data--;
            do {
                *(pz++) = '\\';
                *(pz++) = '\'';
            } while (*++data == '\'');
            if (*data == NUL) {
                *pz = NUL;
                goto returnString;
            }
            *(pz++) = '\'';
        }
    } loopDone:;
    pz[-1] = '\'';
    *pz    = NUL;

 returnString:
    {
        SCM res = AG_SCM_STR02SCM(pzFree);
        AGFREE(pzFree);
        return res;
    }
}
コード例 #15
0
ファイル: expString.c プロジェクト: Distrotech/autogen
/*=gfunc join
 *
 * what:   join string list with separator
 * general_use:
 * exparg: separator, string to insert between entries
 * exparg: list, list of strings to join,, list
 *
 * doc:  With the first argument as the separator string,
 *       joins together an a-list of strings into one long string.
 *       The list may contain nested lists, partly because you
 *       cannot always control that.
=*/
SCM
ag_scm_join(SCM sep, SCM list)
{
    int      l_len, sv_l_len;
    SCM      car;
    SCM      alist = list;
    size_t   sep_len;
    size_t   str_len;
    char *   pzRes;
    char const * pzSep;
    char *   pzScan;

    if (! AG_SCM_STRING_P(sep))
        return SCM_UNDEFINED;

    sv_l_len = l_len = (int)scm_ilength(list);
    if (l_len == 0)
        return AG_SCM_STR02SCM(zNil);

    pzSep   = scm_i_string_chars(sep);
    sep_len = AG_SCM_STRLEN(sep);
    str_len = 0;

    /*
     *  Count up the lengths of all the strings to be joined.
     */
    for (;;) {
        car  = SCM_CAR(list);
        list = SCM_CDR(list);

        /*
         *  This routine is listed as getting a list as the second
         *  argument.  That means that if someone builds a list and
         *  hands it to us, it magically becomes a nested list.
         *  This unravels that.
         */
        if (! AG_SCM_STRING_P(car)) {
            if (car != SCM_UNDEFINED)
                car = ag_scm_join(sep, car);
            if (! AG_SCM_STRING_P(car))
                return SCM_UNDEFINED;
        }

        str_len += AG_SCM_STRLEN(car);

        if (--l_len <= 0)
            break;

        str_len += sep_len;
    }

    l_len = sv_l_len;
    pzRes = pzScan = scribble_get((ssize_t)str_len);

    /*
     *  Now, copy each one into the output
     */
    for (;;) {
        size_t cpy_len;

        car   = SCM_CAR(alist);
        alist = SCM_CDR(alist);

        /*
         *  This unravels nested lists.
         */
        if (! AG_SCM_STRING_P(car))
            car = ag_scm_join(sep, car);

        cpy_len = AG_SCM_STRLEN(car);
        memcpy(VOIDP(pzScan), scm_i_string_chars(car), cpy_len);
        pzScan += cpy_len;

        /*
         *  IF we reach zero, then do not insert a separation and bail out
         */
        if (--l_len <= 0)
            break;
        memcpy(VOIDP(pzScan), VOIDP(pzSep), sep_len);
        pzScan += sep_len;
    }

    return AG_SCM_STR2SCM(pzRes, str_len);
}
コード例 #16
0
static SCM
makeString(char const * pzText, char const * pzNewLine, size_t newLineSize)
{
    char     z[SCRIBBLE_SIZE];
    char*    pzDta;
    char*    pzFre;
    char const * pzScn   = pzText;
    size_t   dtaSize = string_size(pzText, newLineSize);

    /*
     *  We now know how big the string is going to be.
     *  Allocate what we need.
     */
    if (dtaSize >= sizeof(z))
         pzFre = pzDta = AGALOC(dtaSize, "quoting string");
    else pzFre = pzDta = z;

    *(pzDta++) = '"';

    for (;;) {
        unsigned char ch = (unsigned char)*pzScn;
        if ((ch >= ' ') && (ch <= '~')) {
            if ((ch == '"') || (ch == '\\'))
                /*
                 *  We must escape these characters in the output string
                 */
                *(pzDta++) = '\\';
            *(pzDta++) = ch;

        } else switch (ch) {
        case NUL:
            goto copyDone;

        case NL:
            /*
             *  place contiguous new-lines on a single line
             */
            while (pzScn[1] == NL) {
                *(pzDta++) = '\\';
                *(pzDta++) = 'n';
                pzScn++;
            }

            /*
             *  Replace the new-line with its escaped representation.
             *  Also, break and restart the output string, indented
             *  7 spaces (so that after the '"' char is printed,
             *  any contained tabbing will look correct).
             *  Do *not* start a new line if there are no more data.
             */
            if (pzScn[1] == NUL) {
                *(pzDta++) = '\\';
                *(pzDta++) = 'n';
                goto copyDone;
            }

            strcpy(pzDta, pzNewLine);
            pzDta += newLineSize;
            break;

        case '\a':
            *(pzDta++) = '\\';
            *(pzDta++) = 'a';
            break;

        case '\b':
            *(pzDta++) = '\\';
            *(pzDta++) = 'b';
            break;

        case '\f':
            *(pzDta++) = '\\';
            *(pzDta++) = 'f';
            break;

        case '\r':
            *(pzDta++) = '\\';
            *(pzDta++) = 'r';
            break;

        case TAB:
            *(pzDta++) = '\\';
            *(pzDta++) = 't';
            break;

        case '\v':
            *(pzDta++) = '\\';
            *(pzDta++) = 'v';
            break;

        default:
            /*
             *  sprintf is safe here, because we already computed
             *  the amount of space we will be using.
             */
            sprintf(pzDta, MK_STR_OCT_FMT, ch);
            pzDta += 4;
        }

        pzScn++;
    } copyDone:

    /*
     *  End of string.  Terminate the quoted output.
     *  If necessary, deallocate the text string.
     *  Return the scan resumption point.
     */
    *(pzDta++) = '"';
    *pzDta = NUL;

    {
        SCM res = AG_SCM_STR02SCM(pzFre);
        if (pzFre != z)
            AGFREE(pzFre);
        return res;
    }
}