--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/rcomp/src/RCOMP.YACC Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,1295 @@
+%{
+// 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);
+}
+
+