enum keys {
    KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
    KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
    KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
    KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
    KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
    KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
    KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
    KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm, KEY_signature,
    KEY_unknown
};

/* Lookup table for program options */
struct {
    char *name;
    enum keys key;
    int num_plas;
    bool needs_offset;
    bool needs_dcset;
} option_table [] = {
    /* ways to minimize functions */
    {"ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE},    /* must be first */
    {"many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE},
    {"exact", KEY_exact, 1, TRUE, TRUE},
    {"qm", KEY_qm, 1, TRUE, TRUE},
    {"single_output", KEY_so, 1, TRUE, TRUE},
    {"so", KEY_so, 1, TRUE, TRUE},
    {"so_both", KEY_so_both, 1, TRUE, TRUE},
    {"simplify", KEY_simplify, 1, FALSE, FALSE},
    {"echo", KEY_echo, 1, FALSE, FALSE},
    {"signature", KEY_signature, 1, TRUE, TRUE},

    /* output phase assignment and assignment of inputs to two-bit decoders */
    {"opo", KEY_opo, 1, TRUE, TRUE},
    {"opoall", KEY_opoall, 1, TRUE, TRUE},
    {"pair", KEY_pair, 1, TRUE, TRUE},
    {"pairall", KEY_pairall, 1, TRUE, TRUE},

    /* Ways to check covers */
    {"check", KEY_check, 1, TRUE, TRUE},
    {"stats", KEY_stats, 1, FALSE, FALSE},
    {"verify", KEY_verify, 2, FALSE, TRUE},
    {"PLAverify", KEY_PLA_verify, 2, FALSE, TRUE},

    /* hacks */
    {"equiv", KEY_equiv, 1, TRUE, TRUE},
    {"map", KEY_map, 1, FALSE, FALSE},
    {"mapdc", KEY_mapdc, 1, FALSE, FALSE},
    {"fsm", KEY_fsm, 1, FALSE, TRUE},

    /* the basic boolean operations on covers */
    {"contain", KEY_contain, 1, FALSE, FALSE},
    {"d1merge", KEY_d1merge, 1, FALSE, FALSE},
    {"d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE},
    {"disjoint", KEY_disjoint, 1, TRUE, FALSE},
    {"dsharp", KEY_dsharp, 2, FALSE, FALSE},
    {"intersect", KEY_intersect, 2, FALSE, FALSE},
    {"minterms", KEY_minterms, 1, FALSE, FALSE},
    {"primes", KEY_primes, 1, FALSE, TRUE},
    {"separate", KEY_separate, 1, TRUE, TRUE},
    {"sharp", KEY_sharp, 2, FALSE, FALSE},
    {"union", KEY_union, 2, FALSE, FALSE},
    {"xor", KEY_xor, 2, TRUE, TRUE},

    /* debugging only -- call each step of the espresso algorithm */
    {"essen", KEY_essen, 1, FALSE, TRUE},
    {"expand", KEY_expand, 1, TRUE, FALSE},
    {"gasp", KEY_gasp, 1, TRUE, TRUE},
    {"irred", KEY_irred, 1, FALSE, TRUE},
    {"make_sparse", KEY_make_sparse, 1, TRUE, TRUE},
    {"reduce", KEY_reduce, 1, FALSE, TRUE},
    {"taut", KEY_taut, 1, FALSE, FALSE},
    {"super_gasp", KEY_super_gasp, 1, TRUE, TRUE},
    {"lexsort", KEY_lexsort, 1, FALSE, FALSE},
    {"test", KEY_test, 1, TRUE, TRUE},
    {0, KEY_unknown, 0, FALSE, FALSE}             /* must be last */
};


struct {
    char *name;
    int value;
} debug_table[] = {
    {"", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV},
    {"compl",   COMPL},  {"essen",       ESSEN},
    {"expand",  EXPAND}, {"expand1",     EXPAND1|EXPAND},
    {"irred",   IRRED},  {"irred1",      IRRED1|IRRED},
    {"reduce",  REDUCE}, {"reduce1",     REDUCE1|REDUCE},
    {"mincov",  MINCOV}, {"mincov1",     MINCOV1|MINCOV},
    {"sparse",  SPARSE}, {"sharp",       SHARP},
    {"taut",    TAUT},   {"gasp",        GASP},
    {"exact",   EXACT},
    {0, 0}
};


struct {
    char *name;
    int *variable;
    int value;
} esp_opt_table[] = {
    {"eat", &echo_comments, FALSE},
    {"eatdots", &echo_unknown_commands, FALSE},
    {"fast", &single_expand, TRUE},
    {"kiss", &kiss, TRUE},
    {"ness", &remove_essential, FALSE},
    {"nirr", &force_irredundant, FALSE},
    {"nunwrap", &unwrap_onset, FALSE},
    {"onset", &recompute_onset, TRUE},
    {"pos", &pos, TRUE},
    {"random", &use_random_order, FALSE},
    {"strong", &use_super_gasp, TRUE},
    {0, 0, 0}
};
