# Resource file format — `.rss`

## Contents

- Overview
- Resource file definition

- Lexical conventions
- C++ pre-processor statements
- Resource file statements
- Generated resource ids
- STRUCT statement
- RESOURCE statement
- Initialising resource members
- NAME statement
- CHARACTER_SET statement
- ENUM statement

- Compiled resource file format — `.rsc`

## Overview

This section details the source text resource file format, and is a useful reference for developers in C++ and OPL.

Topics covered include; the lexical conventions obeyed, the C++ pre-processor statements supported, and a description of the native resource compiler statements.

## Resource file definition

Section Contents

- Lexical conventions
- C++ pre-processor statements

- Conditional compilation in resource files
- Include files within a source file

- Resource file statements
- Generated resource ids
- STRUCT statement

- Struct names
- Defining struct members
- Arrays within structs

- RESOURCE statement
- Initialising resource members

- Simple member initialisation
- Resource identifiers for LINKs and LLINKs
- Initialising array items
- Initialising `STRUCT` items

- NAME statement
- CHARACTER_SET statement
- ENUM statement

### Lexical conventions

- Whitespace, except when enclosed in quotes for strings, is ignored by the compiler.
- Both C-style (`/* */`) and C++-style (`//`) comments are supported.
- Strings must be enclosed with double-quotes.
- To include a double-quote within a string, enter a double-quote preceded by a backslash. The following resource generates the output string `"text"` : i.e., the binary sequence: `0x22 0x74 0x65 0x78 0x74 0x22`.

`RESOURCE SIMPLE quote_example
{
string="\"text\"";
}`

where string is of type `BUF`.

- To include a backslash within a string, enter two backslash characters. The following resource generates the output string `\text\` : i.e., the binary sequence: `0x5c 0x74 0x65 0x78 0x74 0x5c`.

`RESOURCE SIMPLE backslash_example
{
string="\\text\\";
}`

### C++ pre-processor statements

The following pre-processor statements are supported by the resource compiler:

- `#define`
- `#undef`
- `#line`
- `#include`
- `#ifdef`
- `#ifndef`
- `#if`
- `#else`
- `#endif`

#### Conditional compilation in resource files

The resource compiler supports conditional compilation such as

        #ifdef SOMETHING

        // do something

        #else

        // do something else

        #endif

or

        #ifndef WHATEVER

        // do something

        #endif

#### Include files within a source file

You can include files within the source file by using a `#include` directive, for example:

        #include <eikdef.rh>

or

        #include "eikdef.hrh"

The searching algorithm used by the resource compiler depends on whether the item to be included is enclosed in double-quotes or angled brackets.

If the filename is enclosed in double-quotes, the resource compiler searches for that file through the following directories in the given order:

- the current directory
- the relative directory `..\inc`
- the absolute directory `\epoc32\include`

If the filename is enclosed in angled brackets, the resource compiler searches for that file through the following directories in the given order:

- the relative directory `..\inc`
- the absolute directory `\epoc32\include`

### Resource file statements

  source-file :
  statement-list

A source file consists of any number of statements.

  statement :
  struct-statement
  | resource-statement
  | character_set-statement
  | name-statement
  | offset-statement
  | system-statement
  | enum-statement

The most usual forms of statement are a struct-statement and a resource-statement. The struct statement defines a type of resource, see STRUCT statement. The resource statement defines an actual resource instance of the type defined in a struct, gives it a resource id, see Generated resource ids, and causes it to be generated in the resource file, see RESOURCE statement.

### Generated resource ids

By default, the resource ids in the generated header file are allocated from `1` in ascending sequence. The sequence can be made to begin from another value using the `NAME` statement, see NAME statement.

### STRUCT statement

  struct-statement :
  `STRUCT` struct-name [ `BYTE` | `WORD` ] `{` struct-member-list `}`

A `STRUCT` statement defines the format of a struct; all resources are defined in terms of structs. The struct has a name designated by struct-name, and some items designated by struct-member-list.

The length of most structs is variable. A resource’s entire length can be deduced from the position of the next resource; this information is available in a resource file’s index. If the struct is embedded within a resource, however, its length must be identified another way.

- Use `BYTE` to prefix the struct with a single byte indicating its length (zero to 255 bytes).
- Use `WORD` to prefix the struct with a word indicating its length (zero to 65,535 bytes).

The following are valid `STRUCT` statements:

        STRUCT STRING
              {
              TEXT str;
              }

        STRUCT TEST BYTE
              {
              WORD status;
              STRUCT text;
              }

The first example defines a struct called `STRING` which contains a single `TEXT` item.

The second example defines a struct called `TEST` which contains a `WORD` and an embedded struct. The total length of `TEST` is unknown, but should not exceed 255 bytes: the `BYTE` directive in the definition indicates that, when this struct is embedded within another, it should be preceded with a byte indicating its length (zero to 255 bytes).

The struct-member-list is a sequence of struct-members where each member is terminated by a semi-colon. The complete list is enclosed within a pair of braces as demonstrated by the struct called `TEST`.

#### Struct names

The following rules must be observed for struct-names:

- they must be given in upper case
- they must begin with an alphabetic character, although subsequent characters may be numeric
- they may not begin with any of the following resource compiler keywords — the 12 struct type-names, see Defining struct members, and the keywords: `GLOBAL`, `STRUCT`, `LEN` or `RESOURCE`. This restriction applies only to the struct-name, not the member-name of any individual struct members.

So the following struct definition will generate an error

        STRUCT BUFTHING
              {
              BUF buffer;
              }

whereas this struct definition will compile correctly

        STRUCT ABUFTHING
              {
              BUF buffer;
              }

#### Defining struct members

  struct-member :
  member-declaration [ `=` initialiser ] `;`

  member-declaration :
  type-name member-name
  | [ `LEN` [ `BYTE` ] ] type-name member-name
  [ `(` length-limit `)` ]
  [ `[` [array-size] `]` ]

  type-name :
  `BYTE`
  | `WORD``
  `|`` `LONG`
  | `DOUBLE``
  `| `TEXT``
  `|`` `LTEXT``
  `|`` `BUF
  `| `BUF<n>`
  | `LINK`
  | `LLINK``
  `|`` `SRLINK`
  | `STRUCT`

- Each member of a struct is identified by a declaration followed by an optional initialiser, and then a semi-colon.
- The simplest form of declaration is to specify a type-name and a member-name only:

        STRUCT TEST
              {
              WORD length;
              }

- The type-name must be in upper case (`WORD` in this example).
- The member-name must be in lower case (`length` in this example).
- An `SRLINK` member may not have an initialiser since it is self-referencing and, therefore, only takes the value of the resource id the struct is declared in. This is assigned automatically by the resource compiler.

There are twelve valid types:

`BYTE` | A single byte. Can be treated as a signed integer (–128 to +127) or unsigned integer (0 to 255).
`WORD` | Two bytes. Can be treated as a signed integer (–32,768 to +32,767) or unsigned integer (0 to 65,535).
`LONG` | Four bytes. Can be treated as a signed integer (–2,147,483,648 to 2147483647) or an unsigned integer (0 to 4,294,967,295).
`DOUBLE` | Eight byte real for double precision floating point numbers (approximately 1.7E308).
`TEXT` | An ASCII string, terminated by a null.
`LTEXT` | An ASCII string with a leading byte count, and no terminating null.
`BUF` | An ASCII string with no terminating null and no leading byte count.
`BUF<n>` | An ASCII string with no terminating null and no leading byte count but which has a maximum length `n`. This type is an alternative to using the length-limit with `BUF` types,
`LINK` | The id of another resource (16 bits), rather like a pointer to that resource.
`LLINK` | The id of another resource (32 bits).
`SRLINK` | A self-referencing link. This is a 32 bit link which contains the resource id of the resource it is defined in.
`STRUCT` | Any struct, rather like including that struct as a member in this struct. `STRUCT` members are useful because it means that once a struct has been defined it can be re-used for a variety of resources.

- Numbers more than one byte long are stored little-endian: that is, their least significant byte is stored first.
- `LINK` and `STRUCT` are not type-safe: it is the responsibility of the user of a struct to ensure that the correct resource type is linked or included. The definer of a struct should give some idea, perhaps using a comment:

        STRUCT TEST
              {
              WORD length;
              STRUCT text; // should be a STRING
              }

- a length-limit may be specified for members of string type (`BUF`, `TEXT` and `LTEXT`): the length-limit is enclosed in parentheses after the member name. In the following example

        STRUCT TEST
              {
              TEXT string1(9);
              LTEXT string2(MAX);
              BUF string3;
              }

`string1` has a maximum of 9 characters, `string2` a maximum of `MAX` characters (where `MAX` has been `#defined` elsewhere) and `string3` has no maximum length. Note that this maximum applies only to the actual characters and does not take account of the terminating zero (for `TEXT` members) or leading byte count (for `LTEXT` members).

- An alternative method to using length-limit with a `BUF` type is to use the type `BUF<n>`. For example, given the definition of `TEST` and the resource definitions for `test1`, `test2` and `test3`:

        STRUCT TEST
              {
              BUF<4> string;
              }

        RESOURCE TEST test1
              {
              string="abcd";
              }

        RESOURCE TEST test2
              {
              string="ab";
              }

        RESOURCE TEST test3
              {
              string="abcdef";
              }

`test1` generates `0x61 0x62 0x63 0x64`

`test2` generates `0x61 0x62`

but `test3` generates an error because the maximum length of `string` permitted by the definition of the `STRUCT` is 4.

#### Arrays within structs

Recall the member-declaration syntax; look at a specific subset of this (see Defining struct members for the full syntax of a struct member:

  member-declaration :
  type-name member-name
  | [ `LEN` [ `BYTE` ] ] type-name member-name `[` [array-size] `]`

A declaration of a struct member may either be a simple type-name member-name, or it may be an array of values of identical type.

Arrays are always indicated by square brackets:

        STRUCT HAS_ARRAY
              {
              STRUCT elements[];
              }

In the example above, the `HAS_ARRAY` struct has one array member, `elements`. Each member of `elements` is of `STRUCT` type.

If you specify the array size, inside the square brackets, then the generated resource will contain no count of the number of elements. So this resource:

        STRUCT FIXED_ARRAY
              {
              WORD elements[3];
              }

        RESOURCE FIXED_ARRAY example1
              {
              elements={9,8,7};
              }

will generate the output

        0x09 0x00 0x08 0x00 0x07 0x00

For variable length arrays a count of the number of elements precedes the resource. The default for this is a word, but by prefixing the struct definition with `LEN` `BYTE` it will be a byte count. So the following resource:

        STRUCT VAR_ARRAY
              {
              WORD elements [];
              }

        RESOURCE VAR_ARRAY example2
              {
              elements={9,8,7};
              }

will generate the output

        0x03 0x00 0x09 0x00 0x08 0x00 0x07 0x00

whereas this resource:

        STRUCT VAR_ARRAY2
              {
              LEN BYTE WORD elements[];
              }

        RESOURCE VAR_ARRAY2 example3
              {
              elements={9,8,7};
              }

will generate this output

        0x03 0x09 0x00 0x08 0x00 0x07 0x00

The compiler allows you to prefix `LEN` `BYTE` or `LEN` `WORD` even for fixed length arrays but it has no effect. Fixed length arrays do not generate an element count.

See also the section on initialising array items in Initialising resource members.

### RESOURCE statement

  resource-statement :
  `RESOURCE` struct-name [resource-name] `{` resource-initialiser-list `}`

The `RESOURCE` statement is used to generate a resource in the resource file. The statement specifies three things:

- a struct-name which denotes the structure that will be used for the resource

It must have been defined in a previous `STRUCT` statement and must be in upper case.

- an optional resource-name which identifies the resource

The resource-name must be in lower case.

The resource-name causes a symbolic constant to be generated in the resource compiler’s output header file, so that a resource

        RESOURCE TEST my_test { /* etc */ }

will result in a definition of the form

        #define MY_TEST 1

in the generated header file — see the `.rsg` file referred to in Command line syntax.

The default id for the first resource defined in the file is one with subsequent resources’ ids generated in ascending sequence. See Generated resource ids for more information on how resource ids are generated.

If no resource name is specified then the resource is generated in the object file and assigned a resource id as usual, but will not be published in the header file. Anonymous resources are used mainly for playback scripts where the resources are read in sequentially by default, so that assigning names to them would be superfluous.

The resource-name may also be used by the resource compiler for `LINK` and `LLINK` members — see Resource identifiers for LINKs and LLINKs.

- initialisation for members of the resource struct, where their default values are not appropriate

As an example, given the struct definition

        STRUCT NCEDIT
              {
              WORD current;
              WORD low;
              WORD high=65535;
              }

you could define a resource:

        RESOURCE NCEDIT MEMORY_SIZE
              {
              low=640;
              high=1024;
              }

Thus, in the resource file, `current` has the value compiler default value of 0, `low` has the value 640 (specified in the resource definition) and `high` has the value 1024 (specified in the resource definition, overriding the default for the struct type).

### Initialising resource members

The resource initialiser has different forms depending on whether a single, simple, member is being initialised, or whether a struct or an array is being initialised:

  resource-initialiser : member-name [ `(` length-limit `)` ] `=` initialiser

  initialiser :
  simple-initialiser
  | struct-initialiser
  | array-initialiser

Resource members may be initialised by default (in the struct definition) or explicitly initialised (in the resource definition).

In general,

- If a member is initialised in a `RESOURCE` statement, that is its value.
- If it is initialised in a `STRUCT` statement, that is its value for all resources which do not explicitly initialise it.
- If it is neither initialised in a `RESOURCE` statement nor a `STRUCT` statement, then: `BYTE`, `WORD` and `DOUBLE` members contain zero; `TEXT`, `LTEXT` and `BUF` members contain an empty string.
- It is an error for `LINK` and `LLINK` members to have no explicit value, so they must be initialised, either by default (in the `STRUCT` statement) or explicitly (in the `RESOURCE` statement).
- `SRLINK` members may not be initialised (either in the `STRUCT` statement or a `RESOURCE` statement) since they are automatically assigned the resource id of the resource in which they appear.
- Members which are themselves `STRUCT`s may not be default initialised. They can only be initialised in the `RESOURCE` definition. If they are not explicitly initialised they will take up zero bytes in the resource file. For example, given the following `STRUCT` definition:

`STRUCT TEST2
{
WORD value;
STRUCT tester;
}`

The following `RESOURCE` statement only generates the two bytes `0xFF 0x00`.

`RESOURCE TEST2 item
{
value=255;
}`

Default values can be specified for struct members by using an initialiser, for example

        STRUCT NCEDIT
              {
              WORD current;
              WORD low;
              WORD high=65535;
              }

With this specification, any `NCEDIT` resource will, by default, have a `high` member whose value is 65,535. If the `RESOURCE` statement specifies a different value, it will be used instead.

#### Simple member initialisation

  simple-initialiser :
  number
  | string
  | resource-identifier

- A `BYTE`, `WORD`, `LONG` or `DOUBLE` member must be initialised with a number. The number can be the result of simple expressions such as `3+1` or `NUM1+NUM2` where `NUM1` and `NUM2` have been `#defined` earlier on in the file.
- A `TEXT`, `LTEXT` or `BUF` member must be initialised with a string. If a length-limit has been declared for that member in the `STRUCT` definition then an error will be generated if the string is longer than the limit. You can, however, override any maximum length declared in the struct definition by specifying a new maximum length after the member name in the resource definition. For instance the following resource

        RESOURCE THING
              {
              string(20)="Very long string";
              }

will compile correctly even if the struct definition specified a maximum length of 10 for `string`.

#### Resource identifiers for LINKs and LLINKs

A `LINK` or `LLINK` member must be initialised with a resource-identifier. This resource identifier may be in the form of a resource name or a number.

- If it is a resource name and it is declared in lower case, it refers to a resource in the file.

It is not necessary for the resource to be defined at the time the statement is processed, but an error will result if the resource is not defined in the entire file. When declared in lower case any `NAME` specified in the file will be added onto the resource id.

- If the resource name is declared in upper case, it refers to a resource defined in another file.

To reference it you must `#include` the relevant header file containing the resource. All resource names are turned into upper case when their `#define`s are generated in the header file — this is how the resource compiler recognises that it must look for the resource in another file. If this resource does not exist in any `#include`d file then an error is generated.

- The resource identifier may also be specified as a number: in this case it is the resource id (including `NAME`).

If no such resource id exists either in the file or any `#include`d header files, no error is generated by the compiler. The programmer must therefore ensure that the id is a valid reference.

See Generated resource ids for information on how resource ids are generated. See also NAME statement and related statements.

#### Initialising array items

  array-initialiser :
  `{` array-initialiser-item-comma-list `}`

  array-initialiser-item :
  initialiser

To initialise a member of array type, give the items in the array in sequence. Each initialiser must be of a type compatible with the member being initialised.

##### Fixed-length arrays

If the member was declared as a fixed-length array (e.g., `WORD elements[10]`), then it is an error to specify any more items than were given in the length (either in the `STRUCT` or the `RESOURCE` definition). If fewer items are specified in the default initialisation (i.e. in the `STRUCT` definition) then an error also results. Note that if fewer elements are specified when initialising the array in the `RESOURCE` statement, then any elements not specified after the specified values will be lost, even if they have been default initialised in the `STRUCT` definition. Take the following example:

        STRUCT SAMPLE
              {
              BYTE bts[3]={1,2,3};
              }

In the following resource:

        RESOURCE SAMPLE default
              {}

the output will be the whole default array

        0x01 0x02 0x03

but in this resource:

        RESOURCE SAMPLE first_specified
              {
              bts={5};
              }

the output is:

        0x05

with the second and third elements lost. If you specify only the second element in the `RESOURCE` definition then the first element is taken from the default initialisation, the second from the explicit initialisation and the third element is lost. The following resource:

        RESOURCE SAMPLE  second_specified
              {
              bts[1]=5;
              }

results in the 2-byte output:

        0x01 0x05

If, however, you explicitly initialise an element in the middle of an array without having supplied default values for array members before it, then an error will result.

##### Variable length arrays

If the array was not declared fixed-length then the number of elements is worked out from the initialiser and prepended to the resource. The default for this element count is a word: you may specify it as a byte by declaring `LEN` `BYTE` in front of the array declaration in the `STRUCT` definition; e.g.

        STRUCT VAR_ARRAY
              {
              LEN BYTE WORD [];
              }

##### Using expressions to initialise array elements

You may initialise array elements with expressions. You must explicitly initialise each member component of the array otherwise the expressions will be evaluated incorrectly. The following resource:

        RESOURCE SAMPLE correct_expression
              {
              bts[0]=3+1;
              bts[1]=2;
              bts[2]=3;
              }

will generate the correct output `0x0`4 `0x02 0x03`. However, if you use the following syntax:

        RESOURCE SAMPLE incorrect_expression
              {
              bts={3+1,2,3};
              }

the output will be `0x03 0x02 0x03.` This is because the pre-processor treats ‘`3+1’` as a literal string which is then interpreted by the compiler as 3. In the resource `correct_expression` above the ‘=‘ sign forces the pre-processor to evaluate the expression.

#### Initialising `STRUCT` items

  struct-initialiser :
  struct-name `{` struct-initialiser-item-list `}`

  struct-initialiser-item :
  member-name `=` initialiser `;`

`STRUCT` members may only be initialised in the resource definition.

To initialise a member of `STRUCT` type, give the struct-name with which you wish to initialise it, and then specify each member of that struct which you wish to initialise.

The member-names listed must be members of the struct-name struct. Each initialise must be of a type compatible with the member it is initialising.

The compiler does not enforce type safety. Any struct can be used to initialise a member declared to be of struct type. Usually, however, the designer of the struct will have intended only one or a limited number of structs ever be used to initialise a member. You should ensure that you initialise struct members with the intended struct type.

Given the previously defined struct types

        STRUCT STRINGCOUNT
              {
              BUF message;
              WORD num;
              }

        STRUCT SAMPLE
              {
              WORD anynumber;
              STRUCT text;      // should be a STRINGCOUNT
              }

the following example shows how to define the struct within a resource:

        RESOURCE SAMPLE show_how
              {
              anynumber=10;
              text=STRINGCOUNT
                    {
                    message="Hello"
                    num=5;
                    };
              }

Note the trailing semicolon after the closing `}` of the `text` struct member initialisation: this is because a semicolon follows all member initialisations. For longer, more complicated resources deciding where semicolons must be placed may become confusing. As shown in the following example, array lists are separated by commas and terminated without a semi-colon. Similarly, resources are not terminated by a semi-colon.

        RESOURCE DIALOG example_dialog
              {
              title="Example";
         topsection=DLAY_SECTION
                    {
                    control_list=
                          {
                     ACLIST
                           {
                           butlist_flags=BUTLIST_HORIZONTAL;
         rid=R_HCIL_BUTTONS_OK_CANCEL;
                           },                        // array member so comma needed
                          ACLIST
                           {
                           butlist_flags=BUTLIST_HORIZONTAL;
         rid=R_HCIL_BUTTONS_OK_CANCEL;
                           }      // last item in array so nothing needed
                          };      // end of struct member control_list so ‘;’ needed
                    };            // end of struct member topsection so ‘;’ needed
              }                  // end of resource so nothing needed

The rules to remember are as follows:

type of entity | Punctuation needed after closing ‘}’
resource | nothing
array member (not last one) | ,
last array member | nothing
struct member | ;

See the definitions of resource-statement, struct-statement, struct-member and array-initialiser for a complete explanation of the syntax.

### NAME statement

  name-statement:
  `NAME` short-name

Use this statement to ensure that the resources in the file have a unique id so that an application can use multiple resource files without resource id conflict.

This statement must the first non-comment statement in the file.

The short-name must be between one and four alphabetic characters long and be unique (no other file may use the same one). For the sake of consistency this constant should be in upper case although lower case is allowed (and will be converted to upper case by the compiler). This short-name is then converted into a number and shifted onto the leading 20 bits of the resource id, leaving the bottom 12 bits for the number of the resource in the file. This allows a maximum of 4095 resources to be defined in a source file.

So with `NAME` set to `AAAA`, if this resource is the first resource in the file

        RESOURCE STRING one
              {
              wd=5;
              }

the first entry in the generated header file will be

        #define ONE 0x04FD8001

04FD8 is the leading 20 bits for all ids in the file and 001 is the reference of that resource within the file.

Since the `NAME` statement maps all resource ids within the file onto 32-bit numbers, only `LLINK`s may be used for resource references in that file. Using the `NAME` statement in a resource file means that any attempt to use a `LINK` will generate an error.

### CHARACTER_SET statement

  character_set-statement :
  `CHARACTER_SET` character_set-name

Use a `CHARACTER_SET` statement to define the character set to be used. The permitted values for character_set-name are defined as:

  character_set-name :
  `ASCII`
  | `CP1252``
  `|`` `CP850`
  | `ISOLatin1``
  `| `ShiftJIS`

If the `CHARACTER_SET` statement is omitted from a resource file, character set CP1252 is taken as default.

### ENUM statement

  enum-statement :
  `enum` [ enum-label ] `{` enum-list `}` `;`
  | `ENUM` [ enum-label ] `{` enum-list `}` `;`

Use an `enum` (or an `ENUM`) statement to define a set of integer values. The values are associated with symbols defined in the enum-list; the syntax and the semantics are compatible with those of C++ enumerations.

Each member of the enum-list is followed by a comma except for the last one. The syntax of a member is defined as:

  enum-member :
  member-name [ =initialiser ]

The defined enumerator symbols can be used in both C++ code and resource scripts and are commonly defined in files which have the conventional file extension `hrh`. The `.hrh` files are included in both C++ files and resource source files.

For example, the `enum` definition:

        enum
              {
              EExampleCmdIdFirst=0x100,
              EExampleCmdIdSecond,
              EExampleCmdIdThird,
              EExampleCmdIdFourth
              };

defines the enumerators `EExampleCmdIdFirst`, `EExampleCmdIdSecond` etc. and assigns values to them.

In general, each enumerator can be assigned a specific value. If no value is explicitly assigned, the value generated by the resource compiler is the value of the previous enumerator plus one. Thus, in the above example, `EExampleCmdIdFirst` is assigned the value `0x100` (decimal 256), `EExampleCmdIdSecond` is assigned the value `0x101` (decimal 257) etc.

If the first enumerator is not assigned an explicit value, it defaults to 0.

More than one enumerator may be assigned an explicit value.

The assigned value can be coded in either hexadecimal or plain decimal notation.

        enum      {
              testvalue1=10,
              testvalue2,
              testvalue3=20,
              testvalue4
              };

        STRUCT TEST1
              {
              BYTE b1;
              BYTE b2;
              BYTE b3;
              BYTE b4;
              }

        RESOURCE TEST1 test
              {
              b1=testvalue1;
              b2=testvalue2;
              b3=testvalue3;
              b4=testvalue4;
              }

In this example the resource generated is: `0x0A 0x0B 0x14 0x15`

Note that the final semi-colon in an `enum` may be omitted; however, to retain compatibility with the C++ compiler, it is advisable to retain it.

## Compiled resource file format — `.rsc`

All resource files have the following format:

header | resources | index table

where:

header | is always four bytes long. It consists of two 16-bit numbers: the first gives the file offset of the start of the index table, the second gives the length in bytes of the index table
resources | are a series of variable-length data items generated in the order specified in the source file
index table | is a sequence of 16-bit numbers, the first giving the file offset of the start of the first resource, the second giving the file offset of the start of the second resource and so on up to the last resource in the file. The last 16-bit number gives the file offset of the end of the last resource (i.e. the beginning of the index table)

So for example the following source file:

        STRUCT SIMPLE
              {
              WORD wd;
              LONG lg;
              BUF name;
              }

        RESOURCE SIMPLE one
              {
              wd=5;
              lg=10000;
              name="Simon";
              }

        RESOURCE SIMPLE two
              {
              name="John";
              }

when compiled, will produce the following output resource file:

        0: 19 00 06 00 05 00 10 27 00 00 53 69 6d 6f 6e 00 .......’ ..Simon.

        10: 00 00 00 00 00 4a 6f 68  6e 04 00 0f 00 19 00    .....Joh n......