Allow unseekable files with INCBIN

Go figure the use case, but the feature is there now
This commit is contained in:
ISSOtm
2020-02-09 17:05:29 +01:00
parent eb0d75711a
commit cdabc057a0

View File

@@ -1,4 +1,5 @@
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -404,80 +405,117 @@ void out_PCRelByte(struct Expression *expr)
*/ */
void out_BinaryFile(char const *s) void out_BinaryFile(char const *s)
{ {
FILE *f; FILE *f = fstk_FindFile(s, NULL);
f = fstk_FindFile(s, NULL); if (!f) {
if (f == NULL) {
if (oGeneratedMissingIncludes) { if (oGeneratedMissingIncludes) {
oFailedOnMissingInclude = true; oFailedOnMissingInclude = true;
return; return;
} }
err(1, "Unable to open incbin file '%s'", s); fatalerror("Error opening INCBIN file '%s': %s", s,
strerror(errno));
} }
int32_t fsize; int32_t fsize = -1;
int byte;
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fseek(f, 0, SEEK_SET);
checkcodesection(); checkcodesection();
if (fseek(f, 0, SEEK_END) != -1) {
fsize = ftell(f);
rewind(f);
checksectionoverflow(fsize); checksectionoverflow(fsize);
} else if (errno != ESPIPE) {
yyerror("Error determining size of INCBIN file '%s': %s", s,
strerror(errno));
}
int32_t todo = fsize; while ((byte = fgetc(f)) != EOF) {
if (fsize == -1)
while (todo--) checksectionoverflow(1);
pCurrentSection->tData[pCurrentSection->nPC++] = fgetc(f); pCurrentSection->tData[pCurrentSection->nPC++] = byte;
if (currentLoadSection) if (currentLoadSection)
currentLoadSection->nPC += fsize; currentLoadSection->nPC++;
nPC += fsize; nPC++;
}
if (ferror(f))
yyerror("Error reading INCBIN file '%s': %s", s,
strerror(errno));
fclose(f); fclose(f);
} }
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length) void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
{ {
FILE *f; if (start_pos < 0) {
yyerror("Start position cannot be negative (%d)", start_pos);
start_pos = 0;
}
if (start_pos < 0) if (length < 0) {
fatalerror("Start position cannot be negative"); yyerror("Number of bytes to read cannot be negative (%d)",
length);
length = 0;
}
if (length == 0) /* Don't even bother with 0-byte slices */
return;
if (length < 0) FILE *f = fstk_FindFile(s, NULL);
fatalerror("Number of bytes to read must be greater than zero");
f = fstk_FindFile(s, NULL); if (!f) {
if (f == NULL) {
if (oGeneratedMissingIncludes) { if (oGeneratedMissingIncludes) {
oFailedOnMissingInclude = true; oFailedOnMissingInclude = true;
return; return;
} }
err(1, "Unable to open included file '%s'", s); fatalerror("Error opening INCBIN file '%s': %s", s,
strerror(errno));
} }
checkcodesection();
checksectionoverflow(length);
int32_t fsize; int32_t fsize;
fseek(f, 0, SEEK_END); if (fseek(f, 0, SEEK_END) != -1) {
fsize = ftell(f); fsize = ftell(f);
if (start_pos >= fsize) if (start_pos >= fsize) {
fatalerror("Specified start position is greater than length of file"); yyerror("Specified start position is greater than length of file");
return;
}
if ((start_pos + length) > fsize) if ((start_pos + length) > fsize)
fatalerror("Specified range in INCBIN is out of bounds"); fatalerror("Specified range in INCBIN is out of bounds");
fseek(f, start_pos, SEEK_SET); fseek(f, start_pos, SEEK_SET);
} else {
checkcodesection(); if (errno != ESPIPE)
checksectionoverflow(length); yyerror("Error determining size of INCBIN file '%s': %s",
s, strerror(errno));
/* The file isn't seekable, so we'll just skip bytes */
while (start_pos--)
(void)fgetc(f);
}
int32_t todo = length; int32_t todo = length;
while (todo--) while (todo--) {
pCurrentSection->tData[pCurrentSection->nPC++] = fgetc(f); int byte = fgetc(f);
if (byte != EOF) {
pCurrentSection->tData[pCurrentSection->nPC++] = byte;
if (currentLoadSection) if (currentLoadSection)
currentLoadSection->nPC += length; currentLoadSection->nPC++;
nPC += length; nPC++;
} else if (ferror(f)) {
yyerror("Error reading INCBIN file '%s': %s", s,
strerror(errno));
} else {
yyerror("Premature end of file (%d bytes left to read)",
todo + 1);
}
}
fclose(f); fclose(f);
} }