diff options
author | Thomas Albers Raviola <thomas@thomaslabs.org> | 2025-03-13 15:58:09 +0100 |
---|---|---|
committer | Thomas Albers Raviola <thomas@thomaslabs.org> | 2025-03-13 15:58:09 +0100 |
commit | 5ba1561999f8df7e0e622db8686ec1c4e0045d5f (patch) | |
tree | 1ed2fa10f7cdaa27454c1b3937e07ead78b6536e /src/main.c |
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..fc965aa --- /dev/null +++ b/src/main.c @@ -0,0 +1,150 @@ +/* + ihex + Copyright (C) 2025 Thomas Albers Raviola <thomas@thomaslabs.org> + + 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 <https://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> + +#include <util.h> +#include <ihex.h> +#include <array.h> + +static void +usage(void) +{ + fputs("\ +Usage: ihex [OPTION]... [[BASE:]FILE]...\n", stdout); + fputs("\ +Convert ihex FILEs into binary data\n\n", stdout); + fputs("\ + -h, --help display this help and exit\n", stdout); + fputs("\ + -o, --output=NAME write output to NAME\n", stdout); + fputs("\n\ +The BASE argument is a base 16 encoded number indicating where to place the\n\ +file contents inside the resulting image\n\n", stdout); + fputs("\ +ihex home page: <https://thomaslabs.org/software/ihex>\n\ +\n\ +Copyright (C) 2025 Thomas Albers Raviola\n\ +This program comes with ABSOLUTELY NO WARRANTY.\n\ +This is free software: you free to change and redistribute it.\n", + stdout); +} + +static const char *opts = "ho:"; +static const struct option longopts[] = { + {.name = "help", .has_arg = 0, .flag = NULL, .val = 'h'}, + {.name = "output", .has_arg = 1, .flag = NULL, .val = 'o'}, + {0, 0, 0, 0} +}; + +static const char *output; + +void +decode_args(int argc, char *argv[]) +{ + int c; + while ((c = getopt_long(argc, argv, opts, longopts, NULL)) != -1) { + switch (c) { + case 0: + break; + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 'o': + output = optarg; + break; + case '?': + usage(); + exit(EXIT_FAILURE); + default: + break; + } + } +} + +int +decode_filename(char *arg, long *base_address, const char **filename) +{ + char *junk; + char *sep = strchr(arg, ':'); + + if (sep) { + *sep++ = '\0'; + *filename = sep; + *base_address = strtol(arg, &junk, 16); + + if (*junk) { + fprintf(stderr, "Invalid base address for file %s\n", + *filename); + return -1; + } + } else { + *filename = arg; + *base_address = NO_BASE_ADDRESS; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int err = 0; + unsigned int i; + struct array blocks; + struct array data; + + decode_args(argc, argv); + + init_array(&blocks, sizeof(struct block)); + init_array(&data, sizeof(char)); + + for (i = optind; i < argc; ++i) { + long base_address; + const char *filename; + + err = decode_filename(argv[i], &base_address, &filename); + if (err < 0) + goto error; + + err = read_ihex_file(filename, &blocks, &data, base_address); + if (err < 0) + goto error; + } + + FILE *file = output ? fopen(output, "w") : stdout; + + if (!file) { + err = 1; + fprintf(stderr, "Could not open output file %s\n", output); + goto error; + } + + err = write_hex(&blocks, &data, file); + + if (output) + fclose(file); + +error: + free_array(&blocks); + free_array(&data); + return err; +} |