mirror of
https://github.com/astromaddie/HaloCE-VR.git
synced 2026-10-20 23:00:15 +02:00
Recover transparent geometry submit (+1,285 meaningful code, zero exact losses); reconcile COMMON ownership and Q10 85+EXT1 credit, actions/main data, and separately disclosed denominator corrections. Preserve canonical-only repairs and all held research. C09 is ordinary disclosed cleanup, not a claim of proven scaffolding intent. Clean rebuild, 1,663 tests, parks, audits, provider links and independent EXT1 check pass. Local reconciliation only.
3395 lines
96 KiB
C
3395 lines
96 KiB
C
/*
|
|
HS_COMPILE.C
|
|
|
|
symbols in this file:
|
|
000B46B0 02c0:
|
|
_code_000b46b0 (0000)
|
|
000B4970 00b0:
|
|
_code_000b4970 (0000)
|
|
000B4A20 00b0:
|
|
_hs_compile_initialize (0000)
|
|
000B4AD0 0070:
|
|
_code_000b4ad0 (0000)
|
|
000B4B40 0030:
|
|
_hs_verify_source_offset (0000)
|
|
000B4B70 0050:
|
|
_code_000b4b70 (0000)
|
|
000B4BC0 0020:
|
|
_code_000b4bc0 (0000)
|
|
000B4BE0 0120:
|
|
_code_000b4be0 (0000)
|
|
000B4D00 00c0:
|
|
_code_000b4d00 (0000)
|
|
000B4DC0 0130:
|
|
_code_000b4dc0 (0000)
|
|
000B4EF0 00f0:
|
|
_code_000b4ef0 (0000)
|
|
000B4FE0 0120:
|
|
_code_000b4fe0 (0000)
|
|
000B5100 0080:
|
|
_code_000b5100 (0000)
|
|
000B5180 00b0:
|
|
_code_000b5180 (0000)
|
|
000B5230 00d0:
|
|
_code_000b5230 (0000)
|
|
000B5300 01d0:
|
|
_code_000b5300 (0000)
|
|
000B54D0 0100:
|
|
_code_000b54d0 (0000)
|
|
000B55D0 0070:
|
|
_code_000b55d0 (0000)
|
|
000B5640 0070:
|
|
_code_000b5640 (0000)
|
|
000B56B0 0070:
|
|
_code_000b56b0 (0000)
|
|
000B5720 0070:
|
|
_code_000b5720 (0000)
|
|
000B5790 0070:
|
|
_code_000b5790 (0000)
|
|
000B5800 0070:
|
|
_code_000b5800 (0000)
|
|
000B5870 00b0:
|
|
_code_000b5870 (0000)
|
|
000B5920 0070:
|
|
_code_000b5920 (0000)
|
|
000B5990 0070:
|
|
_code_000b5990 (0000)
|
|
000B5A00 0070:
|
|
_code_000b5a00 (0000)
|
|
000B5A70 0140:
|
|
_code_000b5a70 (0000)
|
|
000B5BB0 00a0:
|
|
_code_000b5bb0 (0000)
|
|
000B5C50 0090:
|
|
_code_000b5c50 (0000)
|
|
000B5CE0 0090:
|
|
_code_000b5ce0 (0000)
|
|
000B5D70 0060:
|
|
_code_000b5d70 (0000)
|
|
000B5DD0 0040:
|
|
_code_000b5dd0 (0000)
|
|
000B5E10 0090:
|
|
_code_000b5e10 (0000)
|
|
000B5EA0 0290:
|
|
_code_000b5ea0 (0000)
|
|
000B6130 0430:
|
|
_code_000b6130 (0000)
|
|
000B6560 00f0:
|
|
_code_000b6560 (0000)
|
|
000B6650 00f0:
|
|
_code_000b6650 (0000)
|
|
000B6740 0120:
|
|
_code_000b6740 (0000)
|
|
000B6860 0380:
|
|
_code_000b6860 (0000)
|
|
000B6BE0 02d0:
|
|
_hs_compile_postprocess (0000)
|
|
000B6EB0 00d0:
|
|
_code_000b6eb0 (0000)
|
|
000B6F80 00c0:
|
|
_code_000b6f80 (0000)
|
|
000B7040 00e0:
|
|
_code_000b7040 (0000)
|
|
000B7120 00d0:
|
|
_hs_parse (0000)
|
|
000B71F0 0120:
|
|
_hs_macro_function_parse (0000)
|
|
000B7310 01b0:
|
|
_hs_parse_begin (0000)
|
|
000B74C0 01c0:
|
|
_hs_parse_if (0000)
|
|
000B7680 00a0:
|
|
_hs_parse_cond (0000)
|
|
000B7720 0230:
|
|
_hs_parse_set (0000)
|
|
000B7950 0170:
|
|
_hs_parse_logical (0000)
|
|
000B7AC0 0190:
|
|
_hs_parse_arithmetic (0000)
|
|
000B7C50 0110:
|
|
_hs_parse_equality (0000)
|
|
000B7D60 01d0:
|
|
_hs_parse_inequality (0000)
|
|
000B7F30 00c0:
|
|
_hs_parse_sleep (0000)
|
|
000B7FF0 00e0:
|
|
_hs_parse_sleep_until (0000)
|
|
000B80D0 00d0:
|
|
_hs_parse_wake (0000)
|
|
000B81A0 00c0:
|
|
_hs_parse_inspect (0000)
|
|
000B8260 0080:
|
|
_hs_parse_object_cast_up (0000)
|
|
000B82E0 0110:
|
|
_hs_parse_debug_string (0000)
|
|
000B83F0 0260:
|
|
_hs_compile_expression (0000)
|
|
000B8650 0140:
|
|
_hs_compile (0000)
|
|
000B8790 0100:
|
|
_hs_compile_finish (0000)
|
|
000B8890 00d0:
|
|
_hs_compile_dispose (0000)
|
|
00269F98 00cc:
|
|
_whitespace_characters (0000)
|
|
_eol_characters (0004)
|
|
_hs_type_primitive_parsers (0008)
|
|
0026A064 0038:
|
|
??_C@_0DI@FFMILLMF@this?5argument?5to?5cond?5should?5be?5@ (0000)
|
|
0026A09C 0026:
|
|
??_C@_0CG@CKIGEJPJ@this?5argument?5to?5cond?5needs?5a?5re@ (0000)
|
|
0026A0C4 0023:
|
|
??_C@_0CD@IJMPPEHP@i?5couldn?8t?5allocate?5a?5syntax?5nod@ (0000)
|
|
0026A0E8 0023:
|
|
??_C@_0CD@CMPGDOHG@the?5?$CFs?5call?5requires?5?$CFd?5argument@ (0000)
|
|
0026A10C 0020:
|
|
??_C@_0CA@FLDPLDBJ@?$CBhs_compile_globals?4initialized?$AA@ (0000)
|
|
0026A12C 001f:
|
|
??_C@_0BP@MLCFIFLN@c?3?2halo?2SOURCE?2hs?2hs_compile?4c?$AA@ (0000)
|
|
0026A14C 002b:
|
|
??_C@_0CL@GBEGGBNG@bad?5source?5offset?5?$CIyou?5need?5to?5r@ (0000)
|
|
0026A178 0023:
|
|
??_C@_0CD@EFKPEBIG@this?5is?5not?5a?5valid?5variable?5nam@ (0000)
|
|
0026A19C 003f:
|
|
??_C@_0DP@PEGJCBIB@i?5expected?5a?5value?5of?5type?5?$CFs?0?5b@ (0000)
|
|
0026A1E0 0042:
|
|
??_C@_0EC@IIFEBBHH@hs_type_valid?$CIexpression?9?$DOtype?$CJ?5@ (0000)
|
|
0026A224 0020:
|
|
??_C@_0CA@DKEMPFLD@predicate?9?$DOfunction_index?$CB?$DNNONE?$AA@ (0000)
|
|
0026A244 001e:
|
|
??_C@_0BO@OIGMDMNN@i?5expected?5?$CCtrue?$CC?5or?5?$CCfalse?$CC?4?$AA@ (0000)
|
|
0026A264 0002:
|
|
??_C@_01HIHLOKLC@1?$AA@ (0000)
|
|
0026A268 0002:
|
|
??_C@_01GBGANLPD@0?$AA@ (0000)
|
|
0026A26C 002c:
|
|
??_C@_0CM@LMJJMGPB@expression?9?$DOconstant_type?$DN?$DNexpre@ (0000)
|
|
0026A298 0023:
|
|
??_C@_0CD@PDJAANOA@expression?9?$DOtype?$DN?$DN_hs_type_boole@ (0000)
|
|
0026A2BC 0021:
|
|
??_C@_0CB@OIAINLCH@this?5is?5not?5a?5valid?5real?5number?4@ (0000)
|
|
0026A2E0 0020:
|
|
??_C@_0CA@FDCELDHN@expression?9?$DOtype?$DN?$DN_hs_type_real?$AA@ (0000)
|
|
0026A300 002d:
|
|
??_C@_0CN@PNJHLLDG@shorts?5must?5be?5in?5the?5range?5?$FL?932@ (0000)
|
|
0026A330 001d:
|
|
??_C@_0BN@MIAGNDJA@this?5is?5not?5a?5valid?5integer?4?$AA@ (0000)
|
|
0026A350 0054:
|
|
??_C@_0FE@HAABGHID@expression?9?$DOtype?$DN?$DN_hs_type_short@ (0000)
|
|
0026A3A4 0022:
|
|
??_C@_0CC@NOGPGKAJ@expression?9?$DOtype?$DN?$DN_hs_type_strin@ (0000)
|
|
0026A3C8 0021:
|
|
??_C@_0CB@PILDPBCN@this?5is?5not?5a?5valid?5script?5name?4@ (0000)
|
|
0026A3EC 0022:
|
|
??_C@_0CC@LHOLJHMC@expression?9?$DOtype?$DN?$DN_hs_type_scrip@ (0000)
|
|
0026A410 002b:
|
|
??_C@_0CL@GNGCJOIJ@HS_TYPE_IS_TAG_REFERENCE?$CIexpress@ (0000)
|
|
0026A43C 0003:
|
|
??_C@_02DAHALNEP@?$CC?4?$AA@ (0000)
|
|
0026A440 0004:
|
|
??_C@_03HPAPFPCK@or?5?$AA@ (0000)
|
|
0026A444 0004:
|
|
??_C@_03HAFDNMHA@?$CC?0?5?$AA@ (0000)
|
|
0026A448 0002:
|
|
??_C@_01BJJEKLCA@?$CC?$AA@ (0000)
|
|
0026A44C 000c:
|
|
??_C@_0M@KDPMODNJ@?$CFs?5must?5be?5?$AA@ (0000)
|
|
0026A458 0017:
|
|
??_C@_0BH@KAIIDDCD@enum_definition?9?$DOcount?$AA@ (0000)
|
|
0026A470 0022:
|
|
??_C@_0CC@MAMGKIFK@HS_TYPE_IS_ENUM?$CIexpression?9?$DOtype@ (0000)
|
|
0026A494 001c:
|
|
??_C@_0BM@LLFLMGFD@this?5is?5not?5a?5valid?5?$CFs?5name?$AA@ (0000)
|
|
0026A4B0 0026:
|
|
??_C@_0CG@KJHDFGKE@offset?$CLTAG_STRING_LENGTH?$DMelement@ (0000)
|
|
0026A4D8 0018:
|
|
??_C@_0BI@DDGKIDCA@element_size?$DM?$DNSHORT_MAX?$AA@ (0000)
|
|
0026A4F0 003f:
|
|
??_C@_0DP@DDIGGJCL@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A530 003e:
|
|
??_C@_0DO@KIKHDLLO@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A570 0046:
|
|
??_C@_0EG@OIMEONBP@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A5B8 003f:
|
|
??_C@_0DP@NJJHMCPO@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A5F8 0043:
|
|
??_C@_0ED@MFJLLEIG@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A63C 003d:
|
|
??_C@_0DN@ENBCEMCP@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A67C 002b:
|
|
??_C@_0CL@GHINNEMH@this?5is?5not?5a?5valid?5ai?5encounter@ (0000)
|
|
0026A6A8 0033:
|
|
??_C@_0DD@BFEBGH@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A6E0 0040:
|
|
??_C@_0EA@CLIOJMOJ@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A720 0041:
|
|
??_C@_0EB@LFKOHNHB@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A764 003d:
|
|
??_C@_0DN@KMDNBPLF@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A7A4 0021:
|
|
??_C@_0CB@NGOPBJNH@this?5is?5not?5a?5valid?5object?5name?4@ (0000)
|
|
0026A7C8 0022:
|
|
??_C@_0CC@PHOMBDHG@this?5is?5not?5an?5object?5of?5type?5?$CFs@ (0000)
|
|
0026A7EC 0027:
|
|
??_C@_0CH@BODOHPOD@object_name?9?$DOruntime_object_type@ (0000)
|
|
0026A814 0029:
|
|
??_C@_0CJ@IEEDGBAJ@HS_TYPE_IS_OBJECT_NAME?$CIexpressio@ (0000)
|
|
0026A840 0024:
|
|
??_C@_0CE@OBCLMFIJ@HS_TYPE_IS_OBJECT?$CIexpression?9?$DOty@ (0000)
|
|
0026A864 0039:
|
|
??_C@_0DJ@MLDFNHMP@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A8A0 003c:
|
|
??_C@_0DM@NDFNDKDO@hs_syntax_get?$CIexpression_index?$CJ?9@ (0000)
|
|
0026A8DC 0027:
|
|
??_C@_0CH@KPEEOMPJ@expression?9?$DOtype?$DN?$DN_hs_type_objec@ (0000)
|
|
0026A904 0029:
|
|
??_C@_0CJ@MJLOCEH@ran?5out?5of?5script?5string?5constan@ (0000)
|
|
0026A930 0031:
|
|
??_C@_0DB@KNNKPLIC@i?5expected?5?$CIglobal?$DMtype?$DO?5?$DMname?$DO?5@ (0000)
|
|
0026A964 003b:
|
|
??_C@_0DL@HEBOLCPD@i?5expected?5a?5global?5variable?5nam@ (0000)
|
|
0026A9A0 002a:
|
|
??_C@_0CK@ILPHLOJN@there?5is?5already?5a?5variable?5by?5t@ (0000)
|
|
0026A9CC 002b:
|
|
??_C@_0CL@FLFKBOAG@i?5couldn?8t?5allocate?5space?5for?5th@ (0000)
|
|
0026A9F8 001a:
|
|
??_C@_0BK@IKPJOEIK@this?5is?5not?5a?5valid?5type?4?$AA@ (0000)
|
|
0026AA14 0032:
|
|
??_C@_0DC@LIKMAGAH@i?5expected?5?$CIscript?5?$DMtype?$DO?5?$DMname?$DO@ (0000)
|
|
0026AA48 0037:
|
|
??_C@_0DH@HLEPKBGC@i?5expected?5?$CIscript?5stub?5?$DMtype?$DO?5?$DM@ (0000)
|
|
0026AA80 0039:
|
|
??_C@_0DJ@ICFJDLL@i?5expected?5?$CIscript?5static?5?$DMtype?$DO@ (0000)
|
|
0026AABC 0032:
|
|
??_C@_0DC@KKMNLEGD@i?5expected?5a?5script?5name?5less?5th@ (0000)
|
|
0026AAF0 0040:
|
|
??_C@_0EA@JEODPONE@only?5static?5scripts?5of?5the?5same?5@ (0000)
|
|
0026AB30 001e:
|
|
??_C@_0BO@DIEOOMIB@i?5couldn?8t?5allocate?5a?5script?4?$AA@ (0000)
|
|
0026AB50 0039:
|
|
??_C@_0DJ@KPBLJMAG@i?5expected?5?$CIscript?5local?5?$DMtype?$DO?5@ (0000)
|
|
0026AB8C 0021:
|
|
??_C@_0CB@IMBMFBPE@this?5is?5not?5a?5valid?5return?5type?4@ (0000)
|
|
0026ABB0 0045:
|
|
??_C@_0EF@HPGCPNKB@script?5type?5must?5be?5?$CCstartup?$CC?0?5?$CC@ (0000)
|
|
0026ABF8 0026:
|
|
??_C@_0CG@DLDLACEH@this?5quoted?5constant?5is?5untermin@ (0000)
|
|
0026AC20 0016:
|
|
??_C@_0BG@OBOCFOLJ@unterminated?5comment?4?$AA@ (0000)
|
|
0026AC38 0032:
|
|
??_C@_0DC@DNDDDIBA@expressions?5of?5type?5?$CFs?5are?5curre@ (0000)
|
|
0026AC70 0043:
|
|
??_C@_0ED@BCCOKIBI@the?5value?5of?5this?5expression?5?$CIin@ (0000)
|
|
0026ACB4 002c:
|
|
??_C@_0CM@DJEKPL@i?5expected?5a?5script?5or?5variable?5@ (0000)
|
|
0026ACE0 0068:
|
|
??_C@_0GI@BHJPJIIC@hs_type_valid?$CIexpression?9?$DOtype?$CJ?5@ (0000)
|
|
0026AD48 0028:
|
|
??_C@_0CI@NKPOIECC@i?5expected?5?$CFs?0?5but?5i?5got?5an?5expr@ (0000)
|
|
0026AD70 0010:
|
|
??_C@_0BA@PAKINOFK@a?5function?5name?$AA@ (0000)
|
|
0026AD80 0015:
|
|
??_C@_0BF@IBMEIANF@?$CCscript?$CC?5or?5?$CCglobal?$CC?$AA@ (0000)
|
|
0026AD98 002d:
|
|
??_C@_0CN@EDPOFKO@this?5is?5not?5a?5valid?5function?5or?5@ (0000)
|
|
0026ADC8 0010:
|
|
??_C@_0BA@LKPMJEGC@function?9?$DOparse?$AA@ (0000)
|
|
0026ADD8 003d:
|
|
??_C@_0DN@MBGBMIIG@it?5is?5illegal?5to?5set?5the?5value?5o@ (0000)
|
|
0026AE18 0028:
|
|
??_C@_0CI@LEFIJLGP@it?5is?5illegal?5to?5block?5in?5this?5c@ (0000)
|
|
0026AE40 0031:
|
|
??_C@_0DB@FJPDKKBL@i?5expected?5a?5?$CFs?0?5but?5this?5functi@ (0000)
|
|
0026AE74 002f:
|
|
??_C@_0CP@EBGMPNCK@i?5expected?5a?5?$CFs?0?5but?5this?5script@ (0000)
|
|
0026AEA4 001d:
|
|
??_C@_0BN@IHENCGGJ@this?5is?5not?5a?5static?5script?4?$AA@ (0000)
|
|
0026AEC4 0021:
|
|
??_C@_0CB@IAHJHNPF@i?5expected?5?$CCscript?$CC?5or?5?$CCglobal?$CC?4@ (0000)
|
|
0026AEE8 002e:
|
|
??_C@_0CO@BFGOLJBG@missing?5type?5?$CIyou?5need?5to?5recomp@ (0000)
|
|
0026AF18 0041:
|
|
??_C@_0EB@EJKNFGEH@type?5is?5inconsistent?5with?5usage?5@ (0000)
|
|
0026AF5C 0035:
|
|
??_C@_0DF@DBAKANGN@corrupt?5syntax?5tree?5?$CIyou?5need?5to@ (0000)
|
|
0026AF94 0032:
|
|
??_C@_0DC@LGOKBIPD@missing?5function?5?$CIyou?5need?5to?5re@ (0000)
|
|
0026AFC8 002a:
|
|
??_C@_0CK@DLLKHDNE@bad?5script?5index?5?$CIyou?5need?5to?5re@ (0000)
|
|
0026AFF4 001a:
|
|
??_C@_0BK@BFLBDCPG@?$CBhs_compile_globals?4error?$AA@ (0000)
|
|
0026B010 001a:
|
|
??_C@_0BK@NAGDEHOO@this?5expression?5is?5empty?4?$AA@ (0000)
|
|
0026B02C 0024:
|
|
??_C@_0CE@GGGJMCLA@this?5left?5parenthesis?5is?5unmatch@ (0000)
|
|
0026B050 005f:
|
|
??_C@_0FP@FAMPHEFE@hs_type_valid?$CIexpected_type?$CJ?5?$HM?$HM?5@ (0000)
|
|
0026B0B0 002d:
|
|
??_C@_0CN@KIPPILAN@the?5?$CC?$CFs?$CC?5call?5requires?5exactly?5?$CF@ (0000)
|
|
0026B0E0 0027:
|
|
??_C@_0CH@HOBBAFGG@hs_type_valid?$CIdefinition?9?$DOreturn@ (0000)
|
|
0026B108 004a:
|
|
??_C@_0EK@BFPAJKIG@begin_random?5can?5take?5a?5maximum?5@ (0000)
|
|
0026B154 0036:
|
|
??_C@_0DG@ILKKMIFN@a?5statement?5block?5must?5contain?5a@ (0000)
|
|
0026B190 0050:
|
|
??_C@_0FA@MLNKNPCC@function_index?$DN?$DN_hs_function_beg@ (0000)
|
|
0026B1E0 0030:
|
|
??_C@_0DA@FDDIOHDH@c?3?2halo?2source?2hs?2hs_library_int@ (0000)
|
|
0026B210 002d:
|
|
??_C@_0CN@FFHDLAIG@i?5expected?5?$CIif?5?$DMcondition?$DO?5?$DMthen@ (0000)
|
|
0026B240 0020:
|
|
??_C@_0CA@JPNHPBMJ@function_index?$DN?$DN_hs_function_if?$AA@ (0000)
|
|
0026B260 002a:
|
|
??_C@_0CK@FOEIDHHM@i?5expected?5a?5variable?5to?5set?5and@ (0000)
|
|
0026B28C 0020:
|
|
??_C@_0CA@PGGJICDP@i?5expected?5an?5assignment?5value?4?$AA@ (0000)
|
|
0026B2AC 001f:
|
|
??_C@_0BP@FENPFJFI@i?5didn?8t?5expect?5this?5argument?4?$AA@ (0000)
|
|
0026B2CC 0025:
|
|
??_C@_0CF@JLOHFOAN@this?5is?5not?5a?5valid?5global?5varia@ (0000)
|
|
0026B2F4 0009:
|
|
??_C@_08NNEKJPJG@asserted?$AA@ (0000)
|
|
0026B300 0055:
|
|
??_C@_0FF@OKNDBCCJ@you?5cannot?5pass?5the?5result?5of?5th@ (0000)
|
|
0026B358 002b:
|
|
??_C@_0CL@HLGBMAID@the?5?$CFs?5call?5requires?5at?5least?52?5@ (0000)
|
|
0026B388 0044:
|
|
??_C@_0EE@DJKKNFEH@function_index?$DN?$DN_hs_function_and@ (0000)
|
|
0026B3CC 0024:
|
|
??_C@_0CE@JPJPEJGL@the?5?$CFs?5call?5requires?5?$CFs2?5argumen@ (0000)
|
|
0026B3F0 000a:
|
|
??_C@_09HJOCAFJB@at?5least?5?$AA@ (0000)
|
|
0026B400 0046:
|
|
??_C@_0EG@NCMDIGON@function_index?$DO?$DN_hs_function_plu@ (0000)
|
|
0026B448 004d:
|
|
??_C@_0EN@LKLJPEDN@function_index?$DN?$DN_hs_function_equ@ (0000)
|
|
0026B498 0044:
|
|
??_C@_0EE@DBJLFPAO@function_index?$DO?$DN_hs_function_gt?5@ (0000)
|
|
0026B4DC 003f:
|
|
??_C@_0DP@OBLOAKOC@the?5sleep?5call?5requires?5a?5time?5a@ (0000)
|
|
0026B51C 0023:
|
|
??_C@_0CD@OEIHEIL@function_index?$DN?$DN_hs_function_sle@ (0000)
|
|
0026B540 0045:
|
|
??_C@_0EF@ONCEJGKM@the?5sleep_until?5call?5requires?5a?5@ (0000)
|
|
0026B588 0029:
|
|
??_C@_0CJ@OOHINAAD@function_index?$DN?$DN_hs_function_sle@ (0000)
|
|
0026B5B4 0027:
|
|
??_C@_0CH@LDNCEPBK@this?5static?5script?5cannot?5be?5awa@ (0000)
|
|
0026B5DC 0022:
|
|
??_C@_0CC@MOINJLCD@function_index?$DN?$DN_hs_function_wak@ (0000)
|
|
0026B600 0048:
|
|
??_C@_0EI@PCGFDELO@this?5is?5not?5a?5global?5variable?5re@ (0000)
|
|
0026B648 0025:
|
|
??_C@_0CF@OOHBFBHF@function_index?$DN?$DN_hs_function_ins@ (0000)
|
|
0026B670 005b:
|
|
??_C@_0FL@GHADBDBJ@function_index?$DO?$DN_hs_function_obj@ (0000)
|
|
0026B6D0 0068:
|
|
??_C@_0GI@HCJMIFHN@?$CIfunction_index?$DO?$DN_hs_function_de@ (0000)
|
|
0026B738 0052:
|
|
??_C@_0FC@BMHAGKNK@hs_compile_globals?4error_offset?$DO@ (0000)
|
|
0026B78C 0023:
|
|
??_C@_0CD@IOHANEHH@hs_compile_globals?4compiled_sour@ (0000)
|
|
0026B7B0 0056:
|
|
??_C@_0FG@HHFCBJJH@global_scenario_get?$CI?$CJ?9?$DOhs_string@ (0000)
|
|
0026B808 002e:
|
|
??_C@_0CO@JFMALCKF@couldn?8t?5allocate?5memory?5for?5com@ (0000)
|
|
0026B838 0057:
|
|
??_C@_0FH@BKGDNNEC@hs_compile_globals?4error_offset?$DO@ (0000)
|
|
0026B890 0044:
|
|
??_C@_0EE@JNFGKPCH@tell?5matt?5that?5somebody?5failed?5t@ (0000)
|
|
0026B8D4 002d:
|
|
??_C@_0CN@CMJJHKPH@increase?5MAXIMUM_HS_STRING_DATA_@ (0000)
|
|
0026B904 001f:
|
|
??_C@_0BP@OAFEJCHM@hs_compile_globals?4initialized?$AA@ (0000)
|
|
00453480 012c:
|
|
_bss_00453480 (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries/cseries.h"
|
|
#include "cache/cache_files.h"
|
|
#include "ai/ai_script.h"
|
|
#include "hs/hs.h"
|
|
#include "hs/hs_library_internal.h"
|
|
#include "hs/hs_library_internal_compile.h"
|
|
#include "hs/hs_scenario_definitions.h"
|
|
#include "interface/hud_definitions.h"
|
|
#include "interface/interface.h"
|
|
#include "memory/data.h"
|
|
#include "scenario/scenario.h"
|
|
#include "scenario/scenario_definitions.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
first_hs_object_type = _hs_type_object,
|
|
first_hs_object_name_type = _hs_type_object_name,
|
|
MAXIMUM_HS_BEGIN_RANDOM_ARGUMENTS = 32,
|
|
HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES = 0x400,
|
|
scenario_cutscene_flag_size = 0x5C,
|
|
scenario_cutscene_title_size = 0x60,
|
|
scenario_recorded_animation_size = 0x40,
|
|
scenario_device_group_size = 0x34,
|
|
scenario_ai_command_list_size = 0x60,
|
|
scenario_conversation_size = 0x74,
|
|
hud_globals_group_tag = 'hudg',
|
|
hud_message_text_group_tag = 'hmt ',
|
|
hud_waypoint_arrow_size = 0x68,
|
|
hud_message_definition_size = 0x40,
|
|
};
|
|
|
|
enum hs_syntax_node_flag_bits
|
|
{
|
|
_hs_syntax_node_primitive_bit = 0,
|
|
_hs_syntax_node_script_bit,
|
|
_hs_syntax_node_variable_bit,
|
|
_hs_syntax_node_permanent_bit,
|
|
};
|
|
|
|
enum hs_tokenizer_state
|
|
{
|
|
_hs_tokenizer_state_normal = 0,
|
|
_hs_tokenizer_state_line_comment,
|
|
_hs_tokenizer_state_block_comment,
|
|
_hs_tokenizer_state_done,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
#define hs_syntax_get(expression_index) ((struct hs_syntax_node *)datum_get(hs_syntax_data, (expression_index)))
|
|
#define hud_globals_definition_get(index) ((struct hud_globals_definition *)tag_get(hud_globals_group_tag, (index)))
|
|
#define hud_message_text_definition_get(index) ((struct hud_message_text_definition *)tag_get(hud_message_text_group_tag, (index)))
|
|
#undef HS_TYPE_IS_OBJECT
|
|
#undef HS_TYPE_IS_OBJECT_NAME
|
|
#define HS_TYPE_IS_OBJECT(type) ((type)>=first_hs_object_type && (type)<=first_hs_object_type+NUMBER_OF_HS_OBJECT_TYPES-1)
|
|
#define HS_TYPE_IS_OBJECT_NAME(type) ((type)>=first_hs_object_name_type && (type)<=first_hs_object_name_type+NUMBER_OF_HS_OBJECT_TYPES-1)
|
|
|
|
/* ---------- structures */
|
|
|
|
struct hs_compile_globals
|
|
{
|
|
boolean initialized;
|
|
byte pad001[3];
|
|
long compiled_source_size;
|
|
char *compiled_source;
|
|
char *string_constant_buffer;
|
|
long string_constant_buffer_offset;
|
|
long string_constant_buffer_size;
|
|
boolean error_since_initialize;
|
|
byte pad019[3];
|
|
char const *error;
|
|
long error_offset;
|
|
char error_buffer[256];
|
|
boolean malloced;
|
|
boolean compiling_scenario;
|
|
boolean disallow_blocks;
|
|
boolean disallow_sets;
|
|
boolean variables_predetermined;
|
|
byte pad129[3];
|
|
};
|
|
|
|
struct hs_tokenizer
|
|
{
|
|
char *cursor;
|
|
};
|
|
|
|
typedef char verify_hs_syntax_node_size[
|
|
sizeof(struct hs_syntax_node) == 0x14 ? 1 : -1];
|
|
|
|
struct hud_message_text_definition
|
|
{
|
|
byte reserved000[0x20];
|
|
struct tag_block messages;
|
|
};
|
|
|
|
typedef boolean (*hs_primitive_parser)(
|
|
long expression_index);
|
|
|
|
typedef char verify_hs_compile_initialized_offset[
|
|
offsetof(struct hs_compile_globals, initialized) == 0x00 ? 1 : -1];
|
|
typedef char verify_hs_compile_compiled_source_size_offset[
|
|
offsetof(struct hs_compile_globals, compiled_source_size) == 0x04 ? 1 : -1];
|
|
typedef char verify_hs_compile_compiled_source_offset[
|
|
offsetof(struct hs_compile_globals, compiled_source) == 0x08 ? 1 : -1];
|
|
typedef char verify_hs_compile_string_constant_buffer_offset[
|
|
offsetof(struct hs_compile_globals, string_constant_buffer) == 0x0C ? 1 : -1];
|
|
typedef char verify_hs_compile_error_since_initialize_offset[
|
|
offsetof(struct hs_compile_globals, error_since_initialize) == 0x18 ? 1 : -1];
|
|
typedef char verify_hs_compile_error_offset[
|
|
offsetof(struct hs_compile_globals, error) == 0x1C ? 1 : -1];
|
|
typedef char verify_hs_compile_compiling_scenario_offset[
|
|
offsetof(struct hs_compile_globals, compiling_scenario) == 0x125 ? 1 : -1];
|
|
typedef char verify_hs_compile_globals_size[
|
|
sizeof(struct hs_compile_globals) == 0x12C ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static boolean hs_parse_scenario_datum(
|
|
long expression_index,
|
|
short offset,
|
|
struct tag_block *block,
|
|
long element_size);
|
|
static boolean hs_parse_trigger_volume(
|
|
long expression_index);
|
|
static boolean hs_parse_cutscene_flag(
|
|
long expression_index);
|
|
static boolean hs_parse_cutscene_camera_point(
|
|
long expression_index);
|
|
static boolean hs_parse_cutscene_title(
|
|
long expression_index);
|
|
static boolean hs_parse_cutscene_recording(
|
|
long expression_index);
|
|
static boolean hs_parse_device_group(
|
|
long expression_index);
|
|
static boolean hs_parse_ai_command_list(
|
|
long expression_index);
|
|
static boolean hs_parse_starting_profile(
|
|
long expression_index);
|
|
static boolean hs_parse_conversation(
|
|
long expression_index);
|
|
static boolean hs_parse_boolean(
|
|
long expression_index);
|
|
static boolean hs_parse_real(
|
|
long expression_index);
|
|
static boolean hs_parse_integer(
|
|
long expression_index);
|
|
static boolean hs_parse_string(
|
|
long expression_index);
|
|
static boolean hs_parse_script(
|
|
long expression_index);
|
|
static boolean hs_parse_tag_reference(
|
|
long expression_index);
|
|
static boolean hs_parse_enum(
|
|
long expression_index);
|
|
static boolean hs_parse_ai(
|
|
long expression_index);
|
|
static boolean hs_parse_object_name(
|
|
long expression_index);
|
|
static boolean hs_parse_object(
|
|
long expression_index);
|
|
static boolean hs_parse_navpoint(
|
|
long expression_index);
|
|
static boolean hs_parse_hud_message(
|
|
long expression_index);
|
|
static boolean hs_parse_object_list(
|
|
long expression_index);
|
|
static char *hs_compile_add_source(
|
|
long source_size,
|
|
char const *source);
|
|
static boolean hs_get_parameter_indices(
|
|
char const *function_name,
|
|
short parameter_count,
|
|
long *parameter_indices,
|
|
long expression_index);
|
|
static void hs_compile_finish(
|
|
void);
|
|
static long hs_find_string_constant(
|
|
char const *string);
|
|
static boolean character_in_list(
|
|
char character,
|
|
short list_count,
|
|
char const *list);
|
|
static boolean hs_parse_variable(
|
|
long expression_index);
|
|
static void hs_parse_call_predicate(
|
|
long expression_index);
|
|
static short string_list_find(
|
|
char const *string,
|
|
short list_count,
|
|
char const **list);
|
|
static long hs_concatenate_string_constant(
|
|
char const *string);
|
|
static boolean hs_add_global(
|
|
long expression_index);
|
|
static boolean hs_add_script(
|
|
long expression_index);
|
|
static void hs_tokenize_primitive(
|
|
struct hs_tokenizer *tokenizer,
|
|
long expression_index);
|
|
static void skip_whitespace(
|
|
char **cursor);
|
|
static boolean hs_parse_primitive(
|
|
long expression_index);
|
|
static boolean hs_parse_nonprimitive(
|
|
long expression_index);
|
|
static void hs_concatenate_expression(
|
|
long expression_index);
|
|
static long hs_tokenize(
|
|
struct hs_tokenizer *tokenizer);
|
|
static void hs_tokenize_nonprimitive(
|
|
struct hs_tokenizer *tokenizer,
|
|
long expression_index);
|
|
|
|
/* ---------- globals */
|
|
|
|
extern struct data_array *hs_syntax_data;
|
|
|
|
static struct hs_compile_globals hs_compile_globals;
|
|
|
|
char const whitespace_characters[2] = { ' ', '\t' };
|
|
char const eol_characters[2] = { '\n', '\r' };
|
|
hs_primitive_parser const hs_type_primitive_parsers[NUMBER_OF_HS_TYPES] =
|
|
{
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
hs_parse_boolean,
|
|
hs_parse_real,
|
|
hs_parse_integer,
|
|
hs_parse_integer,
|
|
hs_parse_string,
|
|
hs_parse_script,
|
|
hs_parse_trigger_volume,
|
|
hs_parse_cutscene_flag,
|
|
hs_parse_cutscene_camera_point,
|
|
hs_parse_cutscene_title,
|
|
hs_parse_cutscene_recording,
|
|
hs_parse_device_group,
|
|
hs_parse_ai,
|
|
hs_parse_ai_command_list,
|
|
hs_parse_starting_profile,
|
|
hs_parse_conversation,
|
|
hs_parse_navpoint,
|
|
hs_parse_hud_message,
|
|
hs_parse_object_list,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_tag_reference,
|
|
hs_parse_enum,
|
|
hs_parse_enum,
|
|
hs_parse_enum,
|
|
hs_parse_enum,
|
|
hs_parse_enum,
|
|
hs_parse_object,
|
|
hs_parse_object,
|
|
hs_parse_object,
|
|
hs_parse_object,
|
|
hs_parse_object,
|
|
hs_parse_object,
|
|
hs_parse_object_name,
|
|
hs_parse_object_name,
|
|
hs_parse_object_name,
|
|
hs_parse_object_name,
|
|
hs_parse_object_name,
|
|
hs_parse_object_name,
|
|
};
|
|
|
|
/* ---------- private code */
|
|
|
|
static long hs_parse_cond_recursive(
|
|
long root_expression_index,
|
|
long expression_index)
|
|
{
|
|
long new_expression_index = datum_new(hs_syntax_data);
|
|
|
|
if (new_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *new_expression = hs_syntax_get(new_expression_index);
|
|
|
|
new_expression->source_offset = hs_syntax_get(root_expression_index)->source_offset;
|
|
new_expression->flags = 0;
|
|
new_expression->next_node_index = NONE;
|
|
if (expression_index == NONE)
|
|
{
|
|
short root_type;
|
|
|
|
new_expression->flags = FLAG(_hs_syntax_node_primitive_bit);
|
|
root_type = hs_syntax_get(root_expression_index)->type;
|
|
new_expression->constant_type = root_type;
|
|
new_expression->type = root_type;
|
|
new_expression->data = 0;
|
|
}
|
|
else if (!TEST_FLAG(hs_syntax_get(expression_index)->flags, _hs_syntax_node_primitive_bit))
|
|
{
|
|
long condition_expression_index = hs_syntax_get(expression_index)->data;
|
|
struct hs_syntax_node *condition_expression = hs_syntax_get(condition_expression_index);
|
|
|
|
/* BUG (preserved for exact matching): January tests the logical negation of the
|
|
* result index against NONE, which is never true, so a clause without a result is
|
|
* not rejected here. A corrected build tests
|
|
* condition_expression->next_node_index != NONE. */
|
|
if (!condition_expression->next_node_index != NONE)
|
|
{
|
|
long if_then_expression_index = datum_new(hs_syntax_data);
|
|
long then_value_expression_index = datum_new(hs_syntax_data);
|
|
|
|
if (if_then_expression_index != NONE && then_value_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *if_then_expression = hs_syntax_get(if_then_expression_index);
|
|
struct hs_syntax_node *then_value_expression = hs_syntax_get(then_value_expression_index);
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
if_then_expression->next_node_index = hs_parse_cond_recursive(
|
|
root_expression_index,
|
|
hs_syntax_get(expression_index)->next_node_index);
|
|
if (if_then_expression->next_node_index != NONE)
|
|
{
|
|
new_expression->constant_type = _hs_function_name;
|
|
new_expression->data = expression_index;
|
|
expression->data = 0;
|
|
expression->function_index = _hs_function_if;
|
|
expression->flags = FLAG(_hs_syntax_node_primitive_bit);
|
|
expression->next_node_index = condition_expression_index;
|
|
expression->source_offset = NONE;
|
|
expression->type = _hs_function_name;
|
|
if_then_expression->data = then_value_expression_index;
|
|
if_then_expression->flags = 0;
|
|
if_then_expression->source_offset = new_expression->source_offset;
|
|
then_value_expression->data = 0;
|
|
then_value_expression->function_index = _hs_function_begin;
|
|
then_value_expression->flags = FLAG(_hs_syntax_node_primitive_bit);
|
|
then_value_expression->next_node_index = hs_syntax_get(condition_expression_index)->next_node_index;
|
|
then_value_expression->source_offset = NONE;
|
|
then_value_expression->type = _hs_function_name;
|
|
condition_expression->next_node_index = if_then_expression_index;
|
|
}
|
|
else
|
|
{
|
|
new_expression_index = NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate a syntax node.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(root_expression_index)->source_offset;
|
|
new_expression_index = NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this argument to cond needs a result.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(condition_expression_index)->source_offset;
|
|
new_expression_index = NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this argument to cond should be a condition/result pair";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
new_expression_index = NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate a syntax node.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(root_expression_index)->source_offset;
|
|
}
|
|
|
|
return new_expression_index;
|
|
}
|
|
|
|
static boolean hs_get_parameter_indices(
|
|
char const *function_name,
|
|
short parameter_count,
|
|
long *parameter_indices,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
long parameter_expression_index = hs_syntax_get(hs_syntax_get(expression_index)->data)->next_node_index;
|
|
short parameter_index;
|
|
|
|
for (parameter_index = 0;
|
|
parameter_expression_index != NONE;
|
|
parameter_expression_index = hs_syntax_get(parameter_expression_index)->next_node_index,
|
|
parameter_index++)
|
|
{
|
|
if (parameter_index >= parameter_count)
|
|
break;
|
|
parameter_indices[parameter_index] = parameter_expression_index;
|
|
}
|
|
|
|
if (parameter_index != parameter_count || parameter_expression_index != NONE)
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"the %s call requires %d arguments.",
|
|
function_name,
|
|
parameter_count);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/* ---------- public code */
|
|
|
|
|
|
void hs_compile_initialize(
|
|
boolean compiling_scenario)
|
|
{
|
|
struct scenario *scenario;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5B,
|
|
!hs_compile_globals.initialized);
|
|
hs_compile_globals.initialized = TRUE;
|
|
hs_compile_globals.compiled_source = NULL;
|
|
hs_compile_globals.compiled_source_size = 0;
|
|
hs_compile_globals.compiling_scenario = compiling_scenario;
|
|
hs_compile_globals.error_since_initialize = FALSE;
|
|
hs_compile_globals.error = NULL;
|
|
if (compiling_scenario)
|
|
{
|
|
scenario = global_scenario_get();
|
|
tag_block_resize(&scenario->hs_scripts, 0);
|
|
tag_block_resize(&scenario->hs_globals, 0);
|
|
tag_block_resize(&scenario->hs_references, 0);
|
|
tag_data_resize(&scenario->hs_string_constants, 0);
|
|
data_delete_all(hs_syntax_data);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void hs_compile_dispose(
|
|
void)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x75,
|
|
hs_compile_globals.initialized);
|
|
if (hs_compile_globals.compiling_scenario)
|
|
{
|
|
if (!hs_compile_globals.error_since_initialize)
|
|
{
|
|
hs_compile_finish();
|
|
}
|
|
else
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
|
|
tag_block_resize(&scenario->hs_scripts, 0);
|
|
tag_block_resize(&scenario->hs_globals, 0);
|
|
tag_data_resize(&scenario->hs_string_constants, 0);
|
|
data_delete_all(hs_syntax_data);
|
|
}
|
|
|
|
if (hs_compile_globals.compiled_source)
|
|
{
|
|
match_free(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x87,
|
|
hs_compile_globals.compiled_source);
|
|
}
|
|
}
|
|
|
|
if (hs_compile_globals.malloced)
|
|
{
|
|
match_free(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x8C,
|
|
hs_compile_globals.compiled_source);
|
|
hs_compile_globals.compiled_source = NULL;
|
|
hs_compile_globals.malloced = FALSE;
|
|
}
|
|
hs_compile_globals.initialized = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
long hs_compile_expression(
|
|
long source_size,
|
|
char const *source,
|
|
char const **error_message,
|
|
char const **error_source)
|
|
{
|
|
struct hs_tokenizer tokenizer;
|
|
long expression_index;
|
|
long begin_expression_index;
|
|
long root_expression_index;
|
|
long source_offset;
|
|
long result = NONE;
|
|
|
|
if (source_size < HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES)
|
|
{
|
|
if (global_scenario_index != NONE)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0xA6,
|
|
global_scenario_get()->hs_string_constants.size>=HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES);
|
|
source_offset = global_scenario_get()->hs_string_constants.size - HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES;
|
|
hs_compile_globals.compiled_source = global_scenario_get()->hs_string_constants.address;
|
|
}
|
|
else
|
|
{
|
|
source_offset = 0;
|
|
hs_compile_globals.compiled_source = match_malloc(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0xAF,
|
|
source_size + 1);
|
|
hs_compile_globals.malloced = TRUE;
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0xB2,
|
|
hs_compile_globals.compiled_source);
|
|
}
|
|
|
|
memcpy(hs_compile_globals.compiled_source + source_offset, source, source_size);
|
|
hs_compile_globals.compiled_source_size = source_offset + source_size;
|
|
hs_compile_globals.compiled_source[hs_compile_globals.compiled_source_size] = 0;
|
|
tokenizer.cursor = hs_compile_globals.compiled_source + source_offset;
|
|
hs_compile_globals.error = NULL;
|
|
*error_message = NULL;
|
|
*error_source = NULL;
|
|
hs_compile_globals.error_offset = NONE;
|
|
skip_whitespace(&tokenizer.cursor);
|
|
if (*tokenizer.cursor)
|
|
{
|
|
expression_index = hs_tokenize(&tokenizer);
|
|
if (!hs_compile_globals.error)
|
|
{
|
|
root_expression_index = datum_new(hs_syntax_data);
|
|
begin_expression_index = datum_new(hs_syntax_data);
|
|
if (root_expression_index != NONE && begin_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *root_expression = hs_syntax_get(root_expression_index);
|
|
struct hs_syntax_node *begin_expression = hs_syntax_get(begin_expression_index);
|
|
|
|
root_expression->data = begin_expression_index;
|
|
root_expression->next_node_index = NONE;
|
|
root_expression->source_offset = hs_syntax_get(expression_index)->source_offset;
|
|
root_expression->flags = 0;
|
|
begin_expression->next_node_index = expression_index;
|
|
begin_expression->source_offset = NONE;
|
|
begin_expression->function_index = _hs_function_inspect;
|
|
begin_expression->flags = FLAG(_hs_syntax_node_primitive_bit);
|
|
begin_expression->type = _hs_function_name;
|
|
if (hs_parse(root_expression_index, _hs_type_void))
|
|
result = root_expression_index;
|
|
}
|
|
}
|
|
|
|
if (result == NONE)
|
|
{
|
|
*error_message = hs_compile_globals.error;
|
|
if (hs_compile_globals.error_offset != NONE)
|
|
{
|
|
hs_compile_globals.error_offset -= source_offset;
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0xEB,
|
|
hs_compile_globals.error_offset>=0 && hs_compile_globals.error_offset<source_size);
|
|
*error_source = source + hs_compile_globals.error_offset;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static char *hs_compile_add_source(
|
|
long source_size,
|
|
char const *source)
|
|
{
|
|
char *result = NULL;
|
|
char *compiled_source = match_realloc(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0xFD,
|
|
hs_compile_globals.compiled_source,
|
|
hs_compile_globals.compiled_source_size + source_size + 1);
|
|
|
|
if (compiled_source)
|
|
{
|
|
hs_compile_globals.compiled_source = compiled_source;
|
|
result = compiled_source + hs_compile_globals.compiled_source_size;
|
|
memcpy(result, source, source_size);
|
|
hs_compile_globals.compiled_source_size += source_size;
|
|
hs_compile_globals.compiled_source[hs_compile_globals.compiled_source_size] = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void hs_compile(
|
|
long source_file_size,
|
|
char const *source,
|
|
char const **error_message,
|
|
char const **error_source)
|
|
{
|
|
struct hs_tokenizer tokenizer;
|
|
boolean valid;
|
|
|
|
tokenizer.cursor = hs_compile_add_source(source_file_size, source);
|
|
if (tokenizer.cursor)
|
|
{
|
|
hs_compile_globals.error = NULL;
|
|
*error_message = NULL;
|
|
*error_source = NULL;
|
|
valid = TRUE;
|
|
hs_compile_globals.error_offset = NONE;
|
|
skip_whitespace(&tokenizer.cursor);
|
|
do
|
|
{
|
|
long expression_index;
|
|
|
|
if (!*tokenizer.cursor)
|
|
break;
|
|
expression_index = hs_tokenize(&tokenizer);
|
|
skip_whitespace(&tokenizer.cursor);
|
|
valid = !hs_compile_globals.error;
|
|
if (valid)
|
|
valid = hs_parse(expression_index, _hs_special_form);
|
|
}
|
|
while (valid);
|
|
|
|
if (!valid)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x131,
|
|
hs_compile_globals.error,
|
|
"tell matt that somebody failed to correctly report a parsing error.");
|
|
*error_message = hs_compile_globals.error;
|
|
hs_compile_globals.error_since_initialize = TRUE;
|
|
if (hs_compile_globals.error_offset != NONE)
|
|
{
|
|
hs_compile_globals.error_offset -= hs_compile_globals.compiled_source_size - source_file_size;
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x13B,
|
|
hs_compile_globals.error_offset>=0 && hs_compile_globals.error_offset<source_file_size);
|
|
*error_source = source + hs_compile_globals.error_offset;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*error_message = "couldn't allocate memory for compiled source.";
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void hs_compile_finish(
|
|
void)
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
boolean success = tag_data_resize(
|
|
&scenario->hs_string_constants,
|
|
hs_compile_globals.compiled_source_size);
|
|
short global_index;
|
|
short script_index;
|
|
|
|
if (success)
|
|
{
|
|
hs_compile_globals.string_constant_buffer = scenario->hs_string_constants.address;
|
|
hs_compile_globals.string_constant_buffer_offset = 0;
|
|
hs_compile_globals.string_constant_buffer_size = hs_compile_globals.compiled_source_size;
|
|
|
|
for (global_index = 0; global_index < scenario->hs_globals.count; global_index++)
|
|
{
|
|
struct hs_global *global = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->hs_globals,
|
|
global_index,
|
|
struct hs_global);
|
|
|
|
hs_concatenate_expression(global->initialization_expression_index);
|
|
}
|
|
|
|
for (script_index = 0; script_index < scenario->hs_scripts.count; script_index++)
|
|
{
|
|
struct hs_script *script = TAG_BLOCK_GET_ELEMENT(
|
|
&scenario->hs_scripts,
|
|
script_index,
|
|
struct hs_script);
|
|
|
|
hs_concatenate_expression(script->root_expression_index);
|
|
}
|
|
|
|
hs_node_gc();
|
|
success = tag_data_resize(
|
|
&scenario->hs_string_constants,
|
|
hs_compile_globals.string_constant_buffer_offset +
|
|
HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES);
|
|
}
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x16D,
|
|
success,
|
|
"increase MAXIMUM_HS_STRING_DATA_PER_SCENARIO");
|
|
|
|
return;
|
|
}
|
|
|
|
boolean hs_verify_source_offset(
|
|
long source_offset)
|
|
{
|
|
boolean valid;
|
|
|
|
valid = TRUE;
|
|
if (source_offset < 0 || source_offset >= hs_compile_globals.compiled_source_size)
|
|
{
|
|
hs_compile_globals.error = "bad source offset (you need to recompile.)";
|
|
valid = FALSE;
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
static long hs_find_string_constant(
|
|
char const *string)
|
|
{
|
|
long offset = 0;
|
|
|
|
while (offset < hs_compile_globals.string_constant_buffer_offset)
|
|
{
|
|
char const *existing_string = hs_compile_globals.string_constant_buffer + offset;
|
|
|
|
if (strcmp(string, existing_string) == 0)
|
|
return offset;
|
|
offset += strlen(existing_string) + 1;
|
|
}
|
|
|
|
return NONE;
|
|
}
|
|
|
|
static boolean character_in_list(
|
|
char character,
|
|
short list_count,
|
|
char const *list)
|
|
{
|
|
short character_index;
|
|
|
|
for (character_index = 0; character_index < list_count; character_index++)
|
|
{
|
|
if (character == list[character_index])
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static boolean hs_parse_variable(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result = FALSE;
|
|
long global_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x4E4,
|
|
hs_type_valid(expression->type) || expression->type==_hs_unparsed);
|
|
|
|
global_index = hs_find_global_by_name(
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
expression->data = global_index;
|
|
if (global_index != NONE)
|
|
{
|
|
short global_type = hs_global_get_type((short)expression->data);
|
|
|
|
if (expression->type && !hs_can_cast(global_type, expression->type))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"i expected a value of type %s, but the variable %s has type %s",
|
|
hs_type_names[expression->type],
|
|
hs_global_get_name((short)expression->data),
|
|
hs_type_names[global_type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else
|
|
{
|
|
if (!expression->type)
|
|
expression->type = global_type;
|
|
SET_FLAG(expression->flags, _hs_syntax_node_variable_bit, TRUE);
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else if (hs_compile_globals.variables_predetermined)
|
|
{
|
|
hs_compile_globals.error = "this is not a valid variable name.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void hs_parse_call_predicate(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long predicate_index = hs_syntax_get(expression_index)->data;
|
|
struct hs_syntax_node *predicate = hs_syntax_get(predicate_index);
|
|
|
|
if (predicate->type != _hs_function_name)
|
|
{
|
|
expression->function_index = hs_find_function_by_name(
|
|
hs_compile_globals.compiled_source + predicate->source_offset);
|
|
predicate->type = _hs_function_name;
|
|
if (expression->function_index == NONE)
|
|
{
|
|
expression->function_index = hs_find_script_by_name(
|
|
hs_compile_globals.compiled_source + predicate->source_offset);
|
|
if (expression->function_index != NONE)
|
|
SET_FLAG(expression->flags, _hs_syntax_node_script_bit, TRUE);
|
|
}
|
|
predicate->function_index = expression->function_index;
|
|
}
|
|
else
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x520,
|
|
predicate->function_index!=NONE);
|
|
expression->function_index = predicate->function_index;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static boolean hs_parse_boolean(
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
boolean value;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
char const *string = hs_compile_globals.compiled_source + expression->source_offset;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5B3,
|
|
expression->type==_hs_type_boolean);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5B4,
|
|
expression->constant_type==expression->type);
|
|
|
|
if (csstrcmp(string, "false") == 0 ||
|
|
csstrcmp(string, "off") == 0 ||
|
|
csstrcmp(string, "0") == 0)
|
|
{
|
|
value = FALSE;
|
|
}
|
|
else if (csstrcmp(string, "true") == 0 ||
|
|
csstrcmp(string, "on") == 0 ||
|
|
csstrcmp(string, "1") == 0)
|
|
{
|
|
value = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected \"true\" or \"false\".";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
}
|
|
if (result)
|
|
expression->boolean_value = value;
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_real(
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
char const *string = hs_compile_globals.compiled_source + expression->source_offset;
|
|
boolean decimal = FALSE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5D6,
|
|
expression->type==_hs_type_real);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5D7,
|
|
expression->constant_type==expression->type);
|
|
|
|
if (*string == '-')
|
|
string++;
|
|
while (*string)
|
|
{
|
|
if (!isdigit(*string))
|
|
{
|
|
if (decimal || *string != '.')
|
|
{
|
|
hs_compile_globals.error = "this is not a valid real number.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
decimal = TRUE;
|
|
}
|
|
string++;
|
|
}
|
|
expression->real_value = (real)atof(
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_integer(
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
char const *string = hs_compile_globals.compiled_source + expression->source_offset;
|
|
long value;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5F7,
|
|
expression->type==_hs_type_short_integer || expression->type==_hs_type_long_integer);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x5F8,
|
|
expression->constant_type==expression->type);
|
|
|
|
if (*string == '-')
|
|
string++;
|
|
while (*string)
|
|
{
|
|
if (!isdigit(*string))
|
|
{
|
|
hs_compile_globals.error = "this is not a valid integer.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
string++;
|
|
}
|
|
|
|
value = atoi(hs_compile_globals.compiled_source + expression->source_offset);
|
|
if (result &&
|
|
expression->type != _hs_type_long_integer &&
|
|
(value > SHORT_MAX || value < SHORT_MIN))
|
|
{
|
|
hs_compile_globals.error = "shorts must be in the range [-32767, 32768].";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
}
|
|
if (expression->type == _hs_type_long_integer)
|
|
expression->data = value;
|
|
else
|
|
expression->short_value = (short)value;
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_string(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x61E,
|
|
expression->type==_hs_type_string);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x61F,
|
|
expression->constant_type==expression->type);
|
|
|
|
expression->data = (long)(hs_compile_globals.compiled_source + expression->source_offset);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean hs_parse_script(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
short script_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x62D,
|
|
expression->type==_hs_type_script);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x62E,
|
|
expression->constant_type==expression->type);
|
|
|
|
script_index = hs_find_script_by_name(
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
if (script_index != NONE)
|
|
{
|
|
expression->short_value = script_index;
|
|
return TRUE;
|
|
}
|
|
|
|
hs_compile_globals.error = "this is not a valid script name.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static boolean hs_parse_tag_reference(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
struct scenario *scenario = global_scenario_get();
|
|
tag group_tag;
|
|
short reference_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x69E,
|
|
HS_TYPE_IS_TAG_REFERENCE(expression->type));
|
|
|
|
group_tag = hs_tag_reference_type_group_tags[expression->type - _hs_type_sound];
|
|
for (reference_index = 0;
|
|
reference_index < scenario->hs_references.count;
|
|
reference_index++)
|
|
{
|
|
struct hs_reference *reference = TAG_BLOCK_GET_ELEMENT(
|
|
&scenario->hs_references,
|
|
reference_index,
|
|
struct hs_reference);
|
|
if (csstrcmp(
|
|
reference->reference.name,
|
|
hs_compile_globals.compiled_source + expression->source_offset) == 0 &&
|
|
reference->reference.group_tag == group_tag)
|
|
{
|
|
expression->data = reference->reference.index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean hs_parse_enum(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
struct hs_enum_definition *enum_definition = &hs_enum_table[expression->type-_hs_type_enum_game_difficulty];
|
|
short value_index;
|
|
boolean result = TRUE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x6BC,
|
|
HS_TYPE_IS_ENUM(expression->type));
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x6BD,
|
|
expression->constant_type==expression->type);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x6BE,
|
|
enum_definition->count);
|
|
|
|
for (value_index = 0; value_index < enum_definition->count; value_index++)
|
|
{
|
|
if (_stricmp(
|
|
hs_compile_globals.compiled_source + expression->source_offset,
|
|
enum_definition->values[value_index]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (value_index == enum_definition->count)
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"%s must be ",
|
|
hs_type_names[expression->type]);
|
|
for (value_index = 0; value_index < enum_definition->count - 1; value_index++)
|
|
{
|
|
csstrcat(hs_compile_globals.error_buffer, "\"");
|
|
csstrcat(hs_compile_globals.error_buffer, enum_definition->values[value_index]);
|
|
csstrcat(hs_compile_globals.error_buffer, "\", ");
|
|
}
|
|
if (enum_definition->count > 1)
|
|
csstrcat(hs_compile_globals.error_buffer, "or ");
|
|
csstrcat(hs_compile_globals.error_buffer, "\"");
|
|
csstrcat(hs_compile_globals.error_buffer, enum_definition->values[value_index]);
|
|
csstrcat(hs_compile_globals.error_buffer, "\".");
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
expression->short_value = value_index;
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_scenario_datum(
|
|
long expression_index,
|
|
short offset,
|
|
struct tag_block *block,
|
|
long element_size)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result = FALSE;
|
|
short element_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x6F1,
|
|
element_size<=SHORT_MAX);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x6F2,
|
|
offset+TAG_STRING_LENGTH<element_size);
|
|
for (element_index = 0; element_index < block->count; element_index++)
|
|
{
|
|
char const *element = tag_block_get_element_with_size(
|
|
block,
|
|
element_index,
|
|
element_size);
|
|
if (_stricmp(
|
|
element + offset,
|
|
hs_compile_globals.compiled_source + expression->source_offset) == 0)
|
|
{
|
|
expression->data = element_index;
|
|
result = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!result)
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"this is not a valid %s name",
|
|
hs_type_names[expression->type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_trigger_volume(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x711,
|
|
hs_syntax_get(expression_index)->type==_hs_type_trigger_volume);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
offsetof(struct scenario_trigger_volume, name),
|
|
&global_scenario_get()->trigger_volumes,
|
|
sizeof(struct scenario_trigger_volume));
|
|
}
|
|
|
|
static boolean hs_parse_cutscene_flag(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x719,
|
|
hs_syntax_get(expression_index)->type==_hs_type_cutscene_flag);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
4,
|
|
&global_scenario_get()->cutscene_flags,
|
|
scenario_cutscene_flag_size);
|
|
}
|
|
|
|
static boolean hs_parse_cutscene_camera_point(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x721,
|
|
hs_syntax_get(expression_index)->type==_hs_type_cutscene_camera_point);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
offsetof(struct scenario_cutscene_camera_point, name),
|
|
&global_scenario_get()->cutscene_camera_points,
|
|
sizeof(struct scenario_cutscene_camera_point));
|
|
}
|
|
|
|
static boolean hs_parse_cutscene_title(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x729,
|
|
hs_syntax_get(expression_index)->type==_hs_type_cutscene_title);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
4,
|
|
&global_scenario_get()->cutscene_chapter_titles,
|
|
scenario_cutscene_title_size);
|
|
}
|
|
|
|
static boolean hs_parse_cutscene_recording(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x731,
|
|
hs_syntax_get(expression_index)->type==_hs_type_cutscene_recording);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&global_scenario_get()->recorded_animations,
|
|
scenario_recorded_animation_size);
|
|
}
|
|
|
|
static boolean hs_parse_device_group(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x739,
|
|
hs_syntax_get(expression_index)->type==_hs_type_device_group);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&global_scenario_get()->device_groups,
|
|
scenario_device_group_size);
|
|
}
|
|
|
|
static boolean hs_parse_ai(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x744,
|
|
hs_syntax_get(expression_index)->type==_hs_type_ai);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x745,
|
|
expression->constant_type==expression->type);
|
|
|
|
result = ai_index_from_string(
|
|
global_scenario_get(),
|
|
hs_compile_globals.compiled_source + expression->source_offset,
|
|
&expression->data);
|
|
if (!result)
|
|
{
|
|
hs_compile_globals.error = "this is not a valid ai encounter or squad.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_ai_command_list(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x755,
|
|
hs_syntax_get(expression_index)->type==_hs_type_ai_command_list);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&global_scenario_get()->ai_command_lists,
|
|
scenario_ai_command_list_size);
|
|
}
|
|
|
|
static boolean hs_parse_starting_profile(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x75D,
|
|
hs_syntax_get(expression_index)->type==_hs_type_starting_profile);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&global_scenario_get()->starting_profiles,
|
|
sizeof(struct scenario_starting_profile));
|
|
}
|
|
|
|
static boolean hs_parse_conversation(
|
|
long expression_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x765,
|
|
hs_syntax_get(expression_index)->type==_hs_type_conversation);
|
|
|
|
return hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&global_scenario_get()->ai_conversations,
|
|
scenario_conversation_size);
|
|
}
|
|
|
|
static boolean hs_parse_object_name(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
short object_name_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x771,
|
|
HS_TYPE_IS_OBJECT_NAME(expression->type));
|
|
|
|
object_name_index = scenario_object_name_index_from_string(
|
|
global_scenario_get(),
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
if (object_name_index != NONE)
|
|
{
|
|
struct scenario_object_name *object_name = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->object_names,
|
|
object_name_index,
|
|
struct scenario_object_name);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x77A,
|
|
object_name->runtime_object_type!=NONE);
|
|
if (TEST_FLAG(
|
|
(short)hs_object_type_masks[expression->type - first_hs_object_name_type],
|
|
object_name->runtime_object_type))
|
|
{
|
|
expression->short_value = object_name_index;
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"this is not an object of type %s.",
|
|
hs_type_names[expression->type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this is not a valid object name.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_object(
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x79A,
|
|
HS_TYPE_IS_OBJECT(expression->type));
|
|
|
|
if (csstrcmp(
|
|
hs_compile_globals.compiled_source + expression->source_offset,
|
|
"none") == 0)
|
|
{
|
|
expression->data = NONE;
|
|
}
|
|
else
|
|
{
|
|
expression->type += NUMBER_OF_HS_OBJECT_TYPES;
|
|
expression->constant_type = expression->type;
|
|
result = hs_parse_object_name(expression_index);
|
|
expression->type -= NUMBER_OF_HS_OBJECT_TYPES;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_navpoint(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long hud_globals_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x7B1,
|
|
hs_syntax_get(expression_index)->type==_hs_type_navpoint);
|
|
|
|
hud_globals_index = interface_get_tag_index(_interface_hud_globals);
|
|
if (hud_globals_index != NONE)
|
|
{
|
|
struct hud_globals_definition *hud_globals;
|
|
|
|
hud_globals = hud_globals_definition_get(
|
|
interface_get_tag_index(_interface_hud_globals));
|
|
result = hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&hud_globals->waypoint.arrows,
|
|
hud_waypoint_arrow_size);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_hud_message(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x7BF,
|
|
hs_syntax_get(expression_index)->type==_hs_type_hud_message);
|
|
|
|
if (global_scenario_get()->hud_messages.index != NONE)
|
|
{
|
|
struct hud_message_text_definition *hud_messages;
|
|
|
|
hud_messages = hud_message_text_definition_get(
|
|
global_scenario_get()->hud_messages.index);
|
|
result = hs_parse_scenario_datum(
|
|
expression_index,
|
|
0,
|
|
&hud_messages->messages,
|
|
hud_message_definition_size);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_object_list(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x7CF,
|
|
expression->type==_hs_type_object_list);
|
|
|
|
expression->constant_type = first_hs_object_name_type;
|
|
expression->type = first_hs_object_name_type;
|
|
result = hs_parse_object_name(expression_index);
|
|
expression->type = _hs_type_object_list;
|
|
|
|
return result;
|
|
}
|
|
|
|
static short string_list_find(
|
|
char const *string,
|
|
short list_count,
|
|
char const **list)
|
|
{
|
|
short list_index;
|
|
|
|
for (list_index = 0; list_index < list_count; list_index++)
|
|
{
|
|
if (!strcmp(string, list[list_index]))
|
|
return list_index;
|
|
}
|
|
|
|
return NONE;
|
|
}
|
|
|
|
static long hs_concatenate_string_constant(
|
|
char const *string)
|
|
{
|
|
long result = hs_find_string_constant(string);
|
|
|
|
if (result == NONE)
|
|
{
|
|
short string_size = (short)(strlen(string) + 1);
|
|
|
|
if (string_size < hs_compile_globals.string_constant_buffer_size)
|
|
{
|
|
memcpy(
|
|
hs_compile_globals.string_constant_buffer + hs_compile_globals.string_constant_buffer_offset,
|
|
string,
|
|
string_size);
|
|
result = hs_compile_globals.string_constant_buffer_offset;
|
|
hs_compile_globals.string_constant_buffer_offset += string_size;
|
|
hs_compile_globals.string_constant_buffer_size -= string_size;
|
|
}
|
|
else
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x264,
|
|
string_size<hs_compile_globals.string_constant_buffer_size,
|
|
"ran out of script string constant memory");
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_add_global(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long type_expression_index = hs_syntax_get(expression->data)->next_node_index;
|
|
long name_expression_index;
|
|
long value_expression_index;
|
|
|
|
if (type_expression_index != NONE
|
|
&& (name_expression_index = hs_syntax_get(type_expression_index)->next_node_index) != NONE
|
|
&& (value_expression_index = hs_syntax_get(name_expression_index)->next_node_index) != NONE
|
|
&& hs_syntax_get(value_expression_index)->next_node_index == NONE)
|
|
{
|
|
char const *type_name = hs_compile_globals.compiled_source + hs_syntax_get(type_expression_index)->source_offset;
|
|
short type = string_list_find(type_name, NUMBER_OF_HS_TYPES, hs_type_names);
|
|
|
|
if (!hs_type_valid(type))
|
|
{
|
|
hs_compile_globals.error = "this is not a valid type.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(type_expression_index)->source_offset;
|
|
}
|
|
else
|
|
{
|
|
char const *global_name = hs_compile_globals.compiled_source + hs_syntax_get(name_expression_index)->source_offset;
|
|
|
|
if (strlen(global_name) > 0 && strlen(global_name) <= TAG_STRING_LENGTH)
|
|
{
|
|
if (hs_find_global_by_name(global_name) == NONE)
|
|
{
|
|
hs_compile_globals.disallow_blocks = TRUE;
|
|
hs_compile_globals.disallow_sets = TRUE;
|
|
if (hs_parse(value_expression_index, type))
|
|
{
|
|
short global_index = (short)tag_block_add_element(&global_scenario_get()->hs_globals);
|
|
|
|
if (global_index != NONE)
|
|
{
|
|
struct hs_global *global = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->hs_globals,
|
|
global_index,
|
|
struct hs_global);
|
|
|
|
strcpy(global->name, global_name);
|
|
global->type = type;
|
|
global->initialization_expression_index = value_expression_index;
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate space for this global.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
}
|
|
hs_compile_globals.disallow_blocks = FALSE;
|
|
hs_compile_globals.disallow_sets = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "there is already a variable by this name.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(name_expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected a global variable name less than 32 characters.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(name_expression_index)->source_offset;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected (global<type> <name> <initial value>)";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_add_script(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long script_type_expression_index = hs_syntax_get(hs_syntax_get(expression_index)->data)->next_node_index;
|
|
|
|
if (script_type_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *script_type_expression = hs_syntax_get(script_type_expression_index);
|
|
short script_type = string_list_find(
|
|
hs_compile_globals.compiled_source + script_type_expression->source_offset,
|
|
NUMBER_OF_HS_SCRIPT_TYPES,
|
|
hs_script_type_names);
|
|
|
|
if (script_type != NONE)
|
|
{
|
|
short return_type;
|
|
long name_expression_index = NONE;
|
|
long body_expression_index;
|
|
|
|
if (script_type == _hs_script_static || script_type == _hs_script_stub)
|
|
{
|
|
long return_type_expression_index = hs_syntax_get(script_type_expression_index)->next_node_index;
|
|
|
|
if (return_type_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *return_type_expression = hs_syntax_get(return_type_expression_index);
|
|
|
|
return_type = string_list_find(
|
|
hs_compile_globals.compiled_source + return_type_expression->source_offset,
|
|
NUMBER_OF_HS_TYPES,
|
|
hs_type_names);
|
|
name_expression_index = hs_syntax_get(return_type_expression_index)->next_node_index;
|
|
if (hs_type_valid(return_type))
|
|
{
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this is not a valid return type.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(return_type_expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected (script local <type> <name> <expression(s)>).";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return_type = _hs_type_void;
|
|
name_expression_index = hs_syntax_get(script_type_expression_index)->next_node_index;
|
|
result = TRUE;
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
result = FALSE;
|
|
if (name_expression_index != NONE &&
|
|
(body_expression_index = hs_syntax_get(name_expression_index)->next_node_index) != NONE)
|
|
{
|
|
struct hs_syntax_node *name_expression = hs_syntax_get(name_expression_index);
|
|
char const *script_name = hs_compile_globals.compiled_source + name_expression->source_offset;
|
|
|
|
if (strlen(script_name) > 0 && strlen(script_name) <= TAG_STRING_LENGTH)
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
long script_index = hs_find_script_by_name(script_name);
|
|
|
|
if (script_index == NONE)
|
|
{
|
|
script_index = tag_block_add_element(&scenario->hs_scripts);
|
|
if (script_index == NONE)
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate a script.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct hs_script *existing_script = TAG_BLOCK_GET_ELEMENT(
|
|
&scenario->hs_scripts,
|
|
script_index,
|
|
struct hs_script);
|
|
|
|
if (existing_script->script_type != _hs_script_stub ||
|
|
existing_script->return_type != return_type ||
|
|
script_type != _hs_script_static)
|
|
{
|
|
if (existing_script->script_type == _hs_script_static &&
|
|
existing_script->return_type == return_type &&
|
|
script_type == _hs_script_stub)
|
|
{
|
|
/* the static script already replaced this stub */
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "only static scripts of the same type can override stub scripts.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
script_index = NONE;
|
|
}
|
|
}
|
|
|
|
if (script_index != NONE)
|
|
{
|
|
struct hs_script *script = TAG_BLOCK_GET_ELEMENT(
|
|
&scenario->hs_scripts,
|
|
script_index,
|
|
struct hs_script);
|
|
long root_expression_index = datum_new(hs_syntax_data);
|
|
long begin_expression_index = datum_new(hs_syntax_data);
|
|
|
|
if (root_expression_index != NONE && begin_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *root_expression = hs_syntax_get(root_expression_index);
|
|
struct hs_syntax_node *begin_expression = hs_syntax_get(begin_expression_index);
|
|
|
|
root_expression->data = begin_expression_index;
|
|
root_expression->next_node_index = NONE;
|
|
root_expression->source_offset = hs_syntax_get(expression_index)->source_offset;
|
|
root_expression->flags = 0;
|
|
begin_expression->next_node_index = body_expression_index;
|
|
begin_expression->source_offset = NONE;
|
|
begin_expression->function_index = _hs_function_begin;
|
|
begin_expression->flags = FLAG(_hs_syntax_node_primitive_bit);
|
|
begin_expression->type = _hs_function_name;
|
|
if (hs_parse(root_expression_index, return_type))
|
|
{
|
|
strcpy(script->name, script_name);
|
|
script->return_type = return_type;
|
|
script->script_type = script_type;
|
|
script->root_expression_index = root_expression_index;
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate a syntax node.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected a script name less than 32 characters.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(name_expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (script_type == _hs_script_static)
|
|
hs_compile_globals.error = "i expected (script static <type> <name> <expression(s)>)";
|
|
else if (script_type == _hs_script_stub)
|
|
hs_compile_globals.error = "i expected (script stub <type> <name> <expression(s)>)";
|
|
else
|
|
hs_compile_globals.error = "i expected (script <type> <name> <expression(s)>)";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "script type must be \"startup\", \"dormant\", \"continuous\", or \"static\".";
|
|
hs_compile_globals.error_offset = hs_syntax_get(script_type_expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected (script <type> <name> <expression(s)>)";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void hs_tokenize_primitive(
|
|
struct hs_tokenizer *tokenizer,
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
char *token_start = tokenizer->cursor;
|
|
char character;
|
|
|
|
if (*token_start == '"')
|
|
{
|
|
tokenizer->cursor = token_start + 1;
|
|
expression->source_offset = tokenizer->cursor - hs_compile_globals.compiled_source;
|
|
while (*tokenizer->cursor && *tokenizer->cursor != '"')
|
|
tokenizer->cursor++;
|
|
if (!*tokenizer->cursor)
|
|
{
|
|
hs_compile_globals.error = "this quoted constant is unterminated.";
|
|
hs_compile_globals.error_offset = expression->source_offset - 1;
|
|
}
|
|
*tokenizer->cursor = 0;
|
|
tokenizer->cursor++;
|
|
}
|
|
else
|
|
{
|
|
expression->source_offset = token_start - hs_compile_globals.compiled_source;
|
|
while (*tokenizer->cursor)
|
|
{
|
|
char *position = tokenizer->cursor;
|
|
|
|
character = *position;
|
|
if (character == ')' || character == ';')
|
|
break;
|
|
if (character_in_list(character, NUMBEROF(whitespace_characters), whitespace_characters) ||
|
|
character_in_list(character, NUMBEROF(eol_characters), eol_characters))
|
|
{
|
|
break;
|
|
}
|
|
tokenizer->cursor = position + 1;
|
|
}
|
|
}
|
|
|
|
strlwr(hs_compile_globals.compiled_source + expression->source_offset);
|
|
return;
|
|
}
|
|
|
|
static boolean hs_parse_primitive(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result = FALSE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x4AF,
|
|
hs_type_valid(expression->type) || expression->type==_hs_special_form || expression->type==_hs_unparsed);
|
|
|
|
if (expression->type == _hs_special_form)
|
|
{
|
|
hs_compile_globals.error = "i expected a script or variable definition.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else if (expression->type == _hs_type_void)
|
|
{
|
|
hs_compile_globals.error = "the value of this expression (in a <void> slot) can never be used.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else
|
|
{
|
|
if (!hs_compile_globals.variables_predetermined ||
|
|
TEST_FLAG(expression->flags, _hs_syntax_node_variable_bit))
|
|
{
|
|
result = hs_parse_variable(expression_index);
|
|
}
|
|
if (!result &&
|
|
expression->type &&
|
|
!hs_compile_globals.error &&
|
|
(!hs_compile_globals.variables_predetermined ||
|
|
!TEST_FLAG(expression->flags, _hs_syntax_node_variable_bit)))
|
|
{
|
|
hs_primitive_parser parser = hs_type_primitive_parsers[expression->type];
|
|
|
|
if (parser)
|
|
{
|
|
return parser(expression_index);
|
|
}
|
|
else
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"expressions of type %s are currently unsupported.",
|
|
hs_type_names[expression->type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean hs_parse_nonprimitive(
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long predicate_index = hs_syntax_get(expression_index)->data;
|
|
struct hs_syntax_node *predicate = hs_syntax_get(predicate_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x534,
|
|
hs_type_valid(expression->type) || expression->type==_hs_special_form || expression->type==_hs_unparsed);
|
|
if (TEST_FLAG(hs_syntax_get(predicate_index)->flags, _hs_syntax_node_primitive_bit))
|
|
{
|
|
if (expression->type == _hs_special_form)
|
|
{
|
|
if (!strcmp(hs_compile_globals.compiled_source + predicate->source_offset, "global"))
|
|
{
|
|
result = hs_add_global(expression_index);
|
|
}
|
|
else if (!strcmp(hs_compile_globals.compiled_source + predicate->source_offset, "script"))
|
|
{
|
|
result = hs_add_script(expression_index);
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected \"script\" or \"global\".";
|
|
hs_compile_globals.error_offset = predicate->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_parse_call_predicate(expression_index);
|
|
if (expression->function_index != NONE)
|
|
{
|
|
if (TEST_FLAG(expression->flags, _hs_syntax_node_script_bit))
|
|
{
|
|
struct hs_script *script = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->hs_scripts,
|
|
expression->function_index,
|
|
struct hs_script);
|
|
|
|
if (script->script_type != _hs_script_static && script->script_type != _hs_script_stub)
|
|
{
|
|
hs_compile_globals.error = "this is not a static script.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else if (expression->type && !hs_can_cast(script->return_type, expression->type))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"i expected a %s, but this script returns a %s.",
|
|
hs_type_names[expression->type],
|
|
hs_type_names[script->return_type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else
|
|
{
|
|
if (!expression->type)
|
|
expression->type = script->return_type;
|
|
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct hs_function_definition *function = hs_function_get(expression->function_index);
|
|
|
|
if (expression->type && !hs_can_cast(function->return_type, expression->type))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"i expected a %s, but this function returns a %s.",
|
|
hs_type_names[expression->type],
|
|
hs_type_names[function->return_type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else if (hs_compile_globals.disallow_blocks &&
|
|
(expression->function_index == _hs_function_sleep || expression->function_index == _hs_function_sleep_until))
|
|
{
|
|
hs_compile_globals.error = "it is illegal to block in this context.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else if (hs_compile_globals.disallow_sets && expression->function_index == _hs_function_set)
|
|
{
|
|
hs_compile_globals.error = "it is illegal to set the value of variables in this context.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
else
|
|
{
|
|
if (!expression->type && function->return_type != _hs_passthrough)
|
|
expression->type = function->return_type;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x58C,
|
|
function->parse);
|
|
result = function->parse(expression->function_index, expression_index);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this is not a valid function or script name.";
|
|
hs_compile_globals.error_offset = predicate->source_offset;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char const *expected_name = expression->type == _hs_special_form ?
|
|
"\"script\" or \"global\"" :
|
|
"a function name";
|
|
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"i expected %s, but i got an expression.",
|
|
expected_name);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = predicate->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_compile_postprocess(
|
|
char const **error_message_pointer,
|
|
char const **error_source_pointer)
|
|
{
|
|
boolean success = TRUE;
|
|
long expression_index;
|
|
short resolved_type;
|
|
struct hs_script *script;
|
|
|
|
hs_compile_globals.compiled_source = global_scenario_get()->hs_string_constants.address;
|
|
hs_compile_globals.compiled_source_size =
|
|
global_scenario_get()->hs_string_constants.size - HS_MAXIMUM_DYNAMIC_SOURCE_DATA_BYTES;
|
|
hs_compile_globals.error = NULL;
|
|
hs_compile_globals.variables_predetermined = TRUE;
|
|
*error_message_pointer = NULL;
|
|
*error_source_pointer = NULL;
|
|
|
|
for (expression_index = data_next_index(hs_syntax_data, NONE);
|
|
success && expression_index != NONE;
|
|
expression_index = data_next_index(hs_syntax_data, expression_index))
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
if (hs_type_valid(expression->type))
|
|
{
|
|
if (TEST_FLAG(hs_syntax_get(expression_index)->flags, _hs_syntax_node_primitive_bit))
|
|
{
|
|
if (expression->type >= _hs_type_string ||
|
|
TEST_FLAG(expression->flags, _hs_syntax_node_variable_bit))
|
|
{
|
|
success = hs_verify_source_offset(expression->source_offset);
|
|
if (success)
|
|
success = hs_parse_primitive(expression_index);
|
|
}
|
|
|
|
if (success && TEST_FLAG(expression->flags, _hs_syntax_node_variable_bit))
|
|
resolved_type = hs_global_get_type((short)expression->data);
|
|
else
|
|
resolved_type = expression->constant_type;
|
|
}
|
|
else if (TEST_FLAG(expression->flags, _hs_syntax_node_script_bit))
|
|
{
|
|
if (expression->script_index >= 0 &&
|
|
expression->script_index < global_scenario_get()->hs_scripts.count &&
|
|
((script = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->hs_scripts,
|
|
expression->script_index,
|
|
struct hs_script))->script_type == _hs_script_static ||
|
|
script->script_type == _hs_script_stub))
|
|
{
|
|
resolved_type = script->return_type;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "bad script index (you need to recompile.)";
|
|
success = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long predicate_index = hs_syntax_get(expression_index)->data;
|
|
struct hs_syntax_node *predicate;
|
|
|
|
if (predicate_index == NONE ||
|
|
(predicate = hs_syntax_get(predicate_index))->type != _hs_function_name)
|
|
{
|
|
hs_compile_globals.error = "corrupt syntax tree (you need to recompile scripts.)";
|
|
success = FALSE;
|
|
}
|
|
else if (hs_verify_source_offset(predicate->source_offset))
|
|
{
|
|
short function_index = hs_find_function_by_name(
|
|
hs_compile_globals.compiled_source + predicate->source_offset);
|
|
|
|
if (function_index != NONE)
|
|
{
|
|
expression->function_index = function_index;
|
|
resolved_type = hs_function_get(expression->function_index)->return_type;
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "missing function (you need to recompile scripts.)";
|
|
success = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
if ((!hs_type_valid(resolved_type) && resolved_type != _hs_passthrough) ||
|
|
!hs_can_cast(resolved_type, expression->type))
|
|
{
|
|
hs_compile_globals.error = "type is inconsistent with usage (you need to recompile scripts.)";
|
|
success = FALSE;
|
|
}
|
|
else
|
|
{
|
|
success = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if (expression->type != _hs_function_name)
|
|
{
|
|
hs_compile_globals.error = "missing type (you need to recompile scripts.)";
|
|
success = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
*error_message_pointer = hs_compile_globals.error;
|
|
if (hs_compile_globals.error_offset != NONE)
|
|
*error_source_pointer = hs_compile_globals.compiled_source + hs_compile_globals.error_offset;
|
|
}
|
|
|
|
hs_compile_globals.compiled_source = NULL;
|
|
hs_compile_globals.error = NULL;
|
|
hs_compile_globals.variables_predetermined = FALSE;
|
|
|
|
return success;
|
|
}
|
|
|
|
static void hs_concatenate_expression(
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
SET_FLAG(expression->flags, _hs_syntax_node_permanent_bit, TRUE);
|
|
if (TEST_FLAG(hs_syntax_get(expression_index)->flags, _hs_syntax_node_primitive_bit))
|
|
{
|
|
if (expression->type == _hs_function_name)
|
|
{
|
|
if (expression->source_offset != NONE)
|
|
{
|
|
expression->source_offset = hs_concatenate_string_constant(
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
}
|
|
else
|
|
{
|
|
expression->source_offset = hs_concatenate_string_constant(
|
|
hs_function_get(expression->function_index)->name);
|
|
}
|
|
}
|
|
else if (TEST_FLAG(expression->flags, _hs_syntax_node_variable_bit) || expression->type >= _hs_type_string)
|
|
{
|
|
expression->source_offset = hs_concatenate_string_constant(
|
|
hs_compile_globals.compiled_source + expression->source_offset);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long child_expression_index;
|
|
|
|
for (child_expression_index = expression->data;
|
|
child_expression_index != NONE;
|
|
child_expression_index = hs_syntax_get(child_expression_index)->next_node_index)
|
|
{
|
|
hs_concatenate_expression(child_expression_index);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static long hs_tokenize(
|
|
struct hs_tokenizer *tokenizer)
|
|
{
|
|
long expression_index = datum_new(hs_syntax_data);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x39E,
|
|
!hs_compile_globals.error);
|
|
if (expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
expression->flags = 0;
|
|
expression->type = _hs_unparsed;
|
|
expression->function_index = NONE;
|
|
expression->next_node_index = NONE;
|
|
expression->flags = *tokenizer->cursor != '(';
|
|
if (TEST_FLAG(hs_syntax_get(expression_index)->flags, _hs_syntax_node_primitive_bit))
|
|
hs_tokenize_primitive(tokenizer, expression_index);
|
|
else
|
|
hs_tokenize_nonprimitive(tokenizer, expression_index);
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i couldn't allocate a syntax node.";
|
|
}
|
|
|
|
return expression_index;
|
|
}
|
|
|
|
static void hs_tokenize_nonprimitive(
|
|
struct hs_tokenizer *tokenizer,
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long *child_link = &expression->data;
|
|
|
|
expression->source_offset = tokenizer->cursor - hs_compile_globals.compiled_source;
|
|
tokenizer->cursor++;
|
|
if (!hs_compile_globals.error)
|
|
{
|
|
do
|
|
{
|
|
char *token_start = tokenizer->cursor;
|
|
long child_index;
|
|
|
|
skip_whitespace(&tokenizer->cursor);
|
|
if (tokenizer->cursor != token_start)
|
|
*token_start = 0;
|
|
if (!*tokenizer->cursor)
|
|
{
|
|
hs_compile_globals.error = "this left parenthesis is unmatched.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
break;
|
|
}
|
|
if (*tokenizer->cursor == ')')
|
|
{
|
|
*tokenizer->cursor = 0;
|
|
tokenizer->cursor++;
|
|
break;
|
|
}
|
|
|
|
child_index = hs_tokenize(tokenizer);
|
|
*child_link = child_index;
|
|
if (child_index != NONE)
|
|
child_link = &hs_syntax_get(child_index)->next_node_index;
|
|
}
|
|
while (!hs_compile_globals.error);
|
|
}
|
|
|
|
if (child_link == &expression->data && !hs_compile_globals.error)
|
|
{
|
|
hs_compile_globals.error = "this expression is empty.";
|
|
hs_compile_globals.error_offset = expression->source_offset;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void skip_whitespace(
|
|
char **cursor)
|
|
{
|
|
short state = _hs_tokenizer_state_normal;
|
|
char *position;
|
|
char character;
|
|
|
|
do
|
|
{
|
|
switch (state)
|
|
{
|
|
case _hs_tokenizer_state_normal:
|
|
position = *cursor;
|
|
character = *position;
|
|
if (character == ';')
|
|
{
|
|
*cursor = position + 1;
|
|
state = _hs_tokenizer_state_line_comment;
|
|
if (position[1] == '*')
|
|
{
|
|
state = _hs_tokenizer_state_block_comment;
|
|
(*cursor)++;
|
|
}
|
|
break;
|
|
}
|
|
if (character_in_list(character, NUMBEROF(whitespace_characters), whitespace_characters) ||
|
|
character_in_list(character, NUMBEROF(eol_characters), eol_characters))
|
|
{
|
|
goto skip_character;
|
|
}
|
|
return;
|
|
|
|
case _hs_tokenizer_state_line_comment:
|
|
position = *cursor;
|
|
if (!*position)
|
|
return;
|
|
if (character_in_list(*position, NUMBEROF(eol_characters), eol_characters))
|
|
state = _hs_tokenizer_state_normal;
|
|
goto skip_character;
|
|
|
|
case _hs_tokenizer_state_block_comment:
|
|
position = *cursor;
|
|
if (!*position)
|
|
{
|
|
hs_compile_globals.error = "unterminated comment.";
|
|
return;
|
|
}
|
|
if (*position == '*' && position[1] == ';')
|
|
{
|
|
state = _hs_tokenizer_state_normal;
|
|
*cursor = position + 1;
|
|
}
|
|
(*cursor)++;
|
|
break;
|
|
|
|
default:
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x46C,
|
|
!"unreachable");
|
|
break;
|
|
}
|
|
continue;
|
|
|
|
skip_character:
|
|
*cursor = position + 1;
|
|
}
|
|
while (state != _hs_tokenizer_state_done);
|
|
|
|
return;
|
|
}
|
|
|
|
boolean hs_parse(
|
|
long expression_index,
|
|
short expected_type)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x48E,
|
|
!hs_compile_globals.error);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x491,
|
|
hs_type_valid(expected_type) || expected_type==_hs_special_form || expected_type==_hs_unparsed);
|
|
if (!expression->type)
|
|
{
|
|
expression->type = expected_type;
|
|
if (TEST_FLAG(hs_syntax_get(expression_index)->flags, _hs_syntax_node_primitive_bit))
|
|
{
|
|
expression->constant_type = expected_type;
|
|
result = hs_parse_primitive(expression_index);
|
|
}
|
|
else
|
|
{
|
|
result = hs_parse_nonprimitive(expression_index);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_macro_function_parse(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_function_definition *definition = hs_function_get(function_index);
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long argument_expression_index = hs_syntax_get(expression->data)->next_node_index;
|
|
short parameter_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\hs\\hs_compile.c",
|
|
0x819,
|
|
hs_type_valid(definition->return_type));
|
|
for (parameter_index = 0;
|
|
result && parameter_index < definition->parameter_count && argument_expression_index != NONE;
|
|
parameter_index++)
|
|
{
|
|
if (hs_parse(argument_expression_index, definition->parameter_types[parameter_index]))
|
|
{
|
|
struct hs_syntax_node *argument = hs_syntax_get(argument_expression_index);
|
|
|
|
argument_expression_index = argument->next_node_index;
|
|
}
|
|
else
|
|
{
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
if (result &&
|
|
(parameter_index != definition->parameter_count || argument_expression_index != NONE))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"the \"%s\" call requires exactly %d arguments.",
|
|
definition->name,
|
|
definition->parameter_count);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_begin(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long argument_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
long next_expression_index;
|
|
short argument_count;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x15,
|
|
function_index==_hs_function_begin || function_index==_hs_function_begin_random);
|
|
for (argument_count = 0;
|
|
result && argument_expression_index != NONE;
|
|
argument_expression_index = next_expression_index, argument_count++)
|
|
{
|
|
next_expression_index = hs_syntax_get(argument_expression_index)->next_node_index;
|
|
if (function_index == _hs_function_begin)
|
|
{
|
|
short expected_type;
|
|
|
|
if (next_expression_index == NONE)
|
|
expected_type = expression->type;
|
|
else
|
|
expected_type = _hs_type_void;
|
|
result = hs_parse(argument_expression_index, expected_type);
|
|
if (next_expression_index == NONE && !expression->type && result)
|
|
expression->type = hs_syntax_get(argument_expression_index)->type;
|
|
}
|
|
else
|
|
{
|
|
result = hs_parse(argument_expression_index, expression->type);
|
|
if (!expression->type && result)
|
|
expression->type = hs_syntax_get(argument_expression_index)->type;
|
|
}
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
if (argument_count < 1)
|
|
{
|
|
/* BUG (preserved for exact matching): January passes the function name
|
|
* although this format has no conversion for it; the argument is ignored. */
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"a statement block must contain at least one argument.",
|
|
hs_function_get(function_index)->name);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
else if (argument_count > MAXIMUM_HS_BEGIN_RANDOM_ARGUMENTS &&
|
|
function_index == _hs_function_begin_random)
|
|
{
|
|
hs_compile_globals.error = "begin_random can take a maximum of 32 arguments (matt can increase this.)";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_if(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
boolean valid = FALSE;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
long condition_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x5B,
|
|
function_index==_hs_function_if);
|
|
if (condition_expression_index != NONE)
|
|
{
|
|
long then_expression_index = hs_syntax_get(condition_expression_index)->next_node_index;
|
|
|
|
if (then_expression_index != NONE)
|
|
{
|
|
long else_expression_index = hs_syntax_get(then_expression_index)->next_node_index;
|
|
|
|
if (else_expression_index == NONE ||
|
|
hs_syntax_get(else_expression_index)->next_node_index == NONE)
|
|
{
|
|
valid = TRUE;
|
|
if (hs_parse(condition_expression_index, _hs_type_boolean))
|
|
{
|
|
if (hs_parse(then_expression_index, expression->type))
|
|
{
|
|
if (!expression->type)
|
|
expression->type = hs_syntax_get(then_expression_index)->type;
|
|
result = else_expression_index == NONE ||
|
|
hs_parse(else_expression_index, expression->type);
|
|
}
|
|
else if (!hs_compile_globals.error &&
|
|
!expression->type &&
|
|
else_expression_index != NONE &&
|
|
hs_parse(else_expression_index, expression->type))
|
|
{
|
|
expression->type = hs_syntax_get(else_expression_index)->type;
|
|
result = hs_parse(then_expression_index, expression->type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!valid)
|
|
{
|
|
hs_compile_globals.error = "i expected (if <condition> <then> [<else>]).";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_cond(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long new_expression_index = hs_parse_cond_recursive(
|
|
expression_index,
|
|
hs_syntax_get(hs_syntax_get(expression_index)->data)->next_node_index);
|
|
|
|
if (new_expression_index != NONE)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
struct hs_syntax_node *new_expression = hs_syntax_get(new_expression_index);
|
|
short datum_header = expression->datum_header;
|
|
short type = expression->type;
|
|
|
|
new_expression->next_node_index = expression->next_node_index;
|
|
*expression = *new_expression;
|
|
expression->datum_header = datum_header;
|
|
result = hs_parse(expression_index, type);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_set(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long variable_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
|
|
if (variable_expression_index != NONE)
|
|
{
|
|
long value_expression_index = hs_syntax_get(variable_expression_index)->next_node_index;
|
|
|
|
if (value_expression_index != NONE)
|
|
{
|
|
if (hs_syntax_get(value_expression_index)->next_node_index == NONE)
|
|
{
|
|
struct hs_syntax_node *variable_expression = hs_syntax_get(variable_expression_index);
|
|
short global_index = hs_find_global_by_name(
|
|
hs_compile_globals.compiled_source + variable_expression->source_offset);
|
|
|
|
if (global_index != NONE)
|
|
{
|
|
short global_type = hs_global_get_type(global_index);
|
|
|
|
variable_expression->type = global_type;
|
|
if (expression->type && !hs_can_cast(global_type, expression->type))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"you cannot pass the result of this set (type %s) to a function that expects type %s.",
|
|
hs_type_names[variable_expression->type],
|
|
hs_type_names[hs_syntax_get(expression_index)->type]);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
else
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x126,
|
|
hs_parse_variable(variable_expression_index),
|
|
"asserted");
|
|
if (!expression->type)
|
|
expression->type = variable_expression->type;
|
|
if (hs_parse(value_expression_index, variable_expression->type))
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "this is not a valid global variable.";
|
|
hs_compile_globals.error_offset = variable_expression->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i didn't expect this argument.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(
|
|
hs_syntax_get(value_expression_index)->next_node_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected an assignment value.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "i expected a variable to set and a value.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_logical(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
long argument_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
short argument_count;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x15D,
|
|
function_index==_hs_function_and || function_index==_hs_function_or);
|
|
for (argument_count = 0;
|
|
result && argument_expression_index != NONE;
|
|
argument_count++)
|
|
{
|
|
result = hs_parse(argument_expression_index, _hs_type_boolean);
|
|
argument_expression_index = hs_syntax_get(argument_expression_index)->next_node_index;
|
|
}
|
|
|
|
if (result && argument_count < 2)
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"the %s call requires at least 2 arguments.",
|
|
hs_function_get(function_index)->name);
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_arithmetic(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
long argument_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
short argument_count;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x17D,
|
|
function_index>=_hs_function_plus && function_index<=_hs_function_max);
|
|
for (argument_count = 0;
|
|
result && argument_expression_index != NONE;
|
|
argument_count++)
|
|
{
|
|
result = hs_parse(argument_expression_index, _hs_type_real);
|
|
argument_expression_index = hs_syntax_get(argument_expression_index)->next_node_index;
|
|
}
|
|
|
|
if ((result && argument_count < 2) ||
|
|
(function_index == _hs_function_divide && argument_count > 2))
|
|
{
|
|
sprintf(
|
|
hs_compile_globals.error_buffer,
|
|
"the %s call requires %s2 arguments.",
|
|
hs_function_get(function_index)->name,
|
|
function_index == _hs_function_divide ? "" : "at least ");
|
|
hs_compile_globals.error = hs_compile_globals.error_buffer;
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_equality(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long argument_indices[2];
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x1BC,
|
|
function_index==_hs_function_equal || function_index==_hs_function_not_equal);
|
|
if (hs_get_parameter_indices(
|
|
hs_function_get(function_index)->name,
|
|
2,
|
|
argument_indices,
|
|
expression_index))
|
|
{
|
|
if (hs_parse(argument_indices[0], _hs_unparsed))
|
|
{
|
|
if (hs_parse(argument_indices[1], hs_syntax_get(argument_indices[0])->type))
|
|
result = TRUE;
|
|
}
|
|
else if (!hs_compile_globals.error)
|
|
{
|
|
if (hs_parse(argument_indices[1], _hs_unparsed))
|
|
{
|
|
if (hs_parse(argument_indices[0], hs_syntax_get(argument_indices[1])->type))
|
|
result = TRUE;
|
|
}
|
|
else if (!hs_compile_globals.error)
|
|
{
|
|
if (hs_parse(argument_indices[0], _hs_type_real) &&
|
|
hs_parse(argument_indices[1], _hs_type_real))
|
|
result = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_inequality(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long argument_indices[2];
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x1E3,
|
|
function_index>=_hs_function_gt && function_index<=_hs_function_lte);
|
|
if (hs_get_parameter_indices(
|
|
hs_function_get(function_index)->name,
|
|
2,
|
|
argument_indices,
|
|
expression_index))
|
|
{
|
|
if (hs_parse(argument_indices[0], _hs_unparsed) &&
|
|
(HS_TYPE_IS_ENUM(hs_syntax_get(argument_indices[0])->type) ||
|
|
(hs_syntax_get(argument_indices[0])->type>=_hs_type_real &&
|
|
hs_syntax_get(argument_indices[0])->type<=_hs_type_long_integer)))
|
|
{
|
|
if (hs_parse(argument_indices[1], hs_syntax_get(argument_indices[0])->type))
|
|
result = TRUE;
|
|
}
|
|
else if (!hs_compile_globals.error)
|
|
{
|
|
if (hs_parse(argument_indices[1], _hs_unparsed) &&
|
|
(HS_TYPE_IS_ENUM(hs_syntax_get(argument_indices[1])->type) ||
|
|
(hs_syntax_get(argument_indices[1])->type>=_hs_type_real &&
|
|
hs_syntax_get(argument_indices[1])->type<=_hs_type_long_integer)))
|
|
{
|
|
if (hs_parse(argument_indices[0], hs_syntax_get(argument_indices[1])->type))
|
|
result = TRUE;
|
|
}
|
|
else if (!hs_compile_globals.error)
|
|
{
|
|
if (hs_parse(argument_indices[0], _hs_type_real) &&
|
|
hs_parse(argument_indices[1], _hs_type_real))
|
|
result = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_sleep(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long ticks_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x20E,
|
|
function_index==_hs_function_sleep);
|
|
if (ticks_expression_index != NONE)
|
|
{
|
|
if (hs_parse(ticks_expression_index, _hs_type_short_integer))
|
|
{
|
|
long script_expression_index = hs_syntax_get(ticks_expression_index)->next_node_index;
|
|
|
|
if (script_expression_index == NONE || hs_parse(script_expression_index, _hs_type_script))
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "the sleep call requires a time and, optionally, a script name.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_sleep_until(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long condition_expression_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x235,
|
|
function_index==_hs_function_sleep_until);
|
|
condition_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
if (condition_expression_index != NONE)
|
|
{
|
|
long period_expression_index = hs_syntax_get(condition_expression_index)->next_node_index;
|
|
|
|
result = hs_parse(condition_expression_index, _hs_type_boolean);
|
|
if (result && period_expression_index != NONE)
|
|
{
|
|
long timeout_expression_index = hs_syntax_get(period_expression_index)->next_node_index;
|
|
|
|
result = hs_parse(period_expression_index, _hs_type_short_integer);
|
|
if (result && timeout_expression_index != NONE)
|
|
result = hs_parse(timeout_expression_index, _hs_type_long_integer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hs_compile_globals.error = "the sleep_until call requires a condition and, optionally, a period.";
|
|
hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_wake(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long script_expression_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x25D,
|
|
function_index==_hs_function_wake);
|
|
if (hs_get_parameter_indices(
|
|
hs_function_get(function_index)->name,
|
|
1,
|
|
&script_expression_index,
|
|
expression_index))
|
|
{
|
|
struct hs_syntax_node *script_expression = hs_syntax_get(script_expression_index);
|
|
|
|
if (hs_parse(script_expression_index, _hs_type_script))
|
|
{
|
|
struct hs_script *script = TAG_BLOCK_GET_ELEMENT(
|
|
&global_scenario_get()->hs_scripts,
|
|
script_expression->short_value,
|
|
struct hs_script);
|
|
|
|
if (script->script_type == _hs_script_static || script->script_type == _hs_script_stub)
|
|
{
|
|
hs_compile_globals.error = "this static script cannot be awakened.";
|
|
hs_compile_globals.error_offset = script_expression->source_offset;
|
|
}
|
|
else
|
|
{
|
|
result = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_inspect(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
struct hs_syntax_node *expression = hs_syntax_get(expression_index);
|
|
boolean result = FALSE;
|
|
long argument_expression_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x27F,
|
|
function_index==_hs_function_inspect);
|
|
if (hs_get_parameter_indices(
|
|
hs_function_get(function_index)->name,
|
|
1,
|
|
&argument_expression_index,
|
|
expression_index))
|
|
{
|
|
struct hs_syntax_node *argument_expression = hs_syntax_get(argument_expression_index);
|
|
|
|
if (hs_parse(argument_expression_index, _hs_unparsed))
|
|
{
|
|
result = TRUE;
|
|
}
|
|
else if (!hs_compile_globals.error)
|
|
{
|
|
hs_compile_globals.error = "this is not a global variable reference, function call, or script call.";
|
|
hs_compile_globals.error_offset = argument_expression->source_offset;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
boolean hs_parse_object_cast_up(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = FALSE;
|
|
long argument_indices[1];
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x29A,
|
|
function_index>=_hs_function_object_to_unit && function_index<=_hs_function_object_to_unit);
|
|
if (hs_get_parameter_indices(
|
|
hs_function_get(function_index)->name,
|
|
1,
|
|
argument_indices,
|
|
expression_index))
|
|
{
|
|
result = hs_parse(argument_indices[0], _hs_type_object);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean hs_parse_debug_string(
|
|
short function_index,
|
|
long expression_index)
|
|
{
|
|
boolean result = TRUE;
|
|
long argument_expression_index = hs_syntax_get(
|
|
hs_syntax_get(expression_index)->data)->next_node_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\source\\hs\\hs_library_internal_compile.h",
|
|
0x2AE,
|
|
(function_index>=_hs_function_debug_string__first) && (function_index<=_hs_function_debug_string__last));
|
|
while (result && argument_expression_index != NONE)
|
|
{
|
|
result = hs_parse(argument_expression_index, _hs_type_string);
|
|
argument_expression_index = hs_syntax_get(argument_expression_index)->next_node_index;
|
|
}
|
|
|
|
return result;
|
|
}
|