From 3cd314ca3bbf0852a6bb2f1708e015ce32ed4c91 Mon Sep 17 00:00:00 2001 From: Jonas Volman Date: Tue, 14 Jul 2026 19:03:06 -0700 Subject: [PATCH] Align typed accessors with HCEX conventions --- config/config.json | 2 + source/bitmaps/bitmap_group.h | 7 ++ source/cache/predicted_resources.c | 8 +- source/devices/device_light_fixtures.c | 93 +++++++------------ source/devices/device_light_fixtures.h | 74 +++++++++++++++ source/items/equipment.c | 10 +- source/items/equipment.h | 5 + source/items/garbage.c | 4 +- source/items/garbage.h | 4 + source/networking/network_game_ui.c | 7 +- source/objects/scenery.c | 37 +++----- source/objects/scenery.h | 15 +++ .../multiplayer_scenario_description.c | 29 +----- .../multiplayer_scenario_description.h | 56 +++++++++++ source/sound/sound_definitions.h | 2 + source/sound/sound_scenery.c | 7 +- source/sound/sound_scenery.h | 6 ++ source/text/text_group.c | 4 +- source/text/text_group.h | 9 ++ 19 files changed, 253 insertions(+), 126 deletions(-) create mode 100644 source/devices/device_light_fixtures.h create mode 100644 source/scenario/multiplayer_scenario_description.h diff --git a/config/config.json b/config/config.json index 614e6eb2..1abc6277 100644 --- a/config/config.json +++ b/config/config.json @@ -130,6 +130,7 @@ "source/cutscene/recorded_animation_playback_v1.h", "source/cutscene/recorded_animations.h", "source/devices/device_definitions.h", + "source/devices/device_light_fixtures.h", "source/devices/devices.h", "source/dialogs/dialogs.h", "source/dialogs/edit_text.h", @@ -320,6 +321,7 @@ "source/saved games/playlist_profile.h", "source/saved games/saved_game_files.h", "source/scenario/fog_definitions.h", + "source/scenario/multiplayer_scenario_description.h", "source/scenario/scenario.h", "source/scenario/scenario_definitions.h", "source/scenario/scenario_placement.h", diff --git a/source/bitmaps/bitmap_group.h b/source/bitmaps/bitmap_group.h index a3b7b436..578e2d3b 100644 --- a/source/bitmaps/bitmap_group.h +++ b/source/bitmaps/bitmap_group.h @@ -15,8 +15,15 @@ header included in hcex build. /* ---------- constants */ +enum +{ + BITMAP_GROUP_TAG = 'bitm', +}; + /* ---------- macros */ +#define bitmap_group_get(index) ((struct bitmap_group *)tag_get(BITMAP_GROUP_TAG, (index))) + /* ---------- structures */ struct bitmap_data diff --git a/source/cache/predicted_resources.c b/source/cache/predicted_resources.c index db5fe961..c3918783 100644 --- a/source/cache/predicted_resources.c +++ b/source/cache/predicted_resources.c @@ -61,7 +61,7 @@ void predicted_resources_precache( case _predicted_resource_bitmap: _texture_cache_bitmap_get_hardware_format( TAG_BLOCK_GET_ELEMENT( - &((struct bitmap_group *)tag_get('bitm', predicted_resource->tag_index))->bitmap_data, + &bitmap_group_get(predicted_resource->tag_index)->bitmap_data, predicted_resource->resource_index, struct bitmap_data), FALSE, @@ -73,6 +73,8 @@ void predicted_resources_precache( break; } } + + return; } /* ---------- private code */ @@ -84,7 +86,7 @@ static void code_001ad870( struct tag_block *pitch_ranges; short pitch_range_index; - sound_definition = (struct sound_definition *)tag_get(SOUND_DEFINITION_TAG, sound_definition_index); + sound_definition = sound_definition_get(sound_definition_index); pitch_range_index = 0; if (sound_definition->pitch_ranges.count <= 0) return; @@ -110,4 +112,6 @@ pitch_range_loop: } if (pitch_range_index < pitch_ranges->count) goto pitch_range_loop; + + return; } diff --git a/source/devices/device_light_fixtures.c b/source/devices/device_light_fixtures.c index 9e01952b..3c71afe1 100644 --- a/source/devices/device_light_fixtures.c +++ b/source/devices/device_light_fixtures.c @@ -23,6 +23,7 @@ symbols in this file: /* ---------- headers */ #include "cseries.h" +#include "devices/device_light_fixtures.h" #include "devices/devices.h" #include "objects/object_types.h" #include "scenario/scenario_definitions.h" @@ -30,107 +31,81 @@ symbols in this file: /* ---------- constants */ -enum -{ - LIGHT_FIXTURE_DEFINITION_TAG = 'lifi', -}; - /* ---------- macros */ /* ---------- structures */ -struct scenario_device_datum -{ - short power_group_index; - short position_group_index; - unsigned long flags; -}; - -struct scenario_light_fixture_datum -{ - struct scenario_object_datum object; - struct scenario_device_datum device; - real_rgb_color color; - real intensity; - real falloff_angle; - real cutoff_angle; -}; - -struct _light_fixture_datum -{ - real_rgb_color color; - real intensity; - real falloff_angle; - real cutoff_angle; -}; - -struct light_fixture_datum -{ - long definition_index; - struct _object_datum object; - struct _device_datum device; - struct _light_fixture_datum light_fixture; -}; - /* ---------- prototypes */ -void device_add_scenario_information(long object_index, struct scenario_device_datum *scenario_device); +void device_add_scenario_information( + long object_index, + struct scenario_device_datum *scenario_device); /* ---------- globals */ /* ---------- public code */ -void -light_fixtures_initialize(void) +void light_fixtures_initialize( + void) { + return; } -void -light_fixtures_dispose(void) +void light_fixtures_dispose( + void) { + return; } -void -light_fixtures_initialize_for_new_map(void) +void light_fixtures_initialize_for_new_map( + void) { + return; } -void -light_fixtures_dispose_from_old_map(void) +void light_fixtures_dispose_from_old_map( + void) { + return; } -void -light_fixture_place(long object_index, struct scenario_light_fixture_datum *scenario_light_fixture) +void light_fixture_place( + long object_index, + struct scenario_light_fixture_datum *scenario_light_fixture) { - struct light_fixture_datum *light_fixture = object_get_and_verify_type(object_index, _object_mask_light_fixture); + struct light_fixture_datum *light_fixture = light_fixture_get(object_index); - tag_get(LIGHT_FIXTURE_DEFINITION_TAG, light_fixture->definition_index); + light_fixture_definition_get(light_fixture->definition_index); device_add_scenario_information(object_index, &scenario_light_fixture->device); light_fixture->light_fixture.color = scenario_light_fixture->color; light_fixture->light_fixture.intensity = scenario_light_fixture->intensity; light_fixture->light_fixture.falloff_angle = scenario_light_fixture->falloff_angle; light_fixture->light_fixture.cutoff_angle = scenario_light_fixture->cutoff_angle; + + return; } -boolean light_fixture_new(long object_index) +boolean light_fixture_new( + long object_index) { - struct light_fixture_datum *light_fixture = object_get_and_verify_type(object_index, _object_mask_light_fixture); + struct light_fixture_datum *light_fixture = light_fixture_get(object_index); - tag_get(LIGHT_FIXTURE_DEFINITION_TAG, light_fixture->definition_index); + light_fixture_definition_get(light_fixture->definition_index); return TRUE; } -void -light_fixture_delete(long object_index) +void light_fixture_delete( + long object_index) { + return; } -boolean light_fixture_update(long object_index) +boolean light_fixture_update( + long object_index) { - struct light_fixture_datum *light_fixture = object_get_and_verify_type(object_index, _object_mask_light_fixture); + struct light_fixture_datum *light_fixture = light_fixture_get(object_index); - tag_get(LIGHT_FIXTURE_DEFINITION_TAG, light_fixture->definition_index); + light_fixture_definition_get(light_fixture->definition_index); return TRUE; } diff --git a/source/devices/device_light_fixtures.h b/source/devices/device_light_fixtures.h new file mode 100644 index 00000000..fb217372 --- /dev/null +++ b/source/devices/device_light_fixtures.h @@ -0,0 +1,74 @@ +/* +DEVICE_LIGHT_FIXTURES.H + +header included in hcex build. +*/ + +#ifndef __DEVICE_LIGHT_FIXTURES_H +#define __DEVICE_LIGHT_FIXTURES_H +#pragma once + +/* ---------- headers */ + +#include "devices/devices.h" +#include "objects/object_types.h" +#include "scenario/scenario_definitions.h" +#include "tag_files/tag_groups.h" + +/* ---------- constants */ + +enum +{ + LIGHT_FIXTURE_DEFINITION_TAG = 'lifi', +}; + +/* ---------- macros */ + +#define light_fixture_definition_get(index) ((struct light_fixture_definition *)tag_get(LIGHT_FIXTURE_DEFINITION_TAG, (index))) +#define light_fixture_get(index) ((struct light_fixture_datum *)object_get_and_verify_type((index), _object_mask_light_fixture)) +#define light_fixture_try_and_get(index) ((struct light_fixture_datum *)object_try_and_get_and_verify_type((index), _object_mask_light_fixture)) + +/* ---------- structures */ + +struct light_fixture_definition; + +struct scenario_device_datum +{ + short power_group_index; + short position_group_index; + unsigned long flags; +}; + +struct scenario_light_fixture_datum +{ + struct scenario_object_datum object; + struct scenario_device_datum device; + real_rgb_color color; + real intensity; + real falloff_angle; + real cutoff_angle; +}; + +struct _light_fixture_datum +{ + real_rgb_color color; + real intensity; + real falloff_angle; + real cutoff_angle; +}; + +struct light_fixture_datum +{ + long definition_index; + struct _object_datum object; + struct _device_datum device; + struct _light_fixture_datum light_fixture; +}; + +/* ---------- prototypes/DEVICE_LIGHT_FIXTURES.C */ + +/* ---------- globals */ + +/* ---------- public code */ + +#endif // __DEVICE_LIGHT_FIXTURES_H diff --git a/source/items/equipment.c b/source/items/equipment.c index 37fda406..e19f0ecf 100644 --- a/source/items/equipment.c +++ b/source/items/equipment.c @@ -37,7 +37,7 @@ void equipment_place( long equipment_index, struct scenario_equipment_datum *scenario_equipment) { - struct item_datum *equipment = (struct item_datum *)object_get_and_verify_type(equipment_index, _object_mask_equipment); + struct item_datum *equipment = equipment_get(equipment_index); SET_FLAG( equipment->object.flags, @@ -51,16 +51,20 @@ void equipment_place( if (!TEST_FLAG(scenario_equipment->object.misc_flags, _scenario_equipment_levitate_bit)) equipment->object.position.z += 0.05f; + + return; } void equipment_handle_pickup( long equipment_index) { - struct item_datum *equipment = (struct item_datum *)object_get_and_verify_type(equipment_index, _object_mask_equipment); + struct item_datum *equipment = equipment_get(equipment_index); struct equipment_definition *equipment_definition = equipment_definition_get(equipment->definition_index); if (equipment_definition->equipment.pickup_sound.index != NONE) unspatialized_impulse_sound_new(equipment_definition->equipment.pickup_sound.index, 1.f); + + return; } void equipment_definition_handle_pickup( @@ -70,6 +74,8 @@ void equipment_definition_handle_pickup( if (equipment_definition->equipment.pickup_sound.index != NONE) unspatialized_impulse_sound_new(equipment_definition->equipment.pickup_sound.index, 1.f); + + return; } /* ---------- private code */ diff --git a/source/items/equipment.h b/source/items/equipment.h index 9ae4f5c7..a8c52df2 100644 --- a/source/items/equipment.h +++ b/source/items/equipment.h @@ -9,6 +9,8 @@ header included in hcex build. #pragma once #include "math/real_math.h" +#include "items/items.h" +#include "objects/object_types.h" #include "scenario/scenario_definitions.h" /* ---------- constants */ @@ -26,6 +28,9 @@ enum /* ---------- macros */ +#define equipment_get(index) ((struct item_datum *)object_get_and_verify_type((index), _object_mask_equipment)) +#define equipment_try_and_get(index) ((struct item_datum *)object_try_and_get_and_verify_type((index), _object_mask_equipment)) + /* ---------- structures */ struct scenario_equipment_datum diff --git a/source/items/garbage.c b/source/items/garbage.c index a35a6612..15817334 100644 --- a/source/items/garbage.c +++ b/source/items/garbage.c @@ -33,7 +33,7 @@ symbols in this file: boolean garbage_update( long garbage_index) { - struct garbage_datum *garbage = (struct garbage_datum *)object_get_and_verify_type(garbage_index, _object_mask_garbage); + struct garbage_datum *garbage = garbage_get(garbage_index); boolean active; --garbage->lifetime_ticks; @@ -48,7 +48,7 @@ boolean garbage_update( boolean garbage_new( long garbage_index) { - struct garbage_datum *garbage = (struct garbage_datum *)object_get_and_verify_type(garbage_index, _object_mask_garbage); + struct garbage_datum *garbage = garbage_get(garbage_index); object_set_garbage(garbage_index, TRUE); garbage->object.flags |= FLAG(_object_shadowless_bit) | FLAG(_object_deleted_when_deactivated_bit); diff --git a/source/items/garbage.h b/source/items/garbage.h index dc083518..baa2015e 100644 --- a/source/items/garbage.h +++ b/source/items/garbage.h @@ -9,11 +9,15 @@ header included in hcex build. #pragma once #include "items/items.h" +#include "objects/object_types.h" /* ---------- constants */ /* ---------- macros */ +#define garbage_get(index) ((struct garbage_datum *)object_get_and_verify_type((index), _object_mask_garbage)) +#define garbage_try_and_get(index) ((struct garbage_datum *)object_try_and_get_and_verify_type((index), _object_mask_garbage)) + /* ---------- structures */ struct garbage_datum diff --git a/source/networking/network_game_ui.c b/source/networking/network_game_ui.c index 706e29cd..87a9fc49 100644 --- a/source/networking/network_game_ui.c +++ b/source/networking/network_game_ui.c @@ -11,6 +11,7 @@ symbols in this file: #include "cseries.h" #include "math/real_math.h" #include "tag_files/tag_groups.h" +#include "text/text_group.h" /* ---------- constants */ @@ -20,8 +21,6 @@ symbols in this file: /* ---------- prototypes */ -wchar_t const *unicode_string_list_get_string(long tag_index, short string_index); - /* ---------- globals */ /* ---------- public code */ @@ -34,14 +33,14 @@ wchar_t const *network_game_get_random_player_name( if (string_list_index != NONE) { - struct tag_block *string_list = tag_get('ustr', string_list_index); + struct string_list *string_list = unicode_string_list_definition_get(string_list_index); if (string_list) { short string_index = seed_random_range( get_global_local_random_seed_address(), 0, - string_list->count - 1); + string_list->strings.count - 1); player_name = unicode_string_list_get_string(string_list_index, string_index); } } diff --git a/source/objects/scenery.c b/source/objects/scenery.c index 1765c19c..91b199d2 100644 --- a/source/objects/scenery.c +++ b/source/objects/scenery.c @@ -45,15 +45,6 @@ symbols in this file: /* ---------- structures */ -struct scenery_datum -{ - struct object_datum object; - unsigned long flags; -}; - -typedef char verify_scenery_extension_offset[ - sizeof(struct object_datum) == 0x1A4 ? 1 : -1]; - /* ---------- prototypes */ short animation_update_internal( @@ -66,43 +57,41 @@ short animation_update_internal( /* ---------- public code */ -void -scenery_initialize( +void scenery_initialize( void) { + return; } -void -scenery_initialize_for_new_map( +void scenery_initialize_for_new_map( void) { + return; } -void -scenery_dispose_from_old_map( +void scenery_dispose_from_old_map( void) { + return; } -void -scenery_dispose( +void scenery_dispose( void) { + return; } -void -scenery_delete( +void scenery_delete( long object_index) { + return; } boolean scenery_update( long object_index) { long animation_graph_index; - struct scenery_datum *scenery = (struct scenery_datum *)object_get_and_verify_type( - object_index, - FLAG(_object_type_scenery)); + struct scenery_datum *scenery = scenery_get(object_index); if (TEST_FLAG(scenery->flags, 0)) { @@ -127,9 +116,7 @@ short scenery_get_animation_time( { struct animation *animation; struct animation_graph *animation_graph; - struct scenery_datum *scenery = (struct scenery_datum *)object_get_and_verify_type( - object_index, - FLAG(_object_type_scenery)); + struct scenery_datum *scenery = scenery_get(object_index); if (TEST_FLAG(scenery->flags, 0)) { diff --git a/source/objects/scenery.h b/source/objects/scenery.h index 9587b73d..4f816cec 100644 --- a/source/objects/scenery.h +++ b/source/objects/scenery.h @@ -8,12 +8,27 @@ header included in hcex build. #define __SCENERY_H #pragma once +#include "objects/object_types.h" +#include "objects/objects.h" + /* ---------- constants */ /* ---------- macros */ +#define scenery_get(index) ((struct scenery_datum *)object_get_and_verify_type((index), _object_mask_scenery)) +#define scenery_try_and_get(index) ((struct scenery_datum *)object_try_and_get_and_verify_type((index), _object_mask_scenery)) + /* ---------- structures */ +struct scenery_datum +{ + struct object_datum object; + unsigned long flags; +}; + +typedef char verify_scenery_extension_offset[ + sizeof(struct object_datum) == 0x1A4 ? 1 : -1]; + /* ---------- prototypes/EXAMPLE.C */ void scenery_initialize(void); diff --git a/source/scenario/multiplayer_scenario_description.c b/source/scenario/multiplayer_scenario_description.c index b4451bd8..8292e5e2 100644 --- a/source/scenario/multiplayer_scenario_description.c +++ b/source/scenario/multiplayer_scenario_description.c @@ -19,43 +19,18 @@ symbols in this file: #include #include "cseries.h" +#include "scenario/multiplayer_scenario_description.h" #include "tag_files/tag_groups.h" /* ---------- constants */ -enum -{ - MULTIPLAYER_SCENARIO_DESCRIPTION_TAG = 'mply' -}; - /* ---------- macros */ /* ---------- structures */ -struct multiplayer_scenario_description_item -{ - struct tag_reference descriptive_bitmap; - struct tag_reference displayed_map_name; - char scenario_tag_path[1]; -}; - -struct multiplayer_scenario_description -{ - struct tag_block scenarios; -}; - -typedef char multiplayer_scenario_description_item_path_offset_assert[ - offsetof(struct multiplayer_scenario_description_item, scenario_tag_path) == 0x20 ? 1 : -1]; - /* ---------- prototypes */ -struct multiplayer_scenario_description_item *multiplayer_scenario_description_get_list(short *count); -boolean map_name_from_multiplayer_scenario_description_item( - struct multiplayer_scenario_description_item const *item, - char *map_name, - unsigned long map_name_size); - /* ---------- globals */ /* ---------- public code */ @@ -71,7 +46,7 @@ struct multiplayer_scenario_description_item *multiplayer_scenario_description_g if (scenario_list_index != NONE) { struct multiplayer_scenario_description *scenario_list = - tag_get(MULTIPLAYER_SCENARIO_DESCRIPTION_TAG, scenario_list_index); + multiplayer_scenario_description_get(scenario_list_index); match_assert("c:\\halo\\SOURCE\\scenario\\multiplayer_scenario_description.c", 66, scenario_list); result = scenario_list->scenarios.address; diff --git a/source/scenario/multiplayer_scenario_description.h b/source/scenario/multiplayer_scenario_description.h new file mode 100644 index 00000000..e211c9ae --- /dev/null +++ b/source/scenario/multiplayer_scenario_description.h @@ -0,0 +1,56 @@ +/* +MULTIPLAYER_SCENARIO_DESCRIPTION.H + +header included in hcex build. +*/ + +#ifndef __MULTIPLAYER_SCENARIO_DESCRIPTION_H +#define __MULTIPLAYER_SCENARIO_DESCRIPTION_H +#pragma once + +/* ---------- headers */ + +#include "tag_files/tag_groups.h" + +/* ---------- constants */ + +enum +{ + MULTIPLAYER_SCENARIO_DESCRIPTION_TAG = 'mply', +}; + +/* ---------- macros */ + +#define multiplayer_scenario_description_get(index) ((struct multiplayer_scenario_description *)tag_get(MULTIPLAYER_SCENARIO_DESCRIPTION_TAG, (index))) + +/* ---------- structures */ + +struct multiplayer_scenario_description_item +{ + struct tag_reference descriptive_bitmap; + struct tag_reference displayed_map_name; + char scenario_tag_path[1]; +}; + +struct multiplayer_scenario_description +{ + struct tag_block scenarios; +}; + +typedef char multiplayer_scenario_description_item_path_offset_assert[ + offsetof(struct multiplayer_scenario_description_item, scenario_tag_path) == 0x20 ? 1 : -1]; + +/* ---------- prototypes/MULTIPLAYER_SCENARIO_DESCRIPTION.C */ + +struct multiplayer_scenario_description_item *multiplayer_scenario_description_get_list( + short *count); +boolean map_name_from_multiplayer_scenario_description_item( + struct multiplayer_scenario_description_item const *item, + char *map_name, + unsigned long map_name_size); + +/* ---------- globals */ + +/* ---------- public code */ + +#endif // __MULTIPLAYER_SCENARIO_DESCRIPTION_H diff --git a/source/sound/sound_definitions.h b/source/sound/sound_definitions.h index 23df6e2c..a72af0c9 100644 --- a/source/sound/sound_definitions.h +++ b/source/sound/sound_definitions.h @@ -41,6 +41,8 @@ enum /* ---------- macros */ +#define sound_definition_get(index) ((struct sound_definition *)tag_get(SOUND_DEFINITION_TAG, (index))) + /* ---------- structures */ struct real_bounds diff --git a/source/sound/sound_scenery.c b/source/sound/sound_scenery.c index 0a29f92a..875793d5 100644 --- a/source/sound/sound_scenery.c +++ b/source/sound/sound_scenery.c @@ -13,6 +13,7 @@ symbols in this file: #include "cseries.h" #include "object_types.h" #include "objects.h" +#include "sound/sound_scenery.h" /* ---------- constants */ @@ -31,16 +32,16 @@ boolean sound_scenery_new( { struct object_datum *object; - object = (struct object_datum *)object_get_and_verify_type(object_index, FLAG(_object_type_sound_scenery)); + object = sound_scenery_get(object_index); object->object.flags |= FLAG(_object_shadowless_bit); return TRUE; } -void -sound_scenery_delete( +void sound_scenery_delete( long object_index) { + return; } /* ---------- private code */ diff --git a/source/sound/sound_scenery.h b/source/sound/sound_scenery.h index 8e109593..57b2b203 100644 --- a/source/sound/sound_scenery.h +++ b/source/sound/sound_scenery.h @@ -8,10 +8,16 @@ header included in hcex build. #define __SOUND_SCENERY_H #pragma once +#include "objects/object_types.h" +#include "objects/objects.h" + /* ---------- constants */ /* ---------- macros */ +#define sound_scenery_get(index) ((struct object_datum *)object_get_and_verify_type((index), _object_mask_sound_scenery)) +#define sound_scenery_try_and_get(index) ((struct object_datum *)object_try_and_get_and_verify_type((index), _object_mask_sound_scenery)) + /* ---------- structures */ /* ---------- prototypes/EXAMPLE.C */ diff --git a/source/text/text_group.c b/source/text/text_group.c index 2a3f6572..693bee81 100644 --- a/source/text/text_group.c +++ b/source/text/text_group.c @@ -36,7 +36,7 @@ char *string_list_get_string(long tag_index, short string_index) if (tag_index != NONE) { - struct string_list *list = tag_get('str#', tag_index); + struct string_list *list = string_list_definition_get(tag_index); if (string_index >= 0 && string_index < list->strings.count) { @@ -62,7 +62,7 @@ wchar_t *unicode_string_list_get_string(long tag_index, short string_index) if (tag_index != NONE) { - struct string_list *list = tag_get('ustr', tag_index); + struct string_list *list = unicode_string_list_definition_get(tag_index); if (string_index >= 0 && string_index < list->strings.count) { diff --git a/source/text/text_group.h b/source/text/text_group.h index 3b4e2dd9..917a9eee 100644 --- a/source/text/text_group.h +++ b/source/text/text_group.h @@ -14,6 +14,12 @@ header included in hcex build. /* ---------- constants */ +enum +{ + STRING_LIST_TAG = 'str#', + UNICODE_STRING_LIST_TAG = 'ustr', +}; + enum { _text_style_plain = NONE, @@ -26,6 +32,9 @@ enum /* ---------- macros */ +#define string_list_definition_get(index) ((struct string_list *)tag_get(STRING_LIST_TAG, (index))) +#define unicode_string_list_definition_get(index) ((struct string_list *)tag_get(UNICODE_STRING_LIST_TAG, (index))) + /* ---------- structures */ struct string_list