Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postfix/src/util/   (Postfix Mailserver Version 3.11©)  Datei vom 24.7.2025 mit Größe 20 kB image not shown  

Quelle  argv.c

  Sprache: C
 

/*++
/* NAME
/* argv 3
/* SUMMARY
/* string array utilities
/* SYNOPSIS
/* #include <argv.h>
/*
/* typedef int (*ARGV_COMPAR_FN)(const void *, const void *);
/*
/* ARGV *argv_alloc(len)
/* ssize_t len;
/*
/* ARGV    *argv_qsort(argvp, compar)
/* ARGV    *argvp;
/* ARGV_COMPAR_FN compar;
/*
/* void argv_uniq(argvp, compar)
/* ARGV *argvp;
/* ARGV_COMPAR_FN compar;
/*
/* ARGV *argv_free(argvp)
/* ARGV *argvp;
/*
/* void argv_add(argvp, arg, ..., ARGV_END)
/* ARGV *argvp;
/* char *arg;
/*
/* void argv_addn(argvp, arg, arg_len, ..., ARGV_END)
/* ARGV *argvp;
/* char *arg;
/* ssize_t arg_len;
/*
/* ARGV *argv_addv(argvp, argv)
/* ARGV *argvp;
/* const char **argv;
/*
/* void argv_terminate(argvp);
/* ARGV *argvp;
/*
/* void argv_truncate(argvp, len);
/* ARGV *argvp;
/* ssize_t len;
/*
/* void argv_insert_one(argvp, pos, arg)
/* ARGV *argvp;
/* ssize_t pos;
/* const char *arg;
/*
/* void argv_replace_one(argvp, pos, arg)
/* ARGV *argvp;
/* ssize_t pos;
/* const char *arg;
/*
/* void argv_delete(argvp, pos, how_many)
/* ARGV *argvp;
/* ssize_t pos;
/* ssize_t how_many;
/*
/* char *argv_join(buf, argvp, delim)
/* VSTRING *buf;
/* ARGV *argvp;
/* int delim;
/*
/* void ARGV_FAKE_BEGIN(argv, arg)
/* const char *arg;
/*
/* void ARGV_FAKE2_BEGIN(argv, arg1, arg2)
/* const char *arg1;
/* const char *arg2;
/*
/* void ARGV_FAKE_END
/* DESCRIPTION
/* The functions in this module manipulate arrays of string
/* pointers. An ARGV structure contains the following members:
/* .IP len
/* The length of the \fIargv\fR array member.
/* .IP argc
/* The number of \fIargv\fR elements used.
/* .IP argv
/* An array of pointers to null-terminated strings.
/* .PP
/* argv_alloc() returns an empty string array of the requested
/* length. The result is ready for use by argv_add(). The array
/* is null terminated.
/*
/* argv_qsort() sorts the elements of argvp in place, and
/* returns its first argument. If the compar argument specifies
/* a null pointer, then argv_qsort() will use byte-by-byte
/* comparison.
/*
/* argv_uniq() reduces adjacent same-value elements to one
/* element, and returns its first argument. If the compar
/* argument specifies a null pointer, then argv_uniq() will
/* use byte-by-byte comparison.
/*
/* argv_add() copies zero or more strings and adds them to the
/* specified string array. The array is null terminated.
/* Terminate the argument list with a null pointer. The manifest
/* constant ARGV_END provides a convenient notation for this.
/*
/* argv_addn() is like argv_add(), but each string is followed
/* by a string length argument.
/*
/* argv_addv() optionally creates an ARGV when the first argument
/* is a null pointer, and appends a null-terminated list of
/* strings. The result is null terminated.
/*
/* argv_free() releases storage for a string array, and conveniently
/* returns a null pointer.
/*
/* argv_terminate() null-terminates its string array argument.
/*
/* argv_truncate() truncates its argument to the specified
/* number of entries, but does not reallocate memory. The
/* result is null-terminated.
/*
/* argv_insert_one() inserts one string at the specified array
/* position.
/*
/* argv_replace_one() replaces one string at the specified
/* position. The old string is destroyed after the update is
/* made.
/*
/* argv_delete() deletes the specified number of elements
/* starting at the specified array position. The result is
/* null-terminated.
/*
/* argv_join() joins all elements in an array using the
/* specified delimiter value, and appends the result to the
/* specified buffer.
/*
/* ARGV_FAKE_BEGIN/END are an optimization for the case where
/* a single string needs to be passed into an ARGV-based
/* interface.  ARGV_FAKE_BEGIN() opens a statement block and
/* allocates a stack-based ARGV structure named after the first
/* argument, that encapsulates the second argument.  This
/* implementation allocates no heap memory and creates no copy
/* of the second argument.  ARGV_FAKE_END closes the statement
/* block and thereby releases storage.
/*
/* ARGV_FAKE2_BEGIN/END provide the same functionality for a pair
/* of strings.
/* SEE ALSO
/* msg(3) diagnostics interface
/* DIAGNOSTICS
/* Fatal errors: memory allocation problem.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*
/* Wietse Venema
/* porcupine.org
/*--*/


/* System libraries. */

#include <sys_defs.h>
#include <stdlib.h>   /* 44BSD stdarg.h uses abort() */
#include <stdarg.h>
#include <string.h>

/* Application-specific. */

#include "mymalloc.h"
#include "msg.h"
#include "vstring.h"
#include "argv.h"

#ifdef TEST
extern NORETURN PRINTFLIKE(12) test_msg_panic(const char *,...);

#define msg_panic test_msg_panic
#endif

/* argv_free - destroy string array */

ARGV   *argv_free(ARGV *argvp)
{
    char  **cpp;

    for (cpp = argvp->argv; cpp < argvp->argv + argvp->argc; cpp++)
 myfree(*cpp);
    myfree((void *) argvp->argv);
    myfree((void *) argvp);
    return (0);
}

/* argv_alloc - initialize string array */

ARGV   *argv_alloc(ssize_t len)
{
    ARGV   *argvp;
    ssize_t sane_len;

    /*
     * Make sure that always argvp->argc < argvp->len.
     */

    argvp = (ARGV *) mymalloc(sizeof(*argvp));
    argvp->len = 0;
    sane_len = (len < 2 ? 2 : len);
    argvp->argv = (char **) mymalloc((sane_len + 1) * sizeof(char *));
    argvp->len = sane_len;
    argvp->argc = 0;
    argvp->argv[0] = 0;
    return (argvp);
}

static int argv_cmp(const void *e1, const void *e2)
{
    const char *s1 = *(const char **) e1;
    const char *s2 = *(const char **) e2;

    return strcmp(s1, s2);
}

/* argv_qsort - sort array in place */

ARGV   *argv_qsort(ARGV *argvp, ARGV_COMPAR_FN compar)
{
    qsort(argvp->argv, argvp->argc, sizeof(argvp->argv[0]),
   compar ? compar : argv_cmp);
    return (argvp);
}

/* argv_sort - binary compatibility */

ARGV   *argv_sort(ARGV *argvp)
{
    qsort(argvp->argv, argvp->argc, sizeof(argvp->argv[0]), argv_cmp);
    return (argvp);
}

/* argv_uniq - deduplicate adjacent array elements */

ARGV   *argv_uniq(ARGV *argvp, ARGV_COMPAR_FN compar)
{
    char  **cpp;
    char  **prev;

    if (compar == 0)
 compar = argv_cmp;
    for (prev = 0, cpp = argvp->argv; cpp < argvp->argv + argvp->argc; cpp++) {
 if (prev != 0 && compar(prev, cpp) == 0) {
     argv_delete(argvp, cpp - argvp->argv, 1);
     cpp = prev;
 } else {
     prev = cpp;
 }
    }
    return (argvp);
}

/* argv_extend - extend array */

static void argv_extend(ARGV *argvp)
{
    ssize_t new_len;

    new_len = argvp->len * 2;
    argvp->argv = (char **)
 myrealloc((void *) argvp->argv, (new_len + 1) * sizeof(char *));
    argvp->len = new_len;
}

/* argv_add - add string to vector */

void    argv_add(ARGV *argvp,...)
{
    char   *arg;
    va_list ap;

    /*
     * Make sure that always argvp->argc < argvp->len.
     */

#define ARGV_SPACE_LEFT(a) ((a)->len - (a)->argc - 1)

    va_start(ap, argvp);
    while ((arg = va_arg(ap, char *)) != 0) {
 if (ARGV_SPACE_LEFT(argvp) <= 0)
     argv_extend(argvp);
 argvp->argv[argvp->argc++] = mystrdup(arg);
    }
    va_end(ap);
    argvp->argv[argvp->argc] = 0;
}

/* argv_addn - add string to vector */

void    argv_addn(ARGV *argvp,...)
{
    char   *arg;
    ssize_t len;
    va_list ap;

    /*
     * Make sure that always argvp->argc < argvp->len.
     */

    va_start(ap, argvp);
    while ((arg = va_arg(ap, char *)) != 0) {
 if ((len = va_arg(ap, ssize_t)) < 0)
     msg_panic("argv_addn: bad string length %ld", (long) len);
 if (ARGV_SPACE_LEFT(argvp) <= 0)
     argv_extend(argvp);
 argvp->argv[argvp->argc++] = mystrndup(arg, len);
    }
    va_end(ap);
    argvp->argv[argvp->argc] = 0;
}

/* argv_addv - optionally create ARGV, append string vector */

ARGV   *argv_addv(ARGV *argvp, const char *const * argv)
{
    const char *const * cpp;

    if (argvp == 0) {
 for (cpp = argv; *cpp; cpp++)
      /* void */ ;
 argvp = argv_alloc(cpp - argv);
    }
    for (cpp = argv; *cpp; cpp++)
 argv_add(argvp, *cpp, (char *) 0);
    argvp->argv[argvp->argc] = 0;
    return (argvp);
}

/* argv_terminate - terminate string array */

void    argv_terminate(ARGV *argvp)
{

    /*
     * Trust that argvp->argc < argvp->len.
     */

    argvp->argv[argvp->argc] = 0;
}

/* argv_truncate - truncate string array */

void    argv_truncate(ARGV *argvp, ssize_t len)
{
    char  **cpp;

    /*
     * Sanity check.
     */

    if (len < 0)
 msg_panic("argv_truncate: bad length %ld", (long) len);

    if (len < argvp->argc) {
 for (cpp = argvp->argv + len; cpp < argvp->argv + argvp->argc; cpp++)
     myfree(*cpp);
 argvp->argc = len;
 argvp->argv[argvp->argc] = 0;
    }
}

/* argv_insert_one - insert one string into array */

void    argv_insert_one(ARGV *argvp, ssize_t where, const char *arg)
{
    ssize_t pos;

    /*
     * Sanity check.
     */

    if (where < 0 || where > argvp->argc)
 msg_panic("argv_insert_one bad position: %ld", (long) where);

    if (ARGV_SPACE_LEFT(argvp) <= 0)
 argv_extend(argvp);
    for (pos = argvp->argc; pos >= where; pos--)
 argvp->argv[pos + 1] = argvp->argv[pos];
    argvp->argv[where] = mystrdup(arg);
    argvp->argc += 1;
}

/* argv_replace_one - replace one string in array */

void    argv_replace_one(ARGV *argvp, ssize_t where, const char *arg)
{
    char   *temp;

    /*
     * Sanity check.
     */

    if (where < 0 || where >= argvp->argc)
 msg_panic("argv_replace_one bad position: %ld", (long) where);

    temp = argvp->argv[where];
    argvp->argv[where] = mystrdup(arg);
    myfree(temp);
}

/* argv_delete - remove string(s) from array */

void    argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
{
    ssize_t pos;

    /*
     * Sanity check.
     */

    if (first < 0 || how_many < 0 || first + how_many > argvp->argc)
 msg_panic("argv_delete bad range: (start=%ld count=%ld)",
    (long) first, (long) how_many);

    for (pos = first; pos < first + how_many; pos++)
 myfree(argvp->argv[pos]);
    for (pos = first; pos <= argvp->argc - how_many; pos++)
 argvp->argv[pos] = argvp->argv[pos + how_many];
    argvp->argc -= how_many;
}

/* argv_join - concatenate array elements with delimiter */

char   *argv_join(VSTRING *buf, ARGV *argv, int delim)
{
    char  **cpp;

    for (cpp = argv->argv; *cpp; cpp++) {
 vstring_strcat(buf, *cpp);
 if (cpp[1])
     VSTRING_ADDCH(buf, delim);
    }
    return (vstring_str(buf));
}

#ifdef TEST

 /*
  * System library.
  */

#include <setjmp.h>

 /*
  * Utility library.
  */

#include <msg_vstream.h>
#include <stringops.h>

#define ARRAY_LEN (10)

typedef struct TEST_CASE {
    const char *label;   /* identifies test case */
    const char *inputs[ARRAY_LEN]; /* input strings */
    int     terminate;   /* terminate result */
    ARGV   *(*populate_fn) (const struct TEST_CASE *, ARGV *);
    const char *exp_panic_msg;  /* expected panic */
    int     exp_argc;   /* expected array length */
    const char *exp_argv[ARRAY_LEN]; /* expected array content */
    int     join_delim;   /* argv_join() delimiter */
} TEST_CASE;

#define TERMINATE_ARRAY (1)

#define PASS (0)
#define FAIL (1)

VSTRING *test_panic_str;
jmp_buf test_panic_jbuf;

/* test_msg_panic - does not return, and does not terminate */

void    test_msg_panic(const char *fmt,...)
{
    va_list ap;

    va_start(ap, fmt);
    test_panic_str = vstring_alloc(100);
    vstring_vsprintf(test_panic_str, fmt, ap);
    va_end(ap);
    longjmp(test_panic_jbuf, 1);
}

/* test_argv_populate - populate result, optionally terminate */

static ARGV *test_argv_populate(const TEST_CASE *tp, ARGV *argvp)
{
    const char *const * cpp;

    for (cpp = tp->inputs; *cpp; cpp++)
 argv_add(argvp, *cpp, (char *) 0);
    if (tp->terminate)
 argv_terminate(argvp);
    return (argvp);
}

/* test_argv_sort - populate and sort result */

static ARGV *test_argv_sort(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_qsort(argvp, (ARGV_COMPAR_FN) 0);
    return (argvp);
}

/* test_argv_sort_uniq - populate, sort, uniq result */

static ARGV *test_argv_sort_uniq(const TEST_CASE *tp, ARGV *argvp)
{

    /*
     * This also tests argv_delete().
     */

    test_argv_sort(tp, argvp);
    argv_uniq(argvp, (ARGV_COMPAR_FN) 0);
    return (argvp);
}

/* test_argv_good_truncate - populate and truncate to good size */

static ARGV *test_argv_good_truncate(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_truncate(argvp, tp->exp_argc);
    return (argvp);
}

/* test_argv_bad_truncate - populate and truncate to bad size */

static ARGV *test_argv_bad_truncate(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_truncate(argvp, -1);
    return (argvp);
}

/* test_argv_good_insert - populate and insert at good position */

static ARGV *test_argv_good_insert(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_insert_one(argvp, 1"new");
    return (argvp);
}

/* test_argv_bad_insert1 - populate and insert at bad position */

static ARGV *test_argv_bad_insert1(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_insert_one(argvp, -1"new");
    return (argvp);
}

/* test_argv_bad_insert2 - populate and insert at bad position */

static ARGV *test_argv_bad_insert2(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_insert_one(argvp, 100"new");
    return (argvp);
}

/* test_argv_good_replace - populate and replace at good position */

static ARGV *test_argv_good_replace(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_replace_one(argvp, 1"new");
    return (argvp);
}

/* test_argv_bad_replace1 - populate and replace at bad position */

static ARGV *test_argv_bad_replace1(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_replace_one(argvp, -1"new");
    return (argvp);
}

/* test_argv_bad_replace2 - populate and replace at bad position */

static ARGV *test_argv_bad_replace2(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_replace_one(argvp, 100"new");
    return (argvp);
}

/* test_argv_bad_delete1 - populate and delete at bad position */

static ARGV *test_argv_bad_delete1(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_delete(argvp, -11);
    return (argvp);
}

/* test_argv_bad_delete2 - populate and delete at bad position */

static ARGV *test_argv_bad_delete2(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_delete(argvp, 0, -1);
    return (argvp);
}

/* test_argv_bad_delete3 - populate and delete at bad position */

static ARGV *test_argv_bad_delete3(const TEST_CASE *tp, ARGV *argvp)
{
    test_argv_populate(tp, argvp);
    argv_delete(argvp, 1001);
    return (argvp);
}

/* test_argv_join - populate, join, and overwrite */

static ARGV *test_argv_join(const TEST_CASE *tp, ARGV *argvp)
{
    VSTRING *buf = vstring_alloc(100);

    /*
     * Impedance mismatch: argv_join() produces output to VSTRING, but the
     * test fixture wants output to ARGV.
     */

    test_argv_populate(tp, argvp);
    argv_join(buf, argvp, tp->join_delim);
    argv_delete(argvp, 0, argvp->argc);
    argv_add(argvp, vstring_str(buf), ARGV_END);
    vstring_free(buf);
    return (argvp);
}

/* test_argv_addv_appends - populate result */

static ARGV *test_argv_addv_appends(const TEST_CASE *tp, ARGV *argvp)
{
    argvp = argv_addv(argvp, tp->inputs);
    return (argvp);
}

/* test_argv_addv_creates_appends - populate result */

static ARGV *test_argv_addv_creates(const TEST_CASE *tp, ARGV *argvp)
{
    argv_free(argvp);
    argvp = argv_addv((ARGV *) 0, tp->inputs);
    return (argvp);
}

/* test_argv_verify - verify result */

static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
{
    int     idx;

    if (tp->exp_panic_msg != 0) {
 if (test_panic_str == 0) {
     msg_warn("test case '%s': got no panic, want: '%s'",
       tp->label, tp->exp_panic_msg);
     return (FAIL);
 }
 if (strcmp(vstring_str(test_panic_str), tp->exp_panic_msg) != 0) {
     msg_warn("test case '%s': got '%s', want: '%s'",
   tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
     return (FAIL);
 }
 return (PASS);
    }
    if (test_panic_str != 0) {
 msg_warn("test case '%s': got '%s', want: no panic",
   tp->label, vstring_str(test_panic_str));
 return (FAIL);
    }
    if (argvp->argc != tp->exp_argc) {
 msg_warn("test case '%s': got argc: %ld, want: %d",
   tp->label, (long) argvp->argc, tp->exp_argc);
 return (FAIL);
    }
    if (argvp->argv[argvp->argc] != 0 && tp->terminate) {
 msg_warn("test case '%s': got unterminated, want: terminated", tp->label);
 return (FAIL);
    }
    for (idx = 0; idx < argvp->argc; idx++) {
 if (strcmp(argvp->argv[idx], tp->exp_argv[idx]) != 0) {
     msg_warn("test case '%s': index %d: got '%s', want: '%s'",
       tp->label, idx, argvp->argv[idx], tp->exp_argv[idx]);
     return (FAIL);
 }
    }
    return (PASS);
}

 /*
  * The test cases. TODO: argv_addn with good and bad string length.
  */

static const TEST_CASE test_cases[] = {
    {"multiple strings, unterminated array",
 {"foo""baz""bar"0}, 0, test_argv_populate,
 03, {"foo""baz""bar"0}
    },
    {"multiple strings, terminated array",
 {"foo""baz""bar"0}, TERMINATE_ARRAY, test_argv_populate,
 03, {"foo""baz""bar"0}
    },
    {"distinct strings, sorted array",
 {"foo""baz""bar"0}, 0, test_argv_sort,
 03, {"bar""baz""foo"0}
    },
    {"duplicate strings, sorted array",
 {"foo""baz""baz""bar"0}, 0, test_argv_sort,
 04, {"bar""baz""baz""foo"0}
    },
    {"duplicate strings, sorted, uniqued-middle elements",
 {"foo""baz""baz""bar"0}, 0, test_argv_sort_uniq,
 03, {"bar""baz""foo"0}
    },
    {"duplicate strings, sorted, uniqued-first elements",
 {"foo""bar""baz""bar"0}, 0, test_argv_sort_uniq,
 03, {"bar""baz""foo"0}
    },
    {"duplicate strings, sorted, uniqued-last elements",
 {"foo""foo""baz""bar"0}, 0, test_argv_sort_uniq,
 03, {"bar""baz""foo"0}
    },
    {"multiple strings, truncate array by one",
 {"foo""baz""bar"0}, 0, test_argv_good_truncate,
 02, {"foo""baz"0}
    },
    {"multiple strings, truncate whole array",
 {"foo""baz""bar"0}, 0, test_argv_good_truncate,
 00, {"foo""baz"0}
    },
    {"multiple strings, bad truncate",
 {"foo""baz""bar"0}, 0, test_argv_bad_truncate,
 "argv_truncate: bad length -1"
    },
    {"multiple strings, insert one at good position",
 {"foo""baz""bar"0}, 0, test_argv_good_insert,
 04, {"foo""new""baz""bar"0}
    },
    {"multiple strings, insert one at bad position",
 {"foo""baz""bar"0}, 0, test_argv_bad_insert1,
 "argv_insert_one bad position: -1"
    },
    {"multiple strings, insert one at bad position",
 {"foo""baz""bar"0}, 0, test_argv_bad_insert2,
 "argv_insert_one bad position: 100"
    },
    {"multiple strings, replace one at good position",
 {"foo""baz""bar"0}, 0, test_argv_good_replace,
 03, {"foo""new""bar"0}
    },
    {"multiple strings, replace one at bad position",
 {"foo""baz""bar"0}, 0, test_argv_bad_replace1,
 "argv_replace_one bad position: -1"
    },
    {"multiple strings, replace one at bad position",
 {"foo""baz""bar"0}, 0, test_argv_bad_replace2,
 "argv_replace_one bad position: 100"
    },
    {"multiple strings, delete one at negative position",
 {"foo""baz""bar"0}, 0, test_argv_bad_delete1,
 "argv_delete bad range: (start=-1 count=1)"
    },
    {"multiple strings, delete with bad range end",
 {"foo""baz""bar"0}, 0, test_argv_bad_delete2,
 "argv_delete bad range: (start=0 count=-1)"
    },
    {"multiple strings, delete at too large position",
 {"foo""baz""bar"0}, 0, test_argv_bad_delete3,
 "argv_delete bad range: (start=100 count=1)"
    },
    {"argv_join, multiple strings",
 {"foo""baz""bar"0}, 0, test_argv_join,
 01, {"foo:baz:bar"0}, ':'
    },
    {"argv_join, one string",
 {"foo"0}, 0, test_argv_join,
 01, {"foo"0}, ':'
    },
    {"argv_join, empty",
 {0}, 0, test_argv_join,
 01, {""0}, ':'
    },
    {"argv_addv appends to ARGV",
 {"foo""baz""bar"0}, /* ignored */ 0, test_argv_addv_appends,
 03, {"foo""baz""bar"0}
    },
    {"argv_addv creates ARGV",
 {"foo""baz""bar"0}, /* ignored */ 0, test_argv_addv_creates,
 03, {"foo""baz""bar"0}
    },
    0,
};

int     main(int argc, char **argv)
{
    const TEST_CASE *tp;
    int     pass = 0;
    int     fail = 0;

    msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);

    for (tp = test_cases; tp->label != 0; tp++) {
 int     test_failed;
 ARGV   *argvp;

 argvp = argv_alloc(1);
 if (setjmp(test_panic_jbuf) == 0)
     argvp = tp->populate_fn(tp, argvp);
 test_failed = test_argv_verify(tp, argvp);
 if (test_failed) {
     msg_info("%s: FAIL", tp->label);
     fail++;
 } else {
     msg_info("%s: PASS", tp->label);
     pass++;
 }
 argv_free(argvp);
 if (test_panic_str) {
     vstring_free(test_panic_str);
     test_panic_str = 0;
 }
    }
    msg_info("PASS=%d FAIL=%d", pass, fail);
    exit(fail != 0);
}

#endif

Messung V0.5 in Prozent
C=83 H=93 G=87

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.