Esempio n. 1
0
/*=macfunc UNKNOWN
 *
 *  what:  Either a user macro or a value name.
 *  handler_proc:
 *  load_proc:
 *  unnamed:
 *
 *  desc:
 *
 *  The macro text has started with a name not known to AutoGen.  If, at run
 *  time, it turns out to be the name of a defined macro, then that macro is
 *  invoked.  If it is not, then it is a conditional expression that is
 *  evaluated only if the name is defined at the time the macro is invoked.
 *
 *  You may not specify @code{UNKNOWN} explicitly.
=*/
tMacro*
mFunc_Unknown(tTemplate* pT, tMacro* pMac)
{
    tTemplate * pInv = findTemplate(pT->pzTemplText + pMac->ozName);
    if (pInv != NULL) {
        if (OPT_VALUE_TRACE >= TRACE_EVERYTHING)
            fprintf(pfTrace, TRACE_FN_REMAPPED, TRACE_FN_REMAP_INVOKE,
                    pMac->funcCode, pT->pzTplFile, pMac->lineNo);
        pMac->funcCode    = FTYP_DEFINE;
        pMac->funcPrivate = (void*)pInv;
        parseMacroArgs(pT, pMac);
        return mFunc_Define(pT, pMac);
    }

    if (OPT_VALUE_TRACE >= TRACE_EVERYTHING) {
        fprintf(pfTrace, TRACE_FN_REMAPPED, TRACE_FN_REMAP_EXPR,
                pMac->funcCode, pT->pzTplFile, pMac->lineNo);
        fprintf(pfTrace, TRACE_FN_REMAP_BASE, pT->pzTemplText + pMac->ozName);
    }

    pMac->funcCode = FTYP_EXPR;
    if (pMac->ozText == 0) {
        pMac->res = EMIT_VALUE;

    } else {
        char* pzExpr = pT->pzTemplText + pMac->ozText;
        switch (*pzExpr) {
        case ';':
        case '(':
            pMac->res = EMIT_EXPRESSION;
            break;

        case '`':
            pMac->res = EMIT_SHELL;
            spanQuote(pzExpr);
            break;

        case '"':
        case '\'':
            spanQuote(pzExpr);
            /* FALLTHROUGH */

        default:
            pMac->res = EMIT_STRING;
        }

        if (OPT_VALUE_TRACE >= TRACE_EVERYTHING)
            fprintf(pfTrace, TRACE_UNKNOWN_FMT, pMac->res, pzExpr);
    }

    return mFunc_Expr(pT, pMac);
}
Esempio n. 2
0
/*=macfunc SELECT
 *
 *  what:    Selection block for CASE function
 *  in-context:
 *  alias:   | ~ | = | * | ! | + |
 *  unload-proc:
 *
 *  desc:
 *    This macro selects a block of text by matching an expression
 *    against the sample text expression evaluated in the @code{CASE}
 *    macro.  @xref{CASE}.
 *
 *    You do not specify a @code{SELECT} macro with the word ``select''.
 *    Instead, you must use one of the 19 match operators described in
 *    the @code{CASE} macro description.
=*/
static tMacro*
mLoad_Select(tTemplate * pT, tMacro* pMac, char const ** ppzScan)
{
    char const *  pzScan = *ppzScan;  /* text after macro */
    char*         pzCopy = pT->pNext; /* next text dest   */
    char const *  pzSrc  = (char*)pMac->ozText; /* macro text */
    long          srcLen = pMac->res;           /* macro len  */

    static char const zInvSel[] = "Invalid selection clause";
    int  typ       = (int)FTYP_SELECT_COMPARE_FULL;

    /*
     *  Set the global macro loading mode
     */
    papLoadProc = apCaseLoad;
    pMac->res   = 0;
    if (srcLen == 0)
        AG_ABEND_IN(pT, pMac, "Empty macro text");

    /*
     *  IF the first character is an asterisk,
     *  THEN the match can start anywhere in the string
     */
    if (*pzSrc == '*') {
        pzSrc++;
        if (IS_WHITESPACE_CHAR(*pzSrc) || (*pzSrc == NUL)) {
            typ    = (int)FTYP_SELECT_MATCH_ANYTHING;
            srcLen = 0;
            pMac->ozText = 0;
            goto selection_done;
        }

        typ |= (int)FTYP_SELECT_COMPARE_SKP_START;
    }

    /*
     *  The next character must indicate whether we are
     *  pattern matching ('~') or doing string compares ('=')
     */
    switch (*pzSrc++) {
    case '~':
        /*
         *  Or in the pattern matching bit
         */
        typ |= (int)FTYP_SELECT_MATCH_FULL;
        pMac->res = REG_EXTENDED;
        /* FALLTHROUGH */

    case '=':
        /*
         *  IF the '~' or '=' is doubled,
         *  THEN it is a case sensitive match.  Skip over the char.
         *  ELSE or in the case insensitive bit
         */
        if (pzSrc[0] == pzSrc[-1]) {
            pzSrc++;
        } else {
            typ |= (int)FTYP_SELECT_EQUIVALENT_FULL;
        }
        break;

    case '!':
    case '+':
        switch (*pzSrc) {
        case 'e':
        case 'E':
            break;
        default:
            goto bad_sel;
        }
        if ((pzSrc[1] != NUL) && (! IS_WHITESPACE_CHAR(pzSrc[1])))
            goto bad_sel;

        typ = (int)((pzSrc[-1] == '!')
            ? FTYP_SELECT_MATCH_NONEXISTENCE : FTYP_SELECT_MATCH_EXISTENCE);
        srcLen = 0;
        pMac->ozText = 0;
        goto selection_done;

    default:
    bad_sel:
        AG_ABEND_IN(pT, pMac, zInvSel);
    }

    /*
     *  IF the last character is an asterisk,
     *  THEN the match may end before the test string ends.
     *       OR in the "may end early" bit.
     */
    if (*pzSrc == '*') {
        pzSrc++;
        typ |= (int)FTYP_SELECT_COMPARE_SKP_END;
    }

    if (! IS_WHITESPACE_CHAR(*pzSrc))
        AG_ABEND_IN(pT, pMac, zInvSel);

    while (IS_WHITESPACE_CHAR(*pzSrc)) pzSrc++;
    srcLen -= pzSrc - (char const *)pMac->ozText;
    if (srcLen <= 0)
        AG_ABEND_IN(pT, pMac, zInvSel);

    /*
     *  See if we are doing case insensitive regular expressions
     */
    if (  (typ & (int)FTYP_SELECT_EQV_MATCH_FULL)
       == (int)FTYP_SELECT_EQV_MATCH_FULL) {
        int  bitSet;
        pMac->res = REG_EXTENDED | REG_ICASE;

        /*
         *  Turn off the case comparison mode for regular expressions.
         *  We don't have to worry about it.  It is done for us.
         */
        bitSet  = ~(int)FTYP_SELECT_EQUIVALENT_FULL;
        bitSet |= (int)FTYP_SELECT_COMPARE_FULL; /* dont turn this bit off! */
        typ    &= bitSet;
    }

    /*
     *  Copy the expression
     */
    pzScan = pzCopy;
    pMac->ozText = (pzCopy - pT->pzTemplText);
    if (typ == (int)FTYP_SELECT_EQUIVALENT) {
        do  {
            *(pzCopy++) = toupper(*(pzSrc++));
        } while (--srcLen > 0);
    } else {
        do  {
            *(pzCopy++) = *(pzSrc++);
        } while (--srcLen > 0);
    }
    *(pzCopy++) = NUL;
    *(pzCopy++) = NUL;
    pT->pNext = pzCopy;

    if ((*pzScan == '"') || (*pzScan == '\'')) {
        void * ptr = (void *)pzScan;
        spanQuote(ptr);
    }

 selection_done:
    pMac->funcCode = (teFuncType)typ;

    current_case.pSelect->sibIndex = (pMac - pT->aMacros);
    current_case.pSelect = (tMacro*)pMac;

    return pMac + 1;
}