/* ihex Copyright (C) 2025 Thomas Albers Raviola 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 . */ #include #include #include #include #include #include #include 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: \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; }