static char rcsver[] = "$Id: vanilla.c,v 2.2 1999/07/12 23:14:08 gorelick Exp $";
static char source_path[] = "$Source: /tes/src/vanilla/RCS/vanilla.c,v $";
 
/**
 ** $Source: /tes/src/vanilla/RCS/vanilla.c,v $
 **
 ** $Log: vanilla.c,v $
 ** Revision 2.2  1999/07/12 23:14:08  gorelick
 ** *** empty log message ***
 **
 ** Revision 2.1  1999/02/10 04:00:50  gorelick
 ** *** empty log message ***
 **
 ** Revision 2.0  1998/12/22 22:47:04  gorelick
 ** release version
 **
 ** Revision 2.0  1998/12/18 01:31:40  gorelick
 ** release version
 **
 ** Revision 1.13  1998/12/18 01:04:48  gorelick
 ** *** empty log message ***
 **
 ** Revision 1.12  1998/12/01 22:42:06  gorelick
 ** *** empty log message ***
 **
 ** Revision 1.11  1998/11/18 00:13:47  gorelick
 ** exit on error now.
 **
 ** Revision 1.10  1998/11/12 22:58:55  gorelick
 ** first release version
 **
 **/

#include <stdio.h>
#include <sys/types.h>
#include "header.h"
#include "version.h"

char *big_endian = 
	"This executable was compiled using the _LITTLE_ENDIAN flag\n"
	"but is actually running on a big endian machine.  You need\n"
	"to recompile without this flag.\n\n"
	"Execution Aborted.\n";

char *little_endian = 
	"This executable was compiled without using the _LITTLE_ENDIAN flag\n"
	"but is actually running on a little endian machine.  You need\n"
	"to recompile with this flag.\n\n"
	"Execution Aborted.\n";

/**
 ** Procedure order:
 **
 ** load dataset
 ** set up selects
 ** set up engine slices
 ** set up output structs (needs slices)
 ** set up buffers
 **/

LIST *olist;

main(int ac, char **av)
{
    char *d=NULL, *fields = NULL, *select = NULL;
    int i, j;
    OSTRUCT *o;
    DATASET *dataset;
    TABLE *t;

    SLICE **slice;
    SEQ keyseq;		/* sequenced keys */

	/**
	 ** Test for endian-ness
	 **/
	 {
		int i = 0x12345678;
		char *p = (char *)&i;
		if (p[0] != 0x12) {
#ifndef _LITTLE_ENDIAN
			exit(fprintf(stderr, little_endian));
#endif
		} else {
#ifdef _LITTLE_ENDIAN
			exit(fprintf(stderr, big_endian));
#endif
		}
	 }

    if (ac == 1) {
        exit(usage(av[0]));
    }

    for (i = 1 ; i < ac ; i++) {
        if (av[i] == NULL) continue;

        if (av[i][0] == '-') {
            if (!strcmp(av[i], "-fields")) {
                fields = av[i+1];
                av[i+1] = NULL;
            } else if (!strcmp(av[i], "-select")) {
                select = av[i+1];
                av[i+1] = NULL;
            } else if (!strcasecmp(av[i], "-v")) {
                printf("%s\n", version);
                exit(1);
            }
        } else {
            d = av[i];
        }
    }

    /**
    ** Load the specified dataset
    **/

    if (d == NULL) exit(fprintf(stderr, "No directory specified\n"));

	fix_path(d);
    if ((dataset = LoadDataset(NULL, d)) == NULL)
        exit(fprintf(stderr, "Unable to load dataset: %s\n", d));

    if (dataset->tables->number == 0) {
        exit(fprintf(stderr, "No tables in dataset.\n"));
    }

    /**
    ** Convert and user specified select strings
    **/
    if (select != NULL) {
        if (ConvertSelect(dataset, select) == 0) exit(1);
    }

    /**
    ** init the output structures
    **/
    olist = ConvertOutput(fields, dataset->tables);

    /**
    ** Limit tables to be only those we care about (selects & output)
    **/
    CollectTables(dataset, olist);
    if (olist->number == 0) {
        exit(1);
    }


    sequence_keys(&keyseq, (TABLE **)dataset->tables->ptr, dataset->tables->number);
    slice = init_slices((TABLE **)dataset->tables->ptr, dataset->tables->number, keyseq);


    setup_output_parameters(olist->ptr, olist->number, 0);

    for (i = 0 ;  i < olist->number ; i++) {
        for (j = 0 ; j < dataset->tables->number ; j++) {
            t = dataset->tables->ptr[j];
            o = olist->ptr[i];
            if (o->table == t) {
                o->slice = &slice[keyseq.count][j];
            }
        }
    }

    OutputHeader(olist);

    search(0, keyseq.count, slice, 
           dataset->tables->ptr, dataset->tables->number);
}

generate_output()
{
    output_rec(olist->ptr, olist->number);
	fflush(stdout);
}

CollectTables(DATASET *dataset, LIST *olist)
{
    LIST *list = new_list();
    LIST *t = dataset->tables;
    int *x;
    int i,j;
    TABLE *t1, *t2;

    x = calloc(t->number, sizeof(int));

    for (i = 0 ; i < t->number ; i++) {
        if (((TABLE **)t->ptr)[i]->selects) x[i]++;
    }

    for (i = 0 ; i < t->number ; i++) {
        t1 = ((TABLE **)(t->ptr))[i];
        for (j = 0 ; j < olist->number ; j++) {
            t2 = ((OSTRUCT **)(olist->ptr))[j]->field->label->table;
            if (t2 == t1) {
                x[i]++;
                break;
            }
        }
    }
    for (i = 0 ; i < t->number ; i++) {
        if (x[i]) {
            list_add(list, ((TABLE **)t->ptr)[i]);
        }
    }

    list_free(dataset->tables);
    dataset->tables = list;
}

char *usage_str =
"usage: %s [options] directory\n"
"\n"
"Options:\n"
"-fields 'field1 field2 ...'                          (required)\n"
"-select 'field1 low high field2 low high ...'        (required)\n";

usage(char *prog)
{
    fprintf(stderr, usage_str, prog);
    return(-1);
}

#define ListElement(a, b, c) 	((a)(b)->ptr)[c]

OutputHeader(LIST *olist)
{
    int i,j;
    int n = olist->number;
    OSTRUCT *o;

    for (j = 0 ; j < n ; j++) {
        o = ListElement(OSTRUCT **, olist, j);
        if (o->field->dimension > 0 || o->field->vardata) { /* An array field */
            for (i = o->cooked.range.start; i <= o->cooked.range.end; i++){
                printf("%s[%d]", o->text, i);
                if (i != o->cooked.range.end) printf("%c", O_DELIM);
            }
        } else {
            printf("%s", o->text);
        }
        if (j != n) printf("%c", O_DELIM);
    }
    printf("\n");
}

fix_path(char *p)
{
	while(p && *p) {
		if (*p == '\\') *p = '/';
		p++;
	}
}