Files
hustoj/core/sim/sim_3_01/options.c
2024-10-10 12:56:56 +08:00

215 lines
4.2 KiB
C

/* This file is part of the software similarity tester SIM.
Written by Dick Grune, Vrije Universiteit, Amsterdam.
$Id: options.c,v 1.20 2017-03-19 09:30:37 dick Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include "sim.h"
#include "token.h"
#include "language.h"
#include "options.h"
static char options[128];
static void bad_option_exit(
const char *progname, const struct option *optlist,
char *msg, int c
);
static int opt_value(
const char *progname, const struct option *op,
const char *arg, const char *argv[]
);
static int do_arg(
const char *progname, const struct option *optlist,
const char *arg, const char *argv[]
);
int
do_options(
const char *progname, const struct option *optlist,
int argc, const char *argv[]
) {
int skips = 0;
while (argc > 0 && argv[0][0] == '-') {
int consumed = do_arg(progname, optlist, &argv[0][1], argv);
argc -= consumed, argv += consumed, skips += consumed;
}
return skips;
}
void
set_option(char ch) {
options[(int)ch]++;
}
int
is_set_option(int ch) {
return options[ch];
}
static int
do_arg(
const char *progname, const struct option *optlist,
const char *arg, const char *argv[]
) {
int consumed = 0;
while (*arg) {
/* treat argument character */
char opc = *arg++;
const struct option *op;
for (op = optlist; op->op_char; op++) {
if (opc == op->op_char) {
set_option(opc);
if (op->op_type != None) {
consumed = opt_value(
progname, op, arg, argv
);
}
break;
}
}
if (!op->op_char) {
bad_option_exit(progname, optlist,
"option -%c unknown", opc
);
/*NOTREACHED*/
}
if (consumed) break;
}
if (!consumed) {
consumed = 1;
}
return consumed;
}
static int
opt_value(
const char *progname, const struct option *op,
const char *arg, const char *argv[]
) {
/* get the string and the number of args consumed */
const char *string;
int consumed;
if (*arg) {
string = arg, consumed = 1;
}
else if (argv[1]) {
string = argv[1], consumed = 2;
} else {
string = 0, consumed = 0;
}
if (!string || !*string) {
bad_option_exit(progname, (struct option *)0,
"option -%c requires another argument", op->op_char
);
/*NOTREACHED*/
}
switch (op->op_type) {
case Number:
*(int *)op->op_value = atoi(string);
break;
case String:
*(const char **)op->op_value = string;
break;
}
return consumed;
}
void
allow_at_most_one_option_out_of(const char *opts) {
const char *first;
for (first = opts; *first; first++) {
const char *second;
for (second = first + 1; *second; second++) {
if (is_set_option(*first) &&is_set_option(*second)) {
char msg[256];
sprintf(msg,
"options -%c and -%c are incompatible",
*first, *second
);
fatal(msg);
}
}
}
}
static void
bad_option_exit(
const char *progname, const struct option *optlist, char *msg, int c
) {
fprintf(stderr, "%s: ", progname);
fprintf(stderr, msg, c);
fprintf(stderr, "\n");
fprintf(stderr, "Possible options are:\n");
const struct option *op;
for (op = optlist; op->op_char; op++) {
if (op->op_char == ' ') {
fprintf(stderr, "\n\t\t%s\n", op->op_text);
} else {
fprintf(stderr, "\t-%c%c\t%s\n",
op->op_char,
( op->op_type == Number ? 'N' :
op->op_type == String ? 'F' :
' '
),
op->op_text
);
}
}
exit(1);
}
static int
is_essential_option(char op_char) {
if (op_char == 'r') return 1;
if (op_char == 'w') return 1;
if (is_set_option('p') && op_char == 't') return 1;
return 0;
}
void
print_options(const char *progname, const struct option *optlist) {
const struct option *op;
if (!is_set_option('T')) {
fprintf(stdout, "%s (%s)\n", progname, Version);
fprintf(stdout, "Subject: %s\n", Subject);
}
fprintf(stdout, "Option settings:");
if (!is_set_option('T')) fprintf(stdout, "\n");
for (op = optlist; op->op_char; op++) {
if ( is_set_option(op->op_char)
|| is_essential_option(op->op_char)
) {
fprintf(stdout, " -%c", op->op_char);
switch (op->op_type) {
case None: break;
case Number:
fprintf(stdout, "%d",
*(int *)op->op_value);
break;
case String:
fprintf(stdout, " %s",
*(const char **)op->op_value);
break;
}
if (!is_set_option('T')) {
fprintf(stdout, " (%s)\n", op->op_text);
}
}
}
if (is_set_option('T')) fprintf(stdout, "\n");
}