--- a/bintools/rcomp/src/RCOMP.YACC Wed Jun 16 16:51:40 2010 +0300
+++ b/bintools/rcomp/src/RCOMP.YACC Wed Jun 23 16:56:47 2010 +0800
@@ -1,1295 +1,1297 @@
-%{
-// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// RCOMP.CPP
-// Generated from RCOMP.Y
-
-#include <assert.h>
-#include <ctype.h>
-#include <string.h>
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-#include <fstream>
-#include <iostream>
-using namespace std;
-using std::cout;
-using std::endl;
-#else //!__MSVCDOTNET__
-#include <fstream.h>
-#endif //__MSVCDOTNET__
-
-#ifdef __VC32__
-#pragma warning( disable : 4065 ) // C4065: switch statement contains 'default' but no 'case' labels
-#pragma warning( disable : 4102 ) // C4102: 'yyerrlab1' : unreferenced label
-#pragma warning( disable : 4127 ) // C4127: conditional expression is constant
-#pragma warning( disable : 4244 ) // C4244: '=' : conversion from 'int' to 'short', possible loss of data
-#endif //__VC32__
-
-#include "resource.h"
-#include "parser.h"
-
-int yylex();
-void yyerror(const char* string, ...);
-int yywrap();
-#define YYDEBUG 1
-extern int yylineno;
-
-#include "rcomp.hpp"
-#include "datatype.h"
-#include "mem.h"
-#include "rcbinstr.h"
-#include "rcscan.h"
-#include "errorhan.h"
-#include "fileacc.h"
-#include "version.h"
-#include "ctable.h"
-#include "localise.h"
-#include "main.h"
-
-#if defined(__VC32__) && !defined(_DEBUG)
-#pragma warning( disable : 4702 ) // unreachable code
-#pragma warning( disable : 4102 ) // 'yyerrlabel' : unreferenced label
-#pragma warning( disable : 4244 ) // '=' : conversion from 'int' to 'short', possible loss of data
-#endif
-
-
-
-String::CharacterSet CharacterSetID( const String & character_set_name );
-void asUTF8(char* aUtf8, int aUnicode);
-void SetIdFromName( const String & NameStatementValue);
-void CheckStructUsage();
-
-unsigned short & d = MemCheckControl::iLogMemory;
-
-StructHeader * pSH;
-
-StructHeaderArray * pSHA; // Used in resource struct handling functions.
-ResourceHeader * pResourceHeader;
-ResourceItemArray * pCurrentRIA;
-StringArray * pUsedLabelsArray = new StringArray();
-int verbose;
-String::CharacterSet SourceCharacterSet = String::CP1252;
-String::CharacterSet TargetCharacterSet = String::CP1252;
-unsigned short logmemorysetting;
-int * pCurrentLineNumber;
-FileLineManager * pFileLineHandler;
-NameIdMap * pResourceNameIds;
-long CurrentEnumValue;
-String CurrentEnumName;
-char TempStr[300];
-rcscan * pScan;
-
-int CurrentIdStep=1;
-long CurrentId=0;
-int FormatIdAsHex=0; // defaults to decimal, changes in SetIdFromName
-
-unsigned long Uid2=0;
-unsigned long Uid3=0;
-
-
-
-const String Divider("*******************************************");
-
-#define REGISTER_LINE ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(* pCurrentLineNumber))
-
-// Convert a string containing a character literal in aQuoted
-// into a value suitable for LCHAR_LITERAL
-void SetCharacterLiteral(char* aOut, const String& aQuoted)
- {
- UTF16 first;
- int length=1;
- if (aQuoted.Length() < 1 )
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: Empty Character literal");
- }
- if (aQuoted.Length() > 1 )
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Error: String Literal length greater than 1");
- exit(1);
- }
- if (aQuoted.Export(&first, length, SourceCharacterSet)==0)
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: Ignoring trailing characters in character literal");
- }
- sprintf(aOut, "%d", first);
- }
-
-%}
-
-%union {
- char Value[1024*8];
- TValueMaybeRls ValueMaybeRls;
- unsigned long Id;
- StructItem * pStructItem;
- SimpleStructItem * pSimpleStructItem;
- ArrayStructItem * pArrayStructItem;
- StructArrayStructItem * pStructArrayStructItem;
- StringArray * pStringArray;
- long NumInitialiser;
- TRlsQualifiers RlsQualifiers;
- TRlsType RlsType;
-}
-
-%token <Id> L_STRUCT L_RESOURCE L_NAME L_OFFSET L_SYSTEM L_GLOBAL L_LOCAL L_CHARACTER_SET
-%token <Id> L_BUF L_WORD L_BYTE L_LONG L_DOUBLE L_TEXT L_LTEXT L_LINK L_LLINK L_SRLINK
-%token <Id> L_BUF8 L_TEXT8 L_LTEXT8 L_BUF16 L_TEXT16 L_LTEXT16 L_UID_TWO L_UID_THREE
-%token <Id> L_RLS_STRING L_RLS_STRING8 L_RLS_DOUBLE
-%token <Id> L_RLS_BYTE L_RLS_WORD L_RLS_LONG
-%token <Id> L_MULTI
-%token <Id> L_TAG_START L_TAG_END
-%token <Value> L_TAG_COMMAND L_TAG_WORD L_TAG_NEW_LINE
-%token <Value> L_LABEL L_NUM_NATURAL L_NUM_FLOAT L_NATURAL_EXPR L_ENUM
-%token <Value> L_LEN
-%token <Value> L_CHAR_LITERAL L_STRING_LITERAL
-
-%type <Id> data_type len_declaration
-%type <pStructItem> struct_item array_struct_item simple_struct_item
-%type <pSimpleStructItem> simple_struct_item_start
-%type <pStructItem> struct_type_struct_item struct_array_struct_item
-%type <pArrayStructItem> array_struct_item_start array_struct_item_base
-%type <pStructArrayStructItem> struct_array_struct_item_base
-%type <Value> simple_initialiser natural_expression
-%type <Value> character_code_expression string_expression string_expression_item
-%type <pStringArray> simple_initialiser_list
-%type <NumInitialiser> natural_expression_numeric
-%type <RlsQualifiers> rls_qualifiers rls_cardinality
-%type <Value> rls_label
-%type <RlsType> rls_string_item rls_num_item rls_float_item
-
-%left '+' '-'
-%left '*' '/'
-%left '|'
-%left UMINUS
-
-%%
-
-/*****************************************************************/
-/* TOP-MOST RULE */
-/*****************************************************************/
-source : statement_list { if(verbose) { MOFF; cout << Divider << "\n" << Divider << endl; MON; }
- }
-;
-/*****************************************************************/
-/* statement-list and statement */
-/*****************************************************************/
-statement_list:
- statement_list statement
-| statement_list comment_tag
-| /* Nothing */
-;
-
-statement:
- struct_statement maybe_semicolon
-| resource_statement maybe_semicolon
-| character_set_statement maybe_semicolon
-| name_statement maybe_semicolon
-| offset_statement maybe_semicolon
-| system_statement maybe_semicolon
-| enum_statement
-| uidX_statement maybe_semicolon
-| rls_item_statement maybe_semicolon
-;
-
-maybe_semicolon:
- ';'
- {
- // This is my gift to the world: no more "syntax error" for adding
- // an extra semicolon at the end of a struct or resource.
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: unnecessary semicolon");
- }
-|
-;
-
-/******************************************************************/
-/* STRUCT statement */
-/******************************************************************/
-struct_statement:
- struct_statement_start struct_item_list '}'
- { if(verbose) { MOFF; cout << Divider << "\n" << * pSH << Divider << endl; MON;} }
-;
-struct_statement_start:
- L_STRUCT L_LABEL maybe_comment_tag '{'
- { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << endl; MON;}
- pSH = new StructHeader($2);
- REGISTER_LINE;
- pG->SHA.Add(pSH);
- }
-| L_STRUCT L_LABEL len_declaration maybe_comment_tag '{'
- { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_statement_start " << $2 << " " << Types.GetName($3) << endl; MON;}
- pSH = new StructHeader($2, $3);
- REGISTER_LINE;
- pG->SHA.Add(pSH);
- }
-| L_STRUCT L_LABEL L_LEN maybe_comment_tag '{'
- { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << " (WORD)" << endl; MON;}
- pSH = new StructHeader($2, L_WORD);
- REGISTER_LINE;
- pG->SHA.Add(pSH);
- }
-;
-struct_item_list:
- struct_item_list struct_item ';' { if(verbose) { MOFF;cout << "struct_item_list Adding struct_item." << endl; MON;}
- REGISTER_LINE;
- pSH->iSIA.Add($2);
- }
-| struct_item_list comment_tag struct_item ';' { if(verbose) { MOFF;cout << "tagged struct_item_list Adding struct_item." << endl; MON;}
- REGISTER_LINE;
- pSH->iSIA.Add($3);
- }
-| /* Nothing */
-;
-struct_item:
- simple_struct_item
-| array_struct_item
-| struct_type_struct_item
-| struct_array_struct_item
-;
-simple_struct_item:
- simple_struct_item_start { $$ = $1;}
-| simple_struct_item_start '(' natural_expression ')'
- { if(verbose) { MOFF;cout << " Limit: " << $3 << endl; MON;}
- $1->iLengthLimit = $3;
- $$ = $1;
- }
-| simple_struct_item_start '=' simple_initialiser /****************************************************************/
- { if(verbose) { MOFF;cout << " Default: " << $3 << endl; MON;}
- $1->iDefault = $3;
- $$ = $1;
- }
-| simple_struct_item_start '(' natural_expression ')' '=' string_expression /****************************************************************/
- { if(verbose) { MOFF;cout << " Limit: " << $3 << ", Default: " << $6 << endl; MON;}
- NumericValue Limit($3, L_LONG);
- if(String($6).ExportLength(TargetCharacterSet,SourceCharacterSet) > Limit.GetULong() )
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Text length exceeds specified limit");
- exit(1);
- }
- $1->iLengthLimit = $3;
- $1->iDefault = $6;
- $$ = $1;
- }
-
-;
-simple_struct_item_start:
- data_type L_LABEL { if(verbose)
- {
- RCTypeArray Types;
- MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $2 << endl; MON;
- }
- $$ = new SimpleStructItem($1,$2);
- assert($$ != NULL);
- }
-| data_type '<' natural_expression_numeric '>' L_LABEL
- { if(verbose)
- { RCTypeArray Types;
- MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $5 << endl; MON;
- }
- String s(NumericValue::ltoa($3));
- $$ = new SimpleStructItem($1,$5,s);
- assert($$ != NULL);
- }
-;
-
-/* Note that generic text identifiers are converted to their explicit
- 8 or 16-bit forms at this point, depending on the target character set.
-*/
-data_type:
- L_BYTE { $$ = L_BYTE;}
-| L_WORD { $$ = L_WORD;}
-| L_LONG { $$ = L_LONG;}
-| L_DOUBLE { $$ = L_DOUBLE;}
-
-
-
-| L_TEXT
- {
- $$ = ( TargetCharacterSet == String::Unicode ) ? L_TEXT16: L_TEXT8;
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT - use LTEXT instead");
- }
-| L_LTEXT
- {
- $$ = ( TargetCharacterSet == String::Unicode ) ? L_LTEXT16: L_LTEXT8;
- }
-| L_BUF
- {
- $$ = ( TargetCharacterSet == String::Unicode ) ? L_BUF16: L_BUF8;
- }
-
-
-
-| L_TEXT8 { $$ = L_TEXT8;
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT8 - use LTEXT8 instead");
- }
-| L_TEXT16 { $$ = L_TEXT16;
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT16 - use LTEXT16 instead");
- }
-| L_LTEXT8 { $$ = L_LTEXT8;}
-| L_LTEXT16 { $$ = L_LTEXT16;}
-| L_BUF8 { $$ = L_BUF8;}
-| L_BUF16 { $$ = L_BUF16;}
-| L_LINK { $$ = L_LINK;}
-| L_LLINK { $$ = L_LLINK;}
-| L_SRLINK { $$ = L_SRLINK;}
-;
-array_struct_item:
- array_struct_item_base { $$ = $1;}
-| array_struct_item_base '=' '{' simple_initialiser_list '}'
- { if(verbose) { MOFF;cout << "array_struct_item with simple_initialiser_list" << endl;MON;}
- $1->iDefaults = * $4;
- if($1->iSize.Length() > 0)
- {
- NumericValue v($1->iSize, L_LONG);
- REGISTER_LINE;
- if($4->Size()!=long(v.GetULong()))
- {
- ErrorHandler::OutputErrorLine("Size does not match number of initialisers");
- exit(1);
- }
- }
- $$ = $1;
- delete $4;
- }
-;
-array_struct_item_base:
- array_struct_item_start ']' { if(verbose) { MOFF;cout << "array_struct_item_base with no size" << endl;MON;}
- $$ =$1;
- }
-| array_struct_item_start natural_expression ']'
- { if(verbose) { MOFF;cout << "array_struct_item_base with size " << $2 << endl;MON;}
- $1->iSize = $2;
- $$ = $1;
- }
-| L_LEN len_declaration array_struct_item_start ']'
- { if(verbose)
- { RCTypeArray Types;
- MOFF;cout << "array_struct_item_base with LenType " << Types.GetName($2) << endl;MON;
- }
- $3->iLenType = $2;
- $$ = $3;
- }
-| L_LEN len_declaration array_struct_item_start natural_expression ']'
- { if(verbose)
- { RCTypeArray Types;
- MOFF;cout << "array_struct_item_base with size " << $4 << " and LenType " << Types.GetName($2) << endl;MON;
- }
- $3->iLenType = $2;
- $3->iSize = $4;
- $$ = $3;
- }
-;
-array_struct_item_start:
- data_type L_LABEL '[' { if(verbose)
- { RCTypeArray Types;
- MOFF;cout << "array_struct_item_start " << Types.GetName($1) << " " << $2 << endl;MON;
- }
- $$ = new ArrayStructItem($1, $2);
- }
-;
-len_declaration:
- L_BYTE { $$ = L_BYTE;}
-| L_WORD { $$ = L_WORD;}
-;
-struct_type_struct_item:
- L_STRUCT L_LABEL { if(verbose) { MOFF;cout << "struct_type_struct_item " << $2 << endl;MON;}
- $$ = new StructTypeStructItem($2);
- }
-;
-struct_array_struct_item:
- struct_array_struct_item_base { $$ = $1;}
-| L_LEN len_declaration struct_array_struct_item_base
- { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_array_struct_item - Setting Size to " << Types.GetName($2) << endl;MON;}
- $3->iLenType = $2; $$ = $3;
- }
-;
-struct_array_struct_item_base:
- L_STRUCT L_LABEL '[' ']' { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << endl;MON;}
- $$ = new StructArrayStructItem($2);
- }
-| L_STRUCT L_LABEL '[' natural_expression ']'
- { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << " " << $4 << endl;MON;}
- $$ = new StructArrayStructItem($2, $4);
- }
-;
-/*********************************************************************/
-/* RESOURCE statement */
-/*********************************************************************/
-resource_statement:
- resource_statement_start '{' resource_item_list '}'
- {
- pResourceHeader->AddDefault();
- CurrentId+=CurrentIdStep;
- if(verbose) { MOFF;cout << "Resource ID "<< CurrentId << endl << Divider << "\n" << * pResourceHeader << Divider << endl;MON;}
- pResourceHeader->SetResourceId(*pResourceNameIds,CurrentId,FormatIdAsHex);
- pG->Index.Add(pResourceHeader);
-
- CheckStructUsage();
-
- pUsedLabelsArray->Empty();
-
- pResourceHeader = NULL;
- }
-;
-resource_statement_start:
- L_GLOBAL resource_statement_start_names {} /* Ignore GLOBAL (obsolete feature).*/
-| L_LOCAL resource_statement_start_names
- {
- if(verbose) { MOFF;cout << "resource_statement_start LOCAL" << endl;MON;}
- assert(pResourceHeader != NULL);
- pResourceHeader->iLocal = 1;
- }
-| resource_statement_start_names {}
-;
-resource_statement_start_names:
- L_RESOURCE L_LABEL L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " " << $3 << endl;MON;}
- assert(pResourceHeader == NULL);
- pResourceHeader = new ResourceHeader($3);
- pCurrentRIA = & (pResourceHeader->iRIA);
- REGISTER_LINE;
- if(pResourceNameIds->IsStored($3))
- {
- ErrorHandler::OutputErrorLine("Resource with this name encountered already");
- exit(1);
- }
- pCurrentRIA->FillFromStruct($2);
- pG->AllIdentifiers.Add(new String($3)); // Add label to store
- }
-| L_RESOURCE L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " <Resource not named>" << endl;MON;}
- assert(pResourceHeader == NULL);
- pResourceHeader = new ResourceHeader;
- pCurrentRIA = & (pResourceHeader->iRIA);
- REGISTER_LINE;
- pCurrentRIA->FillFromStruct($2);
- }
-;
-resource_item_list:
- resource_item_list resource_item ';'{ if(verbose) { MOFF;cout << "resource_item_list" << endl;MON;}}
-| resource_item_list comment_tag resource_item ';'{ if(verbose) { MOFF;cout << "tagged resource_item_list" << endl;MON;}}
-| resource_item_list error ';' { yyerrok; yyclearin; }
-| /* Nothing */
-;
-resource_item:
- L_LABEL '=' simple_initialiser { if(verbose) { MOFF;cout << "resource_item " << $1 << " " << $3 << endl;MON;}
- REGISTER_LINE;/****************************************************************/
- pCurrentRIA->Set($1, $3);
- }
-| resource_simple_array_item
-| struct_resource_item
-| struct_array_resource_item
-;
-resource_simple_array_item:
- L_LABEL '=' '{' '}'
- {
- if (verbose)
- { MOFF;cout << "resource_simple_array_item " << $1 << endl;MON;}
- }
-| L_LABEL '=' '{' simple_initialiser_list '}'
- {
- if (verbose)
- { MOFF;cout << "resource_simple_array_item " << $1 << " with simple_initialiser_list" << endl;MON;}
- REGISTER_LINE;
- pCurrentRIA->Set($1, * $4);
- delete $4;
- }
-;
-
-/*---------------------------------------------------------------------------*/
-/* A note about RIAStack, SRIStack and pCurrentRIA. */
-/* */
-/* RIA stands for Resource Item Array. */
-/* SRI stands for Struct Array Resource Item. */
-/* */
-/* A push to RIAStack is made when dropping inside a STRUCT or STRUCT[] in */
-/* order to set values for the components. When this happens pCurrentRIA is */
-/* set to the RIA for the STRUCT or last item of the STRUCT[]. */
-/* */
-/* pCurrentRIA is set to the result of popping from RIAStack when a closing */
-/* brace is reached. */
-/* */
-/* A push is made to SRIStack when going into an item for a STRUCT[]. On */
-/* reaching a closing brace the STRUCT[] is popped off the SRIStack. An new */
-/* item may then be added to this array. */
-/*---------------------------------------------------------------------------*/
-struct_resource_item:
- struct_resource_item_start resource_item_list '}'
- { if(verbose) { MOFF;cout << "struct_resource_item" << endl;MON;}
- pCurrentRIA = pG->RIAStack.Pop();
- }
-;
-struct_resource_item_start:
- L_LABEL '=' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_resource_item_start " << $1 << " " << $3 << endl;MON;}
- REGISTER_LINE;
- pCurrentRIA->Set($1, $3);
- String * thisLabel = new String($1);
- pUsedLabelsArray->Add(thisLabel);
- // in here add the label to a temp store
- pG->RIAStack.Push(pCurrentRIA);
- pCurrentRIA = pCurrentRIA->Find($1)->GetRIA();
- }
-;
-struct_array_resource_item:
- struct_array_resource_item_start struct_array_resource_item_list_top '}'
- { if(verbose) { MOFF;cout << "struct_array_resource_item" << endl;MON;}
- pG->SRIStack.Pop();
- }
-| struct_array_resource_item_start struct_array_resource_item_list_top error
- { pG->SRIStack.Pop();}
-;
-struct_array_resource_item_start:
- L_LABEL '=' '{' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_start " << $1 << " " << $4 << endl;MON;}
- ResourceItem * p = pCurrentRIA->Find($1);
- pG->SRIStack.Push(p);
- REGISTER_LINE;
- String * thisLabel = new String($1);
- pUsedLabelsArray->Add(thisLabel);
- // in here add the label to a temp store
- p->Set($4);
- pG->RIAStack.Push(pCurrentRIA);
- pCurrentRIA = p->GetRIA();
- }
-;
-struct_array_resource_item_list_top:
- struct_array_resource_item_list_top_start
-| struct_array_resource_item_list_top_start ',' struct_array_resource_item_list
-| struct_array_resource_item_list_top_start ',' error
-;
-struct_array_resource_item_list_top_start:
- resource_item_list '}' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_top " << endl;MON;}
- pCurrentRIA = pG->RIAStack.Pop();
- }
-;
-struct_array_resource_item_list:
- struct_array_resource_item_list_item
-| struct_array_resource_item_list ',' struct_array_resource_item_list_item
-;
-struct_array_resource_item_list_item:
- struct_array_resource_item_list_item_start resource_item_list '}'
- { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item " << endl;MON;}
- pCurrentRIA = pG->RIAStack.Pop();
- }
-;
-struct_array_resource_item_list_item_start:
- L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item_start " << $1 << endl;MON;}
- ResourceItem * p = pG->SRIStack.Peek();
- REGISTER_LINE;
- p->Set($1);
- pG->RIAStack.Push(pCurrentRIA);
- pCurrentRIA = p->GetRIA();
- }
-;
-
-
-/*****************************************************************/
-/* simple_initialiser and simple_initialiser_list */
-/*****************************************************************/
-simple_initialiser:
- L_NUM_FLOAT
-| L_CHAR_LITERAL
- {
- // convert literal to unsigned long value of 1st character
- SetCharacterLiteral($$, $1);
- }
-| string_expression
-| natural_expression
-;
-simple_initialiser_list:
- simple_initialiser
- {
- if(verbose)
- {
- MOFF;cout << "simple_initialiser_list - single string " << $1 << endl;MON;
- }
-
- $$ = new StringArray;
- $$->Add(new String($1) );
- }
-| simple_initialiser_list ',' simple_initialiser
- { if(verbose) { MOFF;cout << "simple_initialiser_list - part of list " << $3 << endl;MON;}
- assert($1 != NULL);
- $1->Add(new String($3 ) );
- $$ = $1;
- }
-;
-
-natural_expression:
- natural_expression_numeric { String s(NumericValue::ltoa($1) ); strcpy($$, s.GetAssertedNonEmptyBuffer() ); }
-;
-natural_expression_numeric:
- L_NUM_NATURAL { if(verbose) { MOFF;cout << "Converting number " << $1 << endl;MON;}
- REGISTER_LINE;
- NumericValue v($1, L_LONG); $$ = (long)v.GetULong();
- }
-| natural_expression_numeric '+' natural_expression_numeric { $$ = $1 + $3; }
-| natural_expression_numeric '-' natural_expression_numeric { $$ = $1 - $3; }
-| natural_expression_numeric '*' natural_expression_numeric { $$ = $1 * $3; }
-| natural_expression_numeric '/' natural_expression_numeric { $$ = $1 / $3; }
-| natural_expression_numeric '|' natural_expression_numeric { $$ = $1 | $3; }
-| '-' natural_expression_numeric %prec UMINUS { if (!NumericValue::CheckSigned($2,L_LONG))
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("Signed value too low");
- exit(1);
- }
- $$ = - $2;
- }
-| '(' natural_expression_numeric ')' { $$ = $2; }
-;
-string_expression:
- string_expression_item
-| string_expression_item string_expression {
- if (strlen($$)+strlen($2) > sizeof($$)-1)
- {
- REGISTER_LINE;
- ErrorHandler::OutputErrorLine("String expression is too long");
- exit(1);
- }
- strcat($$, $2);
- }
-;
-string_expression_item:
- L_STRING_LITERAL
-| character_code_expression
-| L_LABEL
- {
- const char * fileName = (*ErrorHandler::GetFileName()).GetBuffer();
- int lineNumber = ErrorHandler::GetLineNumber();
- QualifiedString * thisLabel = new QualifiedString($1, new String(fileName), lineNumber);
- // store the label in the UsedIdentifiers array for checking
- // whether label was declared
- pG->UsedIdentifiers.Add(thisLabel);
-
- if (pG->EnumValues.IsStored($1))
- {
- sprintf($$, "%d", pG->EnumValues.FindId($1));
- }
- else if (pG->RlsNameIndex.count($1)) // if rls item has already been defined
- {
- // Found a reference to an rls_string.
- RlsValue &rv = pG->RlsValues[pG->RlsNameIndex[$1]];
- ++rv.iCitationCount; // iCitationCount counts the number of times this rls value has been referneced
- // Warn for multiple uses if 'multi' keyword not used.
- if (1 < rv.iCitationCount && rv.iCardinality == ERlsCardinalitySingle)
- {
- Message * message = pG->Messages.GetEntry(LT_001);
- String fileLine = *(rv.iFileName);
- if(message->GetActivated())
- {
- pGL->AddWarningToStore(fileLine, rv.iLineNumber, message->GetMessageOutput());
- }
- REGISTER_LINE;
- if (!pG->WarningMultiExplained)
- {
- Message * message = pG->Messages.GetEntry(LT_002);
- fileLine = String(*(pFileLineHandler->GetCurrentFile()));
- if(message->GetActivated())
- {
- pGL->AddWarningToStore(fileLine, pFileLineHandler->GetErrorLine(* pCurrentLineNumber), message->GetMessageOutput());
- pG->WarningMultiExplained = true;
- }
- }
- }
- switch (rv.iType)
- {
- // Strings and numbers are just copied to the next layer up.
- case ERlsString:
- case ERlsString8:
- case ERlsByte:
- case ERlsWord:
- case ERlsLong:
- case ERlsDouble:
- strcpy($$, rv.iValue.GetBuffer());
- break;
- // Anything else is a character: this is converted to a number.
- case ERlsStringChar:
- case ERlsByteChar:
- case ERlsWordChar:
- case ERlsLongChar:
- SetCharacterLiteral($$, rv.iValue);
- break;
- default:
- Message * message = pG->Messages.GetEntry(LT_031);
- if(message->GetActivated())
- {
- ErrorHandler::OutputErrorLine(message->GetMessageOutput());
- exit(1);
- }
- break;
- }
- }
- else
- {
- /*
- Could be a reference to another resource, perhaps even a forward reference:
- the OverwriteLink functions do FindId again when writing out the data.
- Sadly this also permits things which are really syntax errors, inadvertently
- converting labels into string literals..
- */
- }
- }
-;
-character_code_expression:
- '<' natural_expression_numeric '>'
- {
- REGISTER_LINE;
- if($2 < 0 || ($2 > 255 && TargetCharacterSet != String::Unicode))
- {
- ErrorHandler::OutputErrorLine("Character code must be a number in the range 0 to 255.");
- exit(1);
- }
- if (TargetCharacterSet != String::Unicode)
- {
- * $$ = char($2); * ($$ + 1) = '\0';
- }
- else
- {
- if (SourceCharacterSet == String::CP1252)
- {
- if ( ($2 >= 0x80) && ($2 <= 0x9F ) ) // 80-9F are illegal Unicode values.
- {
- ErrorHandler::OutputErrorLine("Warning: Deprecated non-unicode value in source stream");
- }
- * $$ = char(UnicodeEscape);
- asUTF8($$ + 1, $2);
- }
- else
- if (SourceCharacterSet == String::UTF8)
- {
- asUTF8($$, $2);
- }
- else
- {
- // Unsatisfactory, but do people use other character sets?
- if ($2 > 255)
- {
- ErrorHandler::OutputErrorLine("Don't know how to handle character > 255");
- }
- * $$ = char($2); * ($$ + 1) = '\0';
- }
- }
- }
-;
-
-
-/*****************************************************************/
-/* name_statement */
-/*****************************************************************/
-name_statement:
- L_NAME L_LABEL
- {
- REGISTER_LINE;
- SetIdFromName($2);
- }
-| L_NAME L_STRING_LITERAL
- {
- REGISTER_LINE;
- SetIdFromName($2);
- }
-;
-
-
-/*****************************************************************/
-/* uidX_statement */
-/*****************************************************************/
-uidX_statement:
- L_UID_TWO natural_expression_numeric
- {
- REGISTER_LINE;
- if ($2 == 0)
- { ErrorHandler::OutputErrorLine("UID2 must be non-zero"); exit(1); }
- if (Uid2 != 0)
- { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID2 value"); }
- Uid2=$2;
- if(verbose)
- { MOFF;cout << "uidX_statement UID2 " << Uid2 << endl;MON;}
- }
-| L_UID_THREE natural_expression_numeric
- {
- REGISTER_LINE;
- if ($2 == 0)
- { ErrorHandler::OutputErrorLine("UID3 must be non-zero"); exit(1); }
- if (Uid3 != 0)
- { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID3 value"); }
- Uid3=$2;
- if(verbose)
- { MOFF;cout << "uidX_statement UID3 " << Uid3 << endl;MON;}
- }
-;
-
-
-/*****************************************************************/
-/* character_set_statement */
-/* Defines the SOURCE character set. Note that Unicode is a */
-/* character set id, but we can't read Unicode source */
-/* (because LEX and YACC can't handle it) */
-/*****************************************************************/
-
-character_set_statement:
- L_CHARACTER_SET L_LABEL { if(verbose) { MOFF;cout << "character_set_statement " << $2 << endl;MON;}
- REGISTER_LINE;
- SourceCharacterSet = CharacterSetID($2);
- if ( SourceCharacterSet == String::UNKNOWN )
- {
- String err = "Warning: Unrecognised character set name '";
- err += $2;
- err += "'";
- ErrorHandler::OutputErrorLine(err);
- }
- if ( SourceCharacterSet == String::Unicode )
- {
- SourceCharacterSet = String::UNKNOWN;
- ErrorHandler::OutputErrorLine("Unicode source is unsupported");
- }
- }
-;
-
-
-
-/*****************************************************************/
-/* offset_statement */
-/*****************************************************************/
-offset_statement:
- L_OFFSET natural_expression { if(verbose) { RCTypeArray Types;
- MOFF;cout << "offset_statement " << $2 << endl;MON; }
- REGISTER_LINE;
- CurrentId=((long) NumericValue($2, L_LONG).GetULong() );
- }
-;
-
-/*****************************************************************/
-/* system_statement */
-/*****************************************************************/
-system_statement:
- L_SYSTEM { if(verbose) { MOFF;cout << "system_statement" << endl;MON;}
- CurrentIdStep=-1;
- }
-;
-
-/*****************************************************************/
-/* enum_statement */
-/*****************************************************************/
-enum_statement:
- enum_statement_start enum_list '}'
-| enum_statement_start enum_list '}' ';'
-;
-enum_statement_start:
- L_ENUM L_LABEL '{'
- {
- if(verbose)
- { MOFF;cout << "enum_statement" << endl;MON;}
- CurrentEnumName = $2;
- CurrentEnumValue=0;
- }
-| L_ENUM '{'
- {
- if(verbose)
- { MOFF;cout << "enum_statement" << endl;MON;}
- CurrentEnumName = "";
- CurrentEnumValue=0;
- }
-;
-
-enum_list_entry:
- L_LABEL
- {
- pG->EnumValues.Add($1, CurrentEnumValue++);
- pG->AllIdentifiers.Add(new String($1)); // Add label to store
- }
-| L_LABEL '=' simple_initialiser
- {
- CurrentEnumValue = atol($3);
- pG->EnumValues.Add($1, CurrentEnumValue);
- CurrentEnumValue++; // Increment so that next field has value ($3+1)
- pG->AllIdentifiers.Add(new String($1)); // Add label to store
- }
-;
-
-
-enum_list:
- maybe_comment_tag enum_list_entry
-| enum_list ',' maybe_comment_tag enum_list_entry
-;
-
-/************************/
-/* rls_xxxx statement */
-/************************/
-rls_item_statement:
- rls_string_item rls_qualifiers rls_label string_expression
- {
- pG->RlsNameIndex[$3] = pG->RlsValues.size();
- pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
- ErrorHandler::GetLineNumber(), $4, $1,
- $2.iCardinality, $2.iMaxLength));
- if($2.iMaxLength
- < String($4).ExportLength(TargetCharacterSet,SourceCharacterSet))
- {
- Message * message = pG->Messages.GetEntry(LT_032);
- if(message->GetActivated())
- {
- ErrorHandler::OutputErrorLine(message->GetMessageOutput());
- exit(1);
- }
- }
- }
-| rls_string_item rls_qualifiers rls_label L_CHAR_LITERAL /* This section is only for compatibility */
- {
- Message * message = pG->Messages.GetEntry(LT_033);
- String fileName = *(pFileLineHandler->GetCurrentFile());
- int lineNumber = pFileLineHandler->GetErrorLine(* pCurrentLineNumber);
- if(message->GetActivated())
- {
- pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
- }
- //...
- /* Produce a warning "rls_string used for character constant: use rls_long, rls_word or rls_byte" */
- pG->RlsNameIndex[$3] = pG->RlsValues.size();
- pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
- ErrorHandler::GetLineNumber(), $4, ERlsStringChar,
- $2.iCardinality));
- }
-| rls_float_item rls_cardinality rls_label L_NUM_FLOAT
- {
- pG->RlsNameIndex[$3] = pG->RlsValues.size();
- pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
- ErrorHandler::GetLineNumber(), $4, $1,
- $2.iCardinality));
- }
-| rls_num_item rls_cardinality rls_label L_NUM_NATURAL
- {
- pG->RlsNameIndex[$3] = pG->RlsValues.size();
- pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
- ErrorHandler::GetLineNumber(), $4, $1,
- $2.iCardinality));
- }
-| rls_num_item rls_cardinality rls_label L_CHAR_LITERAL
- {
- TRlsType rlsCharType = $1 == ERlsByte? ERlsByteChar
- : ( $1 == ERlsWord? ERlsWordChar : ERlsLongChar );
- pG->RlsNameIndex[$3] = pG->RlsValues.size();
- pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
- ErrorHandler::GetLineNumber(), $4, rlsCharType,
- $2.iCardinality));
- }
-;
-
-rls_label: L_LABEL
- {
- // Register line even if no warning here so that
- // the rls_ item knows which line the label was on.
- // Without this, the line registered would be the
- // line following the declaration.
- REGISTER_LINE;
- strcpy($$, $1);
-
- if (pG->RlsNameIndex.count($1) != 0)
- {
- Message * message = pG->Messages.GetEntry(LT_003);
- if(message->GetActivated())
- {
- ErrorHandler::OutputErrorLine(message->GetMessageOutput());
- }
- }
- pG->AllIdentifiers.Add(new String($1)); // Add label to store
- }
-
-rls_qualifiers:
- '<' L_NUM_NATURAL '>' rls_cardinality
- {
- NumericValue v($2, L_LONG);
- $$.iMaxLength = v.GetULong();
- $$.iCardinality = $4.iCardinality;
- }
-| rls_cardinality
- { $$ = $1; }
-;
-
-rls_cardinality:
- L_MULTI
- {
- $$.iMaxLength = 0xFFFFFFF;
- $$.iCardinality = ERlsCardinalityMultiple;
- }
-|
- {
- $$.iMaxLength = 0xFFFFFFF;
- $$.iCardinality = ERlsCardinalitySingle;
- }
-;
-
-rls_string_item:
- L_RLS_STRING
- { $$ = ERlsString; }
-| L_RLS_STRING8
- { $$ = ERlsString8; }
-;
-
-rls_num_item:
- L_RLS_BYTE
- { $$ = ERlsByte; }
-| L_RLS_WORD
- { $$ = ERlsWord; }
-| L_RLS_LONG
- { $$ = ERlsLong; }
-;
-
-rls_float_item:
- L_RLS_DOUBLE
- { $$ = ERlsDouble; }
-;
-
-/************************/
-/* comment tags */
-/************************/
-maybe_comment_tag:
- comment_tag
-|
-;
-
-comment_tag:
- L_TAG_START tag_line L_TAG_END {ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(*pCurrentLineNumber)); }
- ;
-
-tag_line:
- tag_line tag_word
-
-|
-;
-
-tag_word:
- L_TAG_NEW_LINE { pGL->StoreComment($1); }
-| L_TAG_COMMAND { pGL->StoreComment($1); }
-| L_TAG_WORD { pGL->StoreComment($1); }
-;
-
-%%
-
-// Function section
-// ================
-
-void asUTF8(char* aUtf8, int aUnicode)
- {
- if ( aUnicode > 0xffff )
- {
- if ( aUnicode > 0x10ffff )
- {
- ErrorHandler::OutputErrorLine("Surrogate character code must be a number in the range 0x10000 to 0x10ffff");
- exit(1);
- }
-
- UTF16 high = (UTF16)(0xD7C0 + (aUnicode >> 10)); // high surrogate
- UTF16 low = (UTF16)(0xDC00 | (aUnicode & 0x3FF)); // low surrogate
-
- *aUtf8++ =(char)(0xe0|(high>>12));
- *aUtf8++ =(char)(0x80|((high>>6)&0x3f));
- *aUtf8++ =(char)(0x80|(high&0x3f));
- *aUtf8++ =(char)(0xe0|(low>>12));
- *aUtf8++ =(char)(0x80|((low>>6)&0x3f));
- *aUtf8 =(char)(0x80|(low&0x3f));
- }
- else if ((aUnicode & 0xff80) == 0x0000)
- {
- *aUtf8 = (char)aUnicode;
- }
- else if ((aUnicode & 0xf800) == 0x0000)
- {
- *aUtf8++ =(char)(0xc0|(aUnicode>>6));
- *aUtf8 =(char)(0x80|(aUnicode&0x3f));
- }
- else
- {
- *aUtf8++ =(char)(0xe0|(aUnicode>>12));
- *aUtf8++ =(char)(0x80|((aUnicode>>6)&0x3f));
- *aUtf8 =(char)(0x80|(aUnicode&0x3f));
- }
- *++aUtf8 = '\0';
- }
-
-
-String::CharacterSet CharacterSetID( const String & character_set_name )
-// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// Return a character set ID from a character set name. The value UNKNOWN
-// is returned if the name is not recognised.
-// ----------------------------------------------------------------------------
-{
- String::CharacterSet ids[] = { String::ISOLatin1, String::ASCII, String::CP1252
- , String::CP850, String::ShiftJIS, String::Unicode
- , String::UTF8
- , String::UNKNOWN
- };
- String names[] = { "ISOLATIN1", "ASCII", "CP1252", "CP850", "SHIFTJIS", "UNICODE", "UTF8" };
-
- for ( int i=0; ids[i]!=String::UNKNOWN; i++ )
- {
- if ( names[i] == character_set_name ) return ids[i];
- }
-
- return String::UNKNOWN;
-
-} // end of CharacterSetID code
-
-void SetIdFromName( const String & NameStatementValue)
- {
- // space 0
- // A 1
- // B 2
- // ...
- // Z 26
- //
- // ABCD corresponds to the number 4321 which becomes ( (4*27 + 3) * 27 + 2) * 27 + 1.
-
- if(verbose)
- { MOFF;cout << "name_statement " << NameStatementValue << endl;MON;}
- if ( NameStatementValue.Length() > 4)
- {
- ErrorHandler::OutputErrorLine( "Name must be no longer than four characters");
- exit( 1);
- }
-
- long NewId = 0;
-
- for( unsigned long i = 0; i < NameStatementValue.Length(); i++)
- {
- NewId *= 27;
- if ( isalpha( NameStatementValue[i]) )
- NewId += toupper( NameStatementValue[i]) - 'A' + 1;
- }
-
- CurrentId = NewId << 12;
- FormatIdAsHex = 1;
- if(verbose)
- { MOFF;cout << "Current id " << CurrentId << endl;MON;}
- }
-
-void RlsUnusedWarnings()
- {
- TNameIndex::iterator end = pG->RlsNameIndex.end();
- for (TNameIndex::iterator i = pG->RlsNameIndex.begin(); i != end; ++i)
- {
- int index = i->second;
- RlsValue& v = pG->RlsValues[index];
- if (v.iCitationCount == 0)
- {
- Message * message = pG->Messages.GetEntry(LT_004);
- String fileLine = *(v.iFileName);
- if(message->GetActivated())
- {
- pGL->AddWarningToStore(fileLine, v.iLineNumber, message->GetMessageOutput());
- }
- }
- }
- }
-
-int ParseSourceFile(FILE* aFile, unsigned short aYYDebug)
- {
- // Set up various global pointers which refer to the pG structure
- pSHA = & (pG->SHA);
- pFileLineHandler = & (pG->FileLineHandler);
- pResourceNameIds = & (pG->ResourceNameIds);
-
- pScan = new rcscan(pG->FileLineHandler, aFile);
-
- yydebug = aYYDebug;
- pCurrentLineNumber = &yylineno;
- int ReturnValue = yyparse();
-
- RlsUnusedWarnings();
-
- int bScanErrorFound = pScan->ErrorWasFound();
-
- delete pScan;
- pScan = NULL;
-
- if(ReturnValue != 0)
- return ReturnValue;
-
- if(bScanErrorFound)
- return 1;
-
- return 0; // successful parse - parse tree now in the pG data structure
- }
-
-
-void CheckStructUsage()
- {
- ResourceItemArrayIterator nextRI( *pCurrentRIA);
- ResourceItem * pRI;
- while ( ( pRI = nextRI() ) != NULL)
- {
- int resourceItemType = pRI->GetResourceItemType();
- String resourceItemLabel = pRI->GetLabel();
- if( (resourceItemType == EStructTypeResourceItem) || (resourceItemType == EStructArrayResourceItem) )
- {
- StringArrayIterator nextLabel( *pUsedLabelsArray);
- String * pLabel;
- bool flag = false;
- while ( ( ( pLabel = nextLabel() ) != NULL ) && (! flag) )
- {
- StringLess stringCompare;
- if( !stringCompare(resourceItemLabel,*pLabel) && !stringCompare(*pLabel,resourceItemLabel) )
- {
- flag = true;
- }
- }
- if(! flag)
- {
- if(resourceItemType == EStructTypeResourceItem)
- {
- Message * message = pG->Messages.GetEntry(LT_046);
- if(message->GetActivated())
- {
- String comment = message->GetMessageOutput();
- comment += "'";
- comment += resourceItemLabel;
- comment += "'";
- ErrorHandler::OutputErrorLine(comment);
- }
- }
- else
- {
- Message * message = pG->Messages.GetEntry(LT_047);
- if(message->GetActivated())
- {
- String comment = message->GetMessageOutput();
- comment += "'";
- comment += resourceItemLabel;
- comment += "'";
- ErrorHandler::OutputErrorLine(comment);
- }
- }
- }
- }
- }
- }
-
-int yywrap()
-{
- return 1;
-}
-
-/* Called by yyparse on error */
-#include <stdarg.h>
-void yyerror (const char *s, ...)
-{
- va_list list;
- va_start(list, s);
- pScan->yyerror(const_cast<char*>(s), list);
- va_end(list);
-}
-
-
+%{
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// RCOMP.CPP
+// Generated from RCOMP.Y
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
+#include <fstream>
+#include <iostream>
+using namespace std;
+using std::cout;
+using std::endl;
+#else //!__MSVCDOTNET__
+#include <fstream.h>
+#endif //__MSVCDOTNET__
+
+#ifdef __VC32__
+#pragma warning( disable : 4065 ) // C4065: switch statement contains 'default' but no 'case' labels
+#pragma warning( disable : 4102 ) // C4102: 'yyerrlab1' : unreferenced label
+#pragma warning( disable : 4127 ) // C4127: conditional expression is constant
+#pragma warning( disable : 4244 ) // C4244: '=' : conversion from 'int' to 'short', possible loss of data
+#endif //__VC32__
+
+//#include "resource.h"
+//#include "parser.h"
+#include "RESOURCE.H"
+#include "parser.h"
+
+int yylex();
+void yyerror(const char* string, ...);
+int yywrap();
+#define YYDEBUG 1
+extern int yylineno;
+
+#include "rcomp.hpp"
+#include "datatype.h"
+#include "mem.h"
+#include "rcbinstr.h"
+#include "rcscan.h"
+#include "errorhan.h"
+#include "fileacc.h"
+#include "version.h"
+#include "ctable.h"
+#include "localise.h"
+#include "main.h"
+
+#if defined(__VC32__) && !defined(_DEBUG)
+#pragma warning( disable : 4702 ) // unreachable code
+#pragma warning( disable : 4102 ) // 'yyerrlabel' : unreferenced label
+#pragma warning( disable : 4244 ) // '=' : conversion from 'int' to 'short', possible loss of data
+#endif
+
+
+
+String::CharacterSet CharacterSetID( const String & character_set_name );
+void asUTF8(char* aUtf8, int aUnicode);
+void SetIdFromName( const String & NameStatementValue);
+void CheckStructUsage();
+
+unsigned short & d = MemCheckControl::iLogMemory;
+
+StructHeader * pSH;
+
+StructHeaderArray * pSHA; // Used in resource struct handling functions.
+ResourceHeader * pResourceHeader;
+ResourceItemArray * pCurrentRIA;
+StringArray * pUsedLabelsArray = new StringArray();
+int verbose;
+String::CharacterSet SourceCharacterSet = String::CP1252;
+String::CharacterSet TargetCharacterSet = String::CP1252;
+unsigned short logmemorysetting;
+int * pCurrentLineNumber;
+FileLineManager * pFileLineHandler;
+NameIdMap * pResourceNameIds;
+long CurrentEnumValue;
+String CurrentEnumName;
+char TempStr[300];
+rcscan * pScan;
+
+int CurrentIdStep=1;
+long CurrentId=0;
+int FormatIdAsHex=0; // defaults to decimal, changes in SetIdFromName
+
+unsigned long Uid2=0;
+unsigned long Uid3=0;
+
+
+
+const String Divider("*******************************************");
+
+#define REGISTER_LINE ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(* pCurrentLineNumber))
+
+// Convert a string containing a character literal in aQuoted
+// into a value suitable for LCHAR_LITERAL
+void SetCharacterLiteral(char* aOut, const String& aQuoted)
+ {
+ UTF16 first;
+ int length=1;
+ if (aQuoted.Length() < 1 )
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: Empty Character literal");
+ }
+ if (aQuoted.Length() > 1 )
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Error: String Literal length greater than 1");
+ exit(1);
+ }
+ if (aQuoted.Export(&first, length, SourceCharacterSet)==0)
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: Ignoring trailing characters in character literal");
+ }
+ sprintf(aOut, "%d", first);
+ }
+
+%}
+
+%union {
+ char Value[1024*8];
+ TValueMaybeRls ValueMaybeRls;
+ unsigned long Id;
+ StructItem * pStructItem;
+ SimpleStructItem * pSimpleStructItem;
+ ArrayStructItem * pArrayStructItem;
+ StructArrayStructItem * pStructArrayStructItem;
+ StringArray * pStringArray;
+ long NumInitialiser;
+ TRlsQualifiers RlsQualifiers;
+ TRlsType RlsType;
+}
+
+%token <Id> L_STRUCT L_RESOURCE L_NAME L_OFFSET L_SYSTEM L_GLOBAL L_LOCAL L_CHARACTER_SET
+%token <Id> L_BUF L_WORD L_BYTE L_LONG L_DOUBLE L_TEXT L_LTEXT L_LINK L_LLINK L_SRLINK
+%token <Id> L_BUF8 L_TEXT8 L_LTEXT8 L_BUF16 L_TEXT16 L_LTEXT16 L_UID_TWO L_UID_THREE
+%token <Id> L_RLS_STRING L_RLS_STRING8 L_RLS_DOUBLE
+%token <Id> L_RLS_BYTE L_RLS_WORD L_RLS_LONG
+%token <Id> L_MULTI
+%token <Id> L_TAG_START L_TAG_END
+%token <Value> L_TAG_COMMAND L_TAG_WORD L_TAG_NEW_LINE
+%token <Value> L_LABEL L_NUM_NATURAL L_NUM_FLOAT L_NATURAL_EXPR L_ENUM
+%token <Value> L_LEN
+%token <Value> L_CHAR_LITERAL L_STRING_LITERAL
+
+%type <Id> data_type len_declaration
+%type <pStructItem> struct_item array_struct_item simple_struct_item
+%type <pSimpleStructItem> simple_struct_item_start
+%type <pStructItem> struct_type_struct_item struct_array_struct_item
+%type <pArrayStructItem> array_struct_item_start array_struct_item_base
+%type <pStructArrayStructItem> struct_array_struct_item_base
+%type <Value> simple_initialiser natural_expression
+%type <Value> character_code_expression string_expression string_expression_item
+%type <pStringArray> simple_initialiser_list
+%type <NumInitialiser> natural_expression_numeric
+%type <RlsQualifiers> rls_qualifiers rls_cardinality
+%type <Value> rls_label
+%type <RlsType> rls_string_item rls_num_item rls_float_item
+
+%left '+' '-'
+%left '*' '/'
+%left '|'
+%left UMINUS
+
+%%
+
+/*****************************************************************/
+/* TOP-MOST RULE */
+/*****************************************************************/
+source : statement_list { if(verbose) { MOFF; cout << Divider << "\n" << Divider << endl; MON; }
+ }
+;
+/*****************************************************************/
+/* statement-list and statement */
+/*****************************************************************/
+statement_list:
+ statement_list statement
+| statement_list comment_tag
+| /* Nothing */
+;
+
+statement:
+ struct_statement maybe_semicolon
+| resource_statement maybe_semicolon
+| character_set_statement maybe_semicolon
+| name_statement maybe_semicolon
+| offset_statement maybe_semicolon
+| system_statement maybe_semicolon
+| enum_statement
+| uidX_statement maybe_semicolon
+| rls_item_statement maybe_semicolon
+;
+
+maybe_semicolon:
+ ';'
+ {
+ // This is my gift to the world: no more "syntax error" for adding
+ // an extra semicolon at the end of a struct or resource.
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: unnecessary semicolon");
+ }
+|
+;
+
+/******************************************************************/
+/* STRUCT statement */
+/******************************************************************/
+struct_statement:
+ struct_statement_start struct_item_list '}'
+ { if(verbose) { MOFF; cout << Divider << "\n" << * pSH << Divider << endl; MON;} }
+;
+struct_statement_start:
+ L_STRUCT L_LABEL maybe_comment_tag '{'
+ { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << endl; MON;}
+ pSH = new StructHeader($2);
+ REGISTER_LINE;
+ pG->SHA.Add(pSH);
+ }
+| L_STRUCT L_LABEL len_declaration maybe_comment_tag '{'
+ { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_statement_start " << $2 << " " << Types.GetName($3) << endl; MON;}
+ pSH = new StructHeader($2, $3);
+ REGISTER_LINE;
+ pG->SHA.Add(pSH);
+ }
+| L_STRUCT L_LABEL L_LEN maybe_comment_tag '{'
+ { if(verbose) { MOFF;cout << "struct_statement_start " << $2 << " (WORD)" << endl; MON;}
+ pSH = new StructHeader($2, L_WORD);
+ REGISTER_LINE;
+ pG->SHA.Add(pSH);
+ }
+;
+struct_item_list:
+ struct_item_list struct_item ';' { if(verbose) { MOFF;cout << "struct_item_list Adding struct_item." << endl; MON;}
+ REGISTER_LINE;
+ pSH->iSIA.Add($2);
+ }
+| struct_item_list comment_tag struct_item ';' { if(verbose) { MOFF;cout << "tagged struct_item_list Adding struct_item." << endl; MON;}
+ REGISTER_LINE;
+ pSH->iSIA.Add($3);
+ }
+| /* Nothing */
+;
+struct_item:
+ simple_struct_item
+| array_struct_item
+| struct_type_struct_item
+| struct_array_struct_item
+;
+simple_struct_item:
+ simple_struct_item_start { $$ = $1;}
+| simple_struct_item_start '(' natural_expression ')'
+ { if(verbose) { MOFF;cout << " Limit: " << $3 << endl; MON;}
+ $1->iLengthLimit = $3;
+ $$ = $1;
+ }
+| simple_struct_item_start '=' simple_initialiser /****************************************************************/
+ { if(verbose) { MOFF;cout << " Default: " << $3 << endl; MON;}
+ $1->iDefault = $3;
+ $$ = $1;
+ }
+| simple_struct_item_start '(' natural_expression ')' '=' string_expression /****************************************************************/
+ { if(verbose) { MOFF;cout << " Limit: " << $3 << ", Default: " << $6 << endl; MON;}
+ NumericValue Limit($3, L_LONG);
+ if(String($6).ExportLength(TargetCharacterSet,SourceCharacterSet) > Limit.GetULong() )
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Text length exceeds specified limit");
+ exit(1);
+ }
+ $1->iLengthLimit = $3;
+ $1->iDefault = $6;
+ $$ = $1;
+ }
+
+;
+simple_struct_item_start:
+ data_type L_LABEL { if(verbose)
+ {
+ RCTypeArray Types;
+ MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $2 << endl; MON;
+ }
+ $$ = new SimpleStructItem($1,$2);
+ assert($$ != NULL);
+ }
+| data_type '<' natural_expression_numeric '>' L_LABEL
+ { if(verbose)
+ { RCTypeArray Types;
+ MOFF;cout << "simple_struct_item " << Types.GetName($1) << " " << $5 << endl; MON;
+ }
+ String s(NumericValue::ltoa($3));
+ $$ = new SimpleStructItem($1,$5,s);
+ assert($$ != NULL);
+ }
+;
+
+/* Note that generic text identifiers are converted to their explicit
+ 8 or 16-bit forms at this point, depending on the target character set.
+*/
+data_type:
+ L_BYTE { $$ = L_BYTE;}
+| L_WORD { $$ = L_WORD;}
+| L_LONG { $$ = L_LONG;}
+| L_DOUBLE { $$ = L_DOUBLE;}
+
+
+
+| L_TEXT
+ {
+ $$ = ( TargetCharacterSet == String::Unicode ) ? L_TEXT16: L_TEXT8;
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT - use LTEXT instead");
+ }
+| L_LTEXT
+ {
+ $$ = ( TargetCharacterSet == String::Unicode ) ? L_LTEXT16: L_LTEXT8;
+ }
+| L_BUF
+ {
+ $$ = ( TargetCharacterSet == String::Unicode ) ? L_BUF16: L_BUF8;
+ }
+
+
+
+| L_TEXT8 { $$ = L_TEXT8;
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT8 - use LTEXT8 instead");
+ }
+| L_TEXT16 { $$ = L_TEXT16;
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Warning: Deprecated use of zero-terminated TEXT16 - use LTEXT16 instead");
+ }
+| L_LTEXT8 { $$ = L_LTEXT8;}
+| L_LTEXT16 { $$ = L_LTEXT16;}
+| L_BUF8 { $$ = L_BUF8;}
+| L_BUF16 { $$ = L_BUF16;}
+| L_LINK { $$ = L_LINK;}
+| L_LLINK { $$ = L_LLINK;}
+| L_SRLINK { $$ = L_SRLINK;}
+;
+array_struct_item:
+ array_struct_item_base { $$ = $1;}
+| array_struct_item_base '=' '{' simple_initialiser_list '}'
+ { if(verbose) { MOFF;cout << "array_struct_item with simple_initialiser_list" << endl;MON;}
+ $1->iDefaults = * $4;
+ if($1->iSize.Length() > 0)
+ {
+ NumericValue v($1->iSize, L_LONG);
+ REGISTER_LINE;
+ if($4->Size()!=long(v.GetULong()))
+ {
+ ErrorHandler::OutputErrorLine("Size does not match number of initialisers");
+ exit(1);
+ }
+ }
+ $$ = $1;
+ delete $4;
+ }
+;
+array_struct_item_base:
+ array_struct_item_start ']' { if(verbose) { MOFF;cout << "array_struct_item_base with no size" << endl;MON;}
+ $$ =$1;
+ }
+| array_struct_item_start natural_expression ']'
+ { if(verbose) { MOFF;cout << "array_struct_item_base with size " << $2 << endl;MON;}
+ $1->iSize = $2;
+ $$ = $1;
+ }
+| L_LEN len_declaration array_struct_item_start ']'
+ { if(verbose)
+ { RCTypeArray Types;
+ MOFF;cout << "array_struct_item_base with LenType " << Types.GetName($2) << endl;MON;
+ }
+ $3->iLenType = $2;
+ $$ = $3;
+ }
+| L_LEN len_declaration array_struct_item_start natural_expression ']'
+ { if(verbose)
+ { RCTypeArray Types;
+ MOFF;cout << "array_struct_item_base with size " << $4 << " and LenType " << Types.GetName($2) << endl;MON;
+ }
+ $3->iLenType = $2;
+ $3->iSize = $4;
+ $$ = $3;
+ }
+;
+array_struct_item_start:
+ data_type L_LABEL '[' { if(verbose)
+ { RCTypeArray Types;
+ MOFF;cout << "array_struct_item_start " << Types.GetName($1) << " " << $2 << endl;MON;
+ }
+ $$ = new ArrayStructItem($1, $2);
+ }
+;
+len_declaration:
+ L_BYTE { $$ = L_BYTE;}
+| L_WORD { $$ = L_WORD;}
+;
+struct_type_struct_item:
+ L_STRUCT L_LABEL { if(verbose) { MOFF;cout << "struct_type_struct_item " << $2 << endl;MON;}
+ $$ = new StructTypeStructItem($2);
+ }
+;
+struct_array_struct_item:
+ struct_array_struct_item_base { $$ = $1;}
+| L_LEN len_declaration struct_array_struct_item_base
+ { if(verbose) { RCTypeArray Types; MOFF;cout << "struct_array_struct_item - Setting Size to " << Types.GetName($2) << endl;MON;}
+ $3->iLenType = $2; $$ = $3;
+ }
+;
+struct_array_struct_item_base:
+ L_STRUCT L_LABEL '[' ']' { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << endl;MON;}
+ $$ = new StructArrayStructItem($2);
+ }
+| L_STRUCT L_LABEL '[' natural_expression ']'
+ { if(verbose) { MOFF;cout << "struct_array_struct_item_base " << $2 << " " << $4 << endl;MON;}
+ $$ = new StructArrayStructItem($2, $4);
+ }
+;
+/*********************************************************************/
+/* RESOURCE statement */
+/*********************************************************************/
+resource_statement:
+ resource_statement_start '{' resource_item_list '}'
+ {
+ pResourceHeader->AddDefault();
+ CurrentId+=CurrentIdStep;
+ if(verbose) { MOFF;cout << "Resource ID "<< CurrentId << endl << Divider << "\n" << * pResourceHeader << Divider << endl;MON;}
+ pResourceHeader->SetResourceId(*pResourceNameIds,CurrentId,FormatIdAsHex);
+ pG->Index.Add(pResourceHeader);
+
+ CheckStructUsage();
+
+ pUsedLabelsArray->Empty();
+
+ pResourceHeader = NULL;
+ }
+;
+resource_statement_start:
+ L_GLOBAL resource_statement_start_names {} /* Ignore GLOBAL (obsolete feature).*/
+| L_LOCAL resource_statement_start_names
+ {
+ if(verbose) { MOFF;cout << "resource_statement_start LOCAL" << endl;MON;}
+ assert(pResourceHeader != NULL);
+ pResourceHeader->iLocal = 1;
+ }
+| resource_statement_start_names {}
+;
+resource_statement_start_names:
+ L_RESOURCE L_LABEL L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " " << $3 << endl;MON;}
+ assert(pResourceHeader == NULL);
+ pResourceHeader = new ResourceHeader($3);
+ pCurrentRIA = & (pResourceHeader->iRIA);
+ REGISTER_LINE;
+ if(pResourceNameIds->IsStored($3))
+ {
+ ErrorHandler::OutputErrorLine("Resource with this name encountered already");
+ exit(1);
+ }
+ pCurrentRIA->FillFromStruct($2);
+ pG->AllIdentifiers.Add(new String($3)); // Add label to store
+ }
+| L_RESOURCE L_LABEL { if(verbose) { MOFF;cout << "resource_statement_start_names " << $2 << " <Resource not named>" << endl;MON;}
+ assert(pResourceHeader == NULL);
+ pResourceHeader = new ResourceHeader;
+ pCurrentRIA = & (pResourceHeader->iRIA);
+ REGISTER_LINE;
+ pCurrentRIA->FillFromStruct($2);
+ }
+;
+resource_item_list:
+ resource_item_list resource_item ';'{ if(verbose) { MOFF;cout << "resource_item_list" << endl;MON;}}
+| resource_item_list comment_tag resource_item ';'{ if(verbose) { MOFF;cout << "tagged resource_item_list" << endl;MON;}}
+| resource_item_list error ';' { yyerrok; yyclearin; }
+| /* Nothing */
+;
+resource_item:
+ L_LABEL '=' simple_initialiser { if(verbose) { MOFF;cout << "resource_item " << $1 << " " << $3 << endl;MON;}
+ REGISTER_LINE;/****************************************************************/
+ pCurrentRIA->Set($1, $3);
+ }
+| resource_simple_array_item
+| struct_resource_item
+| struct_array_resource_item
+;
+resource_simple_array_item:
+ L_LABEL '=' '{' '}'
+ {
+ if (verbose)
+ { MOFF;cout << "resource_simple_array_item " << $1 << endl;MON;}
+ }
+| L_LABEL '=' '{' simple_initialiser_list '}'
+ {
+ if (verbose)
+ { MOFF;cout << "resource_simple_array_item " << $1 << " with simple_initialiser_list" << endl;MON;}
+ REGISTER_LINE;
+ pCurrentRIA->Set($1, * $4);
+ delete $4;
+ }
+;
+
+/*---------------------------------------------------------------------------*/
+/* A note about RIAStack, SRIStack and pCurrentRIA. */
+/* */
+/* RIA stands for Resource Item Array. */
+/* SRI stands for Struct Array Resource Item. */
+/* */
+/* A push to RIAStack is made when dropping inside a STRUCT or STRUCT[] in */
+/* order to set values for the components. When this happens pCurrentRIA is */
+/* set to the RIA for the STRUCT or last item of the STRUCT[]. */
+/* */
+/* pCurrentRIA is set to the result of popping from RIAStack when a closing */
+/* brace is reached. */
+/* */
+/* A push is made to SRIStack when going into an item for a STRUCT[]. On */
+/* reaching a closing brace the STRUCT[] is popped off the SRIStack. An new */
+/* item may then be added to this array. */
+/*---------------------------------------------------------------------------*/
+struct_resource_item:
+ struct_resource_item_start resource_item_list '}'
+ { if(verbose) { MOFF;cout << "struct_resource_item" << endl;MON;}
+ pCurrentRIA = pG->RIAStack.Pop();
+ }
+;
+struct_resource_item_start:
+ L_LABEL '=' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_resource_item_start " << $1 << " " << $3 << endl;MON;}
+ REGISTER_LINE;
+ pCurrentRIA->Set($1, $3);
+ String * thisLabel = new String($1);
+ pUsedLabelsArray->Add(thisLabel);
+ // in here add the label to a temp store
+ pG->RIAStack.Push(pCurrentRIA);
+ pCurrentRIA = pCurrentRIA->Find($1)->GetRIA();
+ }
+;
+struct_array_resource_item:
+ struct_array_resource_item_start struct_array_resource_item_list_top '}'
+ { if(verbose) { MOFF;cout << "struct_array_resource_item" << endl;MON;}
+ pG->SRIStack.Pop();
+ }
+| struct_array_resource_item_start struct_array_resource_item_list_top error
+ { pG->SRIStack.Pop();}
+;
+struct_array_resource_item_start:
+ L_LABEL '=' '{' L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_start " << $1 << " " << $4 << endl;MON;}
+ ResourceItem * p = pCurrentRIA->Find($1);
+ pG->SRIStack.Push(p);
+ REGISTER_LINE;
+ String * thisLabel = new String($1);
+ pUsedLabelsArray->Add(thisLabel);
+ // in here add the label to a temp store
+ p->Set($4);
+ pG->RIAStack.Push(pCurrentRIA);
+ pCurrentRIA = p->GetRIA();
+ }
+;
+struct_array_resource_item_list_top:
+ struct_array_resource_item_list_top_start
+| struct_array_resource_item_list_top_start ',' struct_array_resource_item_list
+| struct_array_resource_item_list_top_start ',' error
+;
+struct_array_resource_item_list_top_start:
+ resource_item_list '}' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_top " << endl;MON;}
+ pCurrentRIA = pG->RIAStack.Pop();
+ }
+;
+struct_array_resource_item_list:
+ struct_array_resource_item_list_item
+| struct_array_resource_item_list ',' struct_array_resource_item_list_item
+;
+struct_array_resource_item_list_item:
+ struct_array_resource_item_list_item_start resource_item_list '}'
+ { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item " << endl;MON;}
+ pCurrentRIA = pG->RIAStack.Pop();
+ }
+;
+struct_array_resource_item_list_item_start:
+ L_LABEL '{' { if(verbose) { MOFF;cout << "struct_array_resource_item_list_item_start " << $1 << endl;MON;}
+ ResourceItem * p = pG->SRIStack.Peek();
+ REGISTER_LINE;
+ p->Set($1);
+ pG->RIAStack.Push(pCurrentRIA);
+ pCurrentRIA = p->GetRIA();
+ }
+;
+
+
+/*****************************************************************/
+/* simple_initialiser and simple_initialiser_list */
+/*****************************************************************/
+simple_initialiser:
+ L_NUM_FLOAT
+| L_CHAR_LITERAL
+ {
+ // convert literal to unsigned long value of 1st character
+ SetCharacterLiteral($$, $1);
+ }
+| string_expression
+| natural_expression
+;
+simple_initialiser_list:
+ simple_initialiser
+ {
+ if(verbose)
+ {
+ MOFF;cout << "simple_initialiser_list - single string " << $1 << endl;MON;
+ }
+
+ $$ = new StringArray;
+ $$->Add(new String($1) );
+ }
+| simple_initialiser_list ',' simple_initialiser
+ { if(verbose) { MOFF;cout << "simple_initialiser_list - part of list " << $3 << endl;MON;}
+ assert($1 != NULL);
+ $1->Add(new String($3 ) );
+ $$ = $1;
+ }
+;
+
+natural_expression:
+ natural_expression_numeric { String s(NumericValue::ltoa($1) ); strcpy($$, s.GetAssertedNonEmptyBuffer() ); }
+;
+natural_expression_numeric:
+ L_NUM_NATURAL { if(verbose) { MOFF;cout << "Converting number " << $1 << endl;MON;}
+ REGISTER_LINE;
+ NumericValue v($1, L_LONG); $$ = (long)v.GetULong();
+ }
+| natural_expression_numeric '+' natural_expression_numeric { $$ = $1 + $3; }
+| natural_expression_numeric '-' natural_expression_numeric { $$ = $1 - $3; }
+| natural_expression_numeric '*' natural_expression_numeric { $$ = $1 * $3; }
+| natural_expression_numeric '/' natural_expression_numeric { $$ = $1 / $3; }
+| natural_expression_numeric '|' natural_expression_numeric { $$ = $1 | $3; }
+| '-' natural_expression_numeric %prec UMINUS { if (!NumericValue::CheckSigned($2,L_LONG))
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("Signed value too low");
+ exit(1);
+ }
+ $$ = - $2;
+ }
+| '(' natural_expression_numeric ')' { $$ = $2; }
+;
+string_expression:
+ string_expression_item
+| string_expression_item string_expression {
+ if (strlen($$)+strlen($2) > sizeof($$)-1)
+ {
+ REGISTER_LINE;
+ ErrorHandler::OutputErrorLine("String expression is too long");
+ exit(1);
+ }
+ strcat($$, $2);
+ }
+;
+string_expression_item:
+ L_STRING_LITERAL
+| character_code_expression
+| L_LABEL
+ {
+ const char * fileName = (*ErrorHandler::GetFileName()).GetBuffer();
+ int lineNumber = ErrorHandler::GetLineNumber();
+ QualifiedString * thisLabel = new QualifiedString($1, new String(fileName), lineNumber);
+ // store the label in the UsedIdentifiers array for checking
+ // whether label was declared
+ pG->UsedIdentifiers.Add(thisLabel);
+
+ if (pG->EnumValues.IsStored($1))
+ {
+ sprintf($$, "%d", (int)(pG->EnumValues.FindId($1)));
+ }
+ else if (pG->RlsNameIndex.count($1)) // if rls item has already been defined
+ {
+ // Found a reference to an rls_string.
+ RlsValue &rv = pG->RlsValues[pG->RlsNameIndex[$1]];
+ ++rv.iCitationCount; // iCitationCount counts the number of times this rls value has been referneced
+ // Warn for multiple uses if 'multi' keyword not used.
+ if (1 < rv.iCitationCount && rv.iCardinality == ERlsCardinalitySingle)
+ {
+ Message * message = pG->Messages.GetEntry(LT_001);
+ String fileLine = *(rv.iFileName);
+ if(message->GetActivated())
+ {
+ pGL->AddWarningToStore(fileLine, rv.iLineNumber, message->GetMessageOutput());
+ }
+ REGISTER_LINE;
+ if (!pG->WarningMultiExplained)
+ {
+ Message * message = pG->Messages.GetEntry(LT_002);
+ fileLine = String(*(pFileLineHandler->GetCurrentFile()));
+ if(message->GetActivated())
+ {
+ pGL->AddWarningToStore(fileLine, pFileLineHandler->GetErrorLine(* pCurrentLineNumber), message->GetMessageOutput());
+ pG->WarningMultiExplained = true;
+ }
+ }
+ }
+ switch (rv.iType)
+ {
+ // Strings and numbers are just copied to the next layer up.
+ case ERlsString:
+ case ERlsString8:
+ case ERlsByte:
+ case ERlsWord:
+ case ERlsLong:
+ case ERlsDouble:
+ strcpy($$, rv.iValue.GetBuffer());
+ break;
+ // Anything else is a character: this is converted to a number.
+ case ERlsStringChar:
+ case ERlsByteChar:
+ case ERlsWordChar:
+ case ERlsLongChar:
+ SetCharacterLiteral($$, rv.iValue);
+ break;
+ default:
+ Message * message = pG->Messages.GetEntry(LT_031);
+ if(message->GetActivated())
+ {
+ ErrorHandler::OutputErrorLine(message->GetMessageOutput());
+ exit(1);
+ }
+ break;
+ }
+ }
+ else
+ {
+ /*
+ Could be a reference to another resource, perhaps even a forward reference:
+ the OverwriteLink functions do FindId again when writing out the data.
+ Sadly this also permits things which are really syntax errors, inadvertently
+ converting labels into string literals..
+ */
+ }
+ }
+;
+character_code_expression:
+ '<' natural_expression_numeric '>'
+ {
+ REGISTER_LINE;
+ if($2 < 0 || ($2 > 255 && TargetCharacterSet != String::Unicode))
+ {
+ ErrorHandler::OutputErrorLine("Character code must be a number in the range 0 to 255.");
+ exit(1);
+ }
+ if (TargetCharacterSet != String::Unicode)
+ {
+ * $$ = char($2); * ($$ + 1) = '\0';
+ }
+ else
+ {
+ if (SourceCharacterSet == String::CP1252)
+ {
+ if ( ($2 >= 0x80) && ($2 <= 0x9F ) ) // 80-9F are illegal Unicode values.
+ {
+ ErrorHandler::OutputErrorLine("Warning: Deprecated non-unicode value in source stream");
+ }
+ * $$ = char(UnicodeEscape);
+ asUTF8($$ + 1, $2);
+ }
+ else
+ if (SourceCharacterSet == String::UTF8)
+ {
+ asUTF8($$, $2);
+ }
+ else
+ {
+ // Unsatisfactory, but do people use other character sets?
+ if ($2 > 255)
+ {
+ ErrorHandler::OutputErrorLine("Don't know how to handle character > 255");
+ }
+ * $$ = char($2); * ($$ + 1) = '\0';
+ }
+ }
+ }
+;
+
+
+/*****************************************************************/
+/* name_statement */
+/*****************************************************************/
+name_statement:
+ L_NAME L_LABEL
+ {
+ REGISTER_LINE;
+ SetIdFromName($2);
+ }
+| L_NAME L_STRING_LITERAL
+ {
+ REGISTER_LINE;
+ SetIdFromName($2);
+ }
+;
+
+
+/*****************************************************************/
+/* uidX_statement */
+/*****************************************************************/
+uidX_statement:
+ L_UID_TWO natural_expression_numeric
+ {
+ REGISTER_LINE;
+ if ($2 == 0)
+ { ErrorHandler::OutputErrorLine("UID2 must be non-zero"); exit(1); }
+ if (Uid2 != 0)
+ { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID2 value"); }
+ Uid2=$2;
+ if(verbose)
+ { MOFF;cout << "uidX_statement UID2 " << Uid2 << endl;MON;}
+ }
+| L_UID_THREE natural_expression_numeric
+ {
+ REGISTER_LINE;
+ if ($2 == 0)
+ { ErrorHandler::OutputErrorLine("UID3 must be non-zero"); exit(1); }
+ if (Uid3 != 0)
+ { ErrorHandler::OutputErrorLine("Warning: overwriting previous UID3 value"); }
+ Uid3=$2;
+ if(verbose)
+ { MOFF;cout << "uidX_statement UID3 " << Uid3 << endl;MON;}
+ }
+;
+
+
+/*****************************************************************/
+/* character_set_statement */
+/* Defines the SOURCE character set. Note that Unicode is a */
+/* character set id, but we can't read Unicode source */
+/* (because LEX and YACC can't handle it) */
+/*****************************************************************/
+
+character_set_statement:
+ L_CHARACTER_SET L_LABEL { if(verbose) { MOFF;cout << "character_set_statement " << $2 << endl;MON;}
+ REGISTER_LINE;
+ SourceCharacterSet = CharacterSetID($2);
+ if ( SourceCharacterSet == String::UNKNOWN )
+ {
+ String err = "Warning: Unrecognised character set name '";
+ err += $2;
+ err += "'";
+ ErrorHandler::OutputErrorLine(err);
+ }
+ if ( SourceCharacterSet == String::Unicode )
+ {
+ SourceCharacterSet = String::UNKNOWN;
+ ErrorHandler::OutputErrorLine("Unicode source is unsupported");
+ }
+ }
+;
+
+
+
+/*****************************************************************/
+/* offset_statement */
+/*****************************************************************/
+offset_statement:
+ L_OFFSET natural_expression { if(verbose) { RCTypeArray Types;
+ MOFF;cout << "offset_statement " << $2 << endl;MON; }
+ REGISTER_LINE;
+ CurrentId=((long) NumericValue($2, L_LONG).GetULong() );
+ }
+;
+
+/*****************************************************************/
+/* system_statement */
+/*****************************************************************/
+system_statement:
+ L_SYSTEM { if(verbose) { MOFF;cout << "system_statement" << endl;MON;}
+ CurrentIdStep=-1;
+ }
+;
+
+/*****************************************************************/
+/* enum_statement */
+/*****************************************************************/
+enum_statement:
+ enum_statement_start enum_list '}'
+| enum_statement_start enum_list '}' ';'
+;
+enum_statement_start:
+ L_ENUM L_LABEL '{'
+ {
+ if(verbose)
+ { MOFF;cout << "enum_statement" << endl;MON;}
+ CurrentEnumName = $2;
+ CurrentEnumValue=0;
+ }
+| L_ENUM '{'
+ {
+ if(verbose)
+ { MOFF;cout << "enum_statement" << endl;MON;}
+ CurrentEnumName = "";
+ CurrentEnumValue=0;
+ }
+;
+
+enum_list_entry:
+ L_LABEL
+ {
+ pG->EnumValues.Add($1, CurrentEnumValue++);
+ pG->AllIdentifiers.Add(new String($1)); // Add label to store
+ }
+| L_LABEL '=' simple_initialiser
+ {
+ CurrentEnumValue = atol($3);
+ pG->EnumValues.Add($1, CurrentEnumValue);
+ CurrentEnumValue++; // Increment so that next field has value ($3+1)
+ pG->AllIdentifiers.Add(new String($1)); // Add label to store
+ }
+;
+
+
+enum_list:
+ maybe_comment_tag enum_list_entry
+| enum_list ',' maybe_comment_tag enum_list_entry
+;
+
+/************************/
+/* rls_xxxx statement */
+/************************/
+rls_item_statement:
+ rls_string_item rls_qualifiers rls_label string_expression
+ {
+ pG->RlsNameIndex[$3] = pG->RlsValues.size();
+ pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
+ ErrorHandler::GetLineNumber(), $4, $1,
+ $2.iCardinality, $2.iMaxLength));
+ if($2.iMaxLength
+ < String($4).ExportLength(TargetCharacterSet,SourceCharacterSet))
+ {
+ Message * message = pG->Messages.GetEntry(LT_032);
+ if(message->GetActivated())
+ {
+ ErrorHandler::OutputErrorLine(message->GetMessageOutput());
+ exit(1);
+ }
+ }
+ }
+| rls_string_item rls_qualifiers rls_label L_CHAR_LITERAL /* This section is only for compatibility */
+ {
+ Message * message = pG->Messages.GetEntry(LT_033);
+ String fileName = *(pFileLineHandler->GetCurrentFile());
+ int lineNumber = pFileLineHandler->GetErrorLine(* pCurrentLineNumber);
+ if(message->GetActivated())
+ {
+ pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+ }
+ //...
+ /* Produce a warning "rls_string used for character constant: use rls_long, rls_word or rls_byte" */
+ pG->RlsNameIndex[$3] = pG->RlsValues.size();
+ pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
+ ErrorHandler::GetLineNumber(), $4, ERlsStringChar,
+ $2.iCardinality));
+ }
+| rls_float_item rls_cardinality rls_label L_NUM_FLOAT
+ {
+ pG->RlsNameIndex[$3] = pG->RlsValues.size();
+ pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
+ ErrorHandler::GetLineNumber(), $4, $1,
+ $2.iCardinality));
+ }
+| rls_num_item rls_cardinality rls_label L_NUM_NATURAL
+ {
+ pG->RlsNameIndex[$3] = pG->RlsValues.size();
+ pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
+ ErrorHandler::GetLineNumber(), $4, $1,
+ $2.iCardinality));
+ }
+| rls_num_item rls_cardinality rls_label L_CHAR_LITERAL
+ {
+ TRlsType rlsCharType = $1 == ERlsByte? ERlsByteChar
+ : ( $1 == ERlsWord? ERlsWordChar : ERlsLongChar );
+ pG->RlsNameIndex[$3] = pG->RlsValues.size();
+ pG->RlsValues.push_back(RlsValue(ErrorHandler::GetFileName(),
+ ErrorHandler::GetLineNumber(), $4, rlsCharType,
+ $2.iCardinality));
+ }
+;
+
+rls_label: L_LABEL
+ {
+ // Register line even if no warning here so that
+ // the rls_ item knows which line the label was on.
+ // Without this, the line registered would be the
+ // line following the declaration.
+ REGISTER_LINE;
+ strcpy($$, $1);
+
+ if (pG->RlsNameIndex.count($1) != 0)
+ {
+ Message * message = pG->Messages.GetEntry(LT_003);
+ if(message->GetActivated())
+ {
+ ErrorHandler::OutputErrorLine(message->GetMessageOutput());
+ }
+ }
+ pG->AllIdentifiers.Add(new String($1)); // Add label to store
+ }
+
+rls_qualifiers:
+ '<' L_NUM_NATURAL '>' rls_cardinality
+ {
+ NumericValue v($2, L_LONG);
+ $$.iMaxLength = v.GetULong();
+ $$.iCardinality = $4.iCardinality;
+ }
+| rls_cardinality
+ { $$ = $1; }
+;
+
+rls_cardinality:
+ L_MULTI
+ {
+ $$.iMaxLength = 0xFFFFFFF;
+ $$.iCardinality = ERlsCardinalityMultiple;
+ }
+|
+ {
+ $$.iMaxLength = 0xFFFFFFF;
+ $$.iCardinality = ERlsCardinalitySingle;
+ }
+;
+
+rls_string_item:
+ L_RLS_STRING
+ { $$ = ERlsString; }
+| L_RLS_STRING8
+ { $$ = ERlsString8; }
+;
+
+rls_num_item:
+ L_RLS_BYTE
+ { $$ = ERlsByte; }
+| L_RLS_WORD
+ { $$ = ERlsWord; }
+| L_RLS_LONG
+ { $$ = ERlsLong; }
+;
+
+rls_float_item:
+ L_RLS_DOUBLE
+ { $$ = ERlsDouble; }
+;
+
+/************************/
+/* comment tags */
+/************************/
+maybe_comment_tag:
+ comment_tag
+|
+;
+
+comment_tag:
+ L_TAG_START tag_line L_TAG_END {ErrorHandler::Register(pFileLineHandler->GetCurrentFile(), pFileLineHandler->GetErrorLine(*pCurrentLineNumber)); }
+ ;
+
+tag_line:
+ tag_line tag_word
+
+|
+;
+
+tag_word:
+ L_TAG_NEW_LINE { pGL->StoreComment($1); }
+| L_TAG_COMMAND { pGL->StoreComment($1); }
+| L_TAG_WORD { pGL->StoreComment($1); }
+;
+
+%%
+
+// Function section
+// ================
+
+void asUTF8(char* aUtf8, int aUnicode)
+ {
+ if ( aUnicode > 0xffff )
+ {
+ if ( aUnicode > 0x10ffff )
+ {
+ ErrorHandler::OutputErrorLine("Surrogate character code must be a number in the range 0x10000 to 0x10ffff");
+ exit(1);
+ }
+
+ UTF16 high = (UTF16)(0xD7C0 + (aUnicode >> 10)); // high surrogate
+ UTF16 low = (UTF16)(0xDC00 | (aUnicode & 0x3FF)); // low surrogate
+
+ *aUtf8++ =(char)(0xe0|(high>>12));
+ *aUtf8++ =(char)(0x80|((high>>6)&0x3f));
+ *aUtf8++ =(char)(0x80|(high&0x3f));
+ *aUtf8++ =(char)(0xe0|(low>>12));
+ *aUtf8++ =(char)(0x80|((low>>6)&0x3f));
+ *aUtf8 =(char)(0x80|(low&0x3f));
+ }
+ else if ((aUnicode & 0xff80) == 0x0000)
+ {
+ *aUtf8 = (char)aUnicode;
+ }
+ else if ((aUnicode & 0xf800) == 0x0000)
+ {
+ *aUtf8++ =(char)(0xc0|(aUnicode>>6));
+ *aUtf8 =(char)(0x80|(aUnicode&0x3f));
+ }
+ else
+ {
+ *aUtf8++ =(char)(0xe0|(aUnicode>>12));
+ *aUtf8++ =(char)(0x80|((aUnicode>>6)&0x3f));
+ *aUtf8 =(char)(0x80|(aUnicode&0x3f));
+ }
+ *++aUtf8 = '\0';
+ }
+
+
+String::CharacterSet CharacterSetID( const String & character_set_name )
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Return a character set ID from a character set name. The value UNKNOWN
+// is returned if the name is not recognised.
+// ----------------------------------------------------------------------------
+{
+ String::CharacterSet ids[] = { String::ISOLatin1, String::ASCII, String::CP1252
+ , String::CP850, String::ShiftJIS, String::Unicode
+ , String::UTF8
+ , String::UNKNOWN
+ };
+ String names[] = { "ISOLATIN1", "ASCII", "CP1252", "CP850", "SHIFTJIS", "UNICODE", "UTF8" };
+
+ for ( int i=0; ids[i]!=String::UNKNOWN; i++ )
+ {
+ if ( names[i] == character_set_name ) return ids[i];
+ }
+
+ return String::UNKNOWN;
+
+} // end of CharacterSetID code
+
+void SetIdFromName( const String & NameStatementValue)
+ {
+ // space 0
+ // A 1
+ // B 2
+ // ...
+ // Z 26
+ //
+ // ABCD corresponds to the number 4321 which becomes ( (4*27 + 3) * 27 + 2) * 27 + 1.
+
+ if(verbose)
+ { MOFF;cout << "name_statement " << NameStatementValue << endl;MON;}
+ if ( NameStatementValue.Length() > 4)
+ {
+ ErrorHandler::OutputErrorLine( "Name must be no longer than four characters");
+ exit( 1);
+ }
+
+ long NewId = 0;
+
+ for( unsigned long i = 0; i < NameStatementValue.Length(); i++)
+ {
+ NewId *= 27;
+ if ( isalpha( NameStatementValue[i]) )
+ NewId += toupper( NameStatementValue[i]) - 'A' + 1;
+ }
+
+ CurrentId = NewId << 12;
+ FormatIdAsHex = 1;
+ if(verbose)
+ { MOFF;cout << "Current id " << CurrentId << endl;MON;}
+ }
+
+void RlsUnusedWarnings()
+ {
+ TNameIndex::iterator end = pG->RlsNameIndex.end();
+ for (TNameIndex::iterator i = pG->RlsNameIndex.begin(); i != end; ++i)
+ {
+ int index = i->second;
+ RlsValue& v = pG->RlsValues[index];
+ if (v.iCitationCount == 0)
+ {
+ Message * message = pG->Messages.GetEntry(LT_004);
+ String fileLine = *(v.iFileName);
+ if(message->GetActivated())
+ {
+ pGL->AddWarningToStore(fileLine, v.iLineNumber, message->GetMessageOutput());
+ }
+ }
+ }
+ }
+
+int ParseSourceFile(FILE* aFile, unsigned short aYYDebug)
+ {
+ // Set up various global pointers which refer to the pG structure
+ pSHA = & (pG->SHA);
+ pFileLineHandler = & (pG->FileLineHandler);
+ pResourceNameIds = & (pG->ResourceNameIds);
+
+ pScan = new rcscan(pG->FileLineHandler, aFile);
+
+ yydebug = aYYDebug;
+ pCurrentLineNumber = &yylineno;
+ int ReturnValue = yyparse();
+
+ RlsUnusedWarnings();
+
+ int bScanErrorFound = pScan->ErrorWasFound();
+
+ delete pScan;
+ pScan = NULL;
+
+ if(ReturnValue != 0)
+ return ReturnValue;
+
+ if(bScanErrorFound)
+ return 1;
+
+ return 0; // successful parse - parse tree now in the pG data structure
+ }
+
+
+void CheckStructUsage()
+ {
+ ResourceItemArrayIterator nextRI( *pCurrentRIA);
+ ResourceItem * pRI;
+ while ( ( pRI = nextRI() ) != NULL)
+ {
+ int resourceItemType = pRI->GetResourceItemType();
+ String resourceItemLabel = pRI->GetLabel();
+ if( (resourceItemType == EStructTypeResourceItem) || (resourceItemType == EStructArrayResourceItem) )
+ {
+ StringArrayIterator nextLabel( *pUsedLabelsArray);
+ String * pLabel;
+ bool flag = false;
+ while ( ( ( pLabel = nextLabel() ) != NULL ) && (! flag) )
+ {
+ StringLess stringCompare;
+ if( !stringCompare(resourceItemLabel,*pLabel) && !stringCompare(*pLabel,resourceItemLabel) )
+ {
+ flag = true;
+ }
+ }
+ if(! flag)
+ {
+ if(resourceItemType == EStructTypeResourceItem)
+ {
+ Message * message = pG->Messages.GetEntry(LT_046);
+ if(message->GetActivated())
+ {
+ String comment = message->GetMessageOutput();
+ comment += "'";
+ comment += resourceItemLabel;
+ comment += "'";
+ ErrorHandler::OutputErrorLine(comment);
+ }
+ }
+ else
+ {
+ Message * message = pG->Messages.GetEntry(LT_047);
+ if(message->GetActivated())
+ {
+ String comment = message->GetMessageOutput();
+ comment += "'";
+ comment += resourceItemLabel;
+ comment += "'";
+ ErrorHandler::OutputErrorLine(comment);
+ }
+ }
+ }
+ }
+ }
+ }
+
+int yywrap()
+{
+ return 1;
+}
+
+/* Called by yyparse on error */
+#include <stdarg.h>
+void yyerror (const char *s, ...)
+{
+ va_list list;
+ va_start(list, s);
+ pScan->yyerror(const_cast<char*>(s), list);
+ va_end(list);
+}
+
+