ref: 366f45c10a632443767cbda6f7b2f3d98a60d60b
parent: 204814c7bb16a8ad45435a15328072681978ea57
author: Fabian Greffrath <fabian@greffrath.com>
date: Mon Sep 8 06:48:56 EDT 2014
add parser for [STRINGS] sections in BEX files
--- a/src/deh_io.c
+++ b/src/deh_io.c
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "i_system.h"
#include "m_misc.h"
@@ -224,7 +225,7 @@
// Read a whole line
-char *DEH_ReadLine(deh_context_t *context)
+char *DEH_ReadLine(deh_context_t *context, boolean extended)
{int c;
int pos;
@@ -245,6 +246,40 @@
if (pos >= context->readbuffer_size)
{IncreaseReadBuffer(context);
+ }
+
+ // extended string support
+ if (extended && c == '\\')
+ {+ escaped:
+ c = DEH_GetChar(context);
+
+ // "\n" in the middle of a string indicates an internal linefeed
+ if (c == 'n')
+ {+ context->readbuffer[pos] = '\n';
+ ++pos;
+ continue;
+ }
+
+ // values to be assigned may be split onto multiple lines by ending
+ // each line that is to be continued with a backslash
+ if (c == '\n')
+ {+ // blanks before the backslash are included in the string
+ // but indentation after the linefeed is not
+ do
+ {+ c = DEH_GetChar(context);
+ } while (isspace(c) && c != '\n');
+
+ // if the next non-space character after an escaped linefeed
+ // is another backslash, repeat again
+ if (c == '\\')
+ {+ goto escaped;
+ }
+ }
}
if (c == '\n')
--- a/src/deh_io.h
+++ b/src/deh_io.h
@@ -24,7 +24,7 @@
deh_context_t *DEH_OpenLump(int lumpnum);
void DEH_CloseFile(deh_context_t *context);
int DEH_GetChar(deh_context_t *context);
-char *DEH_ReadLine(deh_context_t *context);
+char *DEH_ReadLine(deh_context_t *context, boolean extended);
void DEH_Error(deh_context_t *context, char *msg, ...);
void DEH_Warning(deh_context_t *context, char *msg, ...);
--- a/src/deh_main.c
+++ b/src/deh_main.c
@@ -175,7 +175,7 @@
// Read the first line
- line = DEH_ReadLine(context);
+ line = DEH_ReadLine(context, false);
if (line == NULL)
{@@ -244,7 +244,7 @@
{// read a new line
- line = DEH_ReadLine(context);
+ line = DEH_ReadLine(context, current_section == GetSectionByName("[STRINGS]"));// end of file?
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -63,6 +63,7 @@
FEATURE_DEHACKED_SOURCE_FILES = \
deh_ammo.c \
+deh_bexstr.c \
deh_cheat.c \
deh_doom.c \
deh_frame.c \
--- /dev/null
+++ b/src/doom/deh_bexstr.c
@@ -1,0 +1,376 @@
+//
+// Copyright(C) 2005-2014 Simon Howard
+// Copyright(C) 2014 Fabian Greffrath
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+//
+// Parses [STRINGS] sections in BEX files
+//
+
+#include <stdio.h>
+#include <string.h>
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+
+#include "dstrings.h"
+
+typedef struct {+ char *macro;
+ char *string;
+} bex_string;
+
+// mnemonic keys table
+static bex_string bex_stringtable[] = {+ // part 1 - general initialization and prompts
+ {"D_DEVSTR", D_DEVSTR},+ {"D_CDROM", D_CDROM},+ {"QUITMSG", QUITMSG},+ {"LOADNET", LOADNET},+ {"QLOADNET", QLOADNET},+ {"QSAVESPOT", QSAVESPOT},+ {"SAVEDEAD", SAVEDEAD},+ {"QSPROMPT", QSPROMPT},+ {"QLPROMPT", QLPROMPT},+ {"NEWGAME", NEWGAME},+ {"NIGHTMARE", NIGHTMARE},+ {"SWSTRING", SWSTRING},+ {"MSGOFF", MSGOFF},+ {"MSGON", MSGON},+ {"NETEND", NETEND},+ {"ENDGAME", ENDGAME},+ {"DETAILHI", DETAILHI},+ {"DETAILLO", DETAILLO},+ {"GAMMALVL0", GAMMALVL0},+ {"GAMMALVL1", GAMMALVL1},+ {"GAMMALVL2", GAMMALVL2},+ {"GAMMALVL3", GAMMALVL3},+ {"GAMMALVL4", GAMMALVL4},+ {"EMPTYSTRING", EMPTYSTRING},+ {"GGSAVED", GGSAVED},+ {"SAVEGAMENAME", SAVEGAMENAME},+ // part 2 - messages when the player gets things
+ {"GOTARMOR", GOTARMOR},+ {"GOTMEGA", GOTMEGA},+ {"GOTHTHBONUS", GOTHTHBONUS},+ {"GOTARMBONUS", GOTARMBONUS},+ {"GOTSTIM", GOTSTIM},+ {"GOTMEDINEED", GOTMEDINEED},+ {"GOTMEDIKIT", GOTMEDIKIT},+ {"GOTSUPER", GOTSUPER},+ {"GOTBLUECARD", GOTBLUECARD},+ {"GOTYELWCARD", GOTYELWCARD},+ {"GOTREDCARD", GOTREDCARD},+ {"GOTBLUESKUL", GOTBLUESKUL},+ {"GOTYELWSKUL", GOTYELWSKUL},+ {"GOTREDSKULL", GOTREDSKULL},+ {"GOTINVUL", GOTINVUL},+ {"GOTBERSERK", GOTBERSERK},+ {"GOTINVIS", GOTINVIS},+ {"GOTSUIT", GOTSUIT},+ {"GOTMAP", GOTMAP},+ {"GOTVISOR", GOTVISOR},+ {"GOTMSPHERE", GOTMSPHERE},+ {"GOTCLIP", GOTCLIP},+ {"GOTCLIPBOX", GOTCLIPBOX},+ {"GOTROCKET", GOTROCKET},+ {"GOTROCKBOX", GOTROCKBOX},+ {"GOTCELL", GOTCELL},+ {"GOTCELLBOX", GOTCELLBOX},+ {"GOTSHELLS", GOTSHELLS},+ {"GOTSHELLBOX", GOTSHELLBOX},+ {"GOTBACKPACK", GOTBACKPACK},+ {"GOTBFG9000", GOTBFG9000},+ {"GOTCHAINGUN", GOTCHAINGUN},+ {"GOTCHAINSAW", GOTCHAINSAW},+ {"GOTLAUNCHER", GOTLAUNCHER},+ {"GOTPLASMA", GOTPLASMA},+ {"GOTSHOTGUN", GOTSHOTGUN},+ {"GOTSHOTGUN2", GOTSHOTGUN2},+ // part 3 - messages when keys are needed
+ {"PD_BLUEO", PD_BLUEO},+ {"PD_REDO", PD_REDO},+ {"PD_YELLOWO", PD_YELLOWO},+ {"PD_BLUEK", PD_BLUEK},+ {"PD_REDK", PD_REDK},+ {"PD_YELLOWK", PD_YELLOWK},+ // part 4 - multiplayer messaging
+ {"HUSTR_MSGU", HUSTR_MSGU},+ {"HUSTR_MESSAGESENT", HUSTR_MESSAGESENT},+ {"HUSTR_CHATMACRO0", HUSTR_CHATMACRO0},+ {"HUSTR_CHATMACRO1", HUSTR_CHATMACRO1},+ {"HUSTR_CHATMACRO2", HUSTR_CHATMACRO2},+ {"HUSTR_CHATMACRO3", HUSTR_CHATMACRO3},+ {"HUSTR_CHATMACRO4", HUSTR_CHATMACRO4},+ {"HUSTR_CHATMACRO5", HUSTR_CHATMACRO5},+ {"HUSTR_CHATMACRO6", HUSTR_CHATMACRO6},+ {"HUSTR_CHATMACRO7", HUSTR_CHATMACRO7},+ {"HUSTR_CHATMACRO8", HUSTR_CHATMACRO8},+ {"HUSTR_CHATMACRO9", HUSTR_CHATMACRO9},+ {"HUSTR_TALKTOSELF1", HUSTR_TALKTOSELF1},+ {"HUSTR_TALKTOSELF2", HUSTR_TALKTOSELF2},+ {"HUSTR_TALKTOSELF3", HUSTR_TALKTOSELF3},+ {"HUSTR_TALKTOSELF4", HUSTR_TALKTOSELF4},+ {"HUSTR_TALKTOSELF5", HUSTR_TALKTOSELF5},+ {"HUSTR_PLRGREEN", HUSTR_PLRGREEN},+ {"HUSTR_PLRINDIGO", HUSTR_PLRINDIGO},+ {"HUSTR_PLRBROWN", HUSTR_PLRBROWN},+ {"HUSTR_PLRRED", HUSTR_PLRRED},+ // part 5 - level names in the automap
+ {"HUSTR_E1M1", HUSTR_E1M1},+ {"HUSTR_E1M2", HUSTR_E1M2},+ {"HUSTR_E1M3", HUSTR_E1M3},+ {"HUSTR_E1M4", HUSTR_E1M4},+ {"HUSTR_E1M5", HUSTR_E1M5},+ {"HUSTR_E1M6", HUSTR_E1M6},+ {"HUSTR_E1M7", HUSTR_E1M7},+ {"HUSTR_E1M8", HUSTR_E1M8},+ {"HUSTR_E1M9", HUSTR_E1M9},+ {"HUSTR_E2M1", HUSTR_E2M1},+ {"HUSTR_E2M2", HUSTR_E2M2},+ {"HUSTR_E2M3", HUSTR_E2M3},+ {"HUSTR_E2M4", HUSTR_E2M4},+ {"HUSTR_E2M5", HUSTR_E2M5},+ {"HUSTR_E2M6", HUSTR_E2M6},+ {"HUSTR_E2M7", HUSTR_E2M7},+ {"HUSTR_E2M8", HUSTR_E2M8},+ {"HUSTR_E2M9", HUSTR_E2M9},+ {"HUSTR_E3M1", HUSTR_E3M1},+ {"HUSTR_E3M2", HUSTR_E3M2},+ {"HUSTR_E3M3", HUSTR_E3M3},+ {"HUSTR_E3M4", HUSTR_E3M4},+ {"HUSTR_E3M5", HUSTR_E3M5},+ {"HUSTR_E3M6", HUSTR_E3M6},+ {"HUSTR_E3M7", HUSTR_E3M7},+ {"HUSTR_E3M8", HUSTR_E3M8},+ {"HUSTR_E3M9", HUSTR_E3M9},+ {"HUSTR_E4M1", HUSTR_E4M1},+ {"HUSTR_E4M2", HUSTR_E4M2},+ {"HUSTR_E4M3", HUSTR_E4M3},+ {"HUSTR_E4M4", HUSTR_E4M4},+ {"HUSTR_E4M5", HUSTR_E4M5},+ {"HUSTR_E4M6", HUSTR_E4M6},+ {"HUSTR_E4M7", HUSTR_E4M7},+ {"HUSTR_E4M8", HUSTR_E4M8},+ {"HUSTR_E4M9", HUSTR_E4M9},+ {"HUSTR_1", HUSTR_1},+ {"HUSTR_2", HUSTR_2},+ {"HUSTR_3", HUSTR_3},+ {"HUSTR_4", HUSTR_4},+ {"HUSTR_5", HUSTR_5},+ {"HUSTR_6", HUSTR_6},+ {"HUSTR_7", HUSTR_7},+ {"HUSTR_8", HUSTR_8},+ {"HUSTR_9", HUSTR_9},+ {"HUSTR_10", HUSTR_10},+ {"HUSTR_11", HUSTR_11},+ {"HUSTR_12", HUSTR_12},+ {"HUSTR_13", HUSTR_13},+ {"HUSTR_14", HUSTR_14},+ {"HUSTR_15", HUSTR_15},+ {"HUSTR_16", HUSTR_16},+ {"HUSTR_17", HUSTR_17},+ {"HUSTR_18", HUSTR_18},+ {"HUSTR_19", HUSTR_19},+ {"HUSTR_20", HUSTR_20},+ {"HUSTR_21", HUSTR_21},+ {"HUSTR_22", HUSTR_22},+ {"HUSTR_23", HUSTR_23},+ {"HUSTR_24", HUSTR_24},+ {"HUSTR_25", HUSTR_25},+ {"HUSTR_26", HUSTR_26},+ {"HUSTR_27", HUSTR_27},+ {"HUSTR_28", HUSTR_28},+ {"HUSTR_29", HUSTR_29},+ {"HUSTR_30", HUSTR_30},+ {"HUSTR_31", HUSTR_31},+ {"HUSTR_32", HUSTR_32},+ {"PHUSTR_1", PHUSTR_1},+ {"PHUSTR_2", PHUSTR_2},+ {"PHUSTR_3", PHUSTR_3},+ {"PHUSTR_4", PHUSTR_4},+ {"PHUSTR_5", PHUSTR_5},+ {"PHUSTR_6", PHUSTR_6},+ {"PHUSTR_7", PHUSTR_7},+ {"PHUSTR_8", PHUSTR_8},+ {"PHUSTR_9", PHUSTR_9},+ {"PHUSTR_10", PHUSTR_10},+ {"PHUSTR_11", PHUSTR_11},+ {"PHUSTR_12", PHUSTR_12},+ {"PHUSTR_13", PHUSTR_13},+ {"PHUSTR_14", PHUSTR_14},+ {"PHUSTR_15", PHUSTR_15},+ {"PHUSTR_16", PHUSTR_16},+ {"PHUSTR_17", PHUSTR_17},+ {"PHUSTR_18", PHUSTR_18},+ {"PHUSTR_19", PHUSTR_19},+ {"PHUSTR_20", PHUSTR_20},+ {"PHUSTR_21", PHUSTR_21},+ {"PHUSTR_22", PHUSTR_22},+ {"PHUSTR_23", PHUSTR_23},+ {"PHUSTR_24", PHUSTR_24},+ {"PHUSTR_25", PHUSTR_25},+ {"PHUSTR_26", PHUSTR_26},+ {"PHUSTR_27", PHUSTR_27},+ {"PHUSTR_28", PHUSTR_28},+ {"PHUSTR_29", PHUSTR_29},+ {"PHUSTR_30", PHUSTR_30},+ {"PHUSTR_31", PHUSTR_31},+ {"PHUSTR_32", PHUSTR_32},+ {"THUSTR_1", THUSTR_1},+ {"THUSTR_2", THUSTR_2},+ {"THUSTR_3", THUSTR_3},+ {"THUSTR_4", THUSTR_4},+ {"THUSTR_5", THUSTR_5},+ {"THUSTR_6", THUSTR_6},+ {"THUSTR_7", THUSTR_7},+ {"THUSTR_8", THUSTR_8},+ {"THUSTR_9", THUSTR_9},+ {"THUSTR_10", THUSTR_10},+ {"THUSTR_11", THUSTR_11},+ {"THUSTR_12", THUSTR_12},+ {"THUSTR_13", THUSTR_13},+ {"THUSTR_14", THUSTR_14},+ {"THUSTR_15", THUSTR_15},+ {"THUSTR_16", THUSTR_16},+ {"THUSTR_17", THUSTR_17},+ {"THUSTR_18", THUSTR_18},+ {"THUSTR_19", THUSTR_19},+ {"THUSTR_20", THUSTR_20},+ {"THUSTR_21", THUSTR_21},+ {"THUSTR_22", THUSTR_22},+ {"THUSTR_23", THUSTR_23},+ {"THUSTR_24", THUSTR_24},+ {"THUSTR_25", THUSTR_25},+ {"THUSTR_26", THUSTR_26},+ {"THUSTR_27", THUSTR_27},+ {"THUSTR_28", THUSTR_28},+ {"THUSTR_29", THUSTR_29},+ {"THUSTR_30", THUSTR_30},+ {"THUSTR_31", THUSTR_31},+ {"THUSTR_32", THUSTR_32},+ // part 6 - messages as a result of toggling states
+ {"AMSTR_FOLLOWON", AMSTR_FOLLOWON},+ {"AMSTR_FOLLOWOFF", AMSTR_FOLLOWOFF},+ {"AMSTR_GRIDON", AMSTR_GRIDON},+ {"AMSTR_GRIDOFF", AMSTR_GRIDOFF},+ {"AMSTR_MARKEDSPOT", AMSTR_MARKEDSPOT},+ {"AMSTR_MARKSCLEARED", AMSTR_MARKSCLEARED},+ {"STSTR_MUS", STSTR_MUS},+ {"STSTR_NOMUS", STSTR_NOMUS},+ {"STSTR_DQDON", STSTR_DQDON},+ {"STSTR_DQDOFF", STSTR_DQDOFF},+ {"STSTR_KFAADDED", STSTR_KFAADDED},+ {"STSTR_FAADDED", STSTR_FAADDED},+ {"STSTR_NCON", STSTR_NCON},+ {"STSTR_NCOFF", STSTR_NCOFF},+ {"STSTR_BEHOLD", STSTR_BEHOLD},+ {"STSTR_BEHOLDX", STSTR_BEHOLDX},+ {"STSTR_CHOPPERS", STSTR_CHOPPERS},+ {"STSTR_CLEV", STSTR_CLEV},+ // part 7 - episode intermission texts
+ {"E1TEXT", E1TEXT},+ {"E2TEXT", E2TEXT},+ {"E3TEXT", E3TEXT},+ {"E4TEXT", E4TEXT},+ {"C1TEXT", C1TEXT},+ {"C2TEXT", C2TEXT},+ {"C3TEXT", C3TEXT},+ {"C4TEXT", C4TEXT},+ {"C5TEXT", C5TEXT},+ {"C6TEXT", C6TEXT},+ {"P1TEXT", P1TEXT},+ {"P2TEXT", P2TEXT},+ {"P3TEXT", P3TEXT},+ {"P4TEXT", P4TEXT},+ {"P5TEXT", P5TEXT},+ {"P6TEXT", P6TEXT},+ {"T1TEXT", T1TEXT},+ {"T2TEXT", T2TEXT},+ {"T3TEXT", T3TEXT},+ {"T4TEXT", T4TEXT},+ {"T5TEXT", T5TEXT},+ {"T6TEXT", T6TEXT},+ // part 8 - creature names for the finale
+ {"CC_ZOMBIE", CC_ZOMBIE},+ {"CC_SHOTGUN", CC_SHOTGUN},+ {"CC_HEAVY", CC_HEAVY},+ {"CC_IMP", CC_IMP},+ {"CC_DEMON", CC_DEMON},+ {"CC_LOST", CC_LOST},+ {"CC_CACO", CC_CACO},+ {"CC_HELL", CC_HELL},+ {"CC_BARON", CC_BARON},+ {"CC_ARACH", CC_ARACH},+ {"CC_PAIN", CC_PAIN},+ {"CC_REVEN", CC_REVEN},+ {"CC_MANCU", CC_MANCU},+ {"CC_ARCH", CC_ARCH},+ {"CC_SPIDER", CC_SPIDER},+ {"CC_CYBER", CC_CYBER},+ {"CC_HERO", CC_HERO},+ // part 9 - intermission tiled backgrounds
+ {"BGFLATE1", "FLOOR4_8"},+ {"BGFLATE2", "SFLR6_1"},+ {"BGFLATE3", "MFLR8_4"},+ {"BGFLATE4", "MFLR8_3"},+ {"BGFLAT06", "SLIME16"},+ {"BGFLAT11", "RROCK14"},+ {"BGFLAT20", "RROCK07"},+ {"BGFLAT30", "RROCK17"},+ {"BGFLAT15", "RROCK13"},+ {"BGFLAT31", "RROCK19"},+ {"BGCASTCALL", "BOSSBACK"},+};
+
+static void *DEH_BEXStrStart(deh_context_t *context, char *line)
+{+ char s[10];
+
+ if (sscanf(line, "%9s", s) == 0 || strncmp("[STRINGS]", s, sizeof(s)))+ {+ DEH_Warning(context, "Parse error on section start");
+ }
+
+ return NULL;
+}
+
+static void DEH_BEXStrParseLine(deh_context_t *context, char *line, void *tag)
+{+ char *variable_name, *value;
+ int i;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ for (i = 0; i < arrlen(bex_stringtable); i++)
+ {+ if (!strcmp(bex_stringtable[i].macro, variable_name))
+ {+ DEH_AddStringReplacement(bex_stringtable[i].string, strdup(value));
+ }
+ }
+}
+
+deh_section_t deh_section_bexstr =
+{+ "[STRINGS]",
+ NULL,
+ DEH_BEXStrStart,
+ DEH_BEXStrParseLine,
+ NULL,
+ NULL,
+};
--- a/src/doom/deh_doom.c
+++ b/src/doom/deh_doom.c
@@ -44,6 +44,8 @@
extern deh_section_t deh_section_thing;
// deh_weapon.c:
extern deh_section_t deh_section_weapon;
+// deh_bexstr.c:
+extern deh_section_t deh_section_bexstr;
//
// List of section types:
@@ -60,6 +62,7 @@
&deh_section_text,
&deh_section_thing,
&deh_section_weapon,
+ &deh_section_bexstr,
NULL
};
--
⑨