diff -r 7c4a911dc066 -r 541af5ee3ed9 bintools/rcomp/src/RCOMP.YACC --- a/bintools/rcomp/src/RCOMP.YACC Fri Aug 13 14:59:05 2010 +0300 +++ b/bintools/rcomp/src/RCOMP.YACC Wed Aug 18 17:23:33 2010 +0300 @@ -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 -#include -#include - -#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) -#include -#include -using namespace std; -using std::cout; -using std::endl; -#else //!__MSVCDOTNET__ -#include -#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 L_STRUCT L_RESOURCE L_NAME L_OFFSET L_SYSTEM L_GLOBAL L_LOCAL L_CHARACTER_SET -%token L_BUF L_WORD L_BYTE L_LONG L_DOUBLE L_TEXT L_LTEXT L_LINK L_LLINK L_SRLINK -%token L_BUF8 L_TEXT8 L_LTEXT8 L_BUF16 L_TEXT16 L_LTEXT16 L_UID_TWO L_UID_THREE -%token L_RLS_STRING L_RLS_STRING8 L_RLS_DOUBLE -%token L_RLS_BYTE L_RLS_WORD L_RLS_LONG -%token L_MULTI -%token L_TAG_START L_TAG_END -%token L_TAG_COMMAND L_TAG_WORD L_TAG_NEW_LINE -%token L_LABEL L_NUM_NATURAL L_NUM_FLOAT L_NATURAL_EXPR L_ENUM -%token L_LEN -%token L_CHAR_LITERAL L_STRING_LITERAL - -%type data_type len_declaration -%type struct_item array_struct_item simple_struct_item -%type simple_struct_item_start -%type struct_type_struct_item struct_array_struct_item -%type array_struct_item_start array_struct_item_base -%type struct_array_struct_item_base -%type simple_initialiser natural_expression -%type character_code_expression string_expression string_expression_item -%type simple_initialiser_list -%type natural_expression_numeric -%type rls_qualifiers rls_cardinality -%type rls_label -%type 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 << " " << 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 -void yyerror (const char *s, ...) -{ - va_list list; - va_start(list, s); - pScan->yyerror(const_cast(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 +#include +#include + +#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) +#include +#include +using namespace std; +using std::cout; +using std::endl; +#else //!__MSVCDOTNET__ +#include +#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 L_STRUCT L_RESOURCE L_NAME L_OFFSET L_SYSTEM L_GLOBAL L_LOCAL L_CHARACTER_SET +%token L_BUF L_WORD L_BYTE L_LONG L_DOUBLE L_TEXT L_LTEXT L_LINK L_LLINK L_SRLINK +%token L_BUF8 L_TEXT8 L_LTEXT8 L_BUF16 L_TEXT16 L_LTEXT16 L_UID_TWO L_UID_THREE +%token L_RLS_STRING L_RLS_STRING8 L_RLS_DOUBLE +%token L_RLS_BYTE L_RLS_WORD L_RLS_LONG +%token L_MULTI +%token L_TAG_START L_TAG_END +%token L_TAG_COMMAND L_TAG_WORD L_TAG_NEW_LINE +%token L_LABEL L_NUM_NATURAL L_NUM_FLOAT L_NATURAL_EXPR L_ENUM +%token L_LEN +%token L_CHAR_LITERAL L_STRING_LITERAL + +%type data_type len_declaration +%type struct_item array_struct_item simple_struct_item +%type simple_struct_item_start +%type struct_type_struct_item struct_array_struct_item +%type array_struct_item_start array_struct_item_base +%type struct_array_struct_item_base +%type simple_initialiser natural_expression +%type character_code_expression string_expression string_expression_item +%type simple_initialiser_list +%type natural_expression_numeric +%type rls_qualifiers rls_cardinality +%type rls_label +%type 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 << " " << 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 +void yyerror (const char *s, ...) +{ + va_list list; + va_start(list, s); + pScan->yyerror(const_cast(s), list); + va_end(list); +} + +