diff --git a/src/hex.c b/src/hex.c index 81f7ede..f90d480 100644 --- a/src/hex.c +++ b/src/hex.c @@ -22,7 +22,10 @@ void init_flags(struct flags* flags) flags->decimaloffset = false; flags->postscript = false; + flags->c_style = false; + flags->c_filename = NULL; + flags->cap_c_style = false; } void init_cols(struct flags* flags) @@ -132,12 +135,31 @@ static void standard_output(char** text, FILE* stream) } +static void c_output(char** text, FILE* stream) +{ + uint i; + + printf("\t"); + + printf("0x"); + write_octet((*text)[0], (*text)[1], stream); + for (i = 2; i < (flags.cols * 2); i += 2) { + if ((*text)[i] == ' ') + continue; + printf(", 0x"); + write_octet((*text)[i], (*text)[i + 1], stream); + } +} + void display_hex_chunk(hex_chunk_t* chunk, FILE* stream) { if (!flags.postscript && !flags.c_style) write_offset(chunk->line * flags.cols, stream); - standard_output(&(chunk->hex), stream); + if (flags.c_style) + c_output(&(chunk->hex), stream); + else + standard_output(&(chunk->hex), stream); if (!flags.postscript && !flags.c_style) write_text(&(chunk->text), stream); diff --git a/src/include/hex.h b/src/include/hex.h index 78ddb16..0438ae1 100644 --- a/src/include/hex.h +++ b/src/include/hex.h @@ -33,7 +33,10 @@ struct flags { bool decimaloffset; // do decimal offset instead of hex // done bool postscript; // post in plain postscript style + bool c_style; // output in C include file style + char* c_filename; + bool cap_c_style; // capitalize variable names in c style }; // TODO: implement flags and stuff diff --git a/src/main.c b/src/main.c index a53c8c0..a1a5a4b 100644 --- a/src/main.c +++ b/src/main.c @@ -12,12 +12,16 @@ const char* argp_program_bug_address = "supernovaa41@gmx.com"; static char doc[] = "Recreation of the GNU util xxd. Creates a hex dump of the given input."; static char args_doc[] = "[INFILE [OUTFILE]]"; static struct argp_option options[] = { - {"cols", 'c', "cols", 0, "format octets per line. Default 16.", 0}, - {"octets", 'g', "bytes", 0, "number of octets per group in normal output. Default 2.", 0}, - {"len", 'l', "len", 0, "stop after octets.", 0}, - {"uppercase", 'u', 0, 0, "use upper case hex letters.", 0}, - {"decimaloffset", 'd', 0, 0, "show offset in decimal instead of hex.", 0}, + {0, 'c', "cols", 0, "format octets per line. Default 16 (-i: 12, -p: 30).", 0}, + {0, 'g', "bytes", 0, "number of octets per group in normal output. Default 2.", 0}, + {0, 'l', "len", 0, "stop after octets.", 0}, + {0, 'u', 0, 0, "use upper case hex letters.", 0}, + {0, 'd', 0, 0, "show offset in decimal instead of hex.", 0}, {"ps", 'p', 0, 0, "output in postscript plain hexdump style.", 0}, + {0, 'R', "when", 0, "colorize the output; can be 'always' or 'never'. Default: 'always'.", 0}, + {0, 'i', 0, 0, "output in C include file style.", 0}, + {0, 'C', 0, 0, "capitalize variable names in C include file style (-i).", 0}, + {0, 'n', "name", 0, "set the variable name used in C include output (-i).", 0}, {0} }; @@ -25,13 +29,27 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state) { struct flags* flags = state->input; switch(key) { + case 'C': + flags->cap_c_style = true; + break; case 'c': flags->cols = atoi(arg); flags->customcols = true; break; + case 'n': + flags->c_filename = arg; + break; case 'g': flags->octets = atoi(arg); break; + case 'R': + if (strcmp(arg, "none") == 0) + flags->coloured = false; + else if (strcmp(arg, "always") == 0) + flags->coloured = true; + else + flags->coloured = true; + break; case 'l': flags->len = atoi(arg); break; @@ -44,6 +62,11 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state) case 'p': flags->postscript = true; flags->coloured = false; + break; + case 'i': + flags->c_style = true; + flags->coloured = false; + break; case ARGP_KEY_ARG: if (state->arg_num >= 2) argp_usage(state); @@ -87,6 +110,9 @@ static void do_text_parse(hex_chunk_t** lines, bool interactive) } filesize = (flags.len == -1) ? strlen(file_content) : flags.len; + + flags.len = filesize; + hex_lines = get_hex_lines(filesize); *lines = malloc(sizeof(hex_chunk_t) * (hex_lines + 1)); @@ -102,11 +128,37 @@ static void do_text_parse(hex_chunk_t** lines, bool interactive) free(file_content); } +static char parse_c_char(char c) +{ + if (c >= 'A' && c <= 'Z') + return c; + else if (c >= 'a' && c <= 'z') + return (flags.cap_c_style) ? toupper(c) : c; + return '_'; +} + +static void parse_c_filename(char** text, char** filename) +{ + uint i; + + if ((*text)[0] >= '0' && (*text)[0] <= '9') + asprintf(filename, "__%c", (*text)[0]); + else + asprintf(filename, "%c", parse_c_char((*text)[0])); + + for (i = 1; i < strlen(*text); i++) { + asprintf(filename, "%s%c", *filename, + parse_c_char((*text)[i])); + } +} + static void do_display(hex_chunk_t** lines) { int i; - bool fileout = false; + char* filename; + + bool fileout = false; FILE* stream = stdout; if (flags.files[1] != NULL) { @@ -115,9 +167,25 @@ static void do_display(hex_chunk_t** lines) } i = 0; + + if (flags.c_style) { + parse_c_filename((!flags.c_filename) ? &(flags.files[0]) : &(flags.c_filename), + &filename); + + printf("unsigned char %s[] = {\n", filename); + } + while ((*lines)[i].line != -1) display_hex_chunk(&((*lines)[i++]), stream); + if (flags.c_style) { + asprintf(&filename, "%s_%s", filename, (flags.cap_c_style) ? "LEN" : "len"); + + printf("};\n"); + printf("unsigned int %s = %d;\n", filename, flags.len); + free(filename); + } + if (fileout) fclose(stream);