/*
 * Main program that combines the previously separate programs prload,
 * prsave, prcart, prsample, prrfile, prwfile, prdisk.
 * 
 * Each of the components can be selected by renaming or linking the
 * executable to one of the names, or by supplying an initial parameter of
 * the form --name.
 */

#include <stdio.h>

#define __MAIN_C__
#include "prtrans.h"

struct program {
    char           *name;
    main_t         *main;
};

struct program  plist[] = {
    "prcart",	&main_prcart,
    "prdisk",   &main_prdisk,
    "prload",	&main_prload,
    "prrfile",	&main_prrfile,
    "prsample",	&main_prsample,
    "prsave",	&main_prsave,
    "prwfile",	&main_prwfile,
    NULL, NULL
};

struct program *p;

int
findmain(int argc, char **argv)
{
    char           *myname = argv[0];

    for (p = &plist[0]; p->name; p++) {
	if (strcmp(p->name, myname) == 0) {
	    /* Name matches, call appropriate main_ function */
	    return (*p->main)(argc, argv);
	}
    }
    p = NULL;
    return -1;
}

int
main(int argc, char **argv)
{
    char           *myname = argv[0];
    int             exitcode = -1;

    /* First attempt, try first argument */
    if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
	/* Adjust arguments */
	int             ac = argc - 1;
	char          **av = &argv[1];

	av[0] += 2;
	exitcode = findmain(ac, av);
	av[0] -= 2;
    }

    if (p == NULL) {
	/* Second, check the name by which we were invoked */
	exitcode = findmain(argc, argv);
    }

    if (p == NULL) {
	/* Still no go, thow up hands in despair */
	fprintf(stderr,
		"%s: must specify which function to fulfill, either by renaming the\n"
		"executable or specifying a first argument of --name.\n"
		"Available functions are:\n",
		myname);
	for (p = &plist[0]; p->name; p++) {
	    fprintf(stderr, "\t%s\n", p->name);
	}
    }
    return exitcode;
}

/*
 * This is not strictly conforming.
 */
int
vmain(main_t *main, int argc, char *argv0,...)
{
    return (*main)(argc, &argv0);
}

#if 0
#include <stdarg.h>

/*
 * This is strictly conforming but rather inefficient, and makes this
 * whole function rather pointless. We wanted to avoid creating explicit
 * argv[] arrays...
 */
int
vmain(main_t *main, int argc, ...)
{
    char           *av[10];
    int             ac;
    va_list         ap;

    if (argc >= 10)
	return -1;		/* too many arguments */

    va_start(ap, argc);

    for (ac = 0; ac < argc; ac++)
	av[ac] = va_arg(ap, char *);

    va_end(ap);

    av[argc] = NULL;

    return (*main)(argc, av);
}

#endif
