bintools/rcomp/src/RCOMP.YACC
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     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