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