allow full-line comments in tiles source files
Accept
<start of line><optional whitespace>#<anything>
as a comment in win/share/{monsters,objects,other}.txt. Existing
<start of line><optional whitespace># tile <rest of line>
is grandfathered in as data.
It wouldn't take much more to accept
<data><optional whitespace>#<rest of line>
comments too but this hasn't gone that far.
Reading the colormap at the beginning of each of the three files
used "%[A-Za-z0-i]" to read one characer into a two-character array.
Change that to "%1[A-Za-z0-9]" so that it can't overflow the buffer
if the input data gets accidentally or maliciously mangled. (Not a
security issue.)
Remove a spurious blank line from objects.txt.
Also, clean up some warnings when compiling gifread.c for gif2txt
although I ultimately didn't do anything with that.
This commit is contained in:
+15
-12
@@ -70,7 +70,7 @@ static void DoExtension(FILE * fd, int label);
|
|||||||
static boolean ReadColorMap(FILE * fd, int number);
|
static boolean ReadColorMap(FILE * fd, int number);
|
||||||
static void read_header(FILE * fd);
|
static void read_header(FILE * fd);
|
||||||
static int GetCode(FILE * fd, int code_size, int flag);
|
static int GetCode(FILE * fd, int code_size, int flag);
|
||||||
static int LWZReadByte(FILE * fd, int flag, int input_code_size);
|
static int LWZReadByte(FILE * fd, int flag); /*, int input_code_size);*/
|
||||||
static void ReadInterleavedImage(FILE * fd, int len, int height);
|
static void ReadInterleavedImage(FILE * fd, int len, int height);
|
||||||
static void ReadTileStrip(FILE * fd, int len);
|
static void ReadTileStrip(FILE * fd, int len);
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ static void
|
|||||||
DoExtension(FILE *fd, int label)
|
DoExtension(FILE *fd, int label)
|
||||||
{
|
{
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
char *str;
|
const char *str;
|
||||||
|
|
||||||
switch (label) {
|
switch (label) {
|
||||||
case 0x01: /* Plain Text Extension */
|
case 0x01: /* Plain Text Extension */
|
||||||
@@ -328,7 +328,7 @@ GetCode(FILE *fd, int code_size, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
LWZReadByte(FILE *fd, int flag, int input_code_size)
|
LWZReadByte(FILE *fd, int flag) /*, int input_code_size)*/
|
||||||
{
|
{
|
||||||
static int fresh = FALSE;
|
static int fresh = FALSE;
|
||||||
int code, incode;
|
int code, incode;
|
||||||
@@ -446,7 +446,7 @@ ReadInterleavedImage(FILE *fd, int len, int height)
|
|||||||
int v;
|
int v;
|
||||||
int xpos = 0, ypos = 0, pass = 0;
|
int xpos = 0, ypos = 0, pass = 0;
|
||||||
|
|
||||||
while ((v = LWZReadByte(fd, FALSE, (int) input_code_size)) >= 0) {
|
while ((v = LWZReadByte(fd, FALSE /*, (int) input_code_size*/ )) >= 0) {
|
||||||
PPM_ASSIGN(image[ypos][xpos], ColorMap[CM_RED][v],
|
PPM_ASSIGN(image[ypos][xpos], ColorMap[CM_RED][v],
|
||||||
ColorMap[CM_GREEN][v], ColorMap[CM_BLUE][v]);
|
ColorMap[CM_GREEN][v], ColorMap[CM_BLUE][v]);
|
||||||
|
|
||||||
@@ -487,8 +487,8 @@ ReadInterleavedImage(FILE *fd, int len, int height)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fini:
|
fini:
|
||||||
if (LWZReadByte(fd, FALSE, (int) input_code_size) >= 0)
|
if (LWZReadByte(fd, FALSE /*, (int) input_code_size*/ ) >= 0)
|
||||||
Fprintf(stderr, "too much input data, ignoring extra...\n");
|
Fprintf(stderr, "too much input data, ignoring extra...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ ReadTileStrip(FILE *fd, int len)
|
|||||||
int v;
|
int v;
|
||||||
int xpos = 0, ypos = 0;
|
int xpos = 0, ypos = 0;
|
||||||
|
|
||||||
while ((v = LWZReadByte(fd, FALSE, (int) input_code_size)) >= 0) {
|
while ((v = LWZReadByte(fd, FALSE /*, (int) input_code_size*/ )) >= 0) {
|
||||||
PPM_ASSIGN(image[ypos][xpos], ColorMap[CM_RED][v],
|
PPM_ASSIGN(image[ypos][xpos], ColorMap[CM_RED][v],
|
||||||
ColorMap[CM_GREEN][v], ColorMap[CM_BLUE][v]);
|
ColorMap[CM_GREEN][v], ColorMap[CM_BLUE][v]);
|
||||||
|
|
||||||
@@ -564,7 +564,7 @@ fopen_gif_file(const char *filename, const char *type)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LWZReadByte(gif_file, TRUE, (int) input_code_size) < 0) {
|
if (LWZReadByte(gif_file, TRUE /*, (int) input_code_size*/ ) < 0) {
|
||||||
Fprintf(stderr, "error reading image\n");
|
Fprintf(stderr, "error reading image\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -645,9 +645,12 @@ fclose_gif_file(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef AMIGA
|
#ifndef AMIGA
|
||||||
static char *std_args[] = { "tilemap", /* dummy argv[0] */
|
static const char *const std_args[] = {
|
||||||
"monsters.gif", "monsters.txt", "objects.gif",
|
"tilemap", /* dummy argv[0] */
|
||||||
"objects.txt", "other.gif", "other.txt" };
|
"monsters.gif", "monsters.txt",
|
||||||
|
"objects.gif", "objects.txt",
|
||||||
|
"other.gif", "other.txt",
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@@ -656,7 +659,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
argc = SIZE(std_args);
|
argc = SIZE(std_args);
|
||||||
argv = std_args;
|
argv = (char **) std_args;
|
||||||
} else if (argc != 3) {
|
} else if (argc != 3) {
|
||||||
Fprintf(stderr, "usage: gif2txt giffile txtfile\n");
|
Fprintf(stderr, "usage: gif2txt giffile txtfile\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|||||||
@@ -3675,7 +3675,6 @@ Z = (195, 195, 195)
|
|||||||
.......KKKAA....
|
.......KKKAA....
|
||||||
........AAA.....
|
........AAA.....
|
||||||
}
|
}
|
||||||
|
|
||||||
# tile 192 (cubical / amulet of flying)
|
# tile 192 (cubical / amulet of flying)
|
||||||
{
|
{
|
||||||
................
|
................
|
||||||
|
|||||||
+88
-42
@@ -18,16 +18,19 @@ static int placeholder_init = 0;
|
|||||||
static pixel placeholder[TILE_Y][TILE_X];
|
static pixel placeholder[TILE_Y][TILE_X];
|
||||||
static FILE *tile_file;
|
static FILE *tile_file;
|
||||||
static int tile_set, tile_set_indx;
|
static int tile_set, tile_set_indx;
|
||||||
|
static const char *const text_sets[] = {
|
||||||
#if (TILE_X == 8)
|
#if (TILE_X == 8)
|
||||||
static const char *text_sets[] = { "monthin.txt", "objthin.txt",
|
"monthin.txt", "objthin.txt", "oththin.txt"
|
||||||
"oththin.txt" };
|
|
||||||
#else
|
#else
|
||||||
static const char *text_sets[] = { "monsters.txt", "objects.txt",
|
"monsters.txt", "objects.txt", "other.txt"
|
||||||
"other.txt" };
|
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static char inbuf[BUFSZ];
|
||||||
|
|
||||||
extern const char *tilename(int, int, int);
|
extern const char *tilename(int, int, int);
|
||||||
extern boolean acceptable_tilename(int, int, const char *, const char *);
|
extern boolean acceptable_tilename(int, int, const char *, const char *);
|
||||||
|
static int get_next_line(FILE *, boolean);
|
||||||
static void read_text_colormap(FILE *);
|
static void read_text_colormap(FILE *);
|
||||||
static boolean write_text_colormap(FILE *);
|
static boolean write_text_colormap(FILE *);
|
||||||
static boolean read_txttile(FILE *, pixel (*)[TILE_X]);
|
static boolean read_txttile(FILE *, pixel (*)[TILE_X]);
|
||||||
@@ -36,8 +39,8 @@ static void write_txttile(FILE *, pixel (*)[TILE_X]);
|
|||||||
enum { MONSTER_SET, OBJECT_SET, OTHER_SET};
|
enum { MONSTER_SET, OBJECT_SET, OTHER_SET};
|
||||||
|
|
||||||
/* Ugh. DICE doesn't like %[A-Z], so we have to spell it out... */
|
/* Ugh. DICE doesn't like %[A-Z], so we have to spell it out... */
|
||||||
#define FORMAT_STRING \
|
#define FORMAT_STRING \
|
||||||
"%[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.] = " \
|
"%1[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.] = " \
|
||||||
"(%d, %d, %d) "
|
"(%d, %d, %d) "
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -91,6 +94,36 @@ set_grayscale(int gs)
|
|||||||
grayscale = gs;
|
grayscale = gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read next line; repeat until it's a non-comment; populates 'inbuf[]';
|
||||||
|
the buffer might already have data (first line after colormap) */
|
||||||
|
static int
|
||||||
|
get_next_line(FILE *txtfile, boolean force)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (force || !inbuf[0]) {
|
||||||
|
/* skip leading whitespace */
|
||||||
|
do {
|
||||||
|
ch = fgetc(txtfile);
|
||||||
|
} while (ch == ' ');
|
||||||
|
ungetc(ch, txtfile);
|
||||||
|
/* get rest of line */
|
||||||
|
if (!fgets(inbuf, BUFSZ, txtfile))
|
||||||
|
break;
|
||||||
|
force = TRUE;
|
||||||
|
/* ignore blank lines;
|
||||||
|
the old fscanf() processing did that, possibly by accident */
|
||||||
|
if (!inbuf[0] || (inbuf[0] == '\n' && !inbuf[1]))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inbuf[0] != '#' || !strncmp(inbuf, "# tile ", 7))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inbuf[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_text_colormap(FILE *txtfile)
|
read_text_colormap(FILE *txtfile)
|
||||||
{
|
{
|
||||||
@@ -101,7 +134,9 @@ read_text_colormap(FILE *txtfile)
|
|||||||
color_index[i] = -1;
|
color_index[i] = -1;
|
||||||
|
|
||||||
num_colors = 0;
|
num_colors = 0;
|
||||||
while (fscanf(txtfile, FORMAT_STRING, c, &r, &g, &b) == 4) {
|
while (get_next_line(txtfile, TRUE)) {
|
||||||
|
if (sscanf(inbuf, FORMAT_STRING, c, &r, &g, &b) != 4)
|
||||||
|
break;
|
||||||
color_index[(int) c[0]] = num_colors;
|
color_index[(int) c[0]] = num_colors;
|
||||||
ColorMap[CM_RED][num_colors] = r;
|
ColorMap[CM_RED][num_colors] = r;
|
||||||
ColorMap[CM_GREEN][num_colors] = g;
|
ColorMap[CM_GREEN][num_colors] = g;
|
||||||
@@ -140,22 +175,29 @@ write_text_colormap(FILE *txtfile)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read one tile from win/share/{monsters,objects,other}.txt */
|
||||||
static boolean
|
static boolean
|
||||||
read_txttile(FILE *txtfile, pixel (*pixels)[TILE_X])
|
read_txttile(FILE *txtfile, pixel (*pixels)[TILE_X])
|
||||||
{
|
{
|
||||||
|
static int gidx = 0;
|
||||||
int ph, i, j, k, reslt;
|
int ph, i, j, k, reslt;
|
||||||
char buf[BUFSZ], ttype[BUFSZ], gend[BUFSZ];
|
char buf[BUFSZ], ttype[BUFSZ], gend[BUFSZ];
|
||||||
const char *p;
|
const char *p;
|
||||||
char c[2], *q;
|
char *q;
|
||||||
static int gidx = 0;
|
boolean res = FALSE;
|
||||||
|
|
||||||
gend[0] = '\0';
|
gend[0] = '\0';
|
||||||
if (tile_set == MONSTER_SET)
|
reslt = 0;
|
||||||
reslt = fscanf(txtfile, "# %s %d (%[^,],%[^)])", ttype, &i, buf, gend);
|
if (get_next_line(txtfile, FALSE)) {
|
||||||
else
|
if (tile_set == MONSTER_SET)
|
||||||
reslt = fscanf(txtfile, "# %s %d (%[^)])", ttype, &i, buf);
|
reslt = sscanf(inbuf, "# %255s %d (%255[^,],%255[^)])",
|
||||||
|
ttype, &i, buf, gend);
|
||||||
|
else
|
||||||
|
reslt = sscanf(inbuf, "# %255s %d (%255[^)])",
|
||||||
|
ttype, &i, buf);
|
||||||
|
}
|
||||||
if (reslt <= 0)
|
if (reslt <= 0)
|
||||||
return FALSE;
|
goto done;
|
||||||
|
|
||||||
if (tile_set == MONSTER_SET && gend[0] == 'f')
|
if (tile_set == MONSTER_SET && gend[0] == 'f')
|
||||||
gidx = 1;
|
gidx = 1;
|
||||||
@@ -176,6 +218,7 @@ read_txttile(FILE *txtfile, pixel (*pixels)[TILE_X])
|
|||||||
boolean other_mismatch =
|
boolean other_mismatch =
|
||||||
(tile_set == OTHER_SET
|
(tile_set == OTHER_SET
|
||||||
&& !acceptable_tilename(tile_set, tile_set_indx, buf, p));
|
&& !acceptable_tilename(tile_set, tile_set_indx, buf, p));
|
||||||
|
|
||||||
if (tile_set != OTHER_SET || other_mismatch) {
|
if (tile_set != OTHER_SET || other_mismatch) {
|
||||||
Fprintf(stderr, "warning: for tile %d (numbered %d) of %s,\n",
|
Fprintf(stderr, "warning: for tile %d (numbered %d) of %s,\n",
|
||||||
tile_set_indx, i, text_sets[tile_set]);
|
tile_set_indx, i, text_sets[tile_set]);
|
||||||
@@ -185,31 +228,39 @@ read_txttile(FILE *txtfile, pixel (*pixels)[TILE_X])
|
|||||||
tile_set_indx++;
|
tile_set_indx++;
|
||||||
|
|
||||||
/* look for non-whitespace at each stage */
|
/* look for non-whitespace at each stage */
|
||||||
if (fscanf(txtfile, "%1s", c) < 0) {
|
if (!get_next_line(txtfile, TRUE)) {
|
||||||
Fprintf(stderr, "unexpected EOF\n");
|
Fprintf(stderr, "unexpected EOF\n");
|
||||||
return FALSE;
|
goto done;
|
||||||
}
|
}
|
||||||
if (c[0] != '{') {
|
if (inbuf[0] != '{') {
|
||||||
Fprintf(stderr, "didn't find expected '{'\n");
|
Fprintf(stderr, "didn't find expected '{'\n");
|
||||||
return FALSE;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < TILE_Y; j++) {
|
for (j = 0; j < TILE_Y; j++) {
|
||||||
|
/* read next line of color indices */
|
||||||
|
if (!get_next_line(txtfile, TRUE)) {
|
||||||
|
Fprintf(stderr, "unexpected EOF\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((q = strchr(inbuf, '\n')) == 0)
|
||||||
|
q = &inbuf[strlen(inbuf)]; /* eos(inbuf) */
|
||||||
|
while (q < &inbuf[TILE_X])
|
||||||
|
*q++ = '.';
|
||||||
|
*q = '\0';
|
||||||
|
|
||||||
for (i = 0; i < TILE_X; i++) {
|
for (i = 0; i < TILE_X; i++) {
|
||||||
if (fscanf(txtfile, "%1s", c) < 0) {
|
k = color_index[(unsigned char) inbuf[i]];
|
||||||
Fprintf(stderr, "unexpected EOF\n");
|
if (grayscale && k >= 0) {
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
k = color_index[(int) c[0]];
|
|
||||||
if (grayscale) {
|
|
||||||
if (k > (SIZE(graymappings) - 1))
|
if (k > (SIZE(graymappings) - 1))
|
||||||
Fprintf(stderr, "Gray mapping issue %d > %d.\n", k,
|
Fprintf(stderr, "Gray mapping issue %d > %d.\n", k,
|
||||||
SIZE(graymappings) - 1);
|
SIZE(graymappings) - 1);
|
||||||
else
|
else
|
||||||
k = graymappings[k];
|
k = graymappings[k];
|
||||||
}
|
}
|
||||||
if (k == -1)
|
if (k == -1) {
|
||||||
Fprintf(stderr, "color %c not in colormap!\n", c[0]);
|
Fprintf(stderr, "color %c not in colormap!\n", inbuf[i]);
|
||||||
else {
|
} else {
|
||||||
pixels[j][i].r = ColorMap[CM_RED][k];
|
pixels[j][i].r = ColorMap[CM_RED][k];
|
||||||
pixels[j][i].g = ColorMap[CM_GREEN][k];
|
pixels[j][i].g = ColorMap[CM_GREEN][k];
|
||||||
pixels[j][i].b = ColorMap[CM_BLUE][k];
|
pixels[j][i].b = ColorMap[CM_BLUE][k];
|
||||||
@@ -218,25 +269,20 @@ read_txttile(FILE *txtfile, pixel (*pixels)[TILE_X])
|
|||||||
}
|
}
|
||||||
if (ph) {
|
if (ph) {
|
||||||
/* remember it for later */
|
/* remember it for later */
|
||||||
memcpy(placeholder, pixels, sizeof(placeholder));
|
memcpy(placeholder, pixels, sizeof placeholder);
|
||||||
}
|
}
|
||||||
if (fscanf(txtfile, "%1s ", c) < 0) {
|
if (!get_next_line(txtfile, TRUE)) {
|
||||||
Fprintf(stderr, "unexpected EOF\n");
|
Fprintf(stderr, "unexpected EOF\n");
|
||||||
return FALSE;
|
goto done;
|
||||||
}
|
}
|
||||||
if (c[0] != '}') {
|
if (inbuf[0] != '}') {
|
||||||
Fprintf(stderr, "didn't find expected '}'\n");
|
Fprintf(stderr, "didn't find expected '}'\n");
|
||||||
return FALSE;
|
goto done;
|
||||||
}
|
}
|
||||||
#ifdef _DCC
|
res = TRUE;
|
||||||
/* DICE again... it doesn't seem to eat whitespace after the } like
|
done:
|
||||||
* it should, so we have to do so manually.
|
inbuf[0] = '\0';
|
||||||
*/
|
return res;
|
||||||
while ((*c = fgetc(txtfile)) != EOF && isspace((uchar) *c))
|
|
||||||
;
|
|
||||||
ungetc(*c, txtfile);
|
|
||||||
#endif
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -386,7 +432,7 @@ fopen_text_file(const char *filename, const char *type)
|
|||||||
boolean
|
boolean
|
||||||
read_text_tile(pixel (*pixels)[TILE_X])
|
read_text_tile(pixel (*pixels)[TILE_X])
|
||||||
{
|
{
|
||||||
return (read_txttile(tile_file, pixels));
|
return read_txttile(tile_file, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user