/* * Copyright (c) 2005, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: t-strexpmac.c,v 1.4 2006/01/05 22:41:55 ca Exp $") #include "sm/assert.h" #include "sm/magic.h" #include "sm/error.h" #include "sm/rpool.h" #include "sm/test.h" #include "sm/str.h" #include "sm/strexp.h" #include "sm/io.h" extern char *optarg; extern int optind; extern int optopt; extern int opterr; #define SMAXLEN 1024 static int Verbose = 0; #define NMACROS 10 #if TEST_STREXPMAC_CB #define sm_str_expmac(src, dst, f, n, macros, repl) \ sm_str_expmac_cb(src, dst, f, expmac, &t_ctx) struct t_ctx_S { uint t_nmacros; sm_str_P *t_macros; sm_str_P *t_repl; }; typedef struct t_ctx_S t_ctx_T, *t_ctx_P; static sm_ret_T expmac(const sm_str_P src, uint len, sm_str_P dst, uint mac_begin, uint mac_end, void *ctx) { sm_ret_T ret; uint idx; t_ctx_P t_ctx; SM_REQUIRE(ctx != NULL); t_ctx = (t_ctx_P)ctx; ret = sm_find_macro(src, len, mac_begin, mac_end, &idx, t_ctx->t_nmacros, t_ctx->t_macros); if (sm_is_err(ret)) return ret; if (idx < NMACROS && t_ctx->t_repl[idx] != NULL) { ret = sm_str_cat(dst, t_ctx->t_repl[idx]); if (sm_is_err(ret)) return ret; return 1; } return ret; } #endif /* TEST_STREXPMAC_CB */ static void test_harness(sm_rpool_P a) { uint argc; sm_str_P src, dst, macros[NMACROS], repl[NMACROS]; sm_ret_T ret; #if TEST_STREXPMAC_CB t_ctx_T t_ctx; #endif /* TEST_STREXPMAC_CB */ #if TEST_STREXPMAC_CB t_ctx.t_nmacros = 1; t_ctx.t_macros = macros; t_ctx.t_repl = repl; #endif /* TEST_STREXPMAC_CB */ src = sm_str_new(a, SMAXLEN, SMAXLEN); SM_TEST(src != NULL); if (src == NULL) return; dst = sm_str_new(a, SMAXLEN, SMAXLEN); SM_TEST(dst != NULL); if (dst == NULL) return; for (argc = 0; argc < NMACROS; argc++) { macros[argc] = sm_str_new(a, SMAXLEN, SMAXLEN); SM_TEST(macros[argc] != NULL); if (macros[argc] == NULL) return; sm_strprintf(macros[argc], "macro%u", argc); repl[argc] = sm_str_new(a, SMAXLEN, SMAXLEN); SM_TEST(repl[argc] != NULL); if (repl[argc] == NULL) return; sm_strprintf(repl[argc], "repl%uace", argc); } /* simple expansion */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "strrepl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* simple expansion */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "repl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* expansion suppressed */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "${macro0}") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* expansion suppressed */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\\\\\${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "\\\\${macro0}") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* expansion */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\\\${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "\\\\repl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* macro is not "defined", replaced with empty string */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str${macro}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 1); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* expansion fails */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str${macro"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 0); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str${macro") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str$${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 1); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str$${macro0}${}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 1); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace${}") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str$${macro0}${A}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 2); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str${macro0\\}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 1); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "str") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "str${macro0}${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 2); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "strrepl0acerepl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "${macro1}X${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; #if TEST_STREXPMAC_CB t_ctx.t_nmacros = 2; #endif ret = sm_str_expmac(src, dst, 0, 2, macros, repl); SM_TEST(ret == 2); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "repl1aceXrepl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "${macro1}X${macro0}"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; #if TEST_STREXPMAC_CB t_ctx.t_nmacros = 1; #endif ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 2); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "Xrepl0ace") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst); sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 0); if (!sm_is_success(ret)) return; sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\$\\"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret > 0); if (!sm_is_success(ret)) return; sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\a"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 0); if (!sm_is_success(ret)) return; sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "\\\\"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expmac(src, dst, 0, 1, macros, repl); SM_TEST(ret == 0); if (!sm_is_success(ret)) return; #if 0 /* two expansions and keep '%%' */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "%0-%%-%1"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expdig(src, dst, '\0', 2, argv); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-%-arg-1!") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* keep '%%', one expansion does not have an argument */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "%0-%%-%1"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expdig(src, dst, '\0', 1, argv); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-%-") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* two expansions and keep trailing '%' */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "%0-%1-%"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expdig(src, dst, '\0', 2, argv); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-arg-1!-%") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); /* many expansions */ sm_str_clr(src); sm_str_clr(dst); ret = sm_str_scat0(src, "%0.%1.%2.%3.%4.%5.%6.%7.%8.%9.%A"); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return; ret = sm_str_expdig(src, dst, '\0', 10, argv); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) return; SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!.arg-1!.arg-2!.arg-3!.arg-4!.arg-5!.arg-6!.arg-7!.arg-8!.arg-9!.A") == 0); if (Verbose > 2) sm_io_fprintf(smioerr, "dst='%S'\n", dst); #endif for (argc = 0; argc < NMACROS; argc++) { SM_STR_FREE(macros[argc]); SM_STR_FREE(repl[argc]); } sm_str_free(src); sm_str_free(dst); } int main(int argc, char *argv[]) { int c; sm_rpool_P a; while ((c = getopt(argc, argv, "V")) != -1) { switch (c) { case 'V': ++Verbose; break; default: /* usage(prg); */ break; } } sm_test_begin(argc, argv, "test strexpmac()"); argc -= optind; argv += optind; /* create an rpool for entire test */ a = sm_rpool_new(NULL); SM_TEST(a != NULL); test_harness(a); sm_rpool_delete(a); /* test without rpool */ test_harness(NULL); return sm_test_end(); }