~ubuntu-branches/ubuntu/lucid/warzone2100/lucid

« back to all changes in this revision

Viewing changes to src/message_parser.y

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger, Paul Wise, Christoph Egger
  • Date: 2009-06-29 17:12:52 UTC
  • mfrom: (1.1.11 upstream) (2.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090629171252-5ddnlfg3zfchrega
Tags: 2.2.1+dfsg1-1
[ Paul Wise ]
* New upstream release (Closes: #534962)
* Adjust the flex build-depends to take account of the conflict
  with all the versions of flex 2.5.34 (LP: #372872)
* Make the -music Recommends more strict, 2.1 music doesn't work
  with 2.2.
* Upstream moved the downloads to sourceforge, update the watch file
* Bump Standards-Version, no changes needed
* Drop use of dh_desktop since it no longer does anything
* Recommend the new warzone2100-video package, version 2.2 or similar
* Mention the warzone2100 crash reports in the -dbg package description

[ Christoph Egger ]
* Replace CC-2.0 graphic from cybersphinx, create a new tarball
* Add myself to uploaders

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        This file is part of Warzone 2100.
 
3
        Copyright (C) 2008  Giel van Schijndel
 
4
        Copyright (C) 2008-2009  Warzone Resurrection Project
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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
 
19
*/
 
20
%{
 
21
/** @file
 
22
 *
 
23
 *  Parser for message data
 
24
 */
 
25
 
 
26
#include "lib/framework/frame.h"
 
27
#include "lib/framework/strres.h"
 
28
#include "lib/framework/frameresource.h"
 
29
#include "message.h"
 
30
#include "messagedef.h"
 
31
#include "messagely.h"
 
32
#include "text.h"
 
33
 
 
34
extern void yyerror(const char* msg);
 
35
void yyerror(const char* msg)
 
36
{
 
37
        debug(LOG_ERROR, "SMSG file parse error:\n%s at line %d\nText: '%s'", msg, message_get_lineno(), message_get_text());
 
38
}
 
39
 
 
40
typedef struct TEXT_MESSAGE
 
41
{
 
42
        char * str;
 
43
        struct TEXT_MESSAGE* psNext;
 
44
} TEXT_MESSAGE;
 
45
 
 
46
static void freeTextMessageList(TEXT_MESSAGE* list)
 
47
{
 
48
        while (list)
 
49
        {
 
50
                TEXT_MESSAGE* const toDelete = list;
 
51
                list = list->psNext;
 
52
                free(toDelete->str);
 
53
                free(toDelete);
 
54
        }
 
55
}
 
56
 
 
57
typedef struct VIEWDATAMESSAGE
 
58
{
 
59
        VIEWDATA view;
 
60
        struct VIEWDATAMESSAGE* psNext;
 
61
} VIEWDATAMESSAGE;
 
62
 
 
63
static void freeViewDataMessageList(VIEWDATAMESSAGE* list)
 
64
{
 
65
        while (list)
 
66
        {
 
67
                VIEWDATAMESSAGE* const toDelete = list;
 
68
                list = list->psNext;
 
69
                free(toDelete->view.pName);
 
70
                free(toDelete->view.ppTextMsg);
 
71
                switch (toDelete->view.type)
 
72
                {
 
73
                        case VIEW_RES:
 
74
                        {
 
75
                                VIEW_RESEARCH* const psViewRes = toDelete->view.pData;
 
76
                                if (psViewRes->pAudio)
 
77
                                        free(psViewRes->pAudio);
 
78
                                free(psViewRes);
 
79
                                break;
 
80
                        }
 
81
                        default:
 
82
                                ASSERT(!"Unhandled view data type", "Unhandled view data type %u", toDelete->view.type);
 
83
                }
 
84
                free(toDelete);
 
85
        }
 
86
}
 
87
 
 
88
#define YYPARSE_PARAM ppsViewData
 
89
 
 
90
%}
 
91
 
 
92
%name-prefix="message_"
 
93
 
 
94
%union {
 
95
        char*                   sval;
 
96
        struct VIEWDATAMESSAGE* viewdatamsg;
 
97
        struct TEXT_MESSAGE*    txtmsg;
 
98
        VIEW_TYPE               viewtype;
 
99
        VIEW_RESEARCH*          researchdata;
 
100
        struct
 
101
        {
 
102
                const char**    stringArray;
 
103
                unsigned int    count;
 
104
        }                       msg_list;
 
105
}
 
106
 
 
107
        /* value tokens */
 
108
%token <sval> TEXT_T
 
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
 
112
 
 
113
// Rule types
 
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
 
119
 
 
120
%destructor {
 
121
#ifndef WZ_OS_WIN
 
122
        // Force type checking by the compiler
 
123
        char * const s = $$;
 
124
 
 
125
        if (s)
 
126
                free(s);
 
127
#endif
 
128
} TEXT_T QTEXT_T optional_string imd_name imd_name2 sequence_name audio_name
 
129
 
 
130
%destructor {
 
131
        freeTextMessageList($$);
 
132
} text_message text_messages;
 
133
 
 
134
%destructor {
 
135
        // Force type checking by the compiler
 
136
        VIEW_RESEARCH* const r = $$;
 
137
 
 
138
        if (r)
 
139
        {
 
140
                if (r->pAudio)
 
141
                        free(r->pAudio);
 
142
 
 
143
                free(r);
 
144
        }
 
145
} research_message
 
146
 
 
147
%destructor {
 
148
        freeViewDataMessageList($$);
 
149
} all_messages message
 
150
 
 
151
%%
 
152
 
 
153
file:                   all_messages
 
154
                                {
 
155
                                        unsigned int numData = 0, i;
 
156
                                        VIEWDATAMESSAGE* curMsg;
 
157
                                        VIEWDATA* psViewData;
 
158
 
 
159
                                        for (curMsg = $1; curMsg != NULL; curMsg = curMsg->psNext)
 
160
                                        {
 
161
                                                ++numData;
 
162
                                        }
 
163
 
 
164
                                        ASSERT(numData <= UBYTE_MAX, "loadViewData: Didn't expect %d (or more) viewData messages (got %u)!", UBYTE_MAX, numData);
 
165
                                        if (numData > UBYTE_MAX)
 
166
                                        {
 
167
                                                freeViewDataMessageList($1);
 
168
                                                YYABORT;
 
169
                                        }
 
170
 
 
171
                                        psViewData = malloc(numData * sizeof(*psViewData));
 
172
                                        if (psViewData == NULL)
 
173
                                        {
 
174
                                                debug(LOG_ERROR, "Out of memory");
 
175
                                                abort();
 
176
                                                freeViewDataMessageList($1);
 
177
                                                YYABORT;
 
178
                                        }
 
179
 
 
180
                                        curMsg = $1;
 
181
                                        for (i = 0; i < numData; ++i)
 
182
                                        {
 
183
                                                VIEWDATAMESSAGE* const toMove = curMsg;
 
184
                                                assert(toMove != NULL);
 
185
                                                curMsg = curMsg->psNext;
 
186
                                                memcpy(&psViewData[i], &toMove->view, sizeof(psViewData[i]));
 
187
                                                free(toMove);
 
188
                                        }
 
189
 
 
190
                                        addToViewDataList(psViewData, numData);
 
191
                                        *(VIEWDATA**)ppsViewData = psViewData;
 
192
                                }
 
193
                        ;
 
194
 
 
195
all_messages:           message
 
196
                        |       message all_messages
 
197
                                {
 
198
                                        $1->psNext = $2;
 
199
                                        $$ = $1;
 
200
                                }
 
201
                        ;
 
202
 
 
203
message:                TEXT_T '{' message_list ',' research_message '}' ';'
 
204
                                {
 
205
                                        $$ = malloc(sizeof(*$$));
 
206
                                        if ($$ == NULL)
 
207
                                        {
 
208
                                                debug(LOG_ERROR, "Out of memory");
 
209
                                                abort();
 
210
                                                free($1);
 
211
                                                free($3.stringArray);
 
212
                                                if ($5)
 
213
                                                        free($5->pAudio);
 
214
                                                free($5);
 
215
                                                YYABORT;
 
216
                                        }
 
217
 
 
218
                                        $$->view.pName = $1;
 
219
                                        $$->view.numText = $3.count;
 
220
                                        $$->view.ppTextMsg = $3.stringArray;
 
221
                                        $$->view.type = VIEW_RES;
 
222
                                        $$->view.pData = $5;
 
223
                                        $$->psNext = NULL;
 
224
                                }
 
225
                        ;
 
226
 
 
227
research_message:       imd_name ',' imd_name2 ',' sequence_name ',' audio_name ','
 
228
                                {
 
229
                                        $$ = malloc(sizeof(*$$));
 
230
                                        if ($$ == NULL)
 
231
                                        {
 
232
                                                debug(LOG_ERROR, "Out of memory");
 
233
                                                abort();
 
234
                                                free($1);
 
235
                                                free($3);
 
236
                                                free($5);
 
237
                                                free($7);
 
238
                                                YYABORT;
 
239
                                        }
 
240
 
 
241
                                        $$->pAudio = $7;
 
242
                                        sstrcpy($$->sequenceName, $5);
 
243
                                        // Get rid of our tokens ASAP (so that the free() lists on errors become shorter)
 
244
                                        free($5);
 
245
 
 
246
                                        $$->pIMD = (iIMDShape *) resGetData("IMD", $1);
 
247
                                        if ($$->pIMD == NULL)
 
248
                                        {
 
249
                                                ASSERT(LOG_ERROR, "Cannot find PIE \"%s\"", $1);
 
250
                                                free($1);
 
251
                                                free($3);
 
252
                                                YYABORT;
 
253
                                        }
 
254
                                        free($1);
 
255
 
 
256
                                        if ($3)
 
257
                                        {
 
258
                                                $$->pIMD2 = (iIMDShape *) resGetData("IMD", $3);
 
259
                                                if ($$->pIMD2 == NULL)
 
260
                                                {
 
261
                                                        ASSERT(false, "Cannot find 2nd PIE \"%s\"", $3);
 
262
                                                        free($3);
 
263
                                                        YYABORT;
 
264
                                                }
 
265
                                                free($3);
 
266
                                        }
 
267
                                        else
 
268
                                        {
 
269
                                                $$->pIMD2 = NULL;
 
270
                                        }
 
271
                                }
 
272
                        ;
 
273
 
 
274
imd_name:               IMD_NAME_T '=' QTEXT_T              { $$ = $3; }
 
275
                        | QTEXT_T
 
276
                        ;
 
277
 
 
278
imd_name2:              IMD_NAME2_T '=' optional_string     { $$ = $3; }
 
279
                        | optional_string
 
280
                        ;
 
281
 
 
282
sequence_name:          SEQUENCE_NAME_T '=' QTEXT_T         { $$ = $3; }
 
283
                        | QTEXT_T
 
284
                        ;
 
285
 
 
286
audio_name:             AUDIO_NAME_T '=' optional_string    { $$ = $3; }
 
287
                        | optional_string
 
288
                        ;
 
289
 
 
290
optional_string:        QTEXT_T
 
291
                        | NULL_T
 
292
                        ;
 
293
 
 
294
message_list:           '{' text_messages '}'
 
295
                                {
 
296
                                        size_t bytes = 0;
 
297
                                        unsigned int i;
 
298
                                        TEXT_MESSAGE* psCur;
 
299
                                        char* stringStart;
 
300
 
 
301
                                        $$.count = 0;
 
302
 
 
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)
 
305
                                        {
 
306
                                                ++$$.count;
 
307
                                                bytes += sizeof(char*) + strlen(psCur->str) + 1;
 
308
                                        }
 
309
 
 
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)
 
312
                                        {
 
313
                                                YYABORT;
 
314
                                        }
 
315
 
 
316
                                        if ($$.count)
 
317
                                        {
 
318
                                                $$.stringArray = malloc(bytes);
 
319
                                                if ($$.stringArray == NULL)
 
320
                                                {
 
321
                                                        debug(LOG_ERROR, "Out of memory");
 
322
                                                        abort();
 
323
                                                        freeTextMessageList($2);
 
324
                                                        YYABORT;
 
325
                                                }
 
326
 
 
327
                                                stringStart = (char*)&$$.stringArray[$$.count];
 
328
                                                for (psCur = $2, i = 0, stringStart;
 
329
                                                     psCur != NULL && i < $$.count;
 
330
                                                     psCur = psCur->psNext, ++i)
 
331
                                                {
 
332
                                                        assert(&stringStart[strlen(psCur->str)] - (char*)$$.stringArray < bytes);
 
333
                                                        $$.stringArray[i] = strcpy(stringStart, psCur->str);
 
334
                                                        stringStart = &stringStart[strlen(psCur->str) + 1];
 
335
                                                }
 
336
                                        }
 
337
                                        else
 
338
                                        {
 
339
                                                $$.stringArray = NULL;
 
340
                                        }
 
341
 
 
342
                                        // Clean up our tokens
 
343
                                        freeTextMessageList($2);
 
344
                                }
 
345
                        ;
 
346
 
 
347
text_messages:          text_message
 
348
                                /* Allow trailing commas */
 
349
                        | text_message ','
 
350
                        | text_message ',' text_messages
 
351
                                {
 
352
                                        $1->psNext = $3;
 
353
                                        $$ = $1;
 
354
                                }
 
355
                        ;
 
356
 
 
357
text_message:           TEXT_T
 
358
                                {
 
359
                                        const char * const msg = strresGetString(psStringRes, $1);
 
360
                                        if (!msg)
 
361
                                        {
 
362
                                                ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", $1);
 
363
                                                free($1);
 
364
                                                YYABORT;
 
365
                                        }
 
366
 
 
367
                                        $$ = malloc(sizeof(*$$));
 
368
                                        if ($$ == NULL)
 
369
                                        {
 
370
                                                debug(LOG_ERROR, "Out of memory");
 
371
                                                abort();
 
372
                                                free($1);
 
373
                                                YYABORT;
 
374
                                        }
 
375
 
 
376
                                        $$->str = $1;
 
377
                                        $$->psNext = NULL;
 
378
                                }
 
379
                        | QTEXT_T
 
380
                                {
 
381
                                        $$ = malloc(sizeof(*$$));
 
382
                                        if ($$ == NULL)
 
383
                                        {
 
384
                                                debug(LOG_ERROR, "Out of memory");
 
385
                                                abort();
 
386
                                                free($1);
 
387
                                                YYABORT;
 
388
                                        }
 
389
 
 
390
                                        $$->str = $1;
 
391
                                        $$->psNext = NULL;
 
392
                                }
 
393
                        | '_' '(' QTEXT_T ')'
 
394
                                {
 
395
                                        $$ = malloc(sizeof(*$$));
 
396
                                        if ($$ == NULL)
 
397
                                        {
 
398
                                                debug(LOG_ERROR, "Out of memory");
 
399
                                                abort();
 
400
                                                free($3);
 
401
                                                YYABORT;
 
402
                                        }
 
403
 
 
404
                                        $$->str = $3;
 
405
                                        $$->psNext = NULL;
 
406
                                }
 
407
                        ;