/** * Find the end marker for the named section of XML. * Trim that text there, trimming trailing white space for all modes * except for OPTION_LOAD_UNCOOKED. */ static char * trim_xml_text(char * intxt, char const * pznm, tOptionLoadMode mode) { static char const fmt[] = "</%s>"; size_t len = strlen(pznm) + sizeof(fmt) - 2 /* for %s */; char * etext; { char z[64], *pz = z; if (len >= sizeof(z)) pz = AGALOC(len, "scan name"); len = (size_t)sprintf(pz, fmt, pznm); *intxt = ' '; etext = strstr(intxt, pz); if (pz != z) AGFREE(pz); } if (etext == NULL) return etext; { char * result = etext + len; if (mode != OPTION_LOAD_UNCOOKED) etext = SPN_WHITESPACE_BACK(intxt, etext); *etext = NUL; return result; } }
/** * We've found a closing '>' without a preceding '/', thus we must search * the text for '<name/>' where "name" is the name of the XML element. * * @param[in] name the start of the name in the element header * @param[in] nm_len the length of that name * @param[out] len the length of the value (string between header and * the trailer/tail. * @returns the character after the trailer, or NULL if not found. */ static char const * find_end_xml(char const * src, size_t nm_len, char const * val, size_t * len) { char z[72] = "</"; char * dst = z + 2; do { *(dst++) = *(src++); } while (--nm_len > 0); /* nm_len is known to be 64 or less */ *(dst++) = '>'; *dst = NUL; { char const * res = strstr(val, z); if (res != NULL) { char const * end = (option_load_mode != OPTION_LOAD_KEEP) ? SPN_WHITESPACE_BACK(val, res) : res; *len = (size_t)(end - val); /* includes trailing white space */ res = SPN_WHITESPACE_CHARS(res + (dst - z)); } return res; } }
LOCAL void mungeString(char * txt, tOptionLoadMode mode) { char * pzE; if (mode == OPTION_LOAD_KEEP) return; if (IS_WHITESPACE_CHAR(*txt)) { char * pzS = SPN_WHITESPACE_CHARS(txt+1); size_t l = strlen(pzS) + 1; memmove(txt, pzS, l); pzE = txt + l - 1; } else pzE = txt + strlen(txt); pzE = SPN_WHITESPACE_BACK(txt, pzE); *pzE = NUL; if (mode == OPTION_LOAD_UNCOOKED) return; switch (*txt) { default: return; case '"': case '\'': break; } switch (pzE[-1]) { default: return; case '"': case '\'': break; } (void)ao_string_cook(txt, NULL); }
/** * This directive @i{is} processed, but only if the expression begins with * either a back quote (@code{`}) or an open parenthesis (@code{(}). * Text within the back quotes are handed off to the shell for processing * and parenthesized text is handed off to Guile. Multiple line expressions * must be joined with backslashes. * * If the @code{shell-script} or @code{scheme-expr} do not yield @code{true} * valued results, autogen will be aborted. If @code{<anything else>} or * nothing at all is provided, then this directive is ignored. * * The result is @code{false} (and fails) if the result is empty, the * number zero, or a string that starts with the letters 'n' or 'f' ("no" * or "false"). */ char * doDir_assert(directive_enum_t id, char const * dir, char * scan_next) { (void)id; dir = SPN_WHITESPACE_CHARS(dir); switch (*dir) { case '`': { char * pzS = (char *)dir+1; char * pzR = SPN_WHITESPACE_BACK(pzS, NULL); if (*(--pzR) != '`') break; /* not a valid script */ *pzR = NUL; pzS = shell_cmd((char const *)pzS); check_assert_str(pzS, dir); AGFREE(pzS); break; } case '(': { SCM res = ag_scm_c_eval_string_from_file_line( dir, cctx->scx_fname, cctx->scx_line); check_assert_str(scm2display(res), dir); break; } default: break; } return scan_next; }