|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* @file functions.c
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* This module implements text functions.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @addtogroup autogen
|
|
Packit Service |
96b5d3 |
* @{
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* This file is part of AutoGen.
|
|
Packit Service |
96b5d3 |
* AutoGen Copyright (C) 1992-2016 by Bruce Korb - all rights reserved
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* AutoGen is free software: you can redistribute it and/or modify it
|
|
Packit Service |
96b5d3 |
* under the terms of the GNU General Public License as published by the
|
|
Packit Service |
96b5d3 |
* Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
96b5d3 |
* (at your option) any later version.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* AutoGen is distributed in the hope that it will be useful, but
|
|
Packit Service |
96b5d3 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
96b5d3 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit Service |
96b5d3 |
* See the GNU General Public License for more details.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* You should have received a copy of the GNU General Public License along
|
|
Packit Service |
96b5d3 |
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc CONTINUE
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* handler-proc: Break
|
|
Packit Service |
96b5d3 |
* load-proc: Leave
|
|
Packit Service |
96b5d3 |
* what: Skip to end of a FOR or WHILE macro.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
* This will skip the remainder of the loop and start the next.
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc BREAK
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* handler-proc: Break
|
|
Packit Service |
96b5d3 |
* load-proc: Leave
|
|
Packit Service |
96b5d3 |
* what: Leave a FOR or WHILE macro
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
* This will unwind the loop context and resume after ENDFOR/ENDWHILE.
|
|
Packit Service |
96b5d3 |
* Note that unless this happens to be the last iteration anyway,
|
|
Packit Service |
96b5d3 |
* the (last-for?) function will never yield "#t".
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Break(templ_t * tpl, macro_t * mac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
for_state_t * fst = curr_ivk_info->ii_for_data;
|
|
Packit Service |
96b5d3 |
int code = (mac->md_code == FTYP_BREAK) ? LOOP_JMP_BREAK : LOOP_JMP_NEXT;
|
|
Packit Service |
96b5d3 |
if (fst == NULL) {
|
|
Packit Service |
96b5d3 |
char const * which =
|
|
Packit Service |
96b5d3 |
(mac->md_code == FTYP_BREAK) ? BREAK_STR : CONTINUE_STR;
|
|
Packit Service |
96b5d3 |
AG_ABEND(aprf(BAD_BREAK_FMT, which));
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
fst += curr_ivk_info->ii_for_depth - 1;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
(void)tpl;
|
|
Packit Service |
96b5d3 |
(void)mac;
|
|
Packit Service |
96b5d3 |
longjmp(fst->for_env, code);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* wrapper function for calling gen_block in a loop.
|
|
Packit Service |
96b5d3 |
* It sets up and handles the jump buffer, returning the jump result.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @param[in,out] jbuf the jump buffer
|
|
Packit Service |
96b5d3 |
* @param[in] tpl the new active template
|
|
Packit Service |
96b5d3 |
* @param[in] mac the looping macro
|
|
Packit Service |
96b5d3 |
* @param[in] end_mac pointer to the first macro after the block
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @returns either LOOP_JMP_OKAY (0) or LOOP_JMP_BREAK (the caller should
|
|
Packit Service |
96b5d3 |
* exit the loop).
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
LOCAL loop_jmp_type_t
|
|
Packit Service |
96b5d3 |
call_gen_block(jmp_buf jbuf, templ_t * tpl, macro_t * mac, macro_t * end_mac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
switch (setjmp(jbuf)) {
|
|
Packit Service |
96b5d3 |
case LOOP_JMP_OKAY: // 0
|
|
Packit Service |
96b5d3 |
gen_block(tpl, mac, end_mac);
|
|
Packit Service |
96b5d3 |
/* FALLTHROUGH */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case LOOP_JMP_NEXT:
|
|
Packit Service |
96b5d3 |
return LOOP_JMP_OKAY;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case LOOP_JMP_BREAK:
|
|
Packit Service |
96b5d3 |
default:
|
|
Packit Service |
96b5d3 |
return LOOP_JMP_BREAK;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc RETURN
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* handler-proc:
|
|
Packit Service |
96b5d3 |
* load-proc: Leave
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: Leave an INVOKE-d (DEFINE) macro
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
* This will unwind looping constructs inside of a DEFINE-d macro and
|
|
Packit Service |
96b5d3 |
* return to the invocation point. The output files and diversions
|
|
Packit Service |
96b5d3 |
* @i{are left alone}. This means it is unwise to start diversions
|
|
Packit Service |
96b5d3 |
* in a DEFINEd macro and RETURN from it before you have handled the
|
|
Packit Service |
96b5d3 |
* diversion. Unless you are careful. Here is some rope for you.
|
|
Packit Service |
96b5d3 |
* Please be careful using it.
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Return(templ_t * tpl, macro_t * mac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
(void)tpl;
|
|
Packit Service |
96b5d3 |
(void)mac;
|
|
Packit Service |
96b5d3 |
free_for_context(INT_MAX);
|
|
Packit Service |
96b5d3 |
if (curr_ivk_info->ii_prev == NULL)
|
|
Packit Service |
96b5d3 |
AG_ABEND_IN(tpl, mac, RETURN_FROM_NOWHERE);
|
|
Packit Service |
96b5d3 |
longjmp(curr_ivk_info->ii_env, 1);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* Generate a block with a new template context. It may be either
|
|
Packit Service |
96b5d3 |
* an @code{INCLUDE}-d template or a user @code{DEFINE}-d macro.
|
|
Packit Service |
96b5d3 |
* If @code{gen_block} returns with a long jump, the long jump value
|
|
Packit Service |
96b5d3 |
* is ignored. It was terminated early with a @code{RETURN}.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @param[in] tpl new template block (included or invoked).
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
LOCAL void
|
|
Packit Service |
96b5d3 |
gen_new_block(templ_t * tpl)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
templ_t * oldt = current_tpl;
|
|
Packit Service |
96b5d3 |
ivk_info_t ii = IVK_INFO_INITIALIZER(curr_ivk_info);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
curr_ivk_info = ⅈ
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (setjmp(ii.ii_env) == 0) {
|
|
Packit Service |
96b5d3 |
macro_t * m = tpl->td_macros;
|
|
Packit Service |
96b5d3 |
gen_block(tpl, m, m + tpl->td_mac_ct);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
current_tpl = oldt;
|
|
Packit Service |
96b5d3 |
curr_ivk_info = ii.ii_prev;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* Validate the context for leaving early. @code{FOR} and @code{WHILE} loops
|
|
Packit Service |
96b5d3 |
* may leave an interation early with @code{CONTINUE} or @code{BREAK}.
|
|
Packit Service |
96b5d3 |
* @code{DEFINE}-d macros and @code{INCLUDE}-d files may leave early with
|
|
Packit Service |
96b5d3 |
* @code{RETURN}. Loops may not be left early from an @code{INVOKE}-d macro
|
|
Packit Service |
96b5d3 |
* or an @code{INCLUDE}-d template.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* This load function handles @code{BREAK}, @code{CONTINUE} and @code{RETURN}.
|
|
Packit Service |
96b5d3 |
* It is always defined, so it must check for itself whether the
|
|
Packit Service |
96b5d3 |
* context is correct or not.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @param tpl template being loaded
|
|
Packit Service |
96b5d3 |
* @param mac the macro descriptor
|
|
Packit Service |
96b5d3 |
* @param p_scan the input text scanning pointer
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @returns the macro table entry after mac
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mLoad_Leave(templ_t * tpl, macro_t * mac, char const ** p_scan)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
(void) tpl;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (mac->md_code == FTYP_RETURN) {
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Check returns at load time. "break" and "continue" at
|
|
Packit Service |
96b5d3 |
* instantiation time.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
if (! defining_macro && (include_depth == 0))
|
|
Packit Service |
96b5d3 |
(void)mLoad_Bogus(tpl, mac, p_scan);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
return mac + 1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc INCLUDE
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: Read in and emit a template block
|
|
Packit Service |
96b5d3 |
* handler_proc:
|
|
Packit Service |
96b5d3 |
* load_proc: Expr
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* The entire contents of the named file is inserted at this point.
|
|
Packit Service |
96b5d3 |
* The contents of the file are processed for macro expansion. The
|
|
Packit Service |
96b5d3 |
* arguments are eval-ed, so you may compute the name of the file to
|
|
Packit Service |
96b5d3 |
* be included. The included file must not contain any incomplete
|
|
Packit Service |
96b5d3 |
* function blocks. Function blocks are template text beginning with
|
|
Packit Service |
96b5d3 |
* any of the macro functions @samp{CASE}, @samp{DEFINE}, @samp{FOR},
|
|
Packit Service |
96b5d3 |
* @samp{IF} and @samp{WHILE}; extending through their respective
|
|
Packit Service |
96b5d3 |
* terminating macro functions.
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Include(templ_t * tpl, macro_t * mac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
bool allocated_name;
|
|
Packit Service |
96b5d3 |
char const * fname = eval_mac_expr(&allocated_name);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
include_depth++;
|
|
Packit Service |
96b5d3 |
if (*fname != NUL) {
|
|
Packit Service |
96b5d3 |
templ_t * new_tpl = tpl_load(fname, tpl->td_file);
|
|
Packit Service |
96b5d3 |
macro_t * last_mac = new_tpl->td_macros + (new_tpl->td_mac_ct - 1);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (last_mac->md_code == FTYP_TEXT) {
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Strip off trailing white space from included templates
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
char * pz = new_tpl->td_text + last_mac->md_txt_off;
|
|
Packit Service |
96b5d3 |
char * pe = SPN_WHITESPACE_BACK(pz, pz);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* IF there is no text left, remove the macro entirely
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
if (pe > pz) {
|
|
Packit Service |
96b5d3 |
*pe = NUL;
|
|
Packit Service |
96b5d3 |
} else {
|
|
Packit Service |
96b5d3 |
new_tpl->td_mac_ct--;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (OPT_VALUE_TRACE > TRACE_DEBUG_MESSAGE) {
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_FN_INC_TPL, new_tpl->td_file);
|
|
Packit Service |
96b5d3 |
if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_FN_INC_LINE, current_tpl->td_file,
|
|
Packit Service |
96b5d3 |
mac->md_line);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
gen_new_block(new_tpl);
|
|
Packit Service |
96b5d3 |
tpl_unload(new_tpl);
|
|
Packit Service |
96b5d3 |
current_tpl = tpl;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
include_depth--;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (allocated_name)
|
|
Packit Service |
96b5d3 |
AGFREE(fname);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return mac + 1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc UNKNOWN
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: Either a user macro or a value name.
|
|
Packit Service |
96b5d3 |
* handler_proc:
|
|
Packit Service |
96b5d3 |
* load_proc:
|
|
Packit Service |
96b5d3 |
* unnamed:
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* The macro text has started with a name not known to AutoGen. If, at run
|
|
Packit Service |
96b5d3 |
* time, it turns out to be the name of a defined macro, then that macro is
|
|
Packit Service |
96b5d3 |
* invoked. If it is not, then it is a conditional expression that is
|
|
Packit Service |
96b5d3 |
* evaluated only if the name is defined at the time the macro is invoked.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* You may not specify @code{UNKNOWN} explicitly.
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Unknown(templ_t * pT, macro_t * pMac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
templ_t * pInv = find_tpl(pT->td_text + pMac->md_name_off);
|
|
Packit Service |
96b5d3 |
if (pInv != NULL) {
|
|
Packit Service |
96b5d3 |
if (OPT_VALUE_TRACE >= TRACE_EVERYTHING)
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_FN_REMAPPED, TRACE_FN_REMAP_INVOKE,
|
|
Packit Service |
96b5d3 |
pMac->md_code, pT->td_file, pMac->md_line);
|
|
Packit Service |
96b5d3 |
pMac->md_code = FTYP_DEFINE;
|
|
Packit Service |
96b5d3 |
pMac->md_pvt = VOIDP(pInv);
|
|
Packit Service |
96b5d3 |
parse_mac_args(pT, pMac);
|
|
Packit Service |
96b5d3 |
return mFunc_Define(pT, pMac);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (OPT_VALUE_TRACE >= TRACE_EVERYTHING) {
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_FN_REMAPPED, TRACE_FN_REMAP_EXPR,
|
|
Packit Service |
96b5d3 |
pMac->md_code, pT->td_file, pMac->md_line);
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_FN_REMAP_BASE,
|
|
Packit Service |
96b5d3 |
pT->td_text + pMac->md_name_off);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
pMac->md_code = FTYP_EXPR;
|
|
Packit Service |
96b5d3 |
if (pMac->md_txt_off == 0) {
|
|
Packit Service |
96b5d3 |
pMac->md_res = EMIT_VALUE;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
} else {
|
|
Packit Service |
96b5d3 |
char * pzExpr = pT->td_text + pMac->md_txt_off;
|
|
Packit Service |
96b5d3 |
switch (*pzExpr) {
|
|
Packit Service |
96b5d3 |
case ';':
|
|
Packit Service |
96b5d3 |
case '(':
|
|
Packit Service |
96b5d3 |
pMac->md_res = EMIT_EXPRESSION;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case '`':
|
|
Packit Service |
96b5d3 |
pMac->md_res = EMIT_SHELL;
|
|
Packit Service |
96b5d3 |
span_quote(pzExpr);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case '"':
|
|
Packit Service |
96b5d3 |
case '\'':
|
|
Packit Service |
96b5d3 |
span_quote(pzExpr);
|
|
Packit Service |
96b5d3 |
/* FALLTHROUGH */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default:
|
|
Packit Service |
96b5d3 |
pMac->md_res = EMIT_STRING;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (OPT_VALUE_TRACE >= TRACE_EVERYTHING)
|
|
Packit Service |
96b5d3 |
fprintf(trace_fp, TRACE_UNKNOWN_FMT, pMac->md_res, pzExpr);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return mFunc_Expr(pT, pMac);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc BOGUS
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: Out-of-context or unknown functions are bogus.
|
|
Packit Service |
96b5d3 |
* handler_proc:
|
|
Packit Service |
96b5d3 |
* load_proc:
|
|
Packit Service |
96b5d3 |
* unnamed:
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Bogus(templ_t * pT, macro_t * pMac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char * pz = aprf(FN_BOGUS_FMT, pMac->md_code,
|
|
Packit Service |
96b5d3 |
(pMac->md_code < FUNC_CT)
|
|
Packit Service |
96b5d3 |
? ag_fun_names[ pMac->md_code ]
|
|
Packit Service |
96b5d3 |
: FN_BOGUS_HUH);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
AG_ABEND_IN(pT, pMac, pz);
|
|
Packit Service |
96b5d3 |
/* NOTREACHED */
|
|
Packit Service |
96b5d3 |
return pMac;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc TEXT
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: A block of text to be emitted.
|
|
Packit Service |
96b5d3 |
* handler_proc:
|
|
Packit Service |
96b5d3 |
* unnamed:
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mFunc_Text(templ_t * pT, macro_t * pMac)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
fputs(pT->td_text + pMac->md_txt_off, cur_fpstack->stk_fp);
|
|
Packit Service |
96b5d3 |
fflush(cur_fpstack->stk_fp);
|
|
Packit Service |
96b5d3 |
return pMac + 1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*=macfunc COMMENT
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* what: A block of comment to be ignored
|
|
Packit Service |
96b5d3 |
* load_proc:
|
|
Packit Service |
96b5d3 |
* alias: "#"
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* desc:
|
|
Packit Service |
96b5d3 |
* This function can be specified by the user, but there will
|
|
Packit Service |
96b5d3 |
* never be a situation where it will be invoked at emit time.
|
|
Packit Service |
96b5d3 |
* The macro is actually removed from the internal representation.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* If the native macro name code is @code{#}, then the
|
|
Packit Service |
96b5d3 |
* entire macro function is treated as a comment and ignored.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @example
|
|
Packit Service |
96b5d3 |
* [+ # say what you want, but no '+' before any ']' chars +]
|
|
Packit Service |
96b5d3 |
* @end example
|
|
Packit Service |
96b5d3 |
=*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mLoad_Comment(templ_t * tpl, macro_t * mac, char const ** p_scan)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
(void)tpl;
|
|
Packit Service |
96b5d3 |
(void)p_scan;
|
|
Packit Service |
96b5d3 |
memset(VOIDP(mac), 0, sizeof(*mac));
|
|
Packit Service |
96b5d3 |
return mac;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* The default (unknown) load function.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Move any text into the text offset field. This macro will change to
|
|
Packit Service |
96b5d3 |
* either INVOKE or an expression function, depending on whether or not a
|
|
Packit Service |
96b5d3 |
* DEFINE macro corresponds to the name. This is determined at instantiation
|
|
Packit Service |
96b5d3 |
* time. This is used as the default load mechanism.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @param tpl template being loaded
|
|
Packit Service |
96b5d3 |
* @param mac the macro descriptor
|
|
Packit Service |
96b5d3 |
* @param p_scan the input text scanning pointer
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @returns the macro table entry after mac
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mLoad_Unknown(templ_t * tpl, macro_t * mac, char const ** unused)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char const * scan;
|
|
Packit Service |
96b5d3 |
ssize_t src_len = (ssize_t)mac->md_res; /* macro len */
|
|
Packit Service |
96b5d3 |
(void)unused;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (src_len <= 0)
|
|
Packit Service |
96b5d3 |
goto return_emtpy_expr;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
scan = (char const *)mac->md_txt_off; /* macro text */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
switch (*scan) {
|
|
Packit Service |
96b5d3 |
case ';':
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char const * start = scan;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Strip off scheme comments
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
do {
|
|
Packit Service |
96b5d3 |
scan = strchr(scan, NL);
|
|
Packit Service |
96b5d3 |
if (scan == NULL)
|
|
Packit Service |
96b5d3 |
goto return_emtpy_expr;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
scan = SPN_WHITESPACE_CHARS(scan);
|
|
Packit Service |
96b5d3 |
if (*scan == NUL)
|
|
Packit Service |
96b5d3 |
goto return_emtpy_expr;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
src_len -= scan - start;
|
|
Packit Service |
96b5d3 |
if (src_len <= 0)
|
|
Packit Service |
96b5d3 |
goto return_emtpy_expr;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
start = scan;
|
|
Packit Service |
96b5d3 |
} while (*scan == ';');
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case '[':
|
|
Packit Service |
96b5d3 |
case '.':
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* We are going to recopy the definition name, this time as a
|
|
Packit Service |
96b5d3 |
* canonical name (i.e. including '[', ']' and '.' characters,
|
|
Packit Service |
96b5d3 |
* but with all blanks squeezed out)
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
char * cname = tpl->td_text + mac->md_name_off;
|
|
Packit Service |
96b5d3 |
size_t cname_len = strlen(cname);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Move back the source pointer. We may have skipped blanks,
|
|
Packit Service |
96b5d3 |
* so skip over however many first, then back up over the name.
|
|
Packit Service |
96b5d3 |
* We have found a name, so we won't back up past the start.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
while (IS_WHITESPACE_CHAR(scan[-1])) scan--, src_len++;
|
|
Packit Service |
96b5d3 |
scan -= cname_len;
|
|
Packit Service |
96b5d3 |
src_len += (ssize_t)cname_len;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Now copy over the full canonical name. Check for errors.
|
|
Packit Service |
96b5d3 |
* Advance the scan pointer to just past the name we've copied.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
ssize_t rem_len = canonical_name(cname, scan, (int)src_len);
|
|
Packit Service |
96b5d3 |
if (rem_len > src_len)
|
|
Packit Service |
96b5d3 |
AG_ABEND_IN(tpl, mac, LD_UNKNOWN_INVAL_DEF);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
scan += src_len - rem_len;
|
|
Packit Service |
96b5d3 |
src_len = (ssize_t)rem_len;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Where we are stashing text ("td_scan") gets set to just past the
|
|
Packit Service |
96b5d3 |
* NUL byte terminating the name. "cname" is now longer than before.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
tpl->td_scan = cname + strlen(cname) + 1;
|
|
Packit Service |
96b5d3 |
if (src_len <= 0)
|
|
Packit Service |
96b5d3 |
goto return_emtpy_expr;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Copy the expression (the remaining text)
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char * dest = tpl->td_scan; /* next text dest */
|
|
Packit Service |
96b5d3 |
mac->md_txt_off = (uintptr_t)(dest - tpl->td_text);
|
|
Packit Service |
96b5d3 |
mac->md_res = 0;
|
|
Packit Service |
96b5d3 |
memcpy(dest, scan, (size_t)src_len);
|
|
Packit Service |
96b5d3 |
dest += src_len;
|
|
Packit Service |
96b5d3 |
*(dest++) = NUL;
|
|
Packit Service |
96b5d3 |
*dest = NUL; /* double terminate */
|
|
Packit Service |
96b5d3 |
tpl->td_scan = dest;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return mac + 1;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return_emtpy_expr:
|
|
Packit Service |
96b5d3 |
mac->md_txt_off = 0;
|
|
Packit Service |
96b5d3 |
mac->md_res = 0;
|
|
Packit Service |
96b5d3 |
return mac + 1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* Some functions are known to AutoGen, but invalid out of context.
|
|
Packit Service |
96b5d3 |
* For example, ELIF, ELSE and ENDIF are all known to AutoGen.
|
|
Packit Service |
96b5d3 |
* However, the load function pointer for those functions points
|
|
Packit Service |
96b5d3 |
* here, until an "IF" function is encountered.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @param tpl template being loaded
|
|
Packit Service |
96b5d3 |
* @param mac the macro descriptor
|
|
Packit Service |
96b5d3 |
* @param p_scan the input text scanning pointer
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* @returns the macro table entry after mac
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
macro_t *
|
|
Packit Service |
96b5d3 |
mLoad_Bogus(templ_t * tpl, macro_t * mac, char const ** p_scan)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char const * pzSrc = (char const *)mac->md_txt_off; /* macro text */
|
|
Packit Service |
96b5d3 |
char const * pzMac;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
char z[ 64 ];
|
|
Packit Service |
96b5d3 |
(void)p_scan;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (pzSrc != NULL) {
|
|
Packit Service |
96b5d3 |
z[0] = ':';
|
|
Packit Service |
96b5d3 |
z[1] = z[2] = ' ';
|
|
Packit Service |
96b5d3 |
strncpy(z+3, pzSrc, (size_t)60);
|
|
Packit Service |
96b5d3 |
z[63] = NUL;
|
|
Packit Service |
96b5d3 |
pzSrc = z;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
pzSrc = zNil;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int ix = mac->md_code;
|
|
Packit Service |
96b5d3 |
if ((unsigned)ix >= FUNC_CT)
|
|
Packit Service |
96b5d3 |
ix = 0;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
pzMac = ag_fun_names[ ix ];
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
pzSrc = aprf(LD_BOGUS_UNKNOWN, tpl->td_file, mac->md_line, pzMac, pzSrc);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
AG_ABEND_IN(tpl, mac, pzSrc);
|
|
Packit Service |
96b5d3 |
/* NOTREACHED */
|
|
Packit Service |
96b5d3 |
return NULL;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* @}
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Local Variables:
|
|
Packit Service |
96b5d3 |
* mode: C
|
|
Packit Service |
96b5d3 |
* c-file-style: "stroustrup"
|
|
Packit Service |
96b5d3 |
* indent-tabs-mode: nil
|
|
Packit Service |
96b5d3 |
* End:
|
|
Packit Service |
96b5d3 |
* end of agen5/functions.c */
|