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
|
PROGRAM = crc32
|
||||||
.PHONY: all clean install
|
.PHONY: all clean install
|
||||||
FILES = main.c
|
FILES = main.c args.c
|
||||||
|
|
||||||
CFLAGS += -Wall -Werror -ansi -pedantic
|
CFLAGS += -Wall -Werror -ansi -pedantic
|
||||||
LDFLAGS +=
|
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.
|
* copy of the license along with this program; see the file LICENSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ARGS_H_
|
void args_parse(int argc, char** argv,
|
||||||
#define ARGS_H_
|
void flagfn(char, char*()), void plainfn(char*));
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
|
|
103
main.c
103
main.c
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
|
@ -25,69 +26,55 @@ static char print_binary = 0;
|
||||||
static char xor_output = 1;
|
static char xor_output = 1;
|
||||||
static char reflect_output = 0;
|
static char reflect_output = 0;
|
||||||
|
|
||||||
char args_info[] = "crc32 - 32-bit cyclic redundancy check calculator\n";
|
const char help1[] = "\
|
||||||
char args_usage[] = "Usage: %s [-i f] [-s n] [-p n] [-e] [-x] [-r] [-b]\n";
|
crc32 - a 32-bit cyclic rendundancy check calculator\n\
|
||||||
void args_print_help_suffix()
|
\n\
|
||||||
{
|
-h display this text\n\
|
||||||
puts("\n\
|
-i <file> open file for reading (default: stdin)\n\
|
||||||
numbers (n) can be entered as hexadecimal or octal with prefixes");
|
-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\
|
||||||
|
";
|
||||||
|
|
||||||
const int args_switch_count = 9;
|
void handle_flag(char flag, char* (*nextarg)()) {
|
||||||
char* args_switches[] = {
|
/* TODO: check for NULL on nextarg */
|
||||||
"-h","--help"," display this text",
|
switch (flag) {
|
||||||
" ","--license"," show copyright & license information",
|
case 'h':
|
||||||
"-i","--input","f open file f for reading (default: stdin)",
|
printf(help1);
|
||||||
"-s","--start-at","n start cycle with n (default: 0xFFFFFFFF)",
|
printf(help2);
|
||||||
"-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);
|
exit(0);
|
||||||
}
|
case 'i':
|
||||||
|
input_filename = nextarg();
|
||||||
void start_at()
|
break;
|
||||||
{
|
case 's':
|
||||||
remainder = strtoul(args_poll(), NULL, 0);
|
remainder = strtoul(nextarg(), NULL, 0);
|
||||||
}
|
break;
|
||||||
|
case 'p':
|
||||||
void set_input()
|
crc_set_polynomial(strtoul(nextarg(), NULL, 0));
|
||||||
{
|
break;
|
||||||
input_filename = args_poll();
|
case 'e':
|
||||||
}
|
crc_set_big_endian();
|
||||||
|
break;
|
||||||
void set_polynomial()
|
case 'b':
|
||||||
{
|
|
||||||
const int p = strtoul(args_poll(), NULL, 0);
|
|
||||||
crc_set_polynomial(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_binary()
|
|
||||||
{
|
|
||||||
print_binary = 1;
|
print_binary = 1;
|
||||||
}
|
break;
|
||||||
|
case 'x':
|
||||||
void set_xor()
|
|
||||||
{
|
|
||||||
xor_output = 0;
|
xor_output = 0;
|
||||||
}
|
break;
|
||||||
|
case 'r':
|
||||||
void set_reflect()
|
|
||||||
{
|
|
||||||
reflect_output = 1;
|
reflect_output = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(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()
|
static void open_stream()
|
||||||
{
|
{
|
||||||
|
@ -135,7 +122,7 @@ static void print_crc()
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
crc_set_little_endian();
|
crc_set_little_endian();
|
||||||
args_handle(argc, argv);
|
args_parse(argc, argv, handle_flag, NULL);
|
||||||
cycle_input();
|
cycle_input();
|
||||||
print_crc();
|
print_crc();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue