|
1 %{ |
|
2 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 // All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the License "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Nokia Corporation - initial contribution. |
|
11 // |
|
12 // Contributors: |
|
13 // |
|
14 // RCOMP.CPP |
|
15 // Generated from RCOMP.Y |
|
16 |
|
17 #include <assert.h> |
|
18 #include <ctype.h> |
|
19 #include <string.h> |
|
20 |
|
21 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) |
|
22 #include <fstream> |
|
23 #include <iostream> |
|
24 using namespace std; |
|
25 using std::cout; |
|
26 using std::endl; |
|
27 #else //!__MSVCDOTNET__ |
|
28 #include <fstream.h> |
|
29 #endif //__MSVCDOTNET__ |
|
30 |
|
31 #ifdef __VC32__ |
|
32 #pragma warning( disable : 4065 ) // C4065: switch statement contains 'default' but no 'case' labels |
|
33 #pragma warning( disable : 4102 ) // C4102: 'yyerrlab1' : unreferenced label |
|
34 #pragma warning( disable : 4127 ) // C4127: conditional expression is constant |
|
35 #pragma warning( disable : 4244 ) // C4244: '=' : conversion from 'int' to 'short', possible loss of data |
|
36 #endif //__VC32__ |
|
37 |
|
38 #include "resource.h" |
|
39 #include "parser.h" |
|
40 |
|
41 int yylex(); |
|
42 void yyerror(const char* string, ...); |
|
43 int yywrap(); |
|
44 #define YYDEBUG 1 |
|
45 extern int yylineno; |
|
46 |
|
47 #include "rcomp.hpp" |
|
48 #include "datatype.h" |
|
49 #include "mem.h" |
|
50 #include "rcbinstr.h" |
|
51 #include "rcscan.h" |
|
52 #include "errorhan.h" |
|
53 #include "fileacc.h" |
|
54 #include "version.h" |
|
55 #include "ctable.h" |
|
56 #include "localise.h" |
|
57 #include "main.h" |
|
58 |
|
59 #if defined(__VC32__) && !defined(_DEBUG) |
|
60 #pragma warning( disable : 4702 ) // unreachable code |
|
61 #pragma warning( disable : 4102 ) // 'yyerrlabel' : unreferenced label |
|
62 #pragma warning( disable : 4244 ) // '=' : conversion from 'int' to 'short', possible loss of data |
|
63 #endif |
|
64 |
|
65 |
|
66 |
|
67 String::CharacterSet CharacterSetID( const String & character_set_name ); |
|
68 void asUTF8(char* aUtf8, int aUnicode); |
|
69 void SetIdFromName( const String & NameStatementValue); |
|
70 void CheckStructUsage(); |
|
71 |
|
72 unsigned short & d = MemCheckControl::iLogMemory; |
|
73 |
|
74 StructHeader * pSH; |
|
75 |
|
76 StructHeaderArray * pSHA; // Used in resource struct handling functions. |
|
77 ResourceHeader * pResourceHeader; |
|
78 ResourceItemArray * pCurrentRIA; |
|
79 StringArray * pUsedLabelsArray = new StringArray(); |
|
80 int verbose; |
|
81 String::CharacterSet SourceCharacterSet = String::CP1252; |
|
82 String::CharacterSet TargetCharacterSet = String::CP1252; |
|
83 unsigned short logmemorysetting; |
|
84 int * pCurrentLineNumber; |
|
85 FileLineManager * pFileLineHandler; |
|
86 NameIdMap * pResourceNameIds; |
|
87 long CurrentEnumValue; |
|
88 String CurrentEnumName; |
|
89 char TempStr[300]; |
|
90 rcscan * pScan; |
|
91 |
|
92 int CurrentIdStep=1; |
|
93 long CurrentId=0; |
|
94 int FormatIdAsHex=0; // defaults to decimal, changes in SetIdFromName |
|
95 |
|
96 unsigned long Uid2=0; |
|
97 unsigned long Uid3=0; |
|
98 |
|
99 |
|
100 |
|
101 const String Divider("*******************************************"); |
|
102 |
|
103 #define REGISTER_LINE ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(* pCurrentLineNumber)) |
|
104 |
|
105 // Convert a string containing a character literal in aQuoted |
|
106 // into a value suitable for LCHAR_LITERAL |
|
107 void SetCharacterLiteral(char* aOut, const String& aQuoted) |
|
108 { |
|
109 UTF16 first; |
|
110 int length=1; |
|
111 if (aQuoted.Length() < 1 ) |
|
112 { |
|
113 REGISTER_LINE; |
|
114 ErrorHandler::OutputErrorLine("Warning: Empty Character literal"); |
|
115 } |
|
116 if (aQuoted.Length() > 1 ) |
|
117 { |
|
118 REGISTER_LINE; |
|
119 ErrorHandler::OutputErrorLine("Error: String Literal length greater than 1"); |
|
120 exit(1); |
|
121 } |
|
122 if (aQuoted.Export(&first, length, SourceCharacterSet)==0) |
|
123 { |
|
124 REGISTER_LINE; |
|
125 ErrorHandler::OutputErrorLine("Warning: Ignoring trailing characters in character literal"); |
|
126 } |
|
127 sprintf(aOut, "%d", first); |
|
128 } |
|
129 |
|
130 %} |
|
131 |
|
132 %union { |
|
133 char Value[1024*8]; |
|
134 TValueMaybeRls ValueMaybeRls; |
|
135 unsigned long Id; |
|
136 StructItem * pStructItem; |
|
137 SimpleStructItem * pSimpleStructItem; |
|
138 ArrayStructItem * pArrayStructItem; |
|
139 StructArrayStructItem * pStructArrayStructItem; |
|
140 StringArray * pStringArray; |
|
141 long NumInitialiser; |
|
142 TRlsQualifiers RlsQualifiers; |
|
143 TRlsType RlsType; |
|
144 } |
|
145 |
|
146 %token <Id> L_STRUCT L_RESOURCE L_NAME L_OFFSET L_SYSTEM L_GLOBAL L_LOCAL L_CHARACTER_SET |
|
147 %token <Id> L_BUF L_WORD L_BYTE L_LONG L_DOUBLE L_TEXT L_LTEXT L_LINK L_LLINK L_SRLINK |
|
148 %token <Id> L_BUF8 L_TEXT8 L_LTEXT8 L_BUF16 L_TEXT16 L_LTEXT16 L_UID_TWO L_UID_THREE |
|
149 %token <Id> L_RLS_STRING L_RLS_STRING8 L_RLS_DOUBLE |
|
150 %token <Id> L_RLS_BYTE L_RLS_WORD L_RLS_LONG |
|
151 %token <Id> L_MULTI |
|
152 %token <Id> L_TAG_START L_TAG_END |
|
153 %token <Value> L_TAG_COMMAND L_TAG_WORD L_TAG_NEW_LINE |
|
154 %token <Value> L_LABEL L_NUM_NATURAL L_NUM_FLOAT L_NATURAL_EXPR L_ENUM |
|
155 %token <Value> L_LEN |
|
156 %token <Value> L_CHAR_LITERAL L_STRING_LITERAL |
|
157 |
|
158 %type <Id> data_type len_declaration |
|
159 %type <pStructItem> struct_item array_struct_item simple_struct_item |
|
160 %type <pSimpleStructItem> simple_struct_item_start |
|
161 %type <pStructItem> struct_type_struct_item struct_array_struct_item |
|
162 %type <pArrayStructItem> array_struct_item_start array_struct_item_base |
|
163 %type <pStructArrayStructItem> struct_array_struct_item_base |
|
164 %type <Value> simple_initialiser natural_expression |
|
165 %type <Value> character_code_expression string_expression string_expression_item |
|
166 %type <pStringArray> simple_initialiser_list |
|
167 %type <NumInitialiser> natural_expression_numeric |
|
168 %type <RlsQualifiers> rls_qualifiers rls_cardinality |
|
169 %type <Value> rls_label |
|
170 %type <RlsType> rls_string_item rls_num_item rls_float_item |
|
171 |
|
172 %left '+' '-' |
|
173 %left '*' '/' |
|
174 %left '|' |
|
175 %left UMINUS |
|
176 |
|
177 %% |
|
178 |
|
179 /*****************************************************************/ |
|
180 /* TOP-MOST RULE */ |
|
181 /*****************************************************************/ |
|
182 source : statement_list { if(verbose) { MOFF; cout << Divider << "\n" << Divider << endl; MON; } |
|
183 } |
|
184 ; |
|
185 /*****************************************************************/ |
|
186 /* statement-list and statement */ |
|
187 /*****************************************************************/ |
|
188 statement_list: |
|
189 statement_list statement |
|
190 | statement_list comment_tag |
|
191 | /* Nothing */ |
|
192 ; |
|
193 |
|
194 statement: |
|
195 struct_statement maybe_semicolon |
|
196 | resource_statement maybe_semicolon |
|
197 | character_set_statement maybe_semicolon |
|
198 | name_statement maybe_semicolon |
|
199 | offset_statement maybe_semicolon |
|
200 | system_statement maybe_semicolon |
|
201 | enum_statement |
|
202 | uidX_statement maybe_semicolon |
|
203 | rls_item_statement maybe_semicolon |
|
204 ; |
|
205 |
|
206 maybe_semicolon: |
|
207 ';' |
|
208 { |
|
209 // This is my gift to the world: no more "syntax error" for adding |
|
210 // an extra semicolon at the end of a struct or resource. |
|
211 REGISTER_LINE; |
|
212 ErrorHandler::OutputErrorLine("Warning: unnecessary semicolon"); |
|
213 } |
|
214 | |
|
215 ; |
|
216 |
|
217 /******************************************************************/ |
|
218 /* STRUCT statement */ |
|
219 /******************************************************************/ |
|
220 struct_statement: |
|
221 struct_statement_start struct_item_list '}' |
|
222 { if(verbose) { MOFF; cout << Divider << "\n" << * pSH << Divider << endl; MON;} } |
|
223 ; |
|
224 struct_statement_start: |
|
225 L_STRUCT L_LABEL maybe_comment_tag '{' |
|
226 { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << endl; MON;} |
|
227 pSH = new StructHeader($2); |
|
228 REGISTER_LINE; |
|
229 pG->SHA.Add(pSH); |
|
230 } |
|
231 | L_STRUCT L_LABEL len_declaration maybe_comment_tag '{' |
|
232 { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_statement_start " << $2 << " " << Types.GetName($3) << endl; MON;} |
|
233 pSH = new StructHeader($2, $3); |
|
234 REGISTER_LINE; |
|
235 pG->SHA.Add(pSH); |
|
236 } |
|
237 | L_STRUCT L_LABEL L_LEN maybe_comment_tag '{' |
|
238 { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << " (WORD)" << endl; MON;} |
|
239 pSH = new StructHeader($2, L_WORD); |
|
240 REGISTER_LINE; |
|
241 pG->SHA.Add(pSH); |
|
242 } |
|
243 ; |
|
244 struct_item_list: |
|
245 struct_item_list struct_item ';' { if(verbose) { MOFF;cout << "struct_item_list Adding struct_item." << endl; MON;} |
|
246 REGISTER_LINE; |
|
247 pSH->iSIA.Add($2); |
|
248 } |
|
249 | struct_item_list comment_tag struct_item ';' { if(verbose) { MOFF;cout << "tagged struct_item_list Adding struct_item." << endl; MON;} |
|
250 REGISTER_LINE; |
|
251 pSH->iSIA.Add($3); |
|
252 } |
|
253 | /* Nothing */ |
|
254 ; |
|
255 struct_item: |
|
256 simple_struct_item |
|
257 | array_struct_item |
|
258 | struct_type_struct_item |
|
259 | struct_array_struct_item |
|
260 ; |
|
261 simple_struct_item: |
|
262 simple_struct_item_start { $$ = $1;} |
|
263 | simple_struct_item_start '(' natural_expression ')' |
|
264 { if(verbose) { MOFF;cout << " Limit: " << $3 << endl; MON;} |
|
265 $1->iLengthLimit = $3; |
|
266 $$ = $1; |
|
267 } |
|
268 | simple_struct_item_start '=' simple_initialiser /****************************************************************/ |
|
269 { if(verbose) { MOFF;cout << " Default: " << $3 << endl; MON;} |
|
270 $1->iDefault = $3; |
|
271 $$ = $1; |
|
272 } |
|
273 | simple_struct_item_start '(' natural_expression ')' '=' string_expression /****************************************************************/ |
|
274 { if(verbose) { MOFF;cout << " Limit: " << $3 << ", Default: " << $6 << endl; MON;} |
|
275 NumericValue Limit($3, L_LONG); |
|
276 if(String($6).ExportLength(TargetCharacterSet,SourceCharacterSet) > Limit.GetULong() ) |
|
277 { |
|
278 REGISTER_LINE; |
|
279 ErrorHandler::OutputErrorLine("Text length exceeds specified limit"); |
|
280 exit(1); |
|
281 } |
|
282 $1->iLengthLimit = $3; |
|
283 $1->iDefault = $6; |
|
284 $$ = $1; |
|
285 } |
|
286 |
|
287 ; |
|
288 simple_struct_item_start: |
|
289 data_type L_LABEL { if(verbose) |
|
290 { |
|
291 RCTypeArray Types; |
|
292 MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $2 << endl; MON; |
|
293 } |
|
294 $$ = new SimpleStructItem($1,$2); |
|
295 assert($$ != NULL); |
|
296 } |
|
297 | data_type '<' natural_expression_numeric '>' L_LABEL |
|
298 { if(verbose) |
|
299 { RCTypeArray Types; |
|
300 MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $5 << endl; MON; |
|
301 } |
|
302 String s(NumericValue::ltoa($3)); |
|
303 $$ = new SimpleStructItem($1,$5,s); |
|
304 assert($$ != NULL); |
|
305 } |
|
306 ; |
|
307 |
|
308 /* Note that generic text identifiers are converted to their explicit |
|
309 8 or 16-bit forms at this point, depending on the target character set. |
|
310 */ |
|
311 data_type: |
|
312 L_BYTE { $$ = L_BYTE;} |
|
313 | L_WORD { $$ = L_WORD;} |
|
314 | L_LONG { $$ = L_LONG;} |
|
315 | L_DOUBLE { $$ = L_DOUBLE;} |
|
316 |
|
317 |
|
318 |
|
319 | L_TEXT |
|
320 { |
|
321 $$ = ( TargetCharacterSet == String::Unicode ) ? L_TEXT16: L_TEXT8; |
|
322 REGISTER_LINE; |
|
323 ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT - use LTEXT instead"); |
|
324 } |
|
325 | L_LTEXT |
|
326 { |
|
327 $$ = ( TargetCharacterSet == String::Unicode ) ? L_LTEXT16: L_LTEXT8; |
|
328 } |
|
329 | L_BUF |
|
330 { |
|
331 $$ = ( TargetCharacterSet == String::Unicode ) ? L_BUF16: L_BUF8; |
|
332 } |
|
333 |
|
334 |
|
335 |
|
336 | L_TEXT8 { $$ = L_TEXT8; |
|
337 REGISTER_LINE; |
|
338 ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT8 - use LTEXT8 instead"); |
|
339 } |
|
340 | L_TEXT16 { $$ = L_TEXT16; |
|
341 REGISTER_LINE; |
|
342 ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT16 - use LTEXT16 instead"); |
|
343 } |
|
344 | L_LTEXT8 { $$ = L_LTEXT8;} |
|
345 | L_LTEXT16 { $$ = L_LTEXT16;} |
|
346 | L_BUF8 { $$ = L_BUF8;} |
|
347 | L_BUF16 { $$ = L_BUF16;} |
|
348 | L_LINK { $$ = L_LINK;} |
|
349 | L_LLINK { $$ = L_LLINK;} |
|
350 | L_SRLINK { $$ = L_SRLINK;} |
|
351 ; |
|
352 array_struct_item: |
|
353 array_struct_item_base { $$ = $1;} |
|
354 | array_struct_item_base '=' '{' simple_initialiser_list '}' |
|
355 { if(verbose) { MOFF;cout << "array_struct_item with simple_initialiser_list" << endl;MON;} |
|
356 $1->iDefaults = * $4; |
|
357 if($1->iSize.Length() > 0) |
|
358 { |
|
359 NumericValue v($1->iSize, L_LONG); |
|
360 REGISTER_LINE; |
|
361 if($4->Size()!=long(v.GetULong())) |
|
362 { |
|
363 ErrorHandler::OutputErrorLine("Size does not match number of initialisers"); |
|
364 exit(1); |
|
365 } |
|
366 } |
|
367 $$ = $1; |
|
368 delete $4; |
|
369 } |
|
370 ; |
|
371 array_struct_item_base: |
|
372 array_struct_item_start ']' { if(verbose) { MOFF;cout << "array_struct_item_base with no size" << endl;MON;} |
|
373 $$ =$1; |
|
374 } |
|
375 | array_struct_item_start natural_expression ']' |
|
376 { if(verbose) { MOFF;cout << "array_struct_item_base with size " << $2 << endl;MON;} |
|
377 $1->iSize = $2; |
|
378 $$ = $1; |
|
379 } |
|
380 | L_LEN len_declaration array_struct_item_start ']' |
|
381 { if(verbose) |
|
382 { RCTypeArray Types; |
|
383 MOFF;cout << "array_struct_item_base with LenType " << Types.GetName($2) << endl;MON; |
|
384 } |
|
385 $3->iLenType = $2; |
|
386 $$ = $3; |
|
387 } |
|
388 | L_LEN len_declaration array_struct_item_start natural_expression ']' |
|
389 { if(verbose) |
|
390 { RCTypeArray Types; |
|
391 MOFF;cout << "array_struct_item_base with size " << $4 << " and LenType " << Types.GetName($2) << endl;MON; |
|
392 } |
|
393 $3->iLenType = $2; |
|
394 $3->iSize = $4; |
|
395 $$ = $3; |
|
396 } |
|
397 ; |
|
398 array_struct_item_start: |
|
399 data_type L_LABEL '[' { if(verbose) |
|
400 { RCTypeArray Types; |
|
401 MOFF;cout << "array_struct_item_start " << Types.GetName($1) << " " << $2 << endl;MON; |
|
402 } |
|
403 $$ = new ArrayStructItem($1, $2); |
|
404 } |
|
405 ; |
|
406 len_declaration: |
|
407 L_BYTE { $$ = L_BYTE;} |
|
408 | L_WORD { $$ = L_WORD;} |
|
409 ; |
|
410 struct_type_struct_item: |
|
411 L_STRUCT L_LABEL { if(verbose) { MOFF;cout << "struct_type_struct_item " << $2 << endl;MON;} |
|
412 $$ = new StructTypeStructItem($2); |
|
413 } |
|
414 ; |
|
415 struct_array_struct_item: |
|
416 struct_array_struct_item_base { $$ = $1;} |
|
417 | L_LEN len_declaration struct_array_struct_item_base |
|
418 { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_array_struct_item - Setting Size to " << Types.GetName($2) << endl;MON;} |
|
419 $3->iLenType = $2; $$ = $3; |
|
420 } |
|
421 ; |
|
422 struct_array_struct_item_base: |
|
423 L_STRUCT L_LABEL '[' ']' { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << endl;MON;} |
|
424 $$ = new StructArrayStructItem($2); |
|
425 } |
|
426 | L_STRUCT L_LABEL '[' natural_expression ']' |
|
427 { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << " " << $4 << endl;MON;} |
|
428 $$ = new StructArrayStructItem($2, $4); |
|
429 } |
|
430 ; |
|
431 /*********************************************************************/ |
|
432 /* RESOURCE statement */ |
|
433 /*********************************************************************/ |
|
434 resource_statement: |
|
435 resource_statement_start '{' resource_item_list '}' |
|
436 { |
|
437 pResourceHeader->AddDefault(); |
|
438 CurrentId+=CurrentIdStep; |
|
439 if(verbose) { MOFF;cout << "Resource ID "<< CurrentId << endl << Divider << "\n" << * pResourceHeader << Divider << endl;MON;} |
|
440 pResourceHeader->SetResourceId(*pResourceNameIds,CurrentId,FormatIdAsHex); |
|
441 pG->Index.Add(pResourceHeader); |
|
442 |
|
443 CheckStructUsage(); |
|
444 |
|
445 pUsedLabelsArray->Empty(); |
|
446 |
|
447 pResourceHeader = NULL; |
|
448 } |
|
449 ; |
|
450 resource_statement_start: |
|
451 L_GLOBAL resource_statement_start_names {} /* Ignore GLOBAL (obsolete feature).*/ |
|
452 | L_LOCAL resource_statement_start_names |
|
453 { |
|
454 if(verbose) { MOFF;cout << "resource_statement_start LOCAL" << endl;MON;} |
|
455 assert(pResourceHeader != NULL); |
|
456 pResourceHeader->iLocal = 1; |
|
457 } |
|
458 | resource_statement_start_names {} |
|
459 ; |
|
460 resource_statement_start_names: |
|
461 L_RESOURCE L_LABEL L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " " << $3 << endl;MON;} |
|
462 assert(pResourceHeader == NULL); |
|
463 pResourceHeader = new ResourceHeader($3); |
|
464 pCurrentRIA = & (pResourceHeader->iRIA); |
|
465 REGISTER_LINE; |
|
466 if(pResourceNameIds->IsStored($3)) |
|
467 { |
|
468 ErrorHandler::OutputErrorLine("Resource with this name encountered already"); |
|
469 exit(1); |
|
470 } |
|
471 pCurrentRIA->FillFromStruct($2); |
|
472 pG->AllIdentifiers.Add(new String($3)); // Add label to store |
|
473 } |
|
474 | L_RESOURCE L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " <Resource not named>" << endl;MON;} |
|
475 assert(pResourceHeader == NULL); |
|
476 pResourceHeader = new ResourceHeader; |
|
477 pCurrentRIA = & (pResourceHeader->iRIA); |
|
478 REGISTER_LINE; |
|
479 pCurrentRIA->FillFromStruct($2); |
|
480 } |
|
481 ; |
|
482 resource_item_list: |
|
483 resource_item_list resource_item ';'{ if(verbose) { MOFF;cout << "resource_item_list" << endl;MON;}} |
|
484 | resource_item_list comment_tag resource_item ';'{ if(verbose) { MOFF;cout << "tagged resource_item_list" << endl;MON;}} |
|
485 | resource_item_list error ';' { yyerrok; yyclearin; } |
|
486 | /* Nothing */ |
|
487 ; |
|
488 resource_item: |
|
489 L_LABEL '=' simple_initialiser { if(verbose) { MOFF;cout << "resource_item " << $1 << " " << $3 << endl;MON;} |
|
490 REGISTER_LINE;/****************************************************************/ |
|
491 pCurrentRIA->Set($1, $3); |
|
492 } |
|
493 | resource_simple_array_item |
|
494 | struct_resource_item |
|
495 | struct_array_resource_item |
|
496 ; |
|
497 resource_simple_array_item: |
|
498 L_LABEL '=' '{' '}' |
|
499 { |
|
500 if (verbose) |
|
501 { MOFF;cout << "resource_simple_array_item " << $1 << endl;MON;} |
|
502 } |
|
503 | L_LABEL '=' '{' simple_initialiser_list '}' |
|
504 { |
|
505 if (verbose) |
|
506 { MOFF;cout << "resource_simple_array_item " << $1 << " with simple_initialiser_list" << endl;MON;} |
|
507 REGISTER_LINE; |
|
508 pCurrentRIA->Set($1, * $4); |
|
509 delete $4; |
|
510 } |
|
511 ; |
|
512 |
|
513 /*---------------------------------------------------------------------------*/ |
|
514 /* A note about RIAStack, SRIStack and pCurrentRIA. */ |
|
515 /* */ |
|
516 /* RIA stands for Resource Item Array. */ |
|
517 /* SRI stands for Struct Array Resource Item. */ |
|
518 /* */ |
|
519 /* A push to RIAStack is made when dropping inside a STRUCT or STRUCT[] in */ |
|
520 /* order to set values for the components. When this happens pCurrentRIA is */ |
|
521 /* set to the RIA for the STRUCT or last item of the STRUCT[]. */ |
|
522 /* */ |
|
523 /* pCurrentRIA is set to the result of popping from RIAStack when a closing */ |
|
524 /* brace is reached. */ |
|
525 /* */ |
|
526 /* A push is made to SRIStack when going into an item for a STRUCT[]. On */ |
|
527 /* reaching a closing brace the STRUCT[] is popped off the SRIStack. An new */ |
|
528 /* item may then be added to this array. */ |
|
529 /*---------------------------------------------------------------------------*/ |
|
530 struct_resource_item: |
|
531 struct_resource_item_start resource_item_list '}' |
|
532 { if(verbose) { MOFF;cout << "struct_resource_item" << endl;MON;} |
|
533 pCurrentRIA = pG->RIAStack.Pop(); |
|
534 } |
|
535 ; |
|
536 struct_resource_item_start: |
|
537 L_LABEL '=' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_resource_item_start " << $1 << " " << $3 << endl;MON;} |
|
538 REGISTER_LINE; |
|
539 pCurrentRIA->Set($1, $3); |
|
540 String * thisLabel = new String($1); |
|
541 pUsedLabelsArray->Add(thisLabel); |
|
542 // in here add the label to a temp store |
|
543 pG->RIAStack.Push(pCurrentRIA); |
|
544 pCurrentRIA = pCurrentRIA->Find($1)->GetRIA(); |
|
545 } |
|
546 ; |
|
547 struct_array_resource_item: |
|
548 struct_array_resource_item_start struct_array_resource_item_list_top '}' |
|
549 { if(verbose) { MOFF;cout << "struct_array_resource_item" << endl;MON;} |
|
550 pG->SRIStack.Pop(); |
|
551 } |
|
552 | struct_array_resource_item_start struct_array_resource_item_list_top error |
|
553 { pG->SRIStack.Pop();} |
|
554 ; |
|
555 struct_array_resource_item_start: |
|
556 L_LABEL '=' '{' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_start " << $1 << " " << $4 << endl;MON;} |
|
557 ResourceItem * p = pCurrentRIA->Find($1); |
|
558 pG->SRIStack.Push(p); |
|
559 REGISTER_LINE; |
|
560 String * thisLabel = new String($1); |
|
561 pUsedLabelsArray->Add(thisLabel); |
|
562 // in here add the label to a temp store |
|
563 p->Set($4); |
|
564 pG->RIAStack.Push(pCurrentRIA); |
|
565 pCurrentRIA = p->GetRIA(); |
|
566 } |
|
567 ; |
|
568 struct_array_resource_item_list_top: |
|
569 struct_array_resource_item_list_top_start |
|
570 | struct_array_resource_item_list_top_start ',' struct_array_resource_item_list |
|
571 | struct_array_resource_item_list_top_start ',' error |
|
572 ; |
|
573 struct_array_resource_item_list_top_start: |
|
574 resource_item_list '}' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_top " << endl;MON;} |
|
575 pCurrentRIA = pG->RIAStack.Pop(); |
|
576 } |
|
577 ; |
|
578 struct_array_resource_item_list: |
|
579 struct_array_resource_item_list_item |
|
580 | struct_array_resource_item_list ',' struct_array_resource_item_list_item |
|
581 ; |
|
582 struct_array_resource_item_list_item: |
|
583 struct_array_resource_item_list_item_start resource_item_list '}' |
|
584 { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item " << endl;MON;} |
|
585 pCurrentRIA = pG->RIAStack.Pop(); |
|
586 } |
|
587 ; |
|
588 struct_array_resource_item_list_item_start: |
|
589 L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item_start " << $1 << endl;MON;} |
|
590 ResourceItem * p = pG->SRIStack.Peek(); |
|
591 REGISTER_LINE; |
|
592 p->Set($1); |
|
593 pG->RIAStack.Push(pCurrentRIA); |
|
594 pCurrentRIA = p->GetRIA(); |
|
595 } |
|
596 ; |
|
597 |
|
598 |
|
599 /*****************************************************************/ |
|
600 /* simple_initialiser and simple_initialiser_list */ |
|
601 /*****************************************************************/ |
|
602 simple_initialiser: |
|
603 L_NUM_FLOAT |
|
604 | L_CHAR_LITERAL |
|
605 { |
|
606 // convert literal to unsigned long value of 1st character |
|
607 SetCharacterLiteral($$, $1); |
|
608 } |
|
609 | string_expression |
|
610 | natural_expression |
|
611 ; |
|
612 simple_initialiser_list: |
|
613 simple_initialiser |
|
614 { |
|
615 if(verbose) |
|
616 { |
|
617 MOFF;cout << "simple_initialiser_list - single string " << $1 << endl;MON; |
|
618 } |
|
619 |
|
620 $$ = new StringArray; |
|
621 $$->Add(new String($1) ); |
|
622 } |
|
623 | simple_initialiser_list ',' simple_initialiser |
|
624 { if(verbose) { MOFF;cout << "simple_initialiser_list - part of list " << $3 << endl;MON;} |
|
625 assert($1 != NULL); |
|
626 $1->Add(new String($3 ) ); |
|
627 $$ = $1; |
|
628 } |
|
629 ; |
|
630 |
|
631 natural_expression: |
|
632 natural_expression_numeric { String s(NumericValue::ltoa($1) ); strcpy($$, s.GetAssertedNonEmptyBuffer() ); } |
|
633 ; |
|
634 natural_expression_numeric: |
|
635 L_NUM_NATURAL { if(verbose) { MOFF;cout << "Converting number " << $1 << endl;MON;} |
|
636 REGISTER_LINE; |
|
637 NumericValue v($1, L_LONG); $$ = (long)v.GetULong(); |
|
638 } |
|
639 | natural_expression_numeric '+' natural_expression_numeric { $$ = $1 + $3; } |
|
640 | natural_expression_numeric '-' natural_expression_numeric { $$ = $1 - $3; } |
|
641 | natural_expression_numeric '*' natural_expression_numeric { $$ = $1 * $3; } |
|
642 | natural_expression_numeric '/' natural_expression_numeric { $$ = $1 / $3; } |
|
643 | natural_expression_numeric '|' natural_expression_numeric { $$ = $1 | $3; } |
|
644 | '-' natural_expression_numeric %prec UMINUS { if (!NumericValue::CheckSigned($2,L_LONG)) |
|
645 { |
|
646 REGISTER_LINE; |
|
647 ErrorHandler::OutputErrorLine("Signed value too low"); |
|
648 exit(1); |
|
649 } |
|
650 $$ = - $2; |
|
651 } |
|
652 | '(' natural_expression_numeric ')' { $$ = $2; } |
|
653 ; |
|
654 string_expression: |
|
655 string_expression_item |
|
656 | string_expression_item string_expression { |
|
657 if (strlen($$)+strlen($2) > sizeof($$)-1) |
|
658 { |
|
659 REGISTER_LINE; |
|
660 ErrorHandler::OutputErrorLine("String expression is too long"); |
|
661 exit(1); |
|
662 } |
|
663 strcat($$, $2); |
|
664 } |
|
665 ; |
|
666 string_expression_item: |
|
667 L_STRING_LITERAL |
|
668 | character_code_expression |
|
669 | L_LABEL |
|
670 { |
|
671 const char * fileName = (*ErrorHandler::GetFileName()).GetBuffer(); |
|
672 int lineNumber = ErrorHandler::GetLineNumber(); |
|
673 QualifiedString * thisLabel = new QualifiedString($1, new String(fileName), lineNumber); |
|
674 // store the label in the UsedIdentifiers array for checking |
|
675 // whether label was declared |
|
676 pG->UsedIdentifiers.Add(thisLabel); |
|
677 |
|
678 if (pG->EnumValues.IsStored($1)) |
|
679 { |
|
680 sprintf($$, "%d", pG->EnumValues.FindId($1)); |
|
681 } |
|
682 else if (pG->RlsNameIndex.count($1)) // if rls item has already been defined |
|
683 { |
|
684 // Found a reference to an rls_string. |
|
685 RlsValue &rv = pG->RlsValues[pG->RlsNameIndex[$1]]; |
|
686 ++rv.iCitationCount; // iCitationCount counts the number of times this rls value has been referneced |
|
687 // Warn for multiple uses if 'multi' keyword not used. |
|
688 if (1 < rv.iCitationCount && rv.iCardinality == ERlsCardinalitySingle) |
|
689 { |
|
690 Message * message = pG->Messages.GetEntry(LT_001); |
|
691 String fileLine = *(rv.iFileName); |
|
692 if(message->GetActivated()) |
|
693 { |
|
694 pGL->AddWarningToStore(fileLine, rv.iLineNumber, message->GetMessageOutput()); |
|
695 } |
|
696 REGISTER_LINE; |
|
697 if (!pG->WarningMultiExplained) |
|
698 { |
|
699 Message * message = pG->Messages.GetEntry(LT_002); |
|
700 fileLine = String(*(pFileLineHandler->GetCurrentFile())); |
|
701 if(message->GetActivated()) |
|
702 { |
|
703 pGL->AddWarningToStore(fileLine, pFileLineHandler->GetErrorLine(* pCurrentLineNumber), message->GetMessageOutput()); |
|
704 pG->WarningMultiExplained = true; |
|
705 } |
|
706 } |
|
707 } |
|
708 switch (rv.iType) |
|
709 { |
|
710 // Strings and numbers are just copied to the next layer up. |
|
711 case ERlsString: |
|
712 case ERlsString8: |
|
713 case ERlsByte: |
|
714 case ERlsWord: |
|
715 case ERlsLong: |
|
716 case ERlsDouble: |
|
717 strcpy($$, rv.iValue.GetBuffer()); |
|
718 break; |
|
719 // Anything else is a character: this is converted to a number. |
|
720 case ERlsStringChar: |
|
721 case ERlsByteChar: |
|
722 case ERlsWordChar: |
|
723 case ERlsLongChar: |
|
724 SetCharacterLiteral($$, rv.iValue); |
|
725 break; |
|
726 default: |
|
727 Message * message = pG->Messages.GetEntry(LT_031); |
|
728 if(message->GetActivated()) |
|
729 { |
|
730 ErrorHandler::OutputErrorLine(message->GetMessageOutput()); |
|
731 exit(1); |
|
732 } |
|
733 break; |
|
734 } |
|
735 } |
|
736 else |
|
737 { |
|
738 /* |
|
739 Could be a reference to another resource, perhaps even a forward reference: |
|
740 the OverwriteLink functions do FindId again when writing out the data. |
|
741 Sadly this also permits things which are really syntax errors, inadvertently |
|
742 converting labels into string literals.. |
|
743 */ |
|
744 } |
|
745 } |
|
746 ; |
|
747 character_code_expression: |
|
748 '<' natural_expression_numeric '>' |
|
749 { |
|
750 REGISTER_LINE; |
|
751 if($2 < 0 || ($2 > 255 && TargetCharacterSet != String::Unicode)) |
|
752 { |
|
753 ErrorHandler::OutputErrorLine("Character code must be a number in the range 0 to 255."); |
|
754 exit(1); |
|
755 } |
|
756 if (TargetCharacterSet != String::Unicode) |
|
757 { |
|
758 * $$ = char($2); * ($$ + 1) = '\0'; |
|
759 } |
|
760 else |
|
761 { |
|
762 if (SourceCharacterSet == String::CP1252) |
|
763 { |
|
764 if ( ($2 >= 0x80) && ($2 <= 0x9F ) ) // 80-9F are illegal Unicode values. |
|
765 { |
|
766 ErrorHandler::OutputErrorLine("Warning: Deprecated non-unicode value in source stream"); |
|
767 } |
|
768 * $$ = char(UnicodeEscape); |
|
769 asUTF8($$ + 1, $2); |
|
770 } |
|
771 else |
|
772 if (SourceCharacterSet == String::UTF8) |
|
773 { |
|
774 asUTF8($$, $2); |
|
775 } |
|
776 else |
|
777 { |
|
778 // Unsatisfactory, but do people use other character sets? |
|
779 if ($2 > 255) |
|
780 { |
|
781 ErrorHandler::OutputErrorLine("Don't know how to handle character > 255"); |
|
782 } |
|
783 * $$ = char($2); * ($$ + 1) = '\0'; |
|
784 } |
|
785 } |
|
786 } |
|
787 ; |
|
788 |
|
789 |
|
790 /*****************************************************************/ |
|
791 /* name_statement */ |
|
792 /*****************************************************************/ |
|
793 name_statement: |
|
794 L_NAME L_LABEL |
|
795 { |
|
796 REGISTER_LINE; |
|
797 SetIdFromName($2); |
|
798 } |
|
799 | L_NAME L_STRING_LITERAL |
|
800 { |
|
801 REGISTER_LINE; |
|
802 SetIdFromName($2); |
|
803 } |
|
804 ; |
|
805 |
|
806 |
|
807 /*****************************************************************/ |
|
808 /* uidX_statement */ |
|
809 /*****************************************************************/ |
|
810 uidX_statement: |
|
811 L_UID_TWO natural_expression_numeric |
|
812 { |
|
813 REGISTER_LINE; |
|
814 if ($2 == 0) |
|
815 { ErrorHandler::OutputErrorLine("UID2 must be non-zero"); exit(1); } |
|
816 if (Uid2 != 0) |
|
817 { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID2 value"); } |
|
818 Uid2=$2; |
|
819 if(verbose) |
|
820 { MOFF;cout << "uidX_statement UID2 " << Uid2 << endl;MON;} |
|
821 } |
|
822 | L_UID_THREE natural_expression_numeric |
|
823 { |
|
824 REGISTER_LINE; |
|
825 if ($2 == 0) |
|
826 { ErrorHandler::OutputErrorLine("UID3 must be non-zero"); exit(1); } |
|
827 if (Uid3 != 0) |
|
828 { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID3 value"); } |
|
829 Uid3=$2; |
|
830 if(verbose) |
|
831 { MOFF;cout << "uidX_statement UID3 " << Uid3 << endl;MON;} |
|
832 } |
|
833 ; |
|
834 |
|
835 |
|
836 /*****************************************************************/ |
|
837 /* character_set_statement */ |
|
838 /* Defines the SOURCE character set. Note that Unicode is a */ |
|
839 /* character set id, but we can't read Unicode source */ |
|
840 /* (because LEX and YACC can't handle it) */ |
|
841 /*****************************************************************/ |
|
842 |
|
843 character_set_statement: |
|
844 L_CHARACTER_SET L_LABEL { if(verbose) { MOFF;cout << "character_set_statement " << $2 << endl;MON;} |
|
845 REGISTER_LINE; |
|
846 SourceCharacterSet = CharacterSetID($2); |
|
847 if ( SourceCharacterSet == String::UNKNOWN ) |
|
848 { |
|
849 String err = "Warning: Unrecognised character set name '"; |
|
850 err += $2; |
|
851 err += "'"; |
|
852 ErrorHandler::OutputErrorLine(err); |
|
853 } |
|
854 if ( SourceCharacterSet == String::Unicode ) |
|
855 { |
|
856 SourceCharacterSet = String::UNKNOWN; |
|
857 ErrorHandler::OutputErrorLine("Unicode source is unsupported"); |
|
858 } |
|
859 } |
|
860 ; |
|
861 |
|
862 |
|
863 |
|
864 /*****************************************************************/ |
|
865 /* offset_statement */ |
|
866 /*****************************************************************/ |
|
867 offset_statement: |
|
868 L_OFFSET natural_expression { if(verbose) { RCTypeArray Types; |
|
869 MOFF;cout << "offset_statement " << $2 << endl;MON; } |
|
870 REGISTER_LINE; |
|
871 CurrentId=((long) NumericValue($2, L_LONG).GetULong() ); |
|
872 } |
|
873 ; |
|
874 |
|
875 /*****************************************************************/ |
|
876 /* system_statement */ |
|
877 /*****************************************************************/ |
|
878 system_statement: |
|
879 L_SYSTEM { if(verbose) { MOFF;cout << "system_statement" << endl;MON;} |
|
880 CurrentIdStep=-1; |
|
881 } |
|
882 ; |
|
883 |
|
884 /*****************************************************************/ |
|
885 /* enum_statement */ |
|
886 /*****************************************************************/ |
|
887 enum_statement: |
|
888 enum_statement_start enum_list '}' |
|
889 | enum_statement_start enum_list '}' ';' |
|
890 ; |
|
891 enum_statement_start: |
|
892 L_ENUM L_LABEL '{' |
|
893 { |
|
894 if(verbose) |
|
895 { MOFF;cout << "enum_statement" << endl;MON;} |
|
896 CurrentEnumName = $2; |
|
897 CurrentEnumValue=0; |
|
898 } |
|
899 | L_ENUM '{' |
|
900 { |
|
901 if(verbose) |
|
902 { MOFF;cout << "enum_statement" << endl;MON;} |
|
903 CurrentEnumName = ""; |
|
904 CurrentEnumValue=0; |
|
905 } |
|
906 ; |
|
907 |
|
908 enum_list_entry: |
|
909 L_LABEL |
|
910 { |
|
911 pG->EnumValues.Add($1, CurrentEnumValue++); |
|
912 pG->AllIdentifiers.Add(new String($1)); // Add label to store |
|
913 } |
|
914 | L_LABEL '=' simple_initialiser |
|
915 { |
|
916 CurrentEnumValue = atol($3); |
|
917 pG->EnumValues.Add($1, CurrentEnumValue); |
|
918 CurrentEnumValue++; // Increment so that next field has value ($3+1) |
|
919 pG->AllIdentifiers.Add(new String($1)); // Add label to store |
|
920 } |
|
921 ; |
|
922 |
|
923 |
|
924 enum_list: |
|
925 maybe_comment_tag enum_list_entry |
|
926 | enum_list ',' maybe_comment_tag enum_list_entry |
|
927 ; |
|
928 |
|
929 /************************/ |
|
930 /* rls_xxxx statement */ |
|
931 /************************/ |
|
932 rls_item_statement: |
|
933 rls_string_item rls_qualifiers rls_label string_expression |
|
934 { |
|
935 pG->RlsNameIndex[$3] = pG->RlsValues.size(); |
|
936 pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(), |
|
937 ErrorHandler::GetLineNumber(), $4, $1, |
|
938 $2.iCardinality, $2.iMaxLength)); |
|
939 if($2.iMaxLength |
|
940 < String($4).ExportLength(TargetCharacterSet,SourceCharacterSet)) |
|
941 { |
|
942 Message * message = pG->Messages.GetEntry(LT_032); |
|
943 if(message->GetActivated()) |
|
944 { |
|
945 ErrorHandler::OutputErrorLine(message->GetMessageOutput()); |
|
946 exit(1); |
|
947 } |
|
948 } |
|
949 } |
|
950 | rls_string_item rls_qualifiers rls_label L_CHAR_LITERAL /* This section is only for compatibility */ |
|
951 { |
|
952 Message * message = pG->Messages.GetEntry(LT_033); |
|
953 String fileName = *(pFileLineHandler->GetCurrentFile()); |
|
954 int lineNumber = pFileLineHandler->GetErrorLine(* pCurrentLineNumber); |
|
955 if(message->GetActivated()) |
|
956 { |
|
957 pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput()); |
|
958 } |
|
959 //... |
|
960 /* Produce a warning "rls_string used for character constant: use rls_long, rls_word or rls_byte" */ |
|
961 pG->RlsNameIndex[$3] = pG->RlsValues.size(); |
|
962 pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(), |
|
963 ErrorHandler::GetLineNumber(), $4, ERlsStringChar, |
|
964 $2.iCardinality)); |
|
965 } |
|
966 | rls_float_item rls_cardinality rls_label L_NUM_FLOAT |
|
967 { |
|
968 pG->RlsNameIndex[$3] = pG->RlsValues.size(); |
|
969 pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(), |
|
970 ErrorHandler::GetLineNumber(), $4, $1, |
|
971 $2.iCardinality)); |
|
972 } |
|
973 | rls_num_item rls_cardinality rls_label L_NUM_NATURAL |
|
974 { |
|
975 pG->RlsNameIndex[$3] = pG->RlsValues.size(); |
|
976 pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(), |
|
977 ErrorHandler::GetLineNumber(), $4, $1, |
|
978 $2.iCardinality)); |
|
979 } |
|
980 | rls_num_item rls_cardinality rls_label L_CHAR_LITERAL |
|
981 { |
|
982 TRlsType rlsCharType = $1 == ERlsByte? ERlsByteChar |
|
983 : ( $1 == ERlsWord? ERlsWordChar : ERlsLongChar ); |
|
984 pG->RlsNameIndex[$3] = pG->RlsValues.size(); |
|
985 pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(), |
|
986 ErrorHandler::GetLineNumber(), $4, rlsCharType, |
|
987 $2.iCardinality)); |
|
988 } |
|
989 ; |
|
990 |
|
991 rls_label: L_LABEL |
|
992 { |
|
993 // Register line even if no warning here so that |
|
994 // the rls_ item knows which line the label was on. |
|
995 // Without this, the line registered would be the |
|
996 // line following the declaration. |
|
997 REGISTER_LINE; |
|
998 strcpy($$, $1); |
|
999 |
|
1000 if (pG->RlsNameIndex.count($1) != 0) |
|
1001 { |
|
1002 Message * message = pG->Messages.GetEntry(LT_003); |
|
1003 if(message->GetActivated()) |
|
1004 { |
|
1005 ErrorHandler::OutputErrorLine(message->GetMessageOutput()); |
|
1006 } |
|
1007 } |
|
1008 pG->AllIdentifiers.Add(new String($1)); // Add label to store |
|
1009 } |
|
1010 |
|
1011 rls_qualifiers: |
|
1012 '<' L_NUM_NATURAL '>' rls_cardinality |
|
1013 { |
|
1014 NumericValue v($2, L_LONG); |
|
1015 $$.iMaxLength = v.GetULong(); |
|
1016 $$.iCardinality = $4.iCardinality; |
|
1017 } |
|
1018 | rls_cardinality |
|
1019 { $$ = $1; } |
|
1020 ; |
|
1021 |
|
1022 rls_cardinality: |
|
1023 L_MULTI |
|
1024 { |
|
1025 $$.iMaxLength = 0xFFFFFFF; |
|
1026 $$.iCardinality = ERlsCardinalityMultiple; |
|
1027 } |
|
1028 | |
|
1029 { |
|
1030 $$.iMaxLength = 0xFFFFFFF; |
|
1031 $$.iCardinality = ERlsCardinalitySingle; |
|
1032 } |
|
1033 ; |
|
1034 |
|
1035 rls_string_item: |
|
1036 L_RLS_STRING |
|
1037 { $$ = ERlsString; } |
|
1038 | L_RLS_STRING8 |
|
1039 { $$ = ERlsString8; } |
|
1040 ; |
|
1041 |
|
1042 rls_num_item: |
|
1043 L_RLS_BYTE |
|
1044 { $$ = ERlsByte; } |
|
1045 | L_RLS_WORD |
|
1046 { $$ = ERlsWord; } |
|
1047 | L_RLS_LONG |
|
1048 { $$ = ERlsLong; } |
|
1049 ; |
|
1050 |
|
1051 rls_float_item: |
|
1052 L_RLS_DOUBLE |
|
1053 { $$ = ERlsDouble; } |
|
1054 ; |
|
1055 |
|
1056 /************************/ |
|
1057 /* comment tags */ |
|
1058 /************************/ |
|
1059 maybe_comment_tag: |
|
1060 comment_tag |
|
1061 | |
|
1062 ; |
|
1063 |
|
1064 comment_tag: |
|
1065 L_TAG_START tag_line L_TAG_END {ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(*pCurrentLineNumber)); } |
|
1066 ; |
|
1067 |
|
1068 tag_line: |
|
1069 tag_line tag_word |
|
1070 |
|
1071 | |
|
1072 ; |
|
1073 |
|
1074 tag_word: |
|
1075 L_TAG_NEW_LINE { pGL->StoreComment($1); } |
|
1076 | L_TAG_COMMAND { pGL->StoreComment($1); } |
|
1077 | L_TAG_WORD { pGL->StoreComment($1); } |
|
1078 ; |
|
1079 |
|
1080 %% |
|
1081 |
|
1082 // Function section |
|
1083 // ================ |
|
1084 |
|
1085 void asUTF8(char* aUtf8, int aUnicode) |
|
1086 { |
|
1087 if ( aUnicode > 0xffff ) |
|
1088 { |
|
1089 if ( aUnicode > 0x10ffff ) |
|
1090 { |
|
1091 ErrorHandler::OutputErrorLine("Surrogate character code must be a number in the range 0x10000 to 0x10ffff"); |
|
1092 exit(1); |
|
1093 } |
|
1094 |
|
1095 UTF16 high = (UTF16)(0xD7C0 + (aUnicode >> 10)); // high surrogate |
|
1096 UTF16 low = (UTF16)(0xDC00 | (aUnicode & 0x3FF)); // low surrogate |
|
1097 |
|
1098 *aUtf8++ =(char)(0xe0|(high>>12)); |
|
1099 *aUtf8++ =(char)(0x80|((high>>6)&0x3f)); |
|
1100 *aUtf8++ =(char)(0x80|(high&0x3f)); |
|
1101 *aUtf8++ =(char)(0xe0|(low>>12)); |
|
1102 *aUtf8++ =(char)(0x80|((low>>6)&0x3f)); |
|
1103 *aUtf8 =(char)(0x80|(low&0x3f)); |
|
1104 } |
|
1105 else if ((aUnicode & 0xff80) == 0x0000) |
|
1106 { |
|
1107 *aUtf8 = (char)aUnicode; |
|
1108 } |
|
1109 else if ((aUnicode & 0xf800) == 0x0000) |
|
1110 { |
|
1111 *aUtf8++ =(char)(0xc0|(aUnicode>>6)); |
|
1112 *aUtf8 =(char)(0x80|(aUnicode&0x3f)); |
|
1113 } |
|
1114 else |
|
1115 { |
|
1116 *aUtf8++ =(char)(0xe0|(aUnicode>>12)); |
|
1117 *aUtf8++ =(char)(0x80|((aUnicode>>6)&0x3f)); |
|
1118 *aUtf8 =(char)(0x80|(aUnicode&0x3f)); |
|
1119 } |
|
1120 *++aUtf8 = '\0'; |
|
1121 } |
|
1122 |
|
1123 |
|
1124 String::CharacterSet CharacterSetID( const String & character_set_name ) |
|
1125 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
1126 // Return a character set ID from a character set name. The value UNKNOWN |
|
1127 // is returned if the name is not recognised. |
|
1128 // ---------------------------------------------------------------------------- |
|
1129 { |
|
1130 String::CharacterSet ids[] = { String::ISOLatin1, String::ASCII, String::CP1252 |
|
1131 , String::CP850, String::ShiftJIS, String::Unicode |
|
1132 , String::UTF8 |
|
1133 , String::UNKNOWN |
|
1134 }; |
|
1135 String names[] = { "ISOLATIN1", "ASCII", "CP1252", "CP850", "SHIFTJIS", "UNICODE", "UTF8" }; |
|
1136 |
|
1137 for ( int i=0; ids[i]!=String::UNKNOWN; i++ ) |
|
1138 { |
|
1139 if ( names[i] == character_set_name ) return ids[i]; |
|
1140 } |
|
1141 |
|
1142 return String::UNKNOWN; |
|
1143 |
|
1144 } // end of CharacterSetID code |
|
1145 |
|
1146 void SetIdFromName( const String & NameStatementValue) |
|
1147 { |
|
1148 // space 0 |
|
1149 // A 1 |
|
1150 // B 2 |
|
1151 // ... |
|
1152 // Z 26 |
|
1153 // |
|
1154 // ABCD corresponds to the number 4321 which becomes ( (4*27 + 3) * 27 + 2) * 27 + 1. |
|
1155 |
|
1156 if(verbose) |
|
1157 { MOFF;cout << "name_statement " << NameStatementValue << endl;MON;} |
|
1158 if ( NameStatementValue.Length() > 4) |
|
1159 { |
|
1160 ErrorHandler::OutputErrorLine( "Name must be no longer than four characters"); |
|
1161 exit( 1); |
|
1162 } |
|
1163 |
|
1164 long NewId = 0; |
|
1165 |
|
1166 for( unsigned long i = 0; i < NameStatementValue.Length(); i++) |
|
1167 { |
|
1168 NewId *= 27; |
|
1169 if ( isalpha( NameStatementValue[i]) ) |
|
1170 NewId += toupper( NameStatementValue[i]) - 'A' + 1; |
|
1171 } |
|
1172 |
|
1173 CurrentId = NewId << 12; |
|
1174 FormatIdAsHex = 1; |
|
1175 if(verbose) |
|
1176 { MOFF;cout << "Current id " << CurrentId << endl;MON;} |
|
1177 } |
|
1178 |
|
1179 void RlsUnusedWarnings() |
|
1180 { |
|
1181 TNameIndex::iterator end = pG->RlsNameIndex.end(); |
|
1182 for (TNameIndex::iterator i = pG->RlsNameIndex.begin(); i != end; ++i) |
|
1183 { |
|
1184 int index = i->second; |
|
1185 RlsValue& v = pG->RlsValues[index]; |
|
1186 if (v.iCitationCount == 0) |
|
1187 { |
|
1188 Message * message = pG->Messages.GetEntry(LT_004); |
|
1189 String fileLine = *(v.iFileName); |
|
1190 if(message->GetActivated()) |
|
1191 { |
|
1192 pGL->AddWarningToStore(fileLine, v.iLineNumber, message->GetMessageOutput()); |
|
1193 } |
|
1194 } |
|
1195 } |
|
1196 } |
|
1197 |
|
1198 int ParseSourceFile(FILE* aFile, unsigned short aYYDebug) |
|
1199 { |
|
1200 // Set up various global pointers which refer to the pG structure |
|
1201 pSHA = & (pG->SHA); |
|
1202 pFileLineHandler = & (pG->FileLineHandler); |
|
1203 pResourceNameIds = & (pG->ResourceNameIds); |
|
1204 |
|
1205 pScan = new rcscan(pG->FileLineHandler, aFile); |
|
1206 |
|
1207 yydebug = aYYDebug; |
|
1208 pCurrentLineNumber = &yylineno; |
|
1209 int ReturnValue = yyparse(); |
|
1210 |
|
1211 RlsUnusedWarnings(); |
|
1212 |
|
1213 int bScanErrorFound = pScan->ErrorWasFound(); |
|
1214 |
|
1215 delete pScan; |
|
1216 pScan = NULL; |
|
1217 |
|
1218 if(ReturnValue != 0) |
|
1219 return ReturnValue; |
|
1220 |
|
1221 if(bScanErrorFound) |
|
1222 return 1; |
|
1223 |
|
1224 return 0; // successful parse - parse tree now in the pG data structure |
|
1225 } |
|
1226 |
|
1227 |
|
1228 void CheckStructUsage() |
|
1229 { |
|
1230 ResourceItemArrayIterator nextRI( *pCurrentRIA); |
|
1231 ResourceItem * pRI; |
|
1232 while ( ( pRI = nextRI() ) != NULL) |
|
1233 { |
|
1234 int resourceItemType = pRI->GetResourceItemType(); |
|
1235 String resourceItemLabel = pRI->GetLabel(); |
|
1236 if( (resourceItemType == EStructTypeResourceItem) || (resourceItemType == EStructArrayResourceItem) ) |
|
1237 { |
|
1238 StringArrayIterator nextLabel( *pUsedLabelsArray); |
|
1239 String * pLabel; |
|
1240 bool flag = false; |
|
1241 while ( ( ( pLabel = nextLabel() ) != NULL ) && (! flag) ) |
|
1242 { |
|
1243 StringLess stringCompare; |
|
1244 if( !stringCompare(resourceItemLabel,*pLabel) && !stringCompare(*pLabel,resourceItemLabel) ) |
|
1245 { |
|
1246 flag = true; |
|
1247 } |
|
1248 } |
|
1249 if(! flag) |
|
1250 { |
|
1251 if(resourceItemType == EStructTypeResourceItem) |
|
1252 { |
|
1253 Message * message = pG->Messages.GetEntry(LT_046); |
|
1254 if(message->GetActivated()) |
|
1255 { |
|
1256 String comment = message->GetMessageOutput(); |
|
1257 comment += "'"; |
|
1258 comment += resourceItemLabel; |
|
1259 comment += "'"; |
|
1260 ErrorHandler::OutputErrorLine(comment); |
|
1261 } |
|
1262 } |
|
1263 else |
|
1264 { |
|
1265 Message * message = pG->Messages.GetEntry(LT_047); |
|
1266 if(message->GetActivated()) |
|
1267 { |
|
1268 String comment = message->GetMessageOutput(); |
|
1269 comment += "'"; |
|
1270 comment += resourceItemLabel; |
|
1271 comment += "'"; |
|
1272 ErrorHandler::OutputErrorLine(comment); |
|
1273 } |
|
1274 } |
|
1275 } |
|
1276 } |
|
1277 } |
|
1278 } |
|
1279 |
|
1280 int yywrap() |
|
1281 { |
|
1282 return 1; |
|
1283 } |
|
1284 |
|
1285 /* Called by yyparse on error */ |
|
1286 #include <stdarg.h> |
|
1287 void yyerror (const char *s, ...) |
|
1288 { |
|
1289 va_list list; |
|
1290 va_start(list, s); |
|
1291 pScan->yyerror(const_cast<char*>(s), list); |
|
1292 va_end(list); |
|
1293 } |
|
1294 |
|
1295 |