blob: 45e57b4a56120cd134432d144fe894194b84f1ba [file] [log] [blame]
Gavin Howardf8333992018-02-19 13:55:25 -07001/*
Gavin Howardb5904bf2018-02-20 13:28:18 -07002 * *****************************************************************************
Gavin Howardf8333992018-02-19 13:55:25 -07003 *
Gavin Howardb5904bf2018-02-20 13:28:18 -07004 * Copyright 2018 Gavin D. Howard
Gavin Howardf8333992018-02-19 13:55:25 -07005 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 *
Gavin Howardb5904bf2018-02-20 13:28:18 -070017 * *****************************************************************************
Gavin Howardf8333992018-02-19 13:55:25 -070018 *
19 * Generates a const array from a bc script.
20 *
21 */
22
Gavin Howardbe3a3422018-09-07 13:29:10 -060023#include <stdbool.h>
Gavin Howardf8333992018-02-19 13:55:25 -070024#include <stdio.h>
Gavin Howard207053c2018-02-20 11:12:43 -070025#include <stdlib.h>
26#include <string.h>
27
Gavin Howardbe3a3422018-09-07 13:29:10 -060028#include <errno.h>
29
Gavin Howard207053c2018-02-20 11:12:43 -070030#include <libgen.h>
Gavin Howardf8333992018-02-19 13:55:25 -070031
Gavin Howardbe3a3422018-09-07 13:29:10 -060032static const char* const bc_gen_header =
Gavin Howardb52a8792018-09-07 13:37:41 -060033 "// Copyright 2018 Gavin D. Howard. Under a 0-clause BSD license.\n"
Gavin Howardbe3a3422018-09-07 13:29:10 -060034 "// *** AUTOMATICALLY GENERATED FROM %s. DO NOT MODIFY. ***\n";
35
36static const char* const bc_gen_label = "const char *%s = \"%s\";\n\n";
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060037static const char* const bc_gen_ifdef = "#ifdef %s\n";
38static const char* const bc_gen_endif = "#endif // %s\n";
Gavin Howardbe3a3422018-09-07 13:29:10 -060039static const char* const bc_gen_name = "const char %s[] = {\n";
Gavin Howardfe2351d2018-02-19 14:10:15 -070040
41#define INVALID_PARAMS (1)
Gavin Howard207053c2018-02-20 11:12:43 -070042#define MALLOC_FAIL (2)
43#define INVALID_INPUT_FILE (3)
44#define INVALID_OUTPUT_FILE (4)
Gavin Howard1ba6bee2018-03-08 11:52:45 -070045#define INVALID_HEADER_FILE (5)
46#define IO_ERR (6)
Gavin Howardf8333992018-02-19 13:55:25 -070047
Gavin Howard7edf8292018-03-09 02:07:59 -070048#define MAX_WIDTH (74)
49
Gavin Howard8d1f1db2018-02-23 11:29:41 -070050int main(int argc, char *argv[]) {
Gavin Howardf8333992018-02-19 13:55:25 -070051
Gavin Howardbe3a3422018-09-07 13:29:10 -060052 FILE *in, *out;
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060053 char *label, *define, *name;
Gavin Howardbe3a3422018-09-07 13:29:10 -060054 int c, count, err, slashes;
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060055 bool has_label, has_define;
Gavin Howardd571acf2018-02-20 17:13:07 -070056
57 err = 0;
Gavin Howardf8333992018-02-19 13:55:25 -070058
Gavin Howardbe3a3422018-09-07 13:29:10 -060059 if (argc < 4) {
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060060 printf("usage: gen input output name [label [define]]\n");
Gavin Howardfe2351d2018-02-19 14:10:15 -070061 return INVALID_PARAMS;
Gavin Howardf8333992018-02-19 13:55:25 -070062 }
63
Gavin Howardbe3a3422018-09-07 13:29:10 -060064 name = argv[3];
65
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060066 has_label = argc > 4 && strcmp("", argv[4]);
Gavin Howardbe3a3422018-09-07 13:29:10 -060067 label = has_label ? argv[4] : "";
68
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060069 has_define = argc > 5 && strcmp("", argv[5]);
70 define = has_define ? argv[5] : "";
71
Gavin Howardf8333992018-02-19 13:55:25 -070072 in = fopen(argv[1], "r");
73
Gavin Howardb52a8792018-09-07 13:37:41 -060074 if (!in) return INVALID_INPUT_FILE;
Gavin Howardf8333992018-02-19 13:55:25 -070075
76 out = fopen(argv[2], "w");
77
Gavin Howardd571acf2018-02-20 17:13:07 -070078 if (!out) {
79 err = INVALID_OUTPUT_FILE;
80 goto out_err;
81 }
Gavin Howardf8333992018-02-19 13:55:25 -070082
Gavin Howardb52a8792018-09-07 13:37:41 -060083 if (fprintf(out, bc_gen_header, argv[1]) < 0) {
Gavin Howard1ba6bee2018-03-08 11:52:45 -070084 err = IO_ERR;
85 goto error;
86 }
87
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060088 if (has_define && fprintf(out, bc_gen_ifdef, define) < 0) {
89 err = IO_ERR;
90 goto error;
91 }
92
Gavin Howardb52a8792018-09-07 13:37:41 -060093 if (has_label && fprintf(out, bc_gen_label, label, argv[1]) < 0) {
Gavin Howardd571acf2018-02-20 17:13:07 -070094 err = IO_ERR;
95 goto error;
96 }
Gavin Howardfe2351d2018-02-19 14:10:15 -070097
Gavin Howardbe3a3422018-09-07 13:29:10 -060098 if (fprintf(out, bc_gen_name, name) < 0) {
Gavin Howardd571acf2018-02-20 17:13:07 -070099 err = IO_ERR;
100 goto error;
101 }
Gavin Howardf8333992018-02-19 13:55:25 -0700102
Gavin Howard70610172018-09-05 20:30:08 -0600103 c = count = slashes = 0;
Gavin Howard7edf8292018-03-09 02:07:59 -0700104
105 while (slashes < 2 && (c = fgetc(in)) >= 0) {
106 if (slashes == 1 && c == '/' && fgetc(in) == '\n') ++slashes;
107 if (!slashes && c == '/' && fgetc(in) == '*') ++slashes;
108 }
109
110 if (c < 0) {
111 err = INVALID_INPUT_FILE;
112 goto error;
113 }
114
Gavin Howarddb28f432018-09-25 15:55:35 -0600115 c = fgetc(in);
116
117 if (c == '\n') c = fgetc(in);
118
119 while (c >= 0) {
Gavin Howardf8333992018-02-19 13:55:25 -0700120
Gavin Howardfe2351d2018-02-19 14:10:15 -0700121 int val;
Gavin Howardf8333992018-02-19 13:55:25 -0700122
Gavin Howardfe2351d2018-02-19 14:10:15 -0700123 if (!count) {
Gavin Howardd571acf2018-02-20 17:13:07 -0700124 if (fprintf(out, " ") < 0) {
125 err = IO_ERR;
126 goto error;
127 }
Gavin Howardfe2351d2018-02-19 14:10:15 -0700128 }
129
130 val = fprintf(out, "%d,", c);
131
Gavin Howardd571acf2018-02-20 17:13:07 -0700132 if (val < 0) {
133 err = IO_ERR;
134 goto error;
135 }
Gavin Howardfe2351d2018-02-19 14:10:15 -0700136
137 count += val;
Gavin Howardf8333992018-02-19 13:55:25 -0700138
Gavin Howard7edf8292018-03-09 02:07:59 -0700139 if (count > MAX_WIDTH) {
Gavin Howardd571acf2018-02-20 17:13:07 -0700140
Gavin Howardf8333992018-02-19 13:55:25 -0700141 count = 0;
Gavin Howardd571acf2018-02-20 17:13:07 -0700142
143 if (fputc('\n', out) == EOF) {
144 err = IO_ERR;
145 goto error;
146 }
Gavin Howardf8333992018-02-19 13:55:25 -0700147 }
Gavin Howarddb28f432018-09-25 15:55:35 -0600148
149 c = fgetc(in);
Gavin Howardf8333992018-02-19 13:55:25 -0700150 }
151
Gavin Howard8bdbb1f2018-02-20 16:17:16 -0700152 if (!count) {
Gavin Howard7edf8292018-03-09 02:07:59 -0700153 if (fputc(' ', out) == EOF || fputc(' ', out) == EOF) {
Gavin Howardd571acf2018-02-20 17:13:07 -0700154 err = IO_ERR;
155 goto error;
156 }
Gavin Howardfe2351d2018-02-19 14:10:15 -0700157 }
Gavin Howardeb5c6ab2018-10-03 11:47:36 -0600158
Gavin Howardd571acf2018-02-20 17:13:07 -0700159 if (fprintf(out, "0\n};\n") < 0) {
160 err = IO_ERR;
161 goto error;
162 }
Gavin Howardf8333992018-02-19 13:55:25 -0700163
Gavin Howardeb5c6ab2018-10-03 11:47:36 -0600164 if (has_define && fprintf(out, bc_gen_endif, define) < 0) err = IO_ERR;
165
Gavin Howardd571acf2018-02-20 17:13:07 -0700166error:
167
Gavin Howardf8333992018-02-19 13:55:25 -0700168 fclose(out);
169
Gavin Howardd571acf2018-02-20 17:13:07 -0700170out_err:
171
172 fclose(in);
173
Gavin Howardd571acf2018-02-20 17:13:07 -0700174 return err;
Gavin Howardf8333992018-02-19 13:55:25 -0700175}