blob: cdd6bfa89fd27bf554ebb8366f7f9ab962272078 [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 Howard64ae6492018-12-26 17:47:34 -070033 "// Copyright (c) 2018 Gavin D. Howard.\n"
34 "// Licensed under the 0-clause BSD license.\n"
Gavin Howard2b6631f2018-12-13 17:35:08 -070035 "// *** AUTOMATICALLY GENERATED FROM %s. DO NOT MODIFY. ***\n";
Gavin Howardbe3a3422018-09-07 13:29:10 -060036
Gavin Howard1cbfe242019-01-09 17:13:11 -070037static const char* const bc_gen_include = "#include <%s>\n\n";
Gavin Howardbe3a3422018-09-07 13:29:10 -060038static const char* const bc_gen_label = "const char *%s = \"%s\";\n\n";
Gavin Howard64ae6492018-12-26 17:47:34 -070039static const char* const bc_gen_ifdef = "#if %s\n";
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060040static const char* const bc_gen_endif = "#endif // %s\n";
Gavin Howardbe3a3422018-09-07 13:29:10 -060041static const char* const bc_gen_name = "const char %s[] = {\n";
Gavin Howardfe2351d2018-02-19 14:10:15 -070042
43#define INVALID_PARAMS (1)
Gavin Howard1cbfe242019-01-09 17:13:11 -070044#define INVALID_INPUT_FILE (2)
45#define INVALID_OUTPUT_FILE (3)
46#define IO_ERR (4)
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 Howard2b6631f2018-12-13 17:35:08 -070052 FILE *in, *out;
Gavin Howard1cbfe242019-01-09 17:13:11 -070053 char *label, *define, *name, *include;
Gavin Howard2b6631f2018-12-13 17:35:08 -070054 int c, count, err, slashes;
55 bool has_label, has_define, remove_tabs;
Gavin Howardd571acf2018-02-20 17:13:07 -070056
Gavin Howard2b6631f2018-12-13 17:35:08 -070057 err = 0;
Gavin Howardf8333992018-02-19 13:55:25 -070058
Gavin Howard1cbfe242019-01-09 17:13:11 -070059 if (argc < 5) {
60 printf("usage: %s input output name header [label [define [remove_tabs]]]\n", argv[0]);
Gavin Howard2b6631f2018-12-13 17:35:08 -070061 return INVALID_PARAMS;
62 }
Gavin Howardf8333992018-02-19 13:55:25 -070063
Gavin Howard2b6631f2018-12-13 17:35:08 -070064 name = argv[3];
Gavin Howard1cbfe242019-01-09 17:13:11 -070065 include = argv[4];
Gavin Howardbe3a3422018-09-07 13:29:10 -060066
Gavin Howardcaf5fc22019-01-12 21:14:26 -070067 has_label = argc > 5 && strcmp("", argv[5]) != 0;
Gavin Howard1cbfe242019-01-09 17:13:11 -070068 label = has_label ? argv[5] : "";
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060069
Gavin Howardcaf5fc22019-01-12 21:14:26 -070070 has_define = argc > 6 && strcmp("", argv[6]) != 0;
Gavin Howard1cbfe242019-01-09 17:13:11 -070071 define = has_define ? argv[6] : "";
72
73 remove_tabs = argc > 7;
Gavin Howard3f9b5742018-12-13 17:31:00 -070074
Gavin Howard2b6631f2018-12-13 17:35:08 -070075 in = fopen(argv[1], "r");
Gavin Howardf8333992018-02-19 13:55:25 -070076
Gavin Howard2b6631f2018-12-13 17:35:08 -070077 if (!in) return INVALID_INPUT_FILE;
Gavin Howardf8333992018-02-19 13:55:25 -070078
Gavin Howard2b6631f2018-12-13 17:35:08 -070079 out = fopen(argv[2], "w");
Gavin Howardf8333992018-02-19 13:55:25 -070080
Gavin Howard2b6631f2018-12-13 17:35:08 -070081 if (!out) {
82 err = INVALID_OUTPUT_FILE;
83 goto out_err;
84 }
Gavin Howardf8333992018-02-19 13:55:25 -070085
Gavin Howard2b6631f2018-12-13 17:35:08 -070086 if (fprintf(out, bc_gen_header, argv[1]) < 0) {
87 err = IO_ERR;
88 goto error;
89 }
Gavin Howard1ba6bee2018-03-08 11:52:45 -070090
Gavin Howard2b6631f2018-12-13 17:35:08 -070091 if (has_define && fprintf(out, bc_gen_ifdef, define) < 0) {
92 err = IO_ERR;
93 goto error;
94 }
Gavin Howardeb5c6ab2018-10-03 11:47:36 -060095
Gavin Howard1cbfe242019-01-09 17:13:11 -070096 if (fprintf(out, bc_gen_include, include) < 0) {
97 err = IO_ERR;
98 goto error;
99 }
100
Gavin Howard2b6631f2018-12-13 17:35:08 -0700101 if (has_label && fprintf(out, bc_gen_label, label, argv[1]) < 0) {
102 err = IO_ERR;
103 goto error;
104 }
Gavin Howardfe2351d2018-02-19 14:10:15 -0700105
Gavin Howard2b6631f2018-12-13 17:35:08 -0700106 if (fprintf(out, bc_gen_name, name) < 0) {
107 err = IO_ERR;
108 goto error;
109 }
Gavin Howardf8333992018-02-19 13:55:25 -0700110
Gavin Howard2b6631f2018-12-13 17:35:08 -0700111 c = count = slashes = 0;
Gavin Howard7edf8292018-03-09 02:07:59 -0700112
Gavin Howard2b6631f2018-12-13 17:35:08 -0700113 while (slashes < 2 && (c = fgetc(in)) >= 0) {
114 if (slashes == 1 && c == '/' && fgetc(in) == '\n') ++slashes;
115 if (!slashes && c == '/' && fgetc(in) == '*') ++slashes;
116 }
Gavin Howard7edf8292018-03-09 02:07:59 -0700117
Gavin Howard2b6631f2018-12-13 17:35:08 -0700118 if (c < 0) {
119 err = INVALID_INPUT_FILE;
120 goto error;
121 }
Gavin Howard7edf8292018-03-09 02:07:59 -0700122
Gavin Howard2b6631f2018-12-13 17:35:08 -0700123 c = fgetc(in);
Gavin Howarddb28f432018-09-25 15:55:35 -0600124
Gavin Howard2b6631f2018-12-13 17:35:08 -0700125 if (c == '\n') c = fgetc(in);
Gavin Howarddb28f432018-09-25 15:55:35 -0600126
Gavin Howard2b6631f2018-12-13 17:35:08 -0700127 while (c >= 0) {
Gavin Howardf8333992018-02-19 13:55:25 -0700128
Gavin Howard2b6631f2018-12-13 17:35:08 -0700129 int val;
Gavin Howardf8333992018-02-19 13:55:25 -0700130
Gavin Howard2b6631f2018-12-13 17:35:08 -0700131 if (!remove_tabs || c != '\t') {
Gavin Howard3f9b5742018-12-13 17:31:00 -0700132
Gavin Howard2b6631f2018-12-13 17:35:08 -0700133 if (!count) {
134 if (fputc('\t', out) == EOF) {
135 err = IO_ERR;
136 goto error;
137 }
138 }
Gavin Howard3f9b5742018-12-13 17:31:00 -0700139
Gavin Howard2b6631f2018-12-13 17:35:08 -0700140 val = fprintf(out, "%d,", c);
Gavin Howard3f9b5742018-12-13 17:31:00 -0700141
Gavin Howard2b6631f2018-12-13 17:35:08 -0700142 if (val < 0) {
143 err = IO_ERR;
144 goto error;
145 }
Gavin Howardfe2351d2018-02-19 14:10:15 -0700146
Gavin Howard2b6631f2018-12-13 17:35:08 -0700147 count += val;
Gavin Howardfe2351d2018-02-19 14:10:15 -0700148
Gavin Howard2b6631f2018-12-13 17:35:08 -0700149 if (count > MAX_WIDTH) {
Gavin Howardfe2351d2018-02-19 14:10:15 -0700150
Gavin Howard2b6631f2018-12-13 17:35:08 -0700151 count = 0;
Gavin Howardf8333992018-02-19 13:55:25 -0700152
Gavin Howard2b6631f2018-12-13 17:35:08 -0700153 if (fputc('\n', out) == EOF) {
154 err = IO_ERR;
155 goto error;
156 }
157 }
158 }
Gavin Howarddb28f432018-09-25 15:55:35 -0600159
Gavin Howard2b6631f2018-12-13 17:35:08 -0700160 c = fgetc(in);
161 }
Gavin Howardf8333992018-02-19 13:55:25 -0700162
Gavin Howard2b6631f2018-12-13 17:35:08 -0700163 if (!count) {
164 if (fputc(' ', out) == EOF || fputc(' ', out) == EOF) {
165 err = IO_ERR;
166 goto error;
167 }
168 }
Gavin Howardeb5c6ab2018-10-03 11:47:36 -0600169
Gavin Howard2b6631f2018-12-13 17:35:08 -0700170 if (fprintf(out, "0\n};\n") < 0) {
171 err = IO_ERR;
172 goto error;
173 }
Gavin Howardf8333992018-02-19 13:55:25 -0700174
Gavin Howard2b6631f2018-12-13 17:35:08 -0700175 if (has_define && fprintf(out, bc_gen_endif, define) < 0) err = IO_ERR;
Gavin Howardeb5c6ab2018-10-03 11:47:36 -0600176
Gavin Howardd571acf2018-02-20 17:13:07 -0700177error:
Gavin Howard2b6631f2018-12-13 17:35:08 -0700178 fclose(out);
Gavin Howardd571acf2018-02-20 17:13:07 -0700179out_err:
Gavin Howard2b6631f2018-12-13 17:35:08 -0700180 fclose(in);
Gavin Howard2b6631f2018-12-13 17:35:08 -0700181 return err;
Gavin Howardf8333992018-02-19 13:55:25 -0700182}