dc: fix "small dc" to have standard command line API
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -159,8 +159,7 @@ | ||||
| //usage: | ||||
| //usage:#define dc_full_usage "\n" | ||||
| //usage:     "\nTiny RPN calculator. Operations:" | ||||
| //usage:     "\n+, -, *, /, %, ^, exp, ~, divmod, |, " | ||||
| //usage:       "modular exponentiation," | ||||
| //usage:     "\n+, -, *, /, %, ~, ^, |," | ||||
| //usage:     "\np - print top of the stack (without popping)" | ||||
| //usage:     "\nf - print entire stack" | ||||
| //usage:     "\nk - pop the value and set the precision" | ||||
|   | ||||
| @@ -20,7 +20,6 @@ typedef unsigned long long data_t; | ||||
| #define DATA_FMT "ll" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| struct globals { | ||||
| 	unsigned pointer; | ||||
| 	unsigned base; | ||||
| @@ -36,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof( | ||||
| 	base = 10; \ | ||||
| } while (0) | ||||
|  | ||||
|  | ||||
| static void check_under(void) | ||||
| { | ||||
| 	if (pointer == 0) | ||||
| @@ -184,25 +182,25 @@ struct op { | ||||
|  | ||||
| static const struct op operators[] = { | ||||
| #if ENABLE_FEATURE_DC_LIBM | ||||
| 	{"**",  power}, | ||||
| 	{"exp", power}, | ||||
| 	{"pow", power}, | ||||
| 	{"^",   power}, | ||||
| //	{"exp", power}, | ||||
| //	{"pow", power}, | ||||
| #endif | ||||
| 	{"%",   mod}, | ||||
| 	{"mod", mod}, | ||||
| //	{"mod", mod}, | ||||
| 	// logic ops are not standard, remove? | ||||
| 	{"and", and}, | ||||
| 	{"or",  or}, | ||||
| 	{"not", not}, | ||||
| 	{"eor", eor}, | ||||
| 	{"xor", eor}, | ||||
| 	{"+",   add}, | ||||
| 	{"add", add}, | ||||
| //	{"add", add}, | ||||
| 	{"-",   sub}, | ||||
| 	{"sub", sub}, | ||||
| //	{"sub", sub}, | ||||
| 	{"*",   mul}, | ||||
| 	{"mul", mul}, | ||||
| //	{"mul", mul}, | ||||
| 	{"/",   divide}, | ||||
| 	{"div", divide}, | ||||
| //	{"div", divide}, | ||||
| 	{"p", print_no_pop}, | ||||
| 	{"f", print_stack_no_pop}, | ||||
| 	{"o", set_output_base}, | ||||
| @@ -243,24 +241,50 @@ static void stack_machine(const char *argument) | ||||
| 	bb_error_msg_and_die("syntax error at '%s'", argument); | ||||
| } | ||||
|  | ||||
| int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||||
| int dc_main(int argc UNUSED_PARAM, char **argv) | ||||
| static void process_file(FILE *fp) | ||||
| { | ||||
| 	INIT_G(); | ||||
|  | ||||
| //TODO: fix this, should take: dc -eSCRIPT -fFILE FILE | ||||
| 	argv++; | ||||
| 	if (!argv[0]) { | ||||
| 		/* take stuff from stdin if no args are given */ | ||||
| 	char *line; | ||||
| 		while ((line = xmalloc_fgetline(stdin)) != NULL) { | ||||
| 	while ((line = xmalloc_fgetline(fp)) != NULL) { | ||||
| 		stack_machine(line); | ||||
| 		free(line); | ||||
| 	} | ||||
| 	} else { | ||||
| 		do { | ||||
| 			stack_machine(*argv); | ||||
| 		} while (*++argv); | ||||
| } | ||||
|  | ||||
| int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||||
| int dc_main(int argc UNUSED_PARAM, char **argv) | ||||
| { | ||||
| 	bool script = 0; | ||||
|  | ||||
| 	INIT_G(); | ||||
|  | ||||
| 	/* Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs */ | ||||
| 	for (;;) { | ||||
| 		int n = getopt(argc, argv, "e:f:"); | ||||
| 		if (n <= 0) | ||||
| 			break; | ||||
| 		switch (n) { | ||||
| 		case 'e': | ||||
| 			script = 1; | ||||
| 			stack_machine(optarg); | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			script = 1; | ||||
| 			process_file(xfopen_for_read(optarg)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			bb_show_usage(); | ||||
| 		} | ||||
| 	} | ||||
| 	argv += optind; | ||||
|  | ||||
| 	if (*argv) { | ||||
| 		do | ||||
| 			process_file(xfopen_for_read(*argv++)); | ||||
| 		while (*argv); | ||||
| 	} else if (!script) { | ||||
| 		/* Take stuff from stdin if no args are given */ | ||||
| 		process_file(stdin); | ||||
| 	} | ||||
|  | ||||
| 	return EXIT_SUCCESS; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user