/*=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); }
/*=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; }