VirtualBox

source: vbox/trunk/src/bldprogs/bin2c.c

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.9 KB
Line 
1/* $Id: bin2c.c 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * bin2c - Binary 2 C Structure Converter.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <ctype.h>
33#include <stdio.h>
34#include <string.h>
35#include <stdlib.h>
36#include <sys/types.h>
37
38
39/**
40 * File size.
41 *
42 * @returns file size in bytes.
43 * @returns 0 on failure.
44 * @param pFile File to size.
45 */
46static size_t fsize(FILE *pFile)
47{
48 long cbFile;
49 off_t Pos = ftell(pFile);
50 if ( Pos >= 0
51 && !fseek(pFile, 0, SEEK_END))
52 {
53 cbFile = ftell(pFile);
54 if ( cbFile >= 0
55 && !fseek(pFile, 0, SEEK_SET))
56 return cbFile;
57 }
58 return 0;
59}
60
61static int usage(const char *argv0)
62{
63 fprintf(stderr,
64 "Syntax: %s [options] <arrayname> <binaryfile> <outname>\n"
65 " --min <n> check if <binaryfile> is not smaller than <n>KB\n"
66 " --max <n> check if <binaryfile> is not bigger than <n>KB\n"
67 " --mask <n> check if size of binaryfile is <n>-aligned\n"
68 " --width <n> number of bytes per line (default: 16)\n"
69 " --break <n> break every <n> lines (default: -1)\n"
70 , argv0);
71 fprintf(stderr,
72 " --ascii show ASCII representation of binary as comment\n"
73 " --export emit DECLEXPORT\n"
74 " --append append to the output file (default: truncate)\n"
75 " --no-size Skip the size.\n"
76 " --static Static data scope.\n");
77
78 return 1;
79}
80
81int main(int argc, char *argv[])
82{
83 FILE *pFileIn;
84 FILE *pFileOut;
85 int iArg;
86 size_t cbMin = 0;
87 size_t cbMax = ~0U;
88 size_t uMask = 0;
89 int fAscii = 0;
90 int fAppend = 0;
91 int fExport = 0;
92 int fNoSize = 0;
93 int fStatic = 0;
94 long iBreakEvery = -1;
95 unsigned char abLine[32];
96 size_t cbLine = 16;
97 size_t off;
98 size_t cbRead;
99 size_t cbBin;
100 int rc = 1; /* assume the worst... */
101
102 if (argc < 2)
103 return usage(argv[0]);
104
105 for (iArg = 1; iArg < argc; iArg++)
106 {
107 if (!strcmp(argv[iArg], "--min") || !strcmp(argv[iArg], "-min"))
108 {
109 if (++iArg >= argc)
110 return usage(argv[0]);
111 cbMin = 1024 * strtoul(argv[iArg], NULL, 0);
112 }
113 else if (!strcmp(argv[iArg], "--max") || !strcmp(argv[iArg], "-max"))
114 {
115 if (++iArg >= argc)
116 return usage(argv[0]);
117 cbMax = 1024 * strtoul(argv[iArg], NULL, 0);
118 }
119 else if (!strcmp(argv[iArg], "--mask") || !strcmp(argv[iArg], "-mask"))
120 {
121 if (++iArg >= argc)
122 return usage(argv[0]);
123 uMask = strtoul(argv[iArg], NULL, 0);
124 }
125 else if (!strcmp(argv[iArg], "--ascii") || !strcmp(argv[iArg], "-ascii"))
126 fAscii = 1;
127 else if (!strcmp(argv[iArg], "--append"))
128 fAppend = 1;
129 else if (!strcmp(argv[iArg], "--export") || !strcmp(argv[iArg], "-export"))
130 fExport = 1;
131 else if (!strcmp(argv[iArg], "--no-size"))
132 fNoSize = 1;
133 else if (!strcmp(argv[iArg], "--static"))
134 fStatic = 1;
135 else if (!strcmp(argv[iArg], "--width") || !strcmp(argv[iArg], "-width"))
136 {
137 if (++iArg >= argc)
138 return usage(argv[0]);
139 cbLine = strtoul(argv[iArg], NULL, 0);
140 if (cbLine == 0 || cbLine > sizeof(abLine))
141 {
142 fprintf(stderr, "%s: '%s' is too wide, max %u\n",
143 argv[0], argv[iArg], (unsigned)sizeof(abLine));
144 return 1;
145 }
146 }
147 else if (!strcmp(argv[iArg], "--break") || !strcmp(argv[iArg], "-break"))
148 {
149 if (++iArg >= argc)
150 return usage(argv[0]);
151 iBreakEvery = strtol(argv[iArg], NULL, 0);
152 if (iBreakEvery <= 0 && iBreakEvery != -1)
153 {
154 fprintf(stderr, "%s: -break value '%s' is not >= 1 or -1.\n",
155 argv[0], argv[iArg]);
156 return 1;
157 }
158 }
159 else if (iArg == argc - 3)
160 break;
161 else
162 {
163 fprintf(stderr, "%s: syntax error: Unknown argument '%s'\n",
164 argv[0], argv[iArg]);
165 return usage(argv[0]);
166 }
167 }
168
169 pFileIn = fopen(argv[iArg+1], "rb");
170 if (!pFileIn)
171 {
172 fprintf(stderr, "Error: failed to open input file '%s'!\n", argv[iArg+1]);
173 return 1;
174 }
175
176 pFileOut = fopen(argv[iArg+2], fAppend ? "a" : "w"); /* no b! */
177 if (!pFileOut)
178 {
179 fprintf(stderr, "Error: failed to open output file '%s'!\n", argv[iArg+2]);
180 fclose(pFileIn);
181 return 1;
182 }
183
184 cbBin = fsize(pFileIn);
185
186 fprintf(pFileOut,
187 "/*\n"
188 " * This file was automatically generated\n"
189 " * from %s\n"
190 " * by %s.\n"
191 " */\n"
192 "\n"
193 "#include <iprt/cdefs.h>\n"
194 "\n"
195 "%sconst unsigned char%s g_ab%s[] =\n"
196 "{\n",
197 argv[iArg+1], argv[0], fStatic ? "static " : fExport ? "DECLEXPORT(" : "", !fStatic && fExport ? ")" : "", argv[iArg]);
198
199 /* check size restrictions */
200 if (uMask && (cbBin & uMask))
201 fprintf(stderr, "%s: size=%ld - Not aligned!\n", argv[0], (long)cbBin);
202 else if (cbBin < cbMin || cbBin > cbMax)
203 fprintf(stderr, "%s: size=%ld - Not %ld-%ldb in size!\n",
204 argv[0], (long)cbBin, (long)cbMin, (long)cbMax);
205 else
206 {
207 /* the binary data */
208 off = 0;
209 while ((cbRead = fread(&abLine[0], 1, cbLine, pFileIn)) > 0)
210 {
211 size_t j;
212
213 if ( iBreakEvery > 0
214 && off
215 && (off / cbLine) % iBreakEvery == 0)
216 fprintf(pFileOut, "\n");
217
218 fprintf(pFileOut, " ");
219 for (j = 0; j < cbRead; j++)
220 fprintf(pFileOut, " 0x%02x,", abLine[j]);
221 for (; j < cbLine; j++)
222 fprintf(pFileOut, " ");
223 if (fAscii)
224 {
225 fprintf(pFileOut, " /* 0x%08lx: ", (long)off);
226 for (j = 0; j < cbRead; j++)
227 /* be careful with '/' prefixed/followed by a '*'! */
228 fprintf(pFileOut, "%c",
229 isprint(abLine[j]) && abLine[j] != '/' ? abLine[j] : '.');
230 for (; j < cbLine; j++)
231 fprintf(pFileOut, " ");
232 fprintf(pFileOut, " */");
233 }
234 fprintf(pFileOut, "\n");
235
236 off += cbRead;
237 }
238
239 /* check for errors */
240 if (ferror(pFileIn) && !feof(pFileIn))
241 fprintf(stderr, "%s: read error\n", argv[0]);
242 else if (off != cbBin)
243 fprintf(stderr, "%s: read error off=%ld cbBin=%ld\n", argv[0], (long)off, (long)cbBin);
244 else
245 {
246 /* no errors, finish the structure. */
247 fprintf(pFileOut,
248 "};\n");
249
250 if (!fNoSize)
251 fprintf(pFileOut,
252 "\n"
253 "%sconst unsigned%s g_cb%s = sizeof(g_ab%s);\n",
254 fExport ? "DECLEXPORT(" : "", fExport ? ")" : "", argv[iArg], argv[iArg]);
255
256 fprintf(pFileOut, "/* end of file */\n");
257
258 /* flush output and check for error. */
259 fflush(pFileOut);
260 if (ferror(pFileOut))
261 fprintf(stderr, "%s: write error\n", argv[0]);
262 else
263 rc = 0; /* success! */
264 }
265 }
266
267 /* cleanup, delete the output file on failure. */
268 fclose(pFileOut);
269 fclose(pFileIn);
270 if (rc)
271 remove(argv[iArg+2]);
272
273 return rc;
274}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette