/* * mLoad_Include -- digest an INCLUDE macro * * Simply verify that there is some argument to this macro. * Regular "expr" macros are their own argument, so there is always one. */ tMacro* mLoad_Include(tTemplate* pT, tMacro* pMac, char const ** ppzScan) { if ((int)pMac->res == 0) AG_ABEND_IN(pT, pMac, LD_INC_NO_FNAME); return mLoad_Expr(pT, pMac, ppzScan); }
tMacro * mLoad_While(tTemplate* pT, tMacro* pMac, char const ** ppzScan) { size_t srcLen = (size_t)pMac->res; /* macro len */ tpLoadProc const * papLP = papLoadProc; tMacro * pEndMac; /* * While processing an "IF" macro, * we have handler functions for 'ELIF', 'ELSE' and 'ENDIF' * Otherwise, we do not. Switch the callout function table. */ static tpLoadProc apWhileLoad[ FUNC_CT ] = { NULL }; /* * IF there is no associated text expression * THEN woops! what are we to case on? */ if (srcLen == 0) AG_ABEND_IN(pT, pMac, LD_WHILE_NO_EXPR); if (apWhileLoad[0] == NULL) { memcpy((void*)apWhileLoad, apLoadProc, sizeof(apLoadProc)); apWhileLoad[ FTYP_ENDWHILE ] = &mLoad_Ending; } papLoadProc = apWhileLoad; /* * Load the expression */ (void)mLoad_Expr(pT, pMac, ppzScan); /* * Now, do a nested parse of the template. When the matching 'ENDWHILE' * macro is encountered, the handler routine will cause 'parseTemplate()' * to return with the text scanning pointer pointing to the remaining * text. */ pEndMac = parseTemplate(pMac+1, ppzScan); if (*ppzScan == NULL) AG_ABEND_IN(pT, pMac, LD_WHILE_NO_ENDWHILE); pMac->sibIndex = pMac->endIndex = pEndMac - pT->aMacros; /* * Restore the context of any encompassing block macros */ papLoadProc = papLP; return pEndMac; }
/*=macfunc ELIF * * what: Alternate Conditional Template Block * in-context: * * desc: * This macro must only appear after an @code{IF} function, and * before any associated @code{ELSE} or @code{ENDIF} functions. * It denotes the start of an alternate template block for the * @code{IF} function. Its expression argument is evaluated as are * the arguments to @code{IF}. For a complete description @xref{IF}. =*/ static tMacro* mLoad_Elif(tTemplate* pT, tMacro* pMac, char const ** ppzScan) { if ((int)pMac->res == 0) AG_ABEND_IN(pT, pMac, NO_IF_EXPR); /* * Load the expression */ (void)mLoad_Expr(pT, pMac, ppzScan); current_if.pElse->sibIndex = pMac - pT->aMacros; current_if.pElse = pMac; return pMac + 1; }
/* * mLoad_CASE * * This function is called to set up (load) the macro * when the template is first read in (before processing). */ tMacro* mLoad_Case(tTemplate* pT, tMacro* pMac, char const ** ppzScan) { size_t srcLen = (size_t)pMac->res; /* macro len */ tCaseStack save_stack = current_case; tMacro* pEsacMac; /* * Save the global macro loading mode */ tpLoadProc const * papLP = papLoadProc; /* * IF there is no associated text expression * THEN woops! what are we to case on? */ if (srcLen == 0) AG_ABEND_IN(pT, pMac, "expressionless CASE"); /* * Load the expression */ (void)mLoad_Expr(pT, pMac, ppzScan); /* * IF this is the first time here, * THEN set up the "CASE" mode callout tables. * It is the standard table, except entries are inserted * for SELECT and ESAC. */ if (apCaseLoad[0] == NULL) { int i; /* * Until there is a selection clause, only comment and select * macros are allowed. */ for (i=0; i < FUNC_CT; i++) apSelectOnly[i] = mLoad_Bogus; memcpy((void*)apCaseLoad, apLoadProc, sizeof( apLoadProc )); apSelectOnly[ FTYP_COMMENT] = mLoad_Comment; apSelectOnly[ FTYP_SELECT ] = \ apCaseLoad[ FTYP_SELECT ] = mLoad_Select; apCaseLoad[ FTYP_ESAC ] = mLoad_Ending; } /* * Set the "select macro only" loading mode */ papLoadProc = apSelectOnly; /* * Save global pointers to the current macro entry. * We will need this to link the CASE, SELECT and ESAC * functions together. */ current_case.pCase = current_case.pSelect = pMac; /* * Continue parsing the template from this nested level */ pEsacMac = parseTemplate(pMac+1, ppzScan); if (*ppzScan == NULL) AG_ABEND_IN(pT, pMac, "ESAC not found"); /* * Tell the last select macro where its end is. * (It ends with the "next" sibling. Since there * is no "next" at the end, it is a tiny lie.) * * Also, make sure the CASE macro knows where the end is. */ pMac->endIndex = \ current_case.pSelect->sibIndex = (pEsacMac - pT->aMacros); /* * Restore any enclosing CASE function's context. */ current_case = save_stack; /* * Restore the global macro loading mode */ papLoadProc = papLP; /* * Return the next available macro descriptor */ return pEsacMac; }
tMacro* mLoad_If(tTemplate* pT, tMacro* pMac, char const ** ppzScan) { size_t srcLen = (size_t)pMac->res; /* macro len */ tIfStack save_stack = current_if; tpLoadProc const * papLP = papLoadProc; tMacro * pEndifMac; /* * While processing an "IF" macro, * we have handler functions for 'ELIF', 'ELSE' and 'ENDIF' * Otherwise, we do not. Switch the callout function table. */ static tpLoadProc apIfLoad[ FUNC_CT ] = { NULL }; /* * IF there is no associated text expression * THEN woops! what are we to case on? */ if (srcLen == 0) AG_ABEND_IN(pT, pMac, NO_IF_EXPR); if (apIfLoad[0] == NULL) { memcpy((void*)apIfLoad, apLoadProc, sizeof(apLoadProc)); apIfLoad[ FTYP_ELIF ] = &mLoad_Elif; apIfLoad[ FTYP_ELSE ] = &mLoad_Else; apIfLoad[ FTYP_ENDIF ] = &mLoad_Ending; } papLoadProc = apIfLoad; /* * We will need to chain together the 'IF', 'ELIF', and 'ELSE' * macros. The 'ENDIF' gets absorbed. */ current_if.pIf = current_if.pElse = pMac; /* * Load the expression */ (void)mLoad_Expr(pT, pMac, ppzScan); /* * Now, do a nested parse of the template. * When the matching 'ENDIF' macro is encountered, * the handler routine will cause 'parseTemplate()' * to return with the text scanning pointer pointing * to the remaining text. */ pEndifMac = parseTemplate(pMac+1, ppzScan); if (*ppzScan == NULL) AG_ABEND_IN(pT, pMac, LD_IF_NO_ENDIF); current_if.pIf->endIndex = \ current_if.pElse->sibIndex = pEndifMac - pT->aMacros; /* * Restore the context of any encompassing block macros */ current_if = save_stack; papLoadProc = papLP; return pEndifMac; }