init
This commit is contained in:
commit
133ed9188a
3 changed files with 443 additions and 0 deletions
131
args.h
Normal file
131
args.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/* args.h - argument handling
|
||||||
|
Copyright (C) 2012 Connor Olding
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARGS_H_
|
||||||
|
#define ARGS_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* interface */
|
||||||
|
|
||||||
|
extern char args_info[];
|
||||||
|
extern char args_usage[];
|
||||||
|
extern char args_help_suffix[];
|
||||||
|
|
||||||
|
extern const int args_count;
|
||||||
|
extern char* args_args[];
|
||||||
|
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 void args_print_info()
|
||||||
|
{
|
||||||
|
printf(args_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void args_print_usage()
|
||||||
|
{
|
||||||
|
printf(args_usage, args_program_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void args_print_args()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < args_count * args_columns; i += args_columns) {
|
||||||
|
printf(" %s, %s %s\n",
|
||||||
|
args_args[i], args_args[i + 1], args_args[i + 2]);
|
||||||
|
}
|
||||||
|
printf(args_help_suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
void args_print_help()
|
||||||
|
{
|
||||||
|
args_print_info();
|
||||||
|
puts("");
|
||||||
|
args_print_args();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int args_get_index(char* name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < args_count * args_columns; i++) {
|
||||||
|
if (i % args_columns == args_columns - 1)
|
||||||
|
continue; /* skip checking the description column */
|
||||||
|
if (!strcmp(args_args[i], name)) {
|
||||||
|
return i / args_columns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* args_poll()
|
||||||
|
{
|
||||||
|
if (args_current >= args_argc) {
|
||||||
|
if (args_current - 1 == args_previous)
|
||||||
|
fprintf(stderr, "%s requires an argument.\n",
|
||||||
|
args_argv[args_previous]);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s requires another argument.\n",
|
||||||
|
args_argv[args_previous]);
|
||||||
|
args_print_usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
args_current++;
|
||||||
|
return args_argv[args_current - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
index = args_get_index(name);
|
||||||
|
if (index < 0) {
|
||||||
|
fprintf(stderr, "Unknown option: %s\n", name);
|
||||||
|
args_print_usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
args_functions[index]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
161
crc32.h
Normal file
161
crc32.h
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/* crc32.h - 32-bit cyclic redundancy check calcuations
|
||||||
|
Copyright (C) 2012 Connor Olding
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRC32_H_
|
||||||
|
#define CRC32_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* interface */
|
||||||
|
|
||||||
|
typedef unsigned long uint32;
|
||||||
|
|
||||||
|
void crc_cycle(uint32 *remainder, char c);
|
||||||
|
uint32 crc_reflect(uint32 input);
|
||||||
|
|
||||||
|
void crc_set_big_endian();
|
||||||
|
void crc_set_little_endian();
|
||||||
|
void crc_set_polynomial(uint32 p);
|
||||||
|
|
||||||
|
/* implementation */
|
||||||
|
|
||||||
|
static char crc_big_endian = 0;
|
||||||
|
static const int crc_table_size = 0x100;
|
||||||
|
static uint32* crc_be_table = NULL; /* big endian */
|
||||||
|
static uint32* crc_le_table = NULL; /* little endian */
|
||||||
|
static uint32 crc_polynomial = 0x04C11DB7;
|
||||||
|
|
||||||
|
uint32 crc_reflect(uint32 input)
|
||||||
|
{
|
||||||
|
uint32 reflected = 0;
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < sizeof(uint32) * 8; i++) {
|
||||||
|
reflected <<= 1;
|
||||||
|
reflected |= input & 1;
|
||||||
|
input >>= 1;
|
||||||
|
}
|
||||||
|
return reflected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32* crc_alloc(size_t size)
|
||||||
|
{
|
||||||
|
uint32* p = (uint32*) malloc(size * sizeof(uint32));
|
||||||
|
if (p == NULL)
|
||||||
|
exit(1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crc_allocate_tables_once()
|
||||||
|
{
|
||||||
|
static char allocated = 0;
|
||||||
|
if (crc_big_endian && !(allocated & 1)) {
|
||||||
|
crc_be_table = crc_alloc(crc_table_size);
|
||||||
|
allocated |= 1;
|
||||||
|
} else if (!crc_big_endian && !(allocated & 2)) {
|
||||||
|
crc_le_table = crc_alloc(crc_table_size);
|
||||||
|
allocated |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crc_fill_big_endian_table()
|
||||||
|
{
|
||||||
|
const uint32 least_significant_bit = 1 << 31;
|
||||||
|
int c, i;
|
||||||
|
|
||||||
|
crc_allocate_tables_once();
|
||||||
|
|
||||||
|
for (c = 0; c < crc_table_size; c++) {
|
||||||
|
crc_be_table[c] = c << 24;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (crc_be_table[c] & least_significant_bit) {
|
||||||
|
crc_be_table[c] <<= 1;
|
||||||
|
crc_be_table[c] ^= crc_polynomial;
|
||||||
|
} else {
|
||||||
|
crc_be_table[c] <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crc_fill_little_endian_table()
|
||||||
|
{
|
||||||
|
const uint32 least_significant_bit = 1;
|
||||||
|
const uint32 reflected_polynomial = crc_reflect(crc_polynomial);
|
||||||
|
int c, i;
|
||||||
|
|
||||||
|
crc_allocate_tables_once();
|
||||||
|
/* printf("p: %08X\n", (int)reflected_polynomial); */
|
||||||
|
|
||||||
|
for (c = 0; c < crc_table_size; c++) {
|
||||||
|
crc_le_table[c] = c;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (crc_le_table[c] & least_significant_bit) {
|
||||||
|
crc_le_table[c] >>= 1;
|
||||||
|
crc_le_table[c] ^= reflected_polynomial;
|
||||||
|
} else {
|
||||||
|
crc_le_table[c] >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crc_fill_tables_once()
|
||||||
|
{
|
||||||
|
static char filled = 0;
|
||||||
|
if (crc_big_endian && !(filled & 1)) {
|
||||||
|
crc_fill_big_endian_table();
|
||||||
|
filled |= 1;
|
||||||
|
} else if (!crc_big_endian && !(filled & 2)) {
|
||||||
|
crc_fill_little_endian_table();
|
||||||
|
filled |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_set_big_endian()
|
||||||
|
{
|
||||||
|
crc_big_endian = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_set_little_endian()
|
||||||
|
{
|
||||||
|
crc_big_endian = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_set_polynomial(uint32 p)
|
||||||
|
{
|
||||||
|
crc_polynomial = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_cycle(uint32 *remainder, char c)
|
||||||
|
{
|
||||||
|
crc_fill_tables_once();
|
||||||
|
if (crc_big_endian) {
|
||||||
|
const uint32 newByte = crc_be_table[
|
||||||
|
((*remainder) >> 24) ^ c];
|
||||||
|
/* printf("%08X00 ^ %08X =\n",
|
||||||
|
(int)(*remainder), (int)newByte); */
|
||||||
|
*remainder = ((*remainder) << 8) ^ newByte;
|
||||||
|
} else {
|
||||||
|
const uint32 newByte = crc_le_table[
|
||||||
|
((*remainder) ^ c) & 0xFF];
|
||||||
|
/* printf(" %08X ^ %08X =\n",
|
||||||
|
(int)((*remainder) >> 8), (int)newByte); */
|
||||||
|
*remainder = ((*remainder) >> 8) ^ newByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
151
main.c
Normal file
151
main.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* crc32 - 32-bit cyclic redundancy check calculator
|
||||||
|
Copyright (C) 2012 Connor Olding
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "args.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define FREOPEN_BLANK ("")
|
||||||
|
#else
|
||||||
|
#define FREOPEN_BLANK (NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint32 remainder = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
static FILE* input_stream = NULL;
|
||||||
|
static char* input_name = "-";
|
||||||
|
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";
|
||||||
|
char args_help_suffix[] = "\n\
|
||||||
|
numbers (n) can be entered as hexadecimal or octal with prefixes\n";
|
||||||
|
|
||||||
|
const int args_count = 8;
|
||||||
|
|
||||||
|
char* args_args[] = {
|
||||||
|
"-h","--help"," display this text",
|
||||||
|
"-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 for crc calculations (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 start_at()
|
||||||
|
{
|
||||||
|
remainder = strtoul(args_poll(), NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_input()
|
||||||
|
{
|
||||||
|
input_name = args_poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_polynomial()
|
||||||
|
{
|
||||||
|
const int p = strtoul(args_poll(), NULL, 0);
|
||||||
|
crc_set_polynomial(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_big_endian()
|
||||||
|
{
|
||||||
|
crc_set_big_endian();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_binary()
|
||||||
|
{
|
||||||
|
print_binary = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_xor()
|
||||||
|
{
|
||||||
|
xor_output = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_reflect()
|
||||||
|
{
|
||||||
|
reflect_output = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*args_functions[])() =
|
||||||
|
{args_print_help, set_input, start_at, set_polynomial,
|
||||||
|
set_big_endian, set_binary, set_xor, set_reflect};
|
||||||
|
|
||||||
|
static void open_stream()
|
||||||
|
{
|
||||||
|
const char mode[] = "rb";
|
||||||
|
if (!strcmp(input_name, "-")) {
|
||||||
|
freopen(FREOPEN_BLANK, mode, stdin);
|
||||||
|
input_stream = stdin;
|
||||||
|
} else {
|
||||||
|
input_stream = fopen(input_name, mode);
|
||||||
|
}
|
||||||
|
if (input_stream == NULL) {
|
||||||
|
fprintf(stderr, "Could not open file for reading: %s\n",
|
||||||
|
input_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_stream()
|
||||||
|
{
|
||||||
|
fclose(input_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cycle_input()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
open_stream();
|
||||||
|
while ((c = getc(input_stream)) != EOF) {
|
||||||
|
crc_cycle(&remainder, c);
|
||||||
|
}
|
||||||
|
close_stream();
|
||||||
|
|
||||||
|
if (xor_output)
|
||||||
|
remainder ^= 0xFFFFFFFF;
|
||||||
|
if (reflect_output)
|
||||||
|
remainder = crc_reflect(remainder);
|
||||||
|
/* if remainder has unnecessary bits from
|
||||||
|
left shifting, remove them
|
||||||
|
remainder &= 0xFFFFFFFF;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_crc()
|
||||||
|
{
|
||||||
|
if (print_binary)
|
||||||
|
fwrite(&remainder, sizeof(remainder), 1, stdout);
|
||||||
|
else
|
||||||
|
printf("%08X\n", (int) remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
crc_set_little_endian();
|
||||||
|
args_handle(argc, argv);
|
||||||
|
cycle_input();
|
||||||
|
print_crc();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue