2
This file is part of Warzone 2100.
3
Copyright (C) 2008 Giel van Schijndel
4
Copyright (C) 2008-2009 Warzone Resurrection Project
6
Warzone 2100 is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
Warzone 2100 is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with Warzone 2100; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
* Parser for message data
26
#include "lib/framework/frame.h"
27
#include "lib/framework/strres.h"
28
#include "lib/framework/frameresource.h"
30
#include "messagedef.h"
31
#include "messagely.h"
34
extern void yyerror(const char* msg);
35
void yyerror(const char* msg)
37
debug(LOG_ERROR, "SMSG file parse error:\n%s at line %d\nText: '%s'", msg, message_get_lineno(), message_get_text());
40
typedef struct TEXT_MESSAGE
43
struct TEXT_MESSAGE* psNext;
46
static void freeTextMessageList(TEXT_MESSAGE* list)
50
TEXT_MESSAGE* const toDelete = list;
57
typedef struct VIEWDATAMESSAGE
60
struct VIEWDATAMESSAGE* psNext;
63
static void freeViewDataMessageList(VIEWDATAMESSAGE* list)
67
VIEWDATAMESSAGE* const toDelete = list;
69
free(toDelete->view.pName);
70
free(toDelete->view.ppTextMsg);
71
switch (toDelete->view.type)
75
VIEW_RESEARCH* const psViewRes = toDelete->view.pData;
76
if (psViewRes->pAudio)
77
free(psViewRes->pAudio);
82
ASSERT(!"Unhandled view data type", "Unhandled view data type %u", toDelete->view.type);
88
#define YYPARSE_PARAM ppsViewData
92
%name-prefix="message_"
96
struct VIEWDATAMESSAGE* viewdatamsg;
97
struct TEXT_MESSAGE* txtmsg;
99
VIEW_RESEARCH* researchdata;
102
const char** stringArray;
109
%token <sval> QTEXT_T NULL_T /* Text with double quotes surrounding it */
110
%token <viewtype> VIEW_T_RES VIEW_T_RPL VIEW_T_PROX VIEW_T_RPLX VIEW_T_BEACON
111
%token IMD_NAME_T IMD_NAME2_T SEQUENCE_NAME_T AUDIO_NAME_T
114
%type <txtmsg> text_message text_messages
115
%type <msg_list> message_list
116
%type <sval> optional_string imd_name imd_name2 sequence_name audio_name
117
%type <researchdata> research_message
118
%type <viewdatamsg> all_messages message
122
// Force type checking by the compiler
128
} TEXT_T QTEXT_T optional_string imd_name imd_name2 sequence_name audio_name
131
freeTextMessageList($$);
132
} text_message text_messages;
135
// Force type checking by the compiler
136
VIEW_RESEARCH* const r = $$;
148
freeViewDataMessageList($$);
149
} all_messages message
155
unsigned int numData = 0, i;
156
VIEWDATAMESSAGE* curMsg;
157
VIEWDATA* psViewData;
159
for (curMsg = $1; curMsg != NULL; curMsg = curMsg->psNext)
164
ASSERT(numData <= UBYTE_MAX, "loadViewData: Didn't expect %d (or more) viewData messages (got %u)!", UBYTE_MAX, numData);
165
if (numData > UBYTE_MAX)
167
freeViewDataMessageList($1);
171
psViewData = malloc(numData * sizeof(*psViewData));
172
if (psViewData == NULL)
174
debug(LOG_ERROR, "Out of memory");
176
freeViewDataMessageList($1);
181
for (i = 0; i < numData; ++i)
183
VIEWDATAMESSAGE* const toMove = curMsg;
184
assert(toMove != NULL);
185
curMsg = curMsg->psNext;
186
memcpy(&psViewData[i], &toMove->view, sizeof(psViewData[i]));
190
addToViewDataList(psViewData, numData);
191
*(VIEWDATA**)ppsViewData = psViewData;
195
all_messages: message
196
| message all_messages
203
message: TEXT_T '{' message_list ',' research_message '}' ';'
205
$$ = malloc(sizeof(*$$));
208
debug(LOG_ERROR, "Out of memory");
211
free($3.stringArray);
219
$$->view.numText = $3.count;
220
$$->view.ppTextMsg = $3.stringArray;
221
$$->view.type = VIEW_RES;
227
research_message: imd_name ',' imd_name2 ',' sequence_name ',' audio_name ','
229
$$ = malloc(sizeof(*$$));
232
debug(LOG_ERROR, "Out of memory");
242
sstrcpy($$->sequenceName, $5);
243
// Get rid of our tokens ASAP (so that the free() lists on errors become shorter)
246
$$->pIMD = (iIMDShape *) resGetData("IMD", $1);
247
if ($$->pIMD == NULL)
249
ASSERT(LOG_ERROR, "Cannot find PIE \"%s\"", $1);
258
$$->pIMD2 = (iIMDShape *) resGetData("IMD", $3);
259
if ($$->pIMD2 == NULL)
261
ASSERT(false, "Cannot find 2nd PIE \"%s\"", $3);
274
imd_name: IMD_NAME_T '=' QTEXT_T { $$ = $3; }
278
imd_name2: IMD_NAME2_T '=' optional_string { $$ = $3; }
282
sequence_name: SEQUENCE_NAME_T '=' QTEXT_T { $$ = $3; }
286
audio_name: AUDIO_NAME_T '=' optional_string { $$ = $3; }
290
optional_string: QTEXT_T
294
message_list: '{' text_messages '}'
303
// Compute the required space for all strings and an array of pointers to hold it
304
for (psCur = $2; psCur != NULL; psCur = psCur->psNext)
307
bytes += sizeof(char*) + strlen(psCur->str) + 1;
310
ASSERT($$.count <= MAX_DATA, "Too many text strings (%u) provided, with %u as maximum", $$.count, (unsigned int)MAX_DATA);
311
if ($$.count > MAX_DATA)
318
$$.stringArray = malloc(bytes);
319
if ($$.stringArray == NULL)
321
debug(LOG_ERROR, "Out of memory");
323
freeTextMessageList($2);
327
stringStart = (char*)&$$.stringArray[$$.count];
328
for (psCur = $2, i = 0, stringStart;
329
psCur != NULL && i < $$.count;
330
psCur = psCur->psNext, ++i)
332
assert(&stringStart[strlen(psCur->str)] - (char*)$$.stringArray < bytes);
333
$$.stringArray[i] = strcpy(stringStart, psCur->str);
334
stringStart = &stringStart[strlen(psCur->str) + 1];
339
$$.stringArray = NULL;
342
// Clean up our tokens
343
freeTextMessageList($2);
347
text_messages: text_message
348
/* Allow trailing commas */
350
| text_message ',' text_messages
359
const char * const msg = strresGetString(psStringRes, $1);
362
ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", $1);
367
$$ = malloc(sizeof(*$$));
370
debug(LOG_ERROR, "Out of memory");
381
$$ = malloc(sizeof(*$$));
384
debug(LOG_ERROR, "Out of memory");
393
| '_' '(' QTEXT_T ')'
395
$$ = malloc(sizeof(*$$));
398
debug(LOG_ERROR, "Out of memory");