rewrote args handler
This commit is contained in:
parent
113e68a1f5
commit
2a770f0987
4 changed files with 108 additions and 242 deletions
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
PROGRAM = crc32
|
||||
.PHONY: all clean install
|
||||
FILES = main.c
|
||||
FILES = main.c args.c
|
||||
|
||||
CFLAGS += -Wall -Werror -ansi -pedantic
|
||||
LDFLAGS +=
|
||||
|
|
55
args.c
Normal file
55
args.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (C) 2012 Connor Olding
|
||||
*
|
||||
* This program is licensed under the terms of the MIT License, and
|
||||
* is distributed without any warranty. You should have received a
|
||||
* copy of the license along with this program; see the file LICENSE.
|
||||
*/
|
||||
|
||||
#include "args.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static int argc, argi;
|
||||
static char** argv, * flag;
|
||||
|
||||
static char* nextarg()
|
||||
{
|
||||
char* temp = flag;
|
||||
flag = NULL;
|
||||
if (temp[1])
|
||||
return temp + 1;
|
||||
if (++argi == argc)
|
||||
return NULL;
|
||||
return argv[argi];
|
||||
}
|
||||
|
||||
void args_parse(int argc_, char** argv_,
|
||||
void flagfn(char, char*()), void plainfn(char*))
|
||||
{
|
||||
argc = argc_;
|
||||
argv = argv_;
|
||||
for (argi = 1; argi < argc; argi++) {
|
||||
char* arg = argv[argi];
|
||||
if (!arg[0])
|
||||
continue;
|
||||
|
||||
/* if ... || arg == "-" */
|
||||
if (arg[0] != '-' || !arg[1]) {
|
||||
if (plainfn)
|
||||
plainfn(arg);
|
||||
continue;
|
||||
}
|
||||
/* if arg == "--" */
|
||||
if (arg[1] == '-' && !arg[2])
|
||||
break;
|
||||
|
||||
for (flag = arg + 1; *flag; flag++) {
|
||||
flagfn(*flag, nextarg);
|
||||
if (!flag)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; argi < argc; argi++)
|
||||
if (plainfn)
|
||||
plainfn(argv[argi]);
|
||||
}
|
||||
|
180
args.h
180
args.h
|
@ -5,182 +5,6 @@
|
|||
* copy of the license along with this program; see the file LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef ARGS_H_
|
||||
#define ARGS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* interface */
|
||||
|
||||
extern char args_info[];
|
||||
extern char args_usage[];
|
||||
extern void args_print_help_suffix();
|
||||
|
||||
extern const int args_switch_count;
|
||||
extern char* args_switches[];
|
||||
extern void (*args_functions[])();
|
||||
|
||||
void args_handle(int argc, char* argv[]);
|
||||
char* args_poll();
|
||||
void args_print_help();
|
||||
|
||||
/* implemenation */
|
||||
|
||||
static const int args_columns = 3;
|
||||
|
||||
static char* args_program_name = NULL;
|
||||
|
||||
static int args_argc = 0;
|
||||
static char** args_argv = NULL;
|
||||
|
||||
static int args_current = 0;
|
||||
static int args_previous = 0;
|
||||
static char* args_previous_name = NULL;
|
||||
|
||||
static char args_is_blank(char* s)
|
||||
{
|
||||
if (s == NULL || s[0] == '\0' || s[0] == ' ')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char args_is_short(char *s)
|
||||
{
|
||||
if (!args_is_blank(s) && s[0] == '-' && s[1] != '\0' && s[1] != '-')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void args_print_info()
|
||||
{
|
||||
printf(args_info);
|
||||
}
|
||||
|
||||
static void args_print_usage()
|
||||
{
|
||||
printf(args_usage, args_program_name);
|
||||
}
|
||||
|
||||
static void args_print_switches()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < args_switch_count * args_columns; i += args_columns) {
|
||||
printf(" ");
|
||||
if (args_is_blank(args_switches[i])) {
|
||||
printf(" ");
|
||||
} else {
|
||||
printf("%s,", args_switches[i]);
|
||||
}
|
||||
printf(" %s %s\n",
|
||||
args_switches[i + 1],
|
||||
args_switches[i + 2]);
|
||||
}
|
||||
args_print_help_suffix();
|
||||
}
|
||||
|
||||
void args_print_help()
|
||||
{
|
||||
args_print_info();
|
||||
puts("");
|
||||
args_print_switches();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void args_check_bounds()
|
||||
{
|
||||
if (args_current >= args_argc) {
|
||||
if (args_current - 1 == args_previous)
|
||||
fprintf(stderr, "%s requires an argument.\n",
|
||||
args_previous_name);
|
||||
else
|
||||
fprintf(stderr, "%s requires another argument.\n",
|
||||
args_previous_name);
|
||||
args_print_usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int args_get_index(char* name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < args_switch_count * args_columns; i++) {
|
||||
if (i % args_columns == args_columns - 1)
|
||||
continue; /* skip checking the description column */
|
||||
if (args_is_blank(args_switches[i]))
|
||||
continue;
|
||||
if (!strcmp(args_switches[i], name))
|
||||
return i / args_columns;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char* args__poll(char wants_switch)
|
||||
{
|
||||
static char short_[3] = "--";
|
||||
static int pos = 0;
|
||||
char* arg = NULL;
|
||||
|
||||
args_check_bounds();
|
||||
|
||||
arg = args_argv[args_current];
|
||||
if (!wants_switch) {
|
||||
args_current++;
|
||||
arg += pos * sizeof(char);
|
||||
pos = 0;
|
||||
return arg;
|
||||
}
|
||||
if (args_is_short(arg)) {
|
||||
if (pos == 0)
|
||||
pos++;
|
||||
short_[1] = arg[pos];
|
||||
pos++;
|
||||
if (arg[pos] == '\0') {
|
||||
pos = 0;
|
||||
args_current++;
|
||||
}
|
||||
return short_;
|
||||
}
|
||||
args_current++;
|
||||
return arg;
|
||||
}
|
||||
|
||||
static char* args_poll_for_switch()
|
||||
{
|
||||
return args__poll(1);
|
||||
}
|
||||
|
||||
char* args_poll()
|
||||
{
|
||||
return args__poll(0);
|
||||
}
|
||||
|
||||
void args_handle(int argc, char** argv)
|
||||
{
|
||||
args_argc = argc;
|
||||
args_argv = argv;
|
||||
|
||||
args_current = 0;
|
||||
args_program_name = args_poll();
|
||||
|
||||
while (args_current < args_argc) {
|
||||
char* name;
|
||||
int index;
|
||||
|
||||
args_previous = args_current;
|
||||
name = args_poll_for_switch();
|
||||
args_previous_name = name;
|
||||
|
||||
index = args_get_index(name);
|
||||
if (index < 0) {
|
||||
fprintf(stderr, "Unknown option: %s\n", name);
|
||||
args_print_usage();
|
||||
exit(1);
|
||||
}
|
||||
args_functions[index]();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void args_parse(int argc, char** argv,
|
||||
void flagfn(char, char*()), void plainfn(char*));
|
||||
|
||||
|
|
113
main.c
113
main.c
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crc32.h"
|
||||
#include "args.h"
|
||||
|
@ -25,70 +26,56 @@ static char print_binary = 0;
|
|||
static char xor_output = 1;
|
||||
static char reflect_output = 0;
|
||||
|
||||
char args_info[] = "crc32 - 32-bit cyclic redundancy check calculator\n";
|
||||
char args_usage[] = "Usage: %s [-i f] [-s n] [-p n] [-e] [-x] [-r] [-b]\n";
|
||||
void args_print_help_suffix()
|
||||
{
|
||||
puts("\n\
|
||||
numbers (n) can be entered as hexadecimal or octal with prefixes");
|
||||
const char help1[] = "\
|
||||
crc32 - a 32-bit cyclic rendundancy check calculator\n\
|
||||
\n\
|
||||
-h display this text\n\
|
||||
-i <file> open file for reading (default: stdin)\n\
|
||||
-s <n> start cycle with n (default: 0xFFFFFFFF)\n\
|
||||
-p <n> use n as the crc divisor (default: 0x04C11DB7)\n\
|
||||
-e use big endian calculations\n\
|
||||
-b output as binary\n\
|
||||
-x xor the output by 0xFFFFFFFF\n\
|
||||
-r reverse the bits of the output\n\
|
||||
\n\
|
||||
";
|
||||
const char help2[] = "\
|
||||
numbers <n> may be entered as hexadecimal or octal with prefixes\n\
|
||||
";
|
||||
|
||||
void handle_flag(char flag, char* (*nextarg)()) {
|
||||
/* TODO: check for NULL on nextarg */
|
||||
switch (flag) {
|
||||
case 'h':
|
||||
printf(help1);
|
||||
printf(help2);
|
||||
exit(0);
|
||||
case 'i':
|
||||
input_filename = nextarg();
|
||||
break;
|
||||
case 's':
|
||||
remainder = strtoul(nextarg(), NULL, 0);
|
||||
break;
|
||||
case 'p':
|
||||
crc_set_polynomial(strtoul(nextarg(), NULL, 0));
|
||||
break;
|
||||
case 'e':
|
||||
crc_set_big_endian();
|
||||
break;
|
||||
case 'b':
|
||||
print_binary = 1;
|
||||
break;
|
||||
case 'x':
|
||||
xor_output = 0;
|
||||
break;
|
||||
case 'r':
|
||||
reflect_output = 1;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const int args_switch_count = 9;
|
||||
char* args_switches[] = {
|
||||
"-h","--help"," display this text",
|
||||
" ","--license"," show copyright & license information",
|
||||
"-i","--input","f open file f for reading (default: stdin)",
|
||||
"-s","--start-at","n start cycle with n (default: 0xFFFFFFFF)",
|
||||
"-p","--polynomial","n use n as the crc divisor (default: 0x04C11DB7)",
|
||||
"-e","--big-endian"," use big endian calculations (default: little)",
|
||||
"-b","--binary"," output as binary (default: hex with newline)",
|
||||
"-x","--xor"," xor the output by 0xFFFFFFFF",
|
||||
"-r","--reflect"," reverse the bits of the output",
|
||||
};
|
||||
|
||||
void print_license()
|
||||
{
|
||||
puts("crc32 Copyright (C) 2012 Connor Olding\n\
|
||||
This program comes with ABSOLUTELY NO WARRANTY, and is free software.\n\
|
||||
See the file \"LICENSE\" or <http://gnu.org/licenses/gpl.txt> for details.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void start_at()
|
||||
{
|
||||
remainder = strtoul(args_poll(), NULL, 0);
|
||||
}
|
||||
|
||||
void set_input()
|
||||
{
|
||||
input_filename = args_poll();
|
||||
}
|
||||
|
||||
void set_polynomial()
|
||||
{
|
||||
const int p = strtoul(args_poll(), NULL, 0);
|
||||
crc_set_polynomial(p);
|
||||
}
|
||||
|
||||
void set_binary()
|
||||
{
|
||||
print_binary = 1;
|
||||
}
|
||||
|
||||
void set_xor()
|
||||
{
|
||||
xor_output = 0;
|
||||
}
|
||||
|
||||
void set_reflect()
|
||||
{
|
||||
reflect_output = 1;
|
||||
}
|
||||
|
||||
void (*args_functions[])() =
|
||||
{args_print_help, print_license, set_input, start_at, set_polynomial,
|
||||
crc_set_big_endian, set_binary, set_xor, set_reflect};
|
||||
|
||||
static void open_stream()
|
||||
{
|
||||
const char mode[] = "rb";
|
||||
|
@ -135,7 +122,7 @@ static void print_crc()
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
crc_set_little_endian();
|
||||
args_handle(argc, argv);
|
||||
args_parse(argc, argv, handle_flag, NULL);
|
||||
cycle_input();
|
||||
print_crc();
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue