11485d7a2SIngo Weinhold /*
21485d7a2SIngo Weinhold * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
31485d7a2SIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License.
41485d7a2SIngo Weinhold */
51485d7a2SIngo Weinhold
61485d7a2SIngo Weinhold #include <errno.h>
71485d7a2SIngo Weinhold #include <fcntl.h>
81485d7a2SIngo Weinhold #include <stdio.h>
91485d7a2SIngo Weinhold #include <stdlib.h>
101485d7a2SIngo Weinhold #include <string.h>
116fc59c0fSFrançois Revol #include <sys/stat.h>
121485d7a2SIngo Weinhold #include <unistd.h>
131485d7a2SIngo Weinhold
141485d7a2SIngo Weinhold
151485d7a2SIngo Weinhold void
write_string(int fd,const char * data)161485d7a2SIngo Weinhold write_string(int fd, const char* data)
171485d7a2SIngo Weinhold {
181485d7a2SIngo Weinhold int len = strlen(data);
191485d7a2SIngo Weinhold if (len == 0)
201485d7a2SIngo Weinhold return;
211485d7a2SIngo Weinhold
221485d7a2SIngo Weinhold ssize_t written = write(fd, data, len);
231485d7a2SIngo Weinhold if (written < 0) {
241485d7a2SIngo Weinhold fprintf(stderr, "Error: Failed to write to output file: %s\n",
251485d7a2SIngo Weinhold strerror(errno));
261485d7a2SIngo Weinhold exit(1);
271485d7a2SIngo Weinhold }
281485d7a2SIngo Weinhold }
291485d7a2SIngo Weinhold
301485d7a2SIngo Weinhold
311485d7a2SIngo Weinhold int
main(int argc,const char * const * argv)321485d7a2SIngo Weinhold main(int argc, const char* const* argv)
331485d7a2SIngo Weinhold {
341485d7a2SIngo Weinhold if (argc != 5) {
351485d7a2SIngo Weinhold fprintf(stderr,
361485d7a2SIngo Weinhold "Usage: %s <data var name> <size var name> <input> <output>\n",
371485d7a2SIngo Weinhold argv[0]);
381485d7a2SIngo Weinhold exit(1);
391485d7a2SIngo Weinhold }
401485d7a2SIngo Weinhold const char* dataVarName = argv[1];
411485d7a2SIngo Weinhold const char* sizeVarName = argv[2];
421485d7a2SIngo Weinhold const char* inFileName = argv[3];
431485d7a2SIngo Weinhold const char* outFileName = argv[4];
441485d7a2SIngo Weinhold
451485d7a2SIngo Weinhold // open files
461485d7a2SIngo Weinhold int inFD = open(inFileName, O_RDONLY);
471485d7a2SIngo Weinhold if (inFD < 0) {
481485d7a2SIngo Weinhold fprintf(stderr, "Error: Failed to open input file \"%s\": %s\n",
491485d7a2SIngo Weinhold inFileName, strerror(errno));
501485d7a2SIngo Weinhold exit(1);
511485d7a2SIngo Weinhold }
521485d7a2SIngo Weinhold
531485d7a2SIngo Weinhold int outFD = open(outFileName, O_WRONLY | O_CREAT | O_TRUNC,
541485d7a2SIngo Weinhold S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
551485d7a2SIngo Weinhold if (outFD < 0) {
561485d7a2SIngo Weinhold fprintf(stderr, "Error: Failed to open output file \"%s\": %s\n",
571485d7a2SIngo Weinhold outFileName, strerror(errno));
581485d7a2SIngo Weinhold exit(1);
591485d7a2SIngo Weinhold }
601485d7a2SIngo Weinhold
611485d7a2SIngo Weinhold const int kCharsPerLine = 15;
621485d7a2SIngo Weinhold const int kBufferSize = 16 * 1024;
631485d7a2SIngo Weinhold unsigned char buffer[kBufferSize];
641485d7a2SIngo Weinhold char lineBuffer[128];
651485d7a2SIngo Weinhold
66*669e389cSPaweł Dziepak sprintf(lineBuffer, "#include <stddef.h>\n");
67*669e389cSPaweł Dziepak write_string(outFD, lineBuffer);
68*669e389cSPaweł Dziepak sprintf(lineBuffer, "const unsigned char %s[] = {\n", dataVarName);
691485d7a2SIngo Weinhold write_string(outFD, lineBuffer);
701485d7a2SIngo Weinhold
711485d7a2SIngo Weinhold off_t offset = 0;
721485d7a2SIngo Weinhold char* lineBufferEnd = lineBuffer;
731485d7a2SIngo Weinhold *lineBufferEnd = '\0';
741485d7a2SIngo Weinhold while (true) {
751485d7a2SIngo Weinhold // read a buffer
761485d7a2SIngo Weinhold ssize_t bytesRead = read(inFD, buffer, kBufferSize);
771485d7a2SIngo Weinhold if (bytesRead < 0) {
781485d7a2SIngo Weinhold fprintf(stderr, "Error: Failed to read from input file: %s\n",
791485d7a2SIngo Weinhold strerror(errno));
801485d7a2SIngo Weinhold exit(1);
811485d7a2SIngo Weinhold }
821485d7a2SIngo Weinhold if (bytesRead == 0)
831485d7a2SIngo Weinhold break;
841485d7a2SIngo Weinhold
851485d7a2SIngo Weinhold // write lines
861485d7a2SIngo Weinhold for (int i = 0; i < bytesRead; i++, offset++) {
871485d7a2SIngo Weinhold if (offset % kCharsPerLine == 0) {
881485d7a2SIngo Weinhold if (offset > 0) {
891485d7a2SIngo Weinhold // line is full -- flush it
901485d7a2SIngo Weinhold strcpy(lineBufferEnd, ",\n");
911485d7a2SIngo Weinhold write_string(outFD, lineBuffer);
921485d7a2SIngo Weinhold lineBufferEnd = lineBuffer;
931485d7a2SIngo Weinhold *lineBufferEnd = '\0';
941485d7a2SIngo Weinhold }
951485d7a2SIngo Weinhold
961485d7a2SIngo Weinhold sprintf(lineBufferEnd, "\t%u", (unsigned)buffer[i]);
971485d7a2SIngo Weinhold } else
981485d7a2SIngo Weinhold sprintf(lineBufferEnd, ", %u", (unsigned)buffer[i]);
991485d7a2SIngo Weinhold
1001485d7a2SIngo Weinhold lineBufferEnd += strlen(lineBufferEnd);
1011485d7a2SIngo Weinhold }
1021485d7a2SIngo Weinhold }
1031485d7a2SIngo Weinhold
1041485d7a2SIngo Weinhold // flush the line buffer
1051485d7a2SIngo Weinhold if (lineBufferEnd != lineBuffer) {
1061485d7a2SIngo Weinhold strcpy(lineBufferEnd, ",\n");
1071485d7a2SIngo Weinhold write_string(outFD, lineBuffer);
1081485d7a2SIngo Weinhold }
1091485d7a2SIngo Weinhold
1101485d7a2SIngo Weinhold // close the braces and write the size variable
111*669e389cSPaweł Dziepak sprintf(lineBuffer, "};\nconst size_t %s = sizeof(%s);\n", sizeVarName,
112*669e389cSPaweł Dziepak dataVarName);
1131485d7a2SIngo Weinhold write_string(outFD, lineBuffer);
1141485d7a2SIngo Weinhold
1151485d7a2SIngo Weinhold close(inFD);
1161485d7a2SIngo Weinhold close(outFD);
1171485d7a2SIngo Weinhold
1181485d7a2SIngo Weinhold return 0;
1191485d7a2SIngo Weinhold }
120