2019-12-13 04:29:58 +00:00
/*
2020-04-16 03:42:30 +00:00
Copyright ( c ) 2006 - 2020 Chung , Hyung - Hwan . All rights reserved .
2019-12-13 04:29:58 +00:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE AUTHOR " AS IS " AND ANY EXPRESS OR
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "hawk-prv.h"
2020-01-04 04:47:41 +00:00
# define FMT_EBADVAR HAWK_T("'%.*js' not a valid variable name")
# define FMT_ECOMMA HAWK_T("comma expected in place of '%.*js'")
# define FMT_ECOLON HAWK_T("colon expected in place of '%.*js'")
# define FMT_EDUPLCL HAWK_T("duplicate local variable name - %.*js")
# define FMT_EFUNNF HAWK_T("function '%.*js' not defined")
# define FMT_EIDENT HAWK_T("identifier expected in place of '%.*js'")
# define FMT_EINTLIT HAWK_T("integer literal expected in place of '%.*js'")
# define FMT_EIONMNL HAWK_T("invalid I / O name of length %zu containing '\\0'")
# define FMT_EKWFNC HAWK_T("keyword 'function' expected in place of '%.*js'")
# define FMT_EKWIN HAWK_T("keyword 'in' expected in place of '%.*js'")
# define FMT_EKWWHL HAWK_T("keyword 'while' expected in place of '%.*js'")
# define FMT_ELBRACE HAWK_T("left brace expected in place of '%.*js'")
# define FMT_ELPAREN HAWK_T("left parenthesis expected in place of '%.*js'")
# define FMT_ENOENT_GBL_HS HAWK_T("no such global variable - %.*hs")
# define FMT_ENOENT_GBL_LS HAWK_T("no such global variable - %.*ls")
# define FMT_ERBRACK HAWK_T("right bracket expected in place of '%.*js'")
# define FMT_ERPAREN HAWK_T("right parenthesis expected in place of '%.*js'")
# define FMT_ESCOLON HAWK_T("semicolon expected in place of '%.*js'")
# define FMT_ESEGTL HAWK_T("segment '%.*js' too long")
# define FMT_EUNDEF HAWK_T("undefined identifier '%.*js'")
# define FMT_EXKWNR HAWK_T("'%.*js' not recognized")
2020-12-01 10:22:17 +00:00
# define TOK_FLAGS_LPAREN_CLOSER (1 << 0)
2020-01-04 04:47:41 +00:00
2019-12-13 04:29:58 +00:00
enum tok_t
{
TOK_EOF ,
TOK_NEWLINE ,
2024-04-28 19:15:17 +09:00
/* TOK_XXX_ASSNs should be in sync with assop in assign_to_opcode.
2019-12-13 04:29:58 +00:00
* it also should be in the order as hawk_assop_type_t in run . h */
TOK_ASSN ,
TOK_PLUS_ASSN ,
TOK_MINUS_ASSN ,
TOK_MUL_ASSN ,
TOK_DIV_ASSN ,
TOK_IDIV_ASSN ,
TOK_MOD_ASSN ,
TOK_EXP_ASSN , /* ^ - exponentiation */
TOK_CONCAT_ASSN ,
TOK_RS_ASSN ,
TOK_LS_ASSN ,
TOK_BAND_ASSN ,
TOK_BXOR_ASSN ,
TOK_BOR_ASSN ,
/* end of TOK_XXX_ASSN */
TOK_TEQ ,
TOK_TNE ,
TOK_EQ ,
TOK_NE ,
TOK_LE ,
TOK_LT ,
TOK_GE ,
TOK_GT ,
2020-03-04 09:54:38 +00:00
TOK_TILDE , /* ~ - match or bitwise negation */
2019-12-13 04:29:58 +00:00
TOK_NM , /* !~ - not match */
TOK_LNOT , /* ! - logical negation */
TOK_PLUS ,
TOK_PLUSPLUS ,
TOK_MINUS ,
TOK_MINUSMINUS ,
TOK_MUL ,
TOK_DIV ,
TOK_IDIV ,
TOK_MOD ,
TOK_LOR ,
TOK_LAND ,
TOK_BOR ,
TOK_BXOR , /* ^^ - bitwise-xor */
TOK_BAND ,
TOK_RS ,
TOK_LS ,
TOK_IN ,
TOK_EXP ,
TOK_CONCAT , /* %% */
TOK_LPAREN ,
TOK_RPAREN ,
TOK_LBRACE ,
TOK_RBRACE ,
TOK_LBRACK ,
TOK_RBRACK ,
TOK_DOLLAR ,
TOK_COMMA ,
TOK_SEMICOLON ,
TOK_COLON ,
TOK_DBLCOLON ,
TOK_QUEST ,
2024-05-02 22:36:50 +09:00
TOK_ELLIPSIS ,
TOK_DBLPERIOD , /* not used yet */
TOK_PERIOD , /* not used yet */
2019-12-13 04:29:58 +00:00
/* == begin reserved words == */
/* === extended reserved words === */
2024-05-02 22:36:50 +09:00
TOK_XARGC ,
TOK_XARGV ,
TOK_XABORT ,
2019-12-13 04:29:58 +00:00
TOK_XGLOBAL ,
TOK_XINCLUDE ,
TOK_XINCLUDE_ONCE ,
2024-05-02 22:36:50 +09:00
TOK_XLOCAL ,
2019-12-13 04:29:58 +00:00
TOK_XPRAGMA ,
TOK_XRESET ,
/* === normal reserved words === */
TOK_BEGIN ,
TOK_END ,
TOK_FUNCTION ,
TOK_IF ,
TOK_ELSE ,
TOK_WHILE ,
TOK_FOR ,
TOK_DO ,
TOK_BREAK ,
TOK_CONTINUE ,
TOK_RETURN ,
TOK_EXIT ,
TOK_DELETE ,
TOK_NEXT ,
TOK_NEXTFILE ,
TOK_NEXTOFILE ,
TOK_PRINT ,
TOK_PRINTF ,
2020-01-16 09:22:59 +00:00
TOK_GETBLINE ,
2019-12-13 04:29:58 +00:00
TOK_GETLINE ,
/* == end reserved words == */
TOK_IDENT ,
2020-12-05 18:55:05 +00:00
TOK_CHAR ,
2020-12-09 18:07:20 +00:00
TOK_BCHR ,
2019-12-13 04:29:58 +00:00
TOK_INT ,
TOK_FLT ,
TOK_STR ,
TOK_MBS ,
TOK_REX ,
2020-11-10 02:56:29 +00:00
TOK_XNIL ,
2019-12-13 04:29:58 +00:00
__TOKEN_COUNT__
} ;
enum
{
PARSE_GBL ,
PARSE_FUNCTION ,
PARSE_BEGIN ,
PARSE_END ,
PARSE_BEGIN_BLOCK ,
PARSE_END_BLOCK ,
PARSE_PATTERN ,
PARSE_ACTION_BLOCK
} ;
enum
{
PARSE_LOOP_NONE ,
PARSE_LOOP_WHILE ,
PARSE_LOOP_FOR ,
PARSE_LOOP_DOWHILE
} ;
typedef struct binmap_t binmap_t ;
struct binmap_t
{
int token ;
int binop ;
} ;
2020-04-16 03:42:30 +00:00
static int parse_progunit ( hawk_t * hawk ) ;
static hawk_t * collect_globals ( hawk_t * hawk ) ;
static void adjust_static_globals ( hawk_t * hawk ) ;
static hawk_oow_t find_global ( hawk_t * hawk , const hawk_oocs_t * name ) ;
static hawk_t * collect_locals ( hawk_t * hawk , hawk_oow_t nlcls , int istop ) ;
static hawk_nde_t * parse_function ( hawk_t * hawk ) ;
static hawk_nde_t * parse_begin ( hawk_t * hawk ) ;
static hawk_nde_t * parse_end ( hawk_t * hawk ) ;
static hawk_chain_t * parse_action_block ( hawk_t * hawk , hawk_nde_t * ptn , int blockless ) ;
static hawk_nde_t * parse_block_dc ( hawk_t * hawk , const hawk_loc_t * xloc , int istop ) ;
static hawk_nde_t * parse_statement ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_expr_withdc ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_logical_or ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_logical_and ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_in ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_regex_match ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_bitwise_or ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_bitwise_xor ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_bitwise_and ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_equality ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_relational ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_shift ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_concat ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_additive ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_multiplicative ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_unary ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_exponent ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_unary_exp ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_increment ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_primary ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_primary_ident ( hawk_t * hawk , const hawk_loc_t * xloc ) ;
static hawk_nde_t * parse_hashidx ( hawk_t * hawk , const hawk_oocs_t * name , const hawk_loc_t * xloc ) ;
2019-12-13 04:29:58 +00:00
# define FNCALL_FLAG_NOARG (1 << 0) /* no argument */
# define FNCALL_FLAG_VAR (1 << 1)
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_fncall ( hawk_t * hawk , const hawk_oocs_t * name , hawk_fnc_t * fnc , const hawk_loc_t * xloc , int flags ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_ident_segs ( hawk_t * hawk , const hawk_loc_t * xloc , const hawk_oocs_t * full , const hawk_oocs_t segs [ ] , int nsegs ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
static int get_token ( hawk_t * hawk ) ;
static int preget_token ( hawk_t * hawk ) ;
static int get_rexstr ( hawk_t * hawk , hawk_tok_t * tok ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
static int skip_spaces ( hawk_t * hawk ) ;
static int skip_comment ( hawk_t * hawk ) ;
static int classify_ident ( hawk_t * hawk , const hawk_oocs_t * name ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
static int deparse ( hawk_t * hawk ) ;
2019-12-13 04:29:58 +00:00
static hawk_htb_walk_t deparse_func ( hawk_htb_t * map , hawk_htb_pair_t * pair , void * arg ) ;
2020-04-16 03:42:30 +00:00
static int put_char ( hawk_t * hawk , hawk_ooch_t c ) ;
static int flush_out ( hawk_t * hawk ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
static hawk_mod_t * query_module ( hawk_t * hawk , const hawk_oocs_t segs [ ] , int nsegs , hawk_mod_sym_t * sym ) ;
2019-12-13 04:29:58 +00:00
typedef struct kwent_t kwent_t ;
2024-04-28 19:15:17 +09:00
struct kwent_t
{
2019-12-13 04:29:58 +00:00
hawk_oocs_t name ;
2024-04-28 19:15:17 +09:00
int type ;
2019-12-13 04:29:58 +00:00
int trait ; /* the entry is valid when this option is set */
} ;
2024-04-28 19:15:17 +09:00
static kwent_t kwtab [ ] =
2019-12-13 04:29:58 +00:00
{
2020-11-10 02:56:29 +00:00
/* keep this table in sync with the kw_t enums in "parse-prv.h".
2019-12-13 04:29:58 +00:00
* also keep it sorted by the first field for binary search */
{ { HAWK_T ( " @abort " ) , 6 } , TOK_XABORT , 0 } ,
2024-05-02 22:36:50 +09:00
{ { HAWK_T ( " @argc " ) , 5 } , TOK_XARGC , 0 } ,
{ { HAWK_T ( " @argv " ) , 5 } , TOK_XARGV , 0 } ,
2019-12-13 04:29:58 +00:00
{ { HAWK_T ( " @global " ) , 7 } , TOK_XGLOBAL , 0 } ,
{ { HAWK_T ( " @include " ) , 8 } , TOK_XINCLUDE , 0 } ,
{ { HAWK_T ( " @include_once " ) , 13 } , TOK_XINCLUDE_ONCE , 0 } ,
{ { HAWK_T ( " @local " ) , 6 } , TOK_XLOCAL , 0 } ,
2020-11-10 02:56:29 +00:00
{ { HAWK_T ( " @nil " ) , 4 } , TOK_XNIL , 0 } ,
2019-12-13 04:29:58 +00:00
{ { HAWK_T ( " @pragma " ) , 7 } , TOK_XPRAGMA , 0 } ,
{ { HAWK_T ( " @reset " ) , 6 } , TOK_XRESET , 0 } ,
{ { HAWK_T ( " BEGIN " ) , 5 } , TOK_BEGIN , HAWK_PABLOCK } ,
{ { HAWK_T ( " END " ) , 3 } , TOK_END , HAWK_PABLOCK } ,
{ { HAWK_T ( " break " ) , 5 } , TOK_BREAK , 0 } ,
{ { HAWK_T ( " continue " ) , 8 } , TOK_CONTINUE , 0 } ,
{ { HAWK_T ( " delete " ) , 6 } , TOK_DELETE , 0 } ,
{ { HAWK_T ( " do " ) , 2 } , TOK_DO , 0 } ,
{ { HAWK_T ( " else " ) , 4 } , TOK_ELSE , 0 } ,
{ { HAWK_T ( " exit " ) , 4 } , TOK_EXIT , 0 } ,
{ { HAWK_T ( " for " ) , 3 } , TOK_FOR , 0 } ,
{ { HAWK_T ( " function " ) , 8 } , TOK_FUNCTION , 0 } ,
2020-01-16 09:22:59 +00:00
{ { HAWK_T ( " getbline " ) , 8 } , TOK_GETBLINE , HAWK_RIO } ,
2019-12-13 04:29:58 +00:00
{ { HAWK_T ( " getline " ) , 7 } , TOK_GETLINE , HAWK_RIO } ,
{ { HAWK_T ( " if " ) , 2 } , TOK_IF , 0 } ,
{ { HAWK_T ( " in " ) , 2 } , TOK_IN , 0 } ,
{ { HAWK_T ( " next " ) , 4 } , TOK_NEXT , HAWK_PABLOCK } ,
{ { HAWK_T ( " nextfile " ) , 8 } , TOK_NEXTFILE , HAWK_PABLOCK } ,
{ { HAWK_T ( " nextofile " ) , 9 } , TOK_NEXTOFILE , HAWK_PABLOCK | HAWK_NEXTOFILE } ,
{ { HAWK_T ( " print " ) , 5 } , TOK_PRINT , HAWK_RIO } ,
{ { HAWK_T ( " printf " ) , 6 } , TOK_PRINTF , HAWK_RIO } ,
{ { HAWK_T ( " return " ) , 6 } , TOK_RETURN , 0 } ,
{ { HAWK_T ( " while " ) , 5 } , TOK_WHILE , 0 }
} ;
typedef struct global_t global_t ;
struct global_t
{
const hawk_ooch_t * name ;
hawk_oow_t namelen ;
int trait ;
} ;
static global_t gtab [ ] =
{
2024-04-28 19:15:17 +09:00
/*
* this table must match the order of the hawk_gbl_id_t enumerators
2019-12-13 04:29:58 +00:00
*/
/* output real-to-str conversion format for other cases than 'print' */
{ HAWK_T ( " CONVFMT " ) , 7 , 0 } ,
/* current input file name */
{ HAWK_T ( " FILENAME " ) , 8 , HAWK_PABLOCK } ,
/* input record number in current file */
{ HAWK_T ( " FNR " ) , 3 , HAWK_PABLOCK } ,
/* input field separator */
{ HAWK_T ( " FS " ) , 2 , 0 } ,
/* ignore case in string comparison */
{ HAWK_T ( " IGNORECASE " ) , 10 , 0 } ,
2024-04-28 19:15:17 +09:00
/* number of fields in current input record
2019-12-13 04:29:58 +00:00
* NF is also updated if you assign a value to $ 0. so it is not
* associated with HAWK_PABLOCK */
{ HAWK_T ( " NF " ) , 2 , 0 } ,
/* input record number */
{ HAWK_T ( " NR " ) , 2 , HAWK_PABLOCK } ,
2021-10-14 05:00:55 +00:00
/* detect a numeric string */
2024-04-28 19:15:17 +09:00
{ HAWK_T ( " NUMSTRDETECT " ) , 12 , 0 } ,
2021-10-14 05:00:55 +00:00
2019-12-13 04:29:58 +00:00
/* current output file name */
{ HAWK_T ( " OFILENAME " ) , 9 , HAWK_PABLOCK | HAWK_NEXTOFILE } ,
/* output real-to-str conversion format for 'print' */
2024-04-28 19:15:17 +09:00
{ HAWK_T ( " OFMT " ) , 4 , HAWK_RIO } ,
2019-12-13 04:29:58 +00:00
/* output field separator for 'print' */
{ HAWK_T ( " OFS " ) , 3 , HAWK_RIO } ,
/* output record separator. used for 'print' and blockless output */
{ HAWK_T ( " ORS " ) , 3 , HAWK_RIO } ,
{ HAWK_T ( " RLENGTH " ) , 7 , 0 } ,
2020-01-14 14:55:34 +00:00
2019-12-13 04:29:58 +00:00
{ HAWK_T ( " RS " ) , 2 , 0 } ,
{ HAWK_T ( " RSTART " ) , 6 , 0 } ,
2020-03-03 08:03:04 +00:00
{ HAWK_T ( " SCRIPTNAME " ) , 10 , 0 } ,
2024-04-28 19:15:17 +09:00
/* it decides the field construction behavior when FS is a regular expression and
2019-12-13 04:29:58 +00:00
* the field splitter is composed of whitespaces only . e . g ) FS = " [ \t ]* " ;
* if set to a non - zero value , remove leading spaces and trailing spaces off a record
* before field splitting .
* if set to zero , leading spaces and trailing spaces result in 1 empty field respectively .
2020-04-16 03:42:30 +00:00
* if not set , the behavior is dependent on the hawk - > opt . trait & HAWK_STRIPRECSPC */
2024-04-28 19:15:17 +09:00
{ HAWK_T ( " STRIPRECSPC " ) , 11 , 0 } ,
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
{ HAWK_T ( " STRIPSTRSPC " ) , 11 , 0 } ,
2020-03-09 08:52:42 +00:00
2019-12-13 04:29:58 +00:00
{ HAWK_T ( " SUBSEP " ) , 6 , 0 }
} ;
2020-04-16 03:42:30 +00:00
# define GET_CHAR(hawk) \
do { if ( get_char ( hawk ) < = - 1 ) return - 1 ; } while ( 0 )
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
# define GET_CHAR_TO(hawk,c) \
2019-12-13 04:29:58 +00:00
do { \
2020-04-16 03:42:30 +00:00
if ( get_char ( hawk ) < = - 1 ) return - 1 ; \
c = ( hawk ) - > sio . last . c ; \
2019-12-13 04:29:58 +00:00
} while ( 0 )
2020-04-16 03:42:30 +00:00
# define SET_TOKEN_TYPE(hawk,tok,code) \
2019-12-13 04:29:58 +00:00
do { ( tok ) - > type = ( code ) ; } while ( 0 )
2020-04-16 03:42:30 +00:00
# define ADD_TOKEN_CHAR(hawk,tok,c) \
2019-12-13 04:29:58 +00:00
do { \
2020-05-04 07:14:32 +00:00
if ( HAWK_UNLIKELY ( hawk_ooecs_ccat ( ( tok ) - > name , ( c ) ) = = ( hawk_oow_t ) - 1 ) ) \
2019-12-13 04:29:58 +00:00
{ \
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & ( tok ) - > loc ) ; \
2019-12-13 04:29:58 +00:00
return - 1 ; \
} \
} while ( 0 )
2020-04-16 03:42:30 +00:00
# define ADD_TOKEN_STR(hawk,tok,s,l) \
2019-12-13 04:29:58 +00:00
do { \
2020-05-04 07:14:32 +00:00
if ( HAWK_UNLIKELY ( hawk_ooecs_ncat ( ( tok ) - > name , ( s ) , ( l ) ) = = ( hawk_oow_t ) - 1 ) ) \
2019-12-13 04:29:58 +00:00
{ \
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & ( tok ) - > loc ) ; \
2019-12-13 04:29:58 +00:00
return - 1 ; \
} \
} while ( 0 )
# if defined(HAWK_OOCH_IS_BCH)
2020-04-16 03:42:30 +00:00
# define ADD_TOKEN_UINT32(hawk,tok,c) \
2019-12-13 04:29:58 +00:00
do { \
2020-04-16 03:42:30 +00:00
if ( c < = 0xFF ) ADD_TOKEN_CHAR ( hawk , tok , c ) ; \
2019-12-13 04:29:58 +00:00
else \
{ \
hawk_bch_t __xbuf [ HAWK_MBLEN_MAX + 1 ] ; \
hawk_oow_t __len , __i ; \
2020-01-24 06:54:49 +00:00
__len = uc_to_utf8 ( c , __xbuf , HAWK_COUNTOF ( __xbuf ) ) ; /* use utf8 all the time */ \
2020-04-16 03:42:30 +00:00
for ( __i = 0 ; __i < __len ; __i + + ) ADD_TOKEN_CHAR ( hawk , tok , __xbuf [ __i ] ) ; \
2019-12-13 04:29:58 +00:00
} \
} while ( 0 )
# else
2020-04-16 03:42:30 +00:00
# define ADD_TOKEN_UINT32(hawk,tok,c) ADD_TOKEN_CHAR(hawk,tok,c);
2019-12-13 04:29:58 +00:00
# endif
2020-04-16 03:42:30 +00:00
# define MATCH(hawk,tok_type) ((hawk)->tok.type == (tok_type))
# define MATCH_RANGE(hawk,tok_type_start,tok_type_end) ((hawk)->tok.type >= (tok_type_start) && (hawk)->tok.type <= (tok_type_end))
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
# define MATCH_TERMINATOR_NORMAL(hawk) \
( MATCH ( ( hawk ) , TOK_SEMICOLON ) | | MATCH ( ( hawk ) , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
# define MATCH_TERMINATOR_RBRACE(hawk) \
( ( hawk - > opt . trait & HAWK_NEWLINE ) & & MATCH ( ( hawk ) , TOK_RBRACE ) )
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
# define MATCH_TERMINATOR(hawk) \
( MATCH_TERMINATOR_NORMAL ( hawk ) | | MATCH_TERMINATOR_RBRACE ( hawk ) )
2019-12-13 04:29:58 +00:00
2019-12-14 16:05:10 +00:00
# define ADJERR_LOC(hawk,l) do { (hawk)->_gem.errloc = *(l); } while (0)
2019-12-13 04:29:58 +00:00
2020-01-24 06:54:49 +00:00
# if defined(HAWK_OOCH_IS_BCH)
static HAWK_INLINE hawk_oow_t uc_to_utf8 ( hawk_uch_t uc , hawk_bch_t * buf , hawk_oow_t bsz )
{
static hawk_cmgr_t * utf8_cmgr = HAWK_NULL ;
if ( ! utf8_cmgr ) utf8_cmgr = hawk_get_cmgr_by_id ( HAWK_CMGR_UTF8 ) ;
return utf8_cmgr - > uctobc ( uc , buf , bsz ) ;
}
# endif
2019-12-13 04:29:58 +00:00
static HAWK_INLINE int is_plain_var ( hawk_nde_t * nde )
{
return nde - > type = = HAWK_NDE_GBL | |
nde - > type = = HAWK_NDE_LCL | |
nde - > type = = HAWK_NDE_ARG | |
nde - > type = = HAWK_NDE_NAMED ;
}
static HAWK_INLINE int is_var ( hawk_nde_t * nde )
{
return nde - > type = = HAWK_NDE_GBL | |
nde - > type = = HAWK_NDE_LCL | |
nde - > type = = HAWK_NDE_ARG | |
nde - > type = = HAWK_NDE_NAMED | |
nde - > type = = HAWK_NDE_GBLIDX | |
nde - > type = = HAWK_NDE_LCLIDX | |
nde - > type = = HAWK_NDE_ARGIDX | |
nde - > type = = HAWK_NDE_NAMEDIDX ;
}
2020-04-16 03:42:30 +00:00
static int get_char ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_ooi_t n ;
2024-04-28 19:15:17 +09:00
if ( hawk - > sio . nungots > 0 )
2019-12-13 04:29:58 +00:00
{
/* there are something in the unget buffer */
2020-04-16 03:42:30 +00:00
hawk - > sio . last = hawk - > sio . ungot [ - - hawk - > sio . nungots ] ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inp - > b . pos > = hawk - > sio . inp - > b . len )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
n = hawk - > sio . inf (
hawk , HAWK_SIO_CMD_READ , hawk - > sio . inp ,
hawk - > sio . inp - > b . buf , HAWK_COUNTOF ( hawk - > sio . inp - > b . buf )
2019-12-13 04:29:58 +00:00
) ;
2020-01-01 04:46:49 +00:00
if ( n < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
if ( n = = 0 )
{
2020-04-16 03:42:30 +00:00
hawk - > sio . inp - > last . c = HAWK_OOCI_EOF ;
hawk - > sio . inp - > last . line = hawk - > sio . inp - > line ;
hawk - > sio . inp - > last . colm = hawk - > sio . inp - > colm ;
hawk - > sio . inp - > last . file = hawk - > sio . inp - > path ;
hawk - > sio . last = hawk - > sio . inp - > last ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
hawk - > sio . inp - > b . pos = 0 ;
2020-05-04 07:14:32 +00:00
hawk - > sio . inp - > b . len = n ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inp - > last . c = = HAWK_T ( ' \n ' ) )
2019-12-13 04:29:58 +00:00
{
/* if the previous charater was a newline,
* increment the line counter and reset column to 1.
* incrementing it line number here instead of
* updating inp - > last causes the line number for
* TOK_EOF to be the same line as the last newline . */
2020-04-16 03:42:30 +00:00
hawk - > sio . inp - > line + + ;
hawk - > sio . inp - > colm = 1 ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
hawk - > sio . inp - > last . c = hawk - > sio . inp - > b . buf [ hawk - > sio . inp - > b . pos + + ] ;
hawk - > sio . inp - > last . line = hawk - > sio . inp - > line ;
hawk - > sio . inp - > last . colm = hawk - > sio . inp - > colm + + ;
hawk - > sio . inp - > last . file = hawk - > sio . inp - > path ;
hawk - > sio . last = hawk - > sio . inp - > last ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
static void unget_char ( hawk_t * hawk , const hawk_sio_lxc_t * c )
2019-12-13 04:29:58 +00:00
{
/* Make sure that the unget buffer is large enough */
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > sio . nungots < HAWK_COUNTOF ( hawk - > sio . ungot ) ) ;
hawk - > sio . ungot [ hawk - > sio . nungots + + ] = * c ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
const hawk_ooch_t * hawk_getgblname ( hawk_t * hawk , hawk_oow_t idx , hawk_oow_t * len )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( idx < HAWK_ARR_SIZE ( hawk - > parse . gbls ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
* len = HAWK_ARR_DLEN ( hawk - > parse . gbls , idx ) ;
return HAWK_ARR_DPTR ( hawk - > parse . gbls , idx ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
void hawk_getkwname ( hawk_t * hawk , hawk_kwid_t id , hawk_oocs_t * s )
2019-12-13 04:29:58 +00:00
{
* s = kwtab [ id ] . name ;
}
2020-04-16 03:42:30 +00:00
static int parse ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
int ret = - 1 ;
2019-12-13 04:29:58 +00:00
hawk_ooi_t op ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > sio . inf ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
op = hawk - > sio . inf ( hawk , HAWK_SIO_CMD_OPEN , hawk - > sio . inp , HAWK_NULL , 0 ) ;
2019-12-13 04:29:58 +00:00
if ( op < = - 1 )
{
/* cannot open the source file.
* it doesn ' t even have to call CLOSE */
return - 1 ;
}
2020-04-16 03:42:30 +00:00
adjust_static_globals ( hawk ) ;
2019-12-13 04:29:58 +00:00
/* get the first character and the first token */
2024-04-28 19:15:17 +09:00
if ( get_char ( hawk ) < = - 1 | | get_token ( hawk ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-05-02 18:34:18 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_EOF ) ) break ;
2019-12-13 04:29:58 +00:00
2020-05-02 18:34:18 +00:00
if ( parse_progunit ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_IMPLICIT ) )
2019-12-13 04:29:58 +00:00
{
/* ensure that all functions called are defined in the EXPLICIT-only mode.
2020-05-02 18:34:18 +00:00
* otherwise , the error detection will get delay until run - time . */
2019-12-13 04:29:58 +00:00
hawk_htb_pair_t * p ;
2020-03-15 17:39:15 +00:00
hawk_htb_itr_t itr ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
p = hawk_htb_getfirstpair ( hawk - > parse . funs , & itr ) ;
2020-03-15 17:39:15 +00:00
while ( p )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk_htb_search ( hawk - > tree . funs , HAWK_HTB_KPTR ( p ) , HAWK_HTB_KLEN ( p ) ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
/* see parse_fncall() for what is
2020-04-16 03:42:30 +00:00
* stored into hawk - > tree . funs */
2019-12-13 04:29:58 +00:00
nde = ( hawk_nde_t * ) HAWK_HTB_VPTR ( p ) ;
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & nde - > loc , HAWK_EFUNNF , FMT_EFUNNF , HAWK_HTB_KLEN ( p ) , HAWK_HTB_KPTR ( p ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
p = hawk_htb_getnextpair ( hawk - > parse . funs , & itr ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls = = HAWK_ARR_SIZE ( hawk - > parse . gbls ) ) ;
HAWK_ASSERT ( hawk - > sio . inp = = & hawk - > sio . arg ) ;
2019-12-13 04:29:58 +00:00
ret = 0 ;
oops :
if ( ret < = - 1 )
{
/* an error occurred and control has reached here
2024-04-28 19:15:17 +09:00
* probably , some included files might not have been
2019-12-13 04:29:58 +00:00
* closed . close them */
2020-04-16 03:42:30 +00:00
while ( hawk - > sio . inp ! = & hawk - > sio . arg )
2019-12-13 04:29:58 +00:00
{
hawk_sio_arg_t * prev ;
/* nothing much to do about a close error */
2020-04-16 03:42:30 +00:00
hawk - > sio . inf ( hawk , HAWK_SIO_CMD_CLOSE , hawk - > sio . inp , HAWK_NULL , 0 ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
prev = hawk - > sio . inp - > prev ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > sio . inp - > name ! = HAWK_NULL ) ;
hawk_freemem ( hawk , hawk - > sio . inp ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > sio . inp = prev ;
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inf ( hawk , HAWK_SIO_CMD_CLOSE , hawk - > sio . inp , HAWK_NULL , 0 ) ! = 0 & & ret = = 0 ) ret = - 1 ;
2019-12-13 04:29:58 +00:00
2020-01-01 04:46:49 +00:00
/* clear the parse tree partially constructed on error */
2020-04-16 03:42:30 +00:00
if ( ret < = - 1 ) hawk_clear ( hawk ) ;
2019-12-13 04:29:58 +00:00
return ret ;
}
2019-12-25 16:01:43 +00:00
hawk_ooch_t * hawk_addsionamewithuchars ( hawk_t * hawk , const hawk_uch_t * ptr , hawk_oow_t len )
{
hawk_link_t * link ;
/* TODO: duplication check? */
# if defined(HAWK_OOCH_IS_UCH)
link = ( hawk_link_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * link ) + HAWK_SIZEOF ( hawk_uch_t ) * ( len + 1 ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! link ) ) return HAWK_NULL ;
2019-12-25 16:01:43 +00:00
hawk_copy_uchars_to_ucstr_unlimited ( ( hawk_uch_t * ) ( link + 1 ) , ptr , len ) ;
# else
hawk_oow_t bcslen , ucslen ;
ucslen = len ;
if ( hawk_convutobchars ( hawk , ptr , & ucslen , HAWK_NULL , & bcslen ) < = - 1 ) return HAWK_NULL ;
link = ( hawk_link_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * link ) + HAWK_SIZEOF ( hawk_bch_t ) * ( bcslen + 1 ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! link ) ) return HAWK_NULL ;
2019-12-25 16:01:43 +00:00
ucslen = len ;
bcslen = bcslen + 1 ;
hawk_convutobchars ( hawk , ptr , & ucslen , ( hawk_bch_t * ) ( link + 1 ) , & bcslen ) ;
( ( hawk_bch_t * ) ( link + 1 ) ) [ bcslen ] = ' \0 ' ;
# endif
link - > link = hawk - > sio_names ;
hawk - > sio_names = link ;
return ( hawk_ooch_t * ) ( link + 1 ) ;
}
hawk_ooch_t * hawk_addsionamewithbchars ( hawk_t * hawk , const hawk_bch_t * ptr , hawk_oow_t len )
{
hawk_link_t * link ;
/* TODO: duplication check? */
# if defined(HAWK_OOCH_IS_UCH)
hawk_oow_t bcslen , ucslen ;
bcslen = len ;
if ( hawk_convbtouchars ( hawk , ptr , & bcslen , HAWK_NULL , & ucslen , 0 ) < = - 1 ) return HAWK_NULL ;
link = ( hawk_link_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * link ) + HAWK_SIZEOF ( hawk_uch_t ) * ( ucslen + 1 ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! link ) ) return HAWK_NULL ;
2019-12-25 16:01:43 +00:00
bcslen = len ;
ucslen = ucslen + 1 ;
hawk_convbtouchars ( hawk , ptr , & bcslen , ( hawk_uch_t * ) ( link + 1 ) , & ucslen , 0 ) ;
( ( hawk_uch_t * ) ( link + 1 ) ) [ ucslen ] = ' \0 ' ;
# else
link = ( hawk_link_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * link ) + HAWK_SIZEOF ( hawk_bch_t ) * ( len + 1 ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! link ) ) return HAWK_NULL ;
2019-12-25 16:01:43 +00:00
hawk_copy_bchars_to_bcstr_unlimited ( ( hawk_bch_t * ) ( link + 1 ) , ptr , len ) ;
# endif
link - > link = hawk - > sio_names ;
hawk - > sio_names = link ;
return ( hawk_ooch_t * ) ( link + 1 ) ;
}
void hawk_clearsionames ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_link_t * cur ;
2019-12-25 16:01:43 +00:00
while ( hawk - > sio_names )
2019-12-13 04:29:58 +00:00
{
2019-12-25 16:01:43 +00:00
cur = hawk - > sio_names ;
hawk - > sio_names = cur - > link ;
hawk_freemem ( hawk , cur ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
int hawk_parse ( hawk_t * hawk , hawk_sio_cbs_t * sio )
2019-12-13 04:29:58 +00:00
{
int n ;
/* the source code istream must be provided */
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( sio ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
/* the source code input stream must be provided at least */
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( sio - > in ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
if ( ! sio | | ! sio - > in )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EINVAL ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > parse . depth . loop = = 0 ) ;
HAWK_ASSERT ( hawk - > parse . depth . expr = = 0 ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk_clear ( hawk ) ;
hawk_clearsionames ( hawk ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_MEMSET ( & hawk - > sio , 0 , HAWK_SIZEOF ( hawk - > sio ) ) ;
hawk - > sio . inf = sio - > in ;
hawk - > sio . outf = sio - > out ;
hawk - > sio . last . c = HAWK_OOCI_EOF ;
/*hawk->sio.arg.name = HAWK_NULL;
hawk - > sio . arg . handle = HAWK_NULL ;
hawk - > sio . arg . path = HAWK_NULL ; */
hawk - > sio . arg . line = 1 ;
hawk - > sio . arg . colm = 1 ;
hawk - > sio . arg . pragma_trait = 0 ;
hawk - > sio . inp = & hawk - > sio . arg ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
n = parse ( hawk ) ;
2020-05-03 05:45:31 +00:00
if ( n = = 0 & & hawk - > sio . outf ! = HAWK_NULL ) n = deparse ( hawk ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > parse . depth . loop = = 0 ) ;
HAWK_ASSERT ( hawk - > parse . depth . expr = = 0 ) ;
2019-12-13 04:29:58 +00:00
return n ;
}
2020-04-16 03:42:30 +00:00
static int end_include ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
int x ;
hawk_sio_arg_t * cur ;
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inp = = & hawk - > sio . arg ) return 0 ; /* no include */
2019-12-13 04:29:58 +00:00
/* if it is an included file, close it and
* retry to read a character from an outer file */
2020-04-16 03:42:30 +00:00
x = hawk - > sio . inf ( hawk , HAWK_SIO_CMD_CLOSE , hawk - > sio . inp , HAWK_NULL , 0 ) ;
2019-12-13 04:29:58 +00:00
/* if closing has failed, still destroy the
* sio structure first as normal and return
2024-04-28 19:15:17 +09:00
* the failure below . this way , the caller
* does not call HAWK_SIO_CMD_CLOSE on
2020-04-16 03:42:30 +00:00
* hawk - > sio . inp again . */
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
cur = hawk - > sio . inp ;
hawk - > sio . inp = hawk - > sio . inp - > prev ;
2019-12-13 04:29:58 +00:00
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( cur - > name ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
/* restore the pragma values */
2020-04-16 03:42:30 +00:00
hawk - > parse . pragma . trait = cur - > pragma_trait ;
hawk_freemem ( hawk , cur ) ;
hawk - > parse . depth . incl - - ;
2019-12-13 04:29:58 +00:00
if ( x ! = 0 )
{
/* the failure mentioned above is returned here */
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > sio . last = hawk - > sio . inp - > last ;
2019-12-13 04:29:58 +00:00
return 1 ; /* ended the included file successfully */
}
2020-04-16 03:42:30 +00:00
static int ever_included ( hawk_t * hawk , hawk_sio_arg_t * arg )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t i ;
2020-04-16 03:42:30 +00:00
for ( i = 0 ; i < hawk - > parse . incl_hist . count ; i + + )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( HAWK_MEMCMP ( & hawk - > parse . incl_hist . ptr [ i * HAWK_SIZEOF ( arg - > unique_id ) ] , arg - > unique_id , HAWK_SIZEOF ( arg - > unique_id ) ) = = 0 ) return 1 ;
2019-12-13 04:29:58 +00:00
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int record_ever_included ( hawk_t * hawk , hawk_sio_arg_t * arg )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk - > parse . incl_hist . count > = hawk - > parse . incl_hist . capa )
2019-12-13 04:29:58 +00:00
{
hawk_uint8_t * tmp ;
hawk_oow_t newcapa ;
2020-04-16 03:42:30 +00:00
newcapa = hawk - > parse . incl_hist . capa + 128 ;
tmp = ( hawk_uint8_t * ) hawk_reallocmem ( hawk , hawk - > parse . incl_hist . ptr , newcapa * HAWK_SIZEOF ( arg - > unique_id ) ) ;
2019-12-13 04:29:58 +00:00
if ( ! tmp ) return - 1 ;
2020-04-16 03:42:30 +00:00
hawk - > parse . incl_hist . ptr = tmp ;
hawk - > parse . incl_hist . capa = newcapa ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
HAWK_MEMCPY ( & hawk - > parse . incl_hist . ptr [ hawk - > parse . incl_hist . count * HAWK_SIZEOF ( arg - > unique_id ) ] , arg - > unique_id , HAWK_SIZEOF ( arg - > unique_id ) ) ;
hawk - > parse . incl_hist . count + + ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int begin_include ( hawk_t * hawk , int once )
2019-12-13 04:29:58 +00:00
{
hawk_sio_arg_t * arg = HAWK_NULL ;
2019-12-25 16:01:43 +00:00
hawk_ooch_t * sio_name ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk_count_oocstr ( HAWK_OOECS_PTR ( hawk - > tok . name ) ) ! = HAWK_OOECS_LEN ( hawk - > tok . name ) )
2019-12-13 04:29:58 +00:00
{
/* a '\0' character included in the include file name.
* we don ' t support such a file name */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EIONMNL , FMT_EIONMNL , HAWK_OOECS_LEN ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . includedirs . ptr )
2019-12-13 04:29:58 +00:00
{
/* include directory is set... */
/* TODO: search target files in these directories */
}
/* store the include-file name into a list
* and this list is not deleted after hawk_parse .
2019-12-25 16:01:43 +00:00
* the errinfo . loc . file can point to the file name here . */
2020-04-16 03:42:30 +00:00
sio_name = hawk_addsionamewithoochars ( hawk , HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! sio_name ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > ptok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
arg = ( hawk_sio_arg_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * arg ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! arg ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > ptok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2019-12-25 16:01:43 +00:00
arg - > name = sio_name ;
2019-12-13 04:29:58 +00:00
arg - > line = 1 ;
arg - > colm = 1 ;
/* let the argument's prev field point to the current */
2020-04-16 03:42:30 +00:00
arg - > prev = hawk - > sio . inp ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inf ( hawk , HAWK_SIO_CMD_OPEN , arg , HAWK_NULL , 0 ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/* store the pragma value */
2020-04-16 03:42:30 +00:00
arg - > pragma_trait = hawk - > parse . pragma . trait ;
/* but don't change hawk->parse.pragma.trait. it means the included file inherits
2024-04-28 19:15:17 +09:00
* the existing progma values .
2020-04-16 03:42:30 +00:00
hawk - > parse . pragma . trait = ( hawk - > opt . trait & ( HAWK_IMPLICIT | HAWK_MULTILINESTR | HAWK_STRIPRECSPC | HAWK_STRIPSTRSPC ) ) ;
2019-12-13 04:29:58 +00:00
*/
2022-06-10 02:31:20 +00:00
/* update the current pointer after opening is successful */
2020-04-16 03:42:30 +00:00
hawk - > sio . inp = arg ;
hawk - > parse . depth . incl + + ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( once & & ever_included ( hawk , arg ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
end_include ( hawk ) ;
2019-12-13 04:29:58 +00:00
/* it has been included previously. don't include this file again. */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ; /* skip the include file name */
if ( MATCH ( hawk , TOK_SEMICOLON ) | | MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ; /* skip the semicolon */
2019-12-13 04:29:58 +00:00
}
}
else
{
2024-04-28 19:15:17 +09:00
/* read in the first character in the included file.
2019-12-13 04:29:58 +00:00
* so the next call to get_token ( ) sees the character read
* from this file . */
2020-04-16 03:42:30 +00:00
if ( record_ever_included ( hawk , arg ) < = - 1 | | get_char ( hawk ) < = - 1 | | get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
end_include ( hawk ) ;
/* i don't jump to oops since i've called
2020-04-16 03:42:30 +00:00
* end_include ( ) where hawk - > sio . inp / arg is freed . */
2019-12-13 04:29:58 +00:00
return - 1 ;
}
}
return 0 ;
oops :
2020-04-16 03:42:30 +00:00
/* i don't need to free 'link' here since it's linked to hawk->sio_names
2019-12-13 04:29:58 +00:00
* that ' s freed at the beginning of hawk_parse ( ) or by hawk_close ( ) . */
2020-04-16 03:42:30 +00:00
if ( arg ) hawk_freemem ( hawk , arg ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
static int parse_progunit ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
/*
2020-01-11 05:24:07 +00:00
@ pragma . . . .
2019-12-13 04:29:58 +00:00
@ include " xxxx "
@ global xxx , xxxx ;
BEGIN { action }
END { action }
pattern { action }
function name ( parameter - list ) { statement }
*/
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > parse . depth . loop = = 0 ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_XGLOBAL ) )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t ngbls ;
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_GBL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls = = HAWK_ARR_SIZE ( hawk - > parse . gbls ) ) ;
ngbls = hawk - > tree . ngbls ;
2024-04-28 19:15:17 +09:00
if ( collect_globals ( hawk ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_arr_delete ( hawk - > parse . gbls , ngbls , HAWK_ARR_SIZE ( hawk - > parse . gbls ) - ngbls ) ;
hawk - > tree . ngbls = ngbls ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_XINCLUDE ) | | MATCH ( hawk , TOK_XINCLUDE_ONCE ) )
2019-12-13 04:29:58 +00:00
{
int once ;
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . incl > 0 & &
hawk - > parse . depth . incl > = hawk - > opt . depth . s . incl )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLTD ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
once = MATCH ( hawk , TOK_XINCLUDE_ONCE ) ;
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_STR ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLSTR ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( begin_include ( hawk , once ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
/* i just return without doing anything special
2024-04-28 19:15:17 +09:00
* after having setting up the environment for file
* inclusion . the loop in parse ( ) proceeds to call
2019-12-13 04:29:58 +00:00
* parse_progunit ( ) */
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_XPRAGMA ) )
2019-12-13 04:29:58 +00:00
{
hawk_oocs_t name ;
2021-10-14 05:00:55 +00:00
int trait ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > ptok . loc , HAWK_EIDENT , HAWK_T ( " identifier expected for '@pragma' " ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
name . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
name . ptr = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
2021-07-19 19:54:01 +00:00
if ( hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " entry " ) , 0 ) = = 0 )
2020-02-21 07:58:24 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( ! MATCH ( hawk , TOK_IDENT ) )
2020-02-21 07:58:24 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > ptok . loc , HAWK_EIDENT , HAWK_T ( " function name expected for 'entry' " ) ) ;
2020-02-21 07:58:24 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( HAWK_OOECS_LEN ( hawk - > tok . name ) > = HAWK_COUNTOF ( hawk - > parse . pragma . entry ) )
2020-02-21 07:58:24 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EFUNNAM , HAWK_T ( " entry function name too long " ) ) ;
2020-02-21 07:58:24 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inp = = & hawk - > sio . arg )
2020-02-21 07:58:24 +00:00
{
/* only the top level source */
2020-04-16 03:42:30 +00:00
if ( hawk - > parse . pragma . entry [ 0 ] ! = ' \0 ' )
2020-02-21 07:58:24 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EEXIST , HAWK_T ( " @pragma entry already set " ) ) ;
2020-02-21 07:58:24 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk_copy_oochars_to_oocstr ( hawk - > parse . pragma . entry , HAWK_COUNTOF ( hawk - > parse . pragma . entry ) , HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) ) ;
2020-02-21 07:58:24 +00:00
}
}
2021-10-14 05:00:55 +00:00
/* NOTE: trait = is an intended assignment */
else if ( ( ( trait = HAWK_IMPLICIT ) & & hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " implicit " ) , 0 ) = = 0 ) | |
( ( trait = HAWK_MULTILINESTR ) & & hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " multilinestr " ) , 0 ) = = 0 ) )
2019-12-13 04:29:58 +00:00
{
/* @pragma implicit on
2024-04-28 19:15:17 +09:00
* @ pragma implicit off
2021-10-14 05:00:55 +00:00
* @ pragma multilinestr on
* @ pragma multilinestr off */
hawk_oocs_t value ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
error_ident_on_off_expected_for_implicit :
2021-10-14 05:00:55 +00:00
hawk_seterrfmt ( hawk , & hawk - > ptok . loc , HAWK_EIDENT , HAWK_T ( " identifier 'on' or 'off' expected for '%.*js' " ) , name . len , name . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2021-10-14 05:00:55 +00:00
value . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
value . ptr = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
if ( hawk_comp_oochars_oocstr ( value . ptr , value . len , HAWK_T ( " on " ) , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
2021-10-14 05:00:55 +00:00
hawk - > parse . pragma . trait | = trait ;
2019-12-13 04:29:58 +00:00
}
2021-10-14 05:00:55 +00:00
else if ( hawk_comp_oochars_oocstr ( value . ptr , value . len , HAWK_T ( " off " ) , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
2021-10-14 05:00:55 +00:00
hawk - > parse . pragma . trait & = ~ trait ;
2019-12-13 04:29:58 +00:00
}
else
{
goto error_ident_on_off_expected_for_implicit ;
}
}
2021-10-14 05:00:55 +00:00
/* NOTE: trait = is an intended assignment */
else if ( ( ( trait = HAWK_STRIPRECSPC ) & & hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " striprecspc " ) , 0 ) = = 0 ) | |
( ( trait = HAWK_STRIPSTRSPC ) & & hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " stripstrspc " ) , 0 ) = = 0 ) | |
( ( trait = HAWK_NUMSTRDETECT ) & & hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " numstrdetect " ) , 0 ) = = 0 ) )
2020-01-11 05:24:07 +00:00
{
2020-02-21 07:58:24 +00:00
/* @pragma striprecspc on
2024-04-28 19:15:17 +09:00
* @ pragma striprecspc off
2021-10-14 05:00:55 +00:00
* @ pragma stripstrspc on
2024-04-28 19:15:17 +09:00
* @ pragma stripstrspc off
2021-10-14 05:00:55 +00:00
* @ pragma numstrdetect on
2024-04-28 19:15:17 +09:00
* @ pragma numstrdetect off
2020-02-21 07:58:24 +00:00
*
* Take note the global STRIPRECSPC is available for context based change .
* STRIPRECSPC takes precedence over this pragma .
*/
int is_on ;
2021-10-14 05:00:55 +00:00
hawk_oocs_t value ;
2020-02-21 07:58:24 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( ! MATCH ( hawk , TOK_IDENT ) )
2020-01-11 05:24:07 +00:00
{
2020-02-21 07:58:24 +00:00
error_ident_on_off_expected_for_striprecspc :
2021-10-14 05:00:55 +00:00
hawk_seterrfmt ( hawk , & hawk - > ptok . loc , HAWK_EIDENT , HAWK_T ( " identifier 'on' or 'off' expected for '%.*js' " ) , name . len , name . ptr ) ;
2020-03-09 08:52:42 +00:00
return - 1 ;
}
2021-10-14 05:00:55 +00:00
value . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
value . ptr = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
if ( hawk_comp_oochars_oocstr ( value . ptr , value . len , HAWK_T ( " on " ) , 0 ) = = 0 ) is_on = 1 ;
else if ( hawk_comp_oochars_oocstr ( value . ptr , value . len , HAWK_T ( " off " ) , 0 ) = = 0 ) is_on = 0 ;
else goto error_ident_on_off_expected_for_striprecspc ;
2020-03-09 08:52:42 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . inp = = & hawk - > sio . arg )
2020-03-09 08:52:42 +00:00
{
2021-10-14 05:00:55 +00:00
/* only the top level source. ignore the specified pragma in other levels */
2020-03-09 08:52:42 +00:00
if ( is_on )
2021-10-14 05:00:55 +00:00
hawk - > parse . pragma . trait | = trait ;
2020-03-09 08:52:42 +00:00
else
2021-10-14 05:00:55 +00:00
hawk - > parse . pragma . trait & = ~ trait ;
2020-03-09 08:52:42 +00:00
}
}
2024-04-28 19:15:17 +09:00
/* ---------------------------------------------------------------------
* the pragmas up to this point affect the parser
* the following pragmas affect runtime
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
else if ( hawk_comp_oochars_oocstr ( name . ptr , name . len , HAWK_T ( " stack_limit " ) , 0 ) = = 0 )
{
hawk_int_t sl ;
/* @pragma stack_limit 99999 */
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( ! MATCH ( hawk , TOK_INT ) )
{
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EINTLIT , FMT_EINTLIT , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
return - 1 ;
}
sl = hawk_oochars_to_int ( HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOCHARS_TO_INT_MAKE_OPTION ( 0 , 0 , 0 ) , HAWK_NULL , HAWK_NULL ) ;
if ( sl < HAWK_MIN_RTX_STACK_LIMIT ) sl = HAWK_MIN_RTX_STACK_LIMIT ;
else if ( sl > HAWK_MAX_RTX_STACK_LIMIT ) sl = HAWK_MAX_RTX_STACK_LIMIT ;
/* take the specified value if it's greater than the existing value */
if ( sl > hawk - > parse . pragma . rtx_stack_limit ) hawk - > parse . pragma . rtx_stack_limit = sl ;
}
2019-12-13 04:29:58 +00:00
else
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > ptok . loc , HAWK_EIDENT , HAWK_T ( " unknown @pragma identifier - %.*js " ) , name . len , name . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
if ( MATCH ( hawk , TOK_SEMICOLON ) & & get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_FUNCTION ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_FUNCTION ;
if ( parse_function ( hawk ) = = HAWK_NULL ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_BEGIN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_PABLOCK ) ) /* pattern action block not allowed */
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWFNC , FMT_EKWFNC , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_BEGIN ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_NEWLINE ) | | MATCH ( hawk , TOK_EOF ) )
2019-12-13 04:29:58 +00:00
{
/* when HAWK_NEWLINE is set,
* BEGIN and { should be located on the same line */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EBLKBEG ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELBRACE , FMT_ELBRACE , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_BEGIN_BLOCK ;
if ( parse_begin ( hawk ) = = HAWK_NULL ) return - 1 ;
2019-12-13 04:29:58 +00:00
/* skip a semicolon after an action block if any */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_SEMICOLON ) & & get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_END ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_PABLOCK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWFNC , FMT_EKWFNC , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_END ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_NEWLINE ) | | MATCH ( hawk , TOK_EOF ) )
2019-12-13 04:29:58 +00:00
{
/* when HAWK_NEWLINE is set,
* END and { should be located on the same line */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EBLKEND ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELBRACE , FMT_ELBRACE , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_END_BLOCK ;
if ( parse_end ( hawk ) = = HAWK_NULL ) return - 1 ;
2019-12-13 04:29:58 +00:00
/* skip a semicolon after an action block if any */
2020-05-02 18:34:18 +00:00
if ( MATCH ( hawk , TOK_SEMICOLON ) & & get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
/* patternless block */
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_PABLOCK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWFNC , FMT_EKWFNC , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_ACTION_BLOCK ;
if ( parse_action_block ( hawk , HAWK_NULL , 0 ) = = HAWK_NULL ) return - 1 ;
2019-12-13 04:29:58 +00:00
/* skip a semicolon after an action block if any */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_SEMICOLON ) & & get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
else
{
2024-04-28 19:15:17 +09:00
/*
expressions
2019-12-13 04:29:58 +00:00
/ regular expression /
pattern & & pattern
pattern | | pattern
! pattern
( pattern )
pattern , pattern
*/
hawk_nde_t * ptn ;
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_PABLOCK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWFNC , FMT_EKWFNC , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_PATTERN ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2021-08-17 19:26:41 +00:00
ptn = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( ptn = = HAWK_NULL ) return - 1 ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( ptn - > next = = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , ptn ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
ptn - > next = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ptn - > next = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , ptn ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
}
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_NEWLINE ) | | MATCH ( hawk , TOK_SEMICOLON ) | | MATCH ( hawk , TOK_EOF ) )
2019-12-13 04:29:58 +00:00
{
/* blockless pattern */
int eof ;
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
eof = MATCH ( hawk , TOK_EOF ) ;
ploc = hawk - > ptok . loc ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_ACTION_BLOCK ;
if ( parse_action_block ( hawk , ptn , 1 ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , ptn ) ;
2019-12-14 16:05:10 +00:00
return - 1 ;
2019-12-13 04:29:58 +00:00
}
if ( ! eof )
{
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* 'ptn' has been added to the chain.
2019-12-13 04:29:58 +00:00
* it doesn ' t have to be cleared here
* as hawk_clear does it */
2020-04-16 03:42:30 +00:00
/*hawk_clrpt (hawk, ptn);*/
2019-12-13 04:29:58 +00:00
return - 1 ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & HAWK_RIO ) ! = HAWK_RIO )
2019-12-13 04:29:58 +00:00
{
/* blockless pattern requires HAWK_RIO
* to be ON because the implicit block is
* " print $0 " */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & ploc , HAWK_ENOSUP ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
}
else
{
/* parse the action block */
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , ptn ) ;
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELBRACE , FMT_ELBRACE , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . id . block = PARSE_ACTION_BLOCK ;
2024-04-28 19:15:17 +09:00
if ( parse_action_block ( hawk , ptn , 0 ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , ptn ) ;
2019-12-14 16:05:10 +00:00
return - 1 ;
2019-12-13 04:29:58 +00:00
}
/* skip a semicolon after an action block if any */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_SEMICOLON ) & & get_token ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_function ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_oocs_t name ;
hawk_nde_t * body = HAWK_NULL ;
hawk_fun_t * fun = HAWK_NULL ;
hawk_ooch_t * argspec = HAWK_NULL ;
hawk_oow_t argspeccapa = 0 ;
2024-05-03 14:04:03 +09:00
hawk_oow_t argspeclen = 0 ;
2019-12-13 04:29:58 +00:00
hawk_oow_t nargs , g ;
2024-05-02 22:36:50 +09:00
int variadic = 0 ;
2019-12-13 04:29:58 +00:00
hawk_htb_pair_t * pair ;
hawk_loc_t xloc ;
int rederr ;
2020-01-03 10:22:23 +00:00
const hawk_ooch_t * redobj ;
2019-12-13 04:29:58 +00:00
/* eat up the keyword 'function' and get the next token */
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( MATCH ( hawk , TOK_FUNCTION ) ) ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
/* check if an identifier is in place */
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
/* cannot find a valid identifier for a function name */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EFUNNAM , HAWK_T ( " '%.*js' not a valid function name " ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
name . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
name . ptr = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
/* note that i'm assigning to rederr in the 'if' conditions below.
* i ' m not checking equality */
/* check if it is a builtin function */
2020-04-16 03:42:30 +00:00
if ( ( hawk_findfncwithoocs ( hawk , & name ) ! = HAWK_NULL & & ( rederr = HAWK_EFNCRED , redobj = HAWK_T ( " intrinsic function " ) ) ) | |
2019-12-13 04:29:58 +00:00
/* check if it has already been defined as a function */
2020-04-16 03:42:30 +00:00
( hawk_htb_search ( hawk - > tree . funs , name . ptr , name . len ) ! = HAWK_NULL & & ( rederr = HAWK_EFUNRED , redobj = HAWK_T ( " function " ) ) ) | |
2019-12-13 04:29:58 +00:00
/* check if it conflicts with a named variable */
2020-04-16 03:42:30 +00:00
( hawk_htb_search ( hawk - > parse . named , name . ptr , name . len ) ! = HAWK_NULL & & ( rederr = HAWK_EVARRED , redobj = HAWK_T ( " variable " ) ) ) | |
2019-12-13 04:29:58 +00:00
/* check if it coincides to be a global variable name */
2024-04-28 19:15:17 +09:00
( ( ( g = find_global ( hawk , & name ) ) ! = HAWK_ARR_NIL ) & & ( rederr = HAWK_EGBLRED , redobj = HAWK_T ( " global variable " ) ) ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , rederr , HAWK_T ( " %js '%.*js' redefined " ) , redobj , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
/* duplicate the name before it's overridden by get_token() */
2020-04-16 03:42:30 +00:00
name . ptr = hawk_dupoochars ( hawk , name . ptr , name . len ) ;
2019-12-13 04:29:58 +00:00
if ( ! name . ptr )
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
/* get the next token */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* match a left parenthesis */
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
/* a function name is not followed by a left parenthesis */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/* get the next token */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* make sure that parameter table is empty */
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( HAWK_ARR_SIZE ( hawk - > parse . params ) = = 0 ) ;
2019-12-13 04:29:58 +00:00
/* read parameter list */
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
/* no function parameter found. get the next token */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
hawk_ooch_t * pa ;
hawk_oow_t pal ;
2024-05-02 22:36:50 +09:00
if ( MATCH ( hawk , TOK_ELLIPSIS ) )
{
/* this must be the last parameter. the variadic part doesn't support reference */
/* this must be the last token before the parenthesis if given.
* function xxx ( . . . )
* function xxx ( a . . . )
* function xxx ( a , b . . . ) */
if ( get_token ( hawk ) < = - 1 ) goto oops ;
if ( ! MATCH ( hawk , TOK_RPAREN ) )
{
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
goto oops ;
}
variadic = 1 ;
break ;
}
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_BAND ) ) /* &arg */
2019-12-13 04:29:58 +00:00
{
/* pass-by-reference argument */
2020-04-16 03:42:30 +00:00
nargs = HAWK_ARR_SIZE ( hawk - > parse . params ) ;
2019-12-13 04:29:58 +00:00
if ( nargs > = argspeccapa )
{
2020-04-13 08:41:16 +00:00
hawk_oow_t i , newcapa = HAWK_ALIGN_POW2 ( nargs + 2 , 64 ) ;
2020-04-16 03:42:30 +00:00
argspec = hawk_reallocmem ( hawk , argspec , newcapa * HAWK_SIZEOF ( * argspec ) ) ;
2024-05-01 13:24:08 +09:00
if ( HAWK_UNLIKELY ( ! argspec ) ) goto oops ;
2019-12-13 04:29:58 +00:00
for ( i = argspeccapa ; i < newcapa ; i + + ) argspec [ i ] = HAWK_T ( ' ' ) ;
argspeccapa = newcapa ;
}
2020-04-12 18:23:44 +00:00
argspec [ nargs ] = ' r ' ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EBADPAR , HAWK_T ( " '%.*js' not a valid parameter name " ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
pa = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
pal = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
/* NOTE: the following is not a conflict.
2019-12-13 04:29:58 +00:00
* so the parameter is not checked against
* global variables .
2024-04-28 19:15:17 +09:00
* global x ;
* function f ( x ) { print x ; }
2019-12-13 04:29:58 +00:00
* x in print x is a parameter
*/
2024-04-28 19:15:17 +09:00
/* check if a parameter conflicts with the function
2019-12-13 04:29:58 +00:00
* name or other parameters */
2020-04-16 03:42:30 +00:00
if ( ( ( hawk - > opt . trait & HAWK_STRICTNAMING ) & &
2019-12-13 04:29:58 +00:00
hawk_comp_oochars ( pa , pal , name . ptr , name . len , 0 ) = = 0 ) | |
2020-04-16 03:42:30 +00:00
hawk_arr_search ( hawk - > parse . params , 0 , pa , pal ) ! = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EDUPPAR , HAWK_T ( " duplicate parameter name '%.*js' " ) , pal , pa ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/* push the parameter to the parameter list */
2020-04-16 03:42:30 +00:00
if ( HAWK_ARR_SIZE ( hawk - > parse . params ) > = HAWK_MAX_PARAMS )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > tok . loc , HAWK_EPARTM ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( hawk_arr_insert ( hawk - > parse . params , HAWK_ARR_SIZE ( hawk - > parse . params ) , pa , pal ) = = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-05-02 22:36:50 +09:00
/* no ... present after the variable name */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_RPAREN ) ) break ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ECOMMA , FMT_ECOMMA , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
}
2024-05-01 13:24:08 +09:00
if ( argspec )
{
/* nargs is the number taken before the current argument word was added to the parse.params array.
* so the actual number of arguments is nargs + 1 */
argspeclen = nargs + 1 ;
argspec [ argspeclen ] = ' \0 ' ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
/* function body can be placed on a different line
2019-12-13 04:29:58 +00:00
* from a function name and the parameters even if
* HAWK_NEWLINE is set . note TOK_NEWLINE is
* available only when the option is set . */
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
/* check if the function body starts with a left brace */
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELBRACE , FMT_ELBRACE , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* remember the current function name so that the body parser
* can know the name of the current function being parsed */
2020-04-16 03:42:30 +00:00
hawk - > tree . cur_fun . ptr = name . ptr ;
hawk - > tree . cur_fun . len = name . len ;
2019-12-13 04:29:58 +00:00
/* actual function body */
2020-04-16 03:42:30 +00:00
xloc = hawk - > ptok . loc ;
body = parse_block_dc ( hawk , & xloc , 1 ) ;
2019-12-13 04:29:58 +00:00
/* clear the current function name remembered */
2020-04-16 03:42:30 +00:00
hawk - > tree . cur_fun . ptr = HAWK_NULL ;
hawk - > tree . cur_fun . len = 0 ;
2019-12-13 04:29:58 +00:00
if ( ! body ) goto oops ;
2024-04-28 19:15:17 +09:00
/* TODO: study furthur if the parameter names should be saved
2019-12-13 04:29:58 +00:00
* for some reasons - might be needed for better deparsing output */
2020-04-16 03:42:30 +00:00
nargs = HAWK_ARR_SIZE ( hawk - > parse . params ) ;
2019-12-13 04:29:58 +00:00
/* parameter names are not required anymore. clear them */
2020-04-16 03:42:30 +00:00
hawk_arr_clear ( hawk - > parse . params ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
fun = ( hawk_fun_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * fun ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! fun ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/*fun->name.ptr = HAWK_NULL;*/ /* function name is set below */
fun - > name . len = 0 ;
fun - > nargs = nargs ;
2024-05-02 22:36:50 +09:00
fun - > variadic = variadic ;
2019-12-13 04:29:58 +00:00
fun - > argspec = argspec ;
2024-05-01 13:24:08 +09:00
fun - > argspeclen = argspeclen ;
2019-12-13 04:29:58 +00:00
fun - > body = body ;
2020-04-16 03:42:30 +00:00
pair = hawk_htb_insert ( hawk - > tree . funs , name . ptr , name . len , fun , 0 ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! pair ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* if hawk_htb_insert() fails for other reasons than memory
2019-12-13 04:29:58 +00:00
* shortage , there should be implementaion errors as duplicate
* functions are detected earlier in this function */
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2024-04-28 19:15:17 +09:00
/* do some trick to save a string. make it back-point at the key part
2019-12-13 04:29:58 +00:00
* of the pair */
2024-04-28 19:15:17 +09:00
fun - > name . ptr = HAWK_HTB_KPTR ( pair ) ;
2019-12-13 04:29:58 +00:00
fun - > name . len = HAWK_HTB_KLEN ( pair ) ;
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , name . ptr ) ;
2019-12-13 04:29:58 +00:00
/* remove an undefined function call entry from the parse.fun table */
2020-04-16 03:42:30 +00:00
hawk_htb_delete ( hawk - > parse . funs , fun - > name . ptr , name . len ) ;
2019-12-13 04:29:58 +00:00
return body ;
oops :
2020-04-16 03:42:30 +00:00
if ( body ) hawk_clrpt ( hawk , body ) ;
if ( argspec ) hawk_freemem ( hawk , argspec ) ;
if ( fun ) hawk_freemem ( hawk , fun ) ;
hawk_freemem ( hawk , name . ptr ) ;
hawk_arr_clear ( hawk - > parse . params ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_begin ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
hawk_loc_t xloc ;
2020-04-16 03:42:30 +00:00
xloc = hawk - > tok . loc ;
HAWK_ASSERT ( MATCH ( hawk , TOK_LBRACE ) ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-10 02:56:29 +00:00
nde = parse_block_dc ( hawk , & xloc , 1 ) ;
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > tree . begin = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > tree . begin = nde ;
hawk - > tree . begin_tail = nde ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
hawk - > tree . begin_tail - > next = nde ;
hawk - > tree . begin_tail = nde ;
2019-12-13 04:29:58 +00:00
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_end ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
hawk_loc_t xloc ;
2020-04-16 03:42:30 +00:00
xloc = hawk - > tok . loc ;
HAWK_ASSERT ( MATCH ( hawk , TOK_LBRACE ) ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-10 02:56:29 +00:00
nde = parse_block_dc ( hawk , & xloc , 1 ) ;
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > tree . end = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > tree . end = nde ;
hawk - > tree . end_tail = nde ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
hawk - > tree . end_tail - > next = nde ;
hawk - > tree . end_tail = nde ;
2019-12-13 04:29:58 +00:00
}
return nde ;
}
2020-11-10 02:56:29 +00:00
static hawk_chain_t * parse_action_block ( hawk_t * hawk , hawk_nde_t * ptn , int blockless )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
hawk_chain_t * chain ;
hawk_loc_t xloc ;
2020-04-16 03:42:30 +00:00
xloc = hawk - > tok . loc ;
2019-12-13 04:29:58 +00:00
if ( blockless ) nde = HAWK_NULL ;
else
{
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( MATCH ( hawk , TOK_LBRACE ) ) ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-04-16 03:42:30 +00:00
nde = parse_block_dc ( hawk , & xloc , 1 ) ;
2020-11-10 02:56:29 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
chain = ( hawk_chain_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * chain ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! chain ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
ADJERR_LOC ( hawk , & xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
chain - > pattern = ptn ;
chain - > action = nde ;
chain - > next = HAWK_NULL ;
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . chain = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > tree . chain = chain ;
hawk - > tree . chain_tail = chain ;
hawk - > tree . chain_size + + ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > tree . chain_tail - > next = chain ;
hawk - > tree . chain_tail = chain ;
hawk - > tree . chain_size + + ;
2019-12-13 04:29:58 +00:00
}
return chain ;
}
2024-04-28 19:15:17 +09:00
static hawk_nde_t * parse_block ( hawk_t * hawk , const hawk_loc_t * xloc , int istop )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * head , * curr , * nde ;
hawk_nde_blk_t * block ;
2020-11-12 08:02:36 +00:00
hawk_oow_t nlcls_outer , nlcls_max , tmp ;
2019-12-13 04:29:58 +00:00
2020-11-12 08:02:36 +00:00
nlcls_outer = HAWK_ARR_SIZE ( hawk - > parse . lcls ) ;
2020-04-16 03:42:30 +00:00
nlcls_max = hawk - > parse . nlcls_max ;
2019-12-13 04:29:58 +00:00
/* local variable declarations */
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
/* skip new lines before local declaration in a block*/
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_XINCLUDE ) | | MATCH ( hawk , TOK_XINCLUDE_ONCE ) )
2019-12-13 04:29:58 +00:00
{
/* @include ... */
int once ;
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . incl > 0 & &
hawk - > parse . depth . incl > = hawk - > opt . depth . s . incl )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLTD ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
once = MATCH ( hawk , TOK_XINCLUDE_ONCE ) ;
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_STR ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLSTR ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( begin_include ( hawk , once ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_XLOCAL ) )
2019-12-13 04:29:58 +00:00
{
/* @local ... */
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
2020-11-12 08:02:36 +00:00
if ( collect_locals ( hawk , nlcls_outer , istop ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
else break ;
}
/* block body */
head = HAWK_NULL ; curr = HAWK_NULL ;
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
/* skip new lines within a block */
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
/* if EOF is met before the right brace, this is an error */
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_EOF ) )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2020-11-10 02:56:29 +00:00
if ( head ) hawk_clrpt ( hawk , head ) ;
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > tok . loc , HAWK_EEOF ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
/* end the block when the right brace is met */
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_RBRACE ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2020-11-10 02:56:29 +00:00
if ( head ) hawk_clrpt ( hawk , head ) ;
2024-04-28 19:15:17 +09:00
return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
break ;
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_XINCLUDE ) | | MATCH ( hawk , TOK_XINCLUDE_ONCE ) )
2019-12-13 04:29:58 +00:00
{
int once ;
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . incl > 0 & &
hawk - > parse . depth . incl > = hawk - > opt . depth . s . incl )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLTD ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
once = MATCH ( hawk , TOK_XINCLUDE_ONCE ) ;
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_STR ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_EINCLSTR ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( begin_include ( hawk , once ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
else
{
/* parse an actual statement in a block */
{
hawk_loc_t sloc ;
2020-04-16 03:42:30 +00:00
sloc = hawk - > tok . loc ;
2020-11-10 02:56:29 +00:00
nde = parse_statement ( hawk , & sloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2020-04-16 03:42:30 +00:00
if ( head ) hawk_clrpt ( hawk , head ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
/* remove unnecessary statements such as adjacent
2019-12-13 04:29:58 +00:00
* null statements */
2024-04-28 19:15:17 +09:00
if ( nde - > type = = HAWK_NDE_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
continue ;
}
2024-04-28 19:15:17 +09:00
if ( nde - > type = = HAWK_NDE_BLK & & ( ( hawk_nde_blk_t * ) nde ) - > body = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
continue ;
}
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
if ( curr = = HAWK_NULL ) head = nde ;
else curr - > next = nde ;
curr = nde ;
}
}
2020-04-16 03:42:30 +00:00
block = ( hawk_nde_blk_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * block ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! block ) )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , HAWK_ARR_SIZE ( hawk - > parse . lcls ) - nlcls_outer ) ;
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , head ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
tmp = HAWK_ARR_SIZE ( hawk - > parse . lcls ) ;
if ( tmp > hawk - > parse . nlcls_max ) hawk - > parse . nlcls_max = tmp ;
2019-12-13 04:29:58 +00:00
2020-11-10 02:56:29 +00:00
/* remove all lcls to move them up to the top level */
2020-11-12 08:02:36 +00:00
hawk_arr_delete ( hawk - > parse . lcls , nlcls_outer , tmp - nlcls_outer ) ;
2019-12-13 04:29:58 +00:00
/* adjust the number of lcls for a block without any statements */
/* if (head == HAWK_NULL) tmp = 0; */
block - > type = HAWK_NDE_BLK ;
block - > loc = * xloc ;
block - > body = head ;
2020-11-12 08:02:36 +00:00
block - > org_nlcls = tmp - nlcls_outer ; /* number of locals defined in this block */
block - > outer_nlcls = nlcls_outer ; /* number of locals defined in outer blocks */
# if 1
2024-04-28 19:15:17 +09:00
/* TODO: not only local variables but also nested blocks,
unless it is part of other constructs such as if , can be promoted
2019-12-13 04:29:58 +00:00
and merged to top - level block */
2020-11-12 08:02:36 +00:00
/* migrate all block-local variables to the outermost block */
2024-04-28 19:15:17 +09:00
if ( istop )
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
HAWK_ASSERT ( nlcls_outer = = 0 & & nlcls_max = = 0 ) ;
block - > nlcls = hawk - > parse . nlcls_max - nlcls_outer ;
hawk - > parse . nlcls_max = nlcls_max ; /* restore */
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
block - > nlcls = 0 ;
}
2020-11-12 08:02:36 +00:00
# else
/* no migration */
2024-04-28 19:15:17 +09:00
block - > nlcls = block - > org_nlcls ;
2020-11-12 08:02:36 +00:00
# endif
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) block ;
}
2024-04-28 19:15:17 +09:00
static hawk_nde_t * parse_block_dc ( hawk_t * hawk , const hawk_loc_t * xloc , int istop )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
2020-11-10 02:56:29 +00:00
/* perform the depth check before calling parse_block() */
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . block_parse > 0 & &
hawk - > parse . depth . block > = hawk - > opt . depth . s . block_parse )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EBLKNST ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . block + + ;
nde = parse_block ( hawk , xloc , istop ) ;
hawk - > parse . depth . block - - ;
2019-12-13 04:29:58 +00:00
return nde ;
}
2020-04-16 03:42:30 +00:00
int hawk_initgbls ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
int id ;
/* hawk_initgbls is not generic-purpose. call this from
* hawk_open only . */
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls_base = = 0 & & hawk - > tree . ngbls = = 0 ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > tree . ngbls_base = 0 ;
hawk - > tree . ngbls = 0 ;
2019-12-13 04:29:58 +00:00
for ( id = HAWK_MIN_GBL_ID ; id < = HAWK_MAX_GBL_ID ; id + + )
{
hawk_oow_t g ;
2020-04-16 03:42:30 +00:00
g = hawk_arr_insert ( hawk - > parse . gbls , HAWK_ARR_SIZE ( hawk - > parse . gbls ) , ( hawk_ooch_t * ) gtab [ id ] . name , gtab [ id ] . namelen ) ;
2019-12-13 04:29:58 +00:00
if ( g = = HAWK_ARR_NIL ) return - 1 ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( ( int ) g = = id ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > tree . ngbls_base + + ;
hawk - > tree . ngbls + + ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls_base = = HAWK_MAX_GBL_ID - HAWK_MIN_GBL_ID + 1 ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
static void adjust_static_globals ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
int id ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls_base > = HAWK_MAX_GBL_ID - HAWK_MAX_GBL_ID + 1 ) ;
2019-12-13 04:29:58 +00:00
for ( id = HAWK_MIN_GBL_ID ; id < = HAWK_MAX_GBL_ID ; id + + )
{
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & gtab [ id ] . trait ) ! = gtab [ id ] . trait )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
HAWK_ARR_DLEN ( hawk - > parse . gbls , id ) = 0 ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
HAWK_ARR_DLEN ( hawk - > parse . gbls , id ) = gtab [ id ] . namelen ;
2019-12-13 04:29:58 +00:00
}
}
}
2020-04-16 03:42:30 +00:00
static hawk_oow_t get_global ( hawk_t * hawk , const hawk_oocs_t * name )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t i ;
2020-04-16 03:42:30 +00:00
hawk_arr_t * gbls = hawk - > parse . gbls ;
2019-12-13 04:29:58 +00:00
for ( i = HAWK_ARR_SIZE ( gbls ) ; i > 0 ; )
{
i - - ;
if ( hawk_comp_oochars ( HAWK_ARR_DPTR ( gbls , i ) , HAWK_ARR_DLEN ( gbls , i ) , name - > ptr , name - > len , 0 ) = = 0 ) return i ;
}
return HAWK_ARR_NIL ;
}
2020-04-16 03:42:30 +00:00
static hawk_oow_t find_global ( hawk_t * hawk , const hawk_oocs_t * name )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t i ;
2020-04-16 03:42:30 +00:00
hawk_arr_t * gbls = hawk - > parse . gbls ;
2019-12-13 04:29:58 +00:00
for ( i = 0 ; i < HAWK_ARR_SIZE ( gbls ) ; i + + )
{
if ( hawk_comp_oochars ( HAWK_ARR_DPTR ( gbls , i ) , HAWK_ARR_DLEN ( gbls , i ) , name - > ptr , name - > len , 0 ) = = 0 ) return i ;
}
return HAWK_ARR_NIL ;
}
2020-04-16 03:42:30 +00:00
static int add_global ( hawk_t * hawk , const hawk_oocs_t * name , hawk_loc_t * xloc , int disabled )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t ngbls ;
/* check if it is a keyword */
2020-04-16 03:42:30 +00:00
if ( classify_ident ( hawk , name ) ! = TOK_IDENT )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EKWRED , HAWK_T ( " keyword '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
/* check if it conflicts with a builtin function name */
2020-04-16 03:42:30 +00:00
if ( hawk_findfncwithoocs ( hawk , name ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFNCRED , HAWK_T ( " intrinsic function '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
/* check if it conflicts with a function name */
2024-04-28 19:15:17 +09:00
if ( hawk_htb_search ( hawk - > tree . funs , name - > ptr , name - > len ) ! = HAWK_NULL | |
2020-01-03 10:22:23 +00:00
/* check if it conflicts with a function name caught in the function call table */
2024-04-28 19:15:17 +09:00
hawk_htb_search ( hawk - > parse . funs , name - > ptr , name - > len ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFUNRED , HAWK_T ( " function '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
/* check if it conflicts with other global variable names */
2020-04-16 03:42:30 +00:00
if ( find_global ( hawk , name ) ! = HAWK_ARR_NIL )
2024-04-28 19:15:17 +09:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EDUPGBL , HAWK_T ( " duplicate global variable name '%.*js' " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
#if 0
2024-04-28 19:15:17 +09:00
/* TODO: need to check if it conflicts with a named variable to
2019-12-13 04:29:58 +00:00
* disallow such a program shown below ( IMPLICIT & EXPLICIT on )
* BEGIN { X = 20 ; x ( ) ; x ( ) ; x ( ) ; print X }
2020-01-03 10:22:23 +00:00
* @ global X ;
2019-12-13 04:29:58 +00:00
* function x ( ) { print X + + ; }
*/
2020-04-16 03:42:30 +00:00
if ( hawk_htb_search ( hawk - > parse . named , name , len ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EVARRED , HAWK_T ( " variable '%.*js' redefined " ) , len , name ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# endif
2020-04-16 03:42:30 +00:00
ngbls = HAWK_ARR_SIZE ( hawk - > parse . gbls ) ;
2019-12-13 04:29:58 +00:00
if ( ngbls > = HAWK_MAX_GBLS )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EGBLTM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
if ( hawk_arr_insert ( hawk - > parse . gbls , HAWK_ARR_SIZE ( hawk - > parse . gbls ) , ( hawk_ooch_t * ) name - > ptr , name - > len ) = = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( ngbls = = HAWK_ARR_SIZE ( hawk - > parse . gbls ) - 1 ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
/* the disabled item is inserted normally but
2019-12-13 04:29:58 +00:00
* the name length is reset to zero . */
2020-04-16 03:42:30 +00:00
if ( disabled ) HAWK_ARR_DLEN ( hawk - > parse . gbls , ngbls ) = 0 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > tree . ngbls = HAWK_ARR_SIZE ( hawk - > parse . gbls ) ;
HAWK_ASSERT ( ngbls = = hawk - > tree . ngbls - 1 ) ;
2019-12-13 04:29:58 +00:00
/* return the id which is the index to the gbl table. */
return ( int ) ngbls ;
}
2020-04-16 03:42:30 +00:00
int hawk_addgblwithbcstr ( hawk_t * hawk , const hawk_bch_t * name )
2019-12-13 04:29:58 +00:00
{
int n ;
hawk_bcs_t ncs ;
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . ngbls > hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
/* this function is not allowed after hawk_parse is called */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EPERM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
ncs . ptr = ( hawk_bch_t * ) name ;
ncs . len = hawk_count_bcstr ( name ) ; ;
if ( ncs . len < = 0 )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EINVAL ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
2020-04-16 03:42:30 +00:00
n = add_global ( hawk , & ncs , HAWK_NULL , 0 ) ;
2019-12-13 04:29:58 +00:00
# else
{
hawk_ucs_t wcs ;
2020-04-16 03:42:30 +00:00
wcs . ptr = hawk_dupbtoucstr ( hawk , ncs . ptr , & wcs . len , 0 ) ;
2019-12-13 04:29:58 +00:00
if ( ! wcs . ptr ) return - 1 ;
2020-04-16 03:42:30 +00:00
n = add_global ( hawk , & wcs , HAWK_NULL , 0 ) ;
hawk_freemem ( hawk , wcs . ptr ) ;
2019-12-13 04:29:58 +00:00
}
# endif
2024-04-28 19:15:17 +09:00
/* update the count of the static globals.
2019-12-13 04:29:58 +00:00
* the total global count has been updated inside add_global . */
2024-04-28 19:15:17 +09:00
if ( n > = 0 ) hawk - > tree . ngbls_base + + ;
2019-12-13 04:29:58 +00:00
return n ;
}
2020-04-16 03:42:30 +00:00
int hawk_addgblwithucstr ( hawk_t * hawk , const hawk_uch_t * name )
2019-12-13 04:29:58 +00:00
{
int n ;
hawk_ucs_t ncs ;
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . ngbls > hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
/* this function is not allowed after hawk_parse is called */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EPERM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
ncs . ptr = ( hawk_uch_t * ) name ;
ncs . len = hawk_count_ucstr ( name ) ; ;
if ( ncs . len < = 0 )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EINVAL ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
{
hawk_bcs_t mbs ;
2020-04-16 03:42:30 +00:00
mbs . ptr = hawk_duputobcstr ( hawk , ncs . ptr , & mbs . len ) ;
2019-12-13 04:29:58 +00:00
if ( ! mbs . ptr ) return - 1 ;
2020-04-16 03:42:30 +00:00
n = add_global ( hawk , & mbs , HAWK_NULL , 0 ) ;
hawk_freemem ( hawk , mbs . ptr ) ;
2019-12-13 04:29:58 +00:00
}
# else
2020-04-16 03:42:30 +00:00
n = add_global ( hawk , & ncs , HAWK_NULL , 0 ) ;
2019-12-13 04:29:58 +00:00
# endif
2024-04-28 19:15:17 +09:00
/* update the count of the static globals.
2019-12-13 04:29:58 +00:00
* the total global count has been updated inside add_global . */
2024-04-28 19:15:17 +09:00
if ( n > = 0 ) hawk - > tree . ngbls_base + + ;
2019-12-13 04:29:58 +00:00
return n ;
}
# define HAWK_NUM_STATIC_GBLS \
( HAWK_MAX_GBL_ID - HAWK_MIN_GBL_ID + 1 )
2019-12-16 15:09:58 +00:00
int hawk_delgblwithbcstr ( hawk_t * hawk , const hawk_bch_t * name )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t n ;
hawk_bcs_t ncs ;
hawk_ucs_t wcs ;
ncs . ptr = ( hawk_bch_t * ) name ;
ncs . len = hawk_count_bcstr ( name ) ;
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . ngbls > hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
/* this function is not allow after hawk_parse is called */
2020-01-01 04:46:49 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EPERM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
2019-12-16 15:09:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , HAWK_NUM_STATIC_GBLS , ncs . ptr , ncs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_HS , ncs . len , ncs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# else
2019-12-16 15:09:58 +00:00
wcs . ptr = hawk_dupbtoucstr ( hawk , ncs . ptr , & wcs . len , 0 ) ;
2019-12-13 04:29:58 +00:00
if ( ! wcs . ptr ) return - 1 ;
2019-12-16 15:09:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , HAWK_NUM_STATIC_GBLS , wcs . ptr , wcs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_LS , wcs . len , wcs . ptr ) ;
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , wcs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , wcs . ptr ) ;
2019-12-13 04:29:58 +00:00
# endif
/* invalidate the name if deletion is requested.
* this approach does not delete the entry .
* if hawk_delgbl ( ) is called with the same name
2024-04-28 19:15:17 +09:00
* again , the entry will be appended again .
2019-12-13 04:29:58 +00:00
* never call this funciton unless it is really required . */
/*
2019-12-16 15:09:58 +00:00
hawk - > parse . gbls . buf [ n ] . name . ptr [ 0 ] = HAWK_T ( ' \0 ' ) ;
hawk - > parse . gbls . buf [ n ] . name . len = 0 ;
2019-12-13 04:29:58 +00:00
*/
2019-12-16 15:09:58 +00:00
n = hawk_arr_uplete ( hawk - > parse . gbls , n , 1 ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( n = = 1 ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2019-12-16 15:09:58 +00:00
int hawk_delgblwithucstr ( hawk_t * hawk , const hawk_uch_t * name )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t n ;
hawk_ucs_t ncs ;
hawk_bcs_t mbs ;
ncs . ptr = ( hawk_uch_t * ) name ;
ncs . len = hawk_count_ucstr ( name ) ;
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . ngbls > hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
/* this function is not allow after hawk_parse is called */
2020-01-01 04:46:49 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EPERM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
2019-12-16 15:09:58 +00:00
mbs . ptr = hawk_duputobcstr ( hawk , ncs . ptr , & mbs . len ) ;
2019-12-13 04:29:58 +00:00
if ( ! mbs . ptr ) return - 1 ;
2019-12-16 15:09:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , HAWK_NUM_STATIC_GBLS , mbs . ptr , mbs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_HS , mbs . len , mbs . ptr ) ;
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , mbs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , mbs . ptr ) ;
2019-12-13 04:29:58 +00:00
# else
2019-12-16 15:09:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , HAWK_NUM_STATIC_GBLS , ncs . ptr , ncs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_LS , ncs . len , ncs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# endif
/* invalidate the name if deletion is requested.
* this approach does not delete the entry .
* if hawk_delgbl ( ) is called with the same name
2024-04-28 19:15:17 +09:00
* again , the entry will be appended again .
2019-12-13 04:29:58 +00:00
* never call this funciton unless it is really required . */
/*
2019-12-16 15:09:58 +00:00
hawk - > parse . gbls . buf [ n ] . name . ptr [ 0 ] = HAWK_T ( ' \0 ' ) ;
hawk - > parse . gbls . buf [ n ] . name . len = 0 ;
2019-12-13 04:29:58 +00:00
*/
2019-12-16 15:09:58 +00:00
n = hawk_arr_uplete ( hawk - > parse . gbls , n , 1 ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( n = = 1 ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-03-05 06:33:58 +00:00
int hawk_findgblwithbcstr ( hawk_t * hawk , const hawk_bch_t * name , int inc_builtins )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t n ;
hawk_bcs_t ncs ;
hawk_ucs_t wcs ;
ncs . ptr = ( hawk_bch_t * ) name ;
ncs . len = hawk_count_bcstr ( name ) ;
# if defined(HAWK_OOCH_IS_BCH)
2020-03-05 06:33:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , ( inc_builtins ? 0 : HAWK_NUM_STATIC_GBLS ) , ncs . ptr , ncs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_HS , ncs . len , ncs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# else
2019-12-16 15:09:58 +00:00
wcs . ptr = hawk_dupbtoucstr ( hawk , ncs . ptr , & wcs . len , 0 ) ;
2019-12-13 04:29:58 +00:00
if ( ! wcs . ptr ) return - 1 ;
2020-03-05 06:33:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , ( inc_builtins ? 0 : HAWK_NUM_STATIC_GBLS ) , wcs . ptr , wcs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_LS , wcs . len , wcs . ptr ) ;
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , wcs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , wcs . ptr ) ;
2019-12-13 04:29:58 +00:00
# endif
return ( int ) n ;
}
2020-03-05 06:33:58 +00:00
int hawk_findgblwithucstr ( hawk_t * hawk , const hawk_uch_t * name , int inc_builtins )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t n ;
hawk_ucs_t ncs ;
hawk_bcs_t mbs ;
ncs . ptr = ( hawk_uch_t * ) name ;
ncs . len = hawk_count_ucstr ( name ) ;
# if defined(HAWK_OOCH_IS_BCH)
2019-12-16 15:09:58 +00:00
mbs . ptr = hawk_duputobcstr ( hawk , ncs . ptr , & mbs . len ) ;
2019-12-13 04:29:58 +00:00
if ( ! mbs . ptr ) return - 1 ;
2020-03-05 06:33:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , ( inc_builtins ? 0 : HAWK_NUM_STATIC_GBLS ) , mbs . ptr , mbs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_HS , mbs . len , mbs . ptr ) ;
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , mbs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2019-12-16 15:09:58 +00:00
hawk_freemem ( hawk , mbs . ptr ) ;
2019-12-13 04:29:58 +00:00
# else
2020-03-05 06:33:58 +00:00
n = hawk_arr_search ( hawk - > parse . gbls , ( inc_builtins ? 0 : HAWK_NUM_STATIC_GBLS ) , ncs . ptr , ncs . len ) ;
2019-12-13 04:29:58 +00:00
if ( n = = HAWK_ARR_NIL )
{
2020-01-04 04:47:41 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , FMT_ENOENT_GBL_LS , ncs . len , ncs . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# endif
return ( int ) n ;
}
2020-04-16 03:42:30 +00:00
static hawk_t * collect_globals ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* special check if the first name is on the
2019-12-13 04:29:58 +00:00
* same line when HAWK_NEWLINE is on */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EVARMS ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EBADVAR , FMT_EBADVAR , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( add_global ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) , & hawk - > tok . loc , 0 ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH_TERMINATOR_NORMAL ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* skip a terminator (;, <NL>) */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
break ;
}
/*
* unlike collect_locals ( ) , the right brace cannot
* terminate a global declaration as it can never be
2024-04-28 19:15:17 +09:00
* placed within a block .
2020-04-16 03:42:30 +00:00
* so do not perform MATCH_TERMINATOR_RBRACE ( hawk ) )
2019-12-13 04:29:58 +00:00
*/
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ECOMMA , FMT_ECOMMA , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2024-04-28 19:15:17 +09:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
return hawk ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_t * collect_locals ( hawk_t * hawk , hawk_oow_t nlcls , int istop )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* special check if the first name is on the
2019-12-13 04:29:58 +00:00
* same line when HAWK_NEWLINE is on */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EVARMS ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
hawk_oocs_t lcl ;
hawk_oow_t n ;
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EBADVAR , FMT_EBADVAR , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
lcl = * HAWK_OOECS_OOCS ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
/* check if it conflicts with a builtin function name
2019-12-13 04:29:58 +00:00
* function f ( ) { local length ; } */
2020-04-16 03:42:30 +00:00
if ( hawk_findfncwithoocs ( hawk , & lcl ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EFNCRED , HAWK_T ( " intrinsic function '%.*js' redefined " ) , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
if ( istop )
{
/* check if it conflicts with a parameter name.
* the first level declaration is treated as the same
* scope as the parameter list */
2020-04-16 03:42:30 +00:00
n = hawk_arr_search ( hawk - > parse . params , 0 , lcl . ptr , lcl . len ) ;
2019-12-13 04:29:58 +00:00
if ( n ! = HAWK_ARR_NIL )
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EPARRED , HAWK_T ( " parameter '%.*js' redefined " ) , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_STRICTNAMING )
2019-12-13 04:29:58 +00:00
{
/* check if it conflicts with the owning function */
2020-04-16 03:42:30 +00:00
if ( hawk - > tree . cur_fun . ptr ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk_comp_oochars ( lcl . ptr , lcl . len , hawk - > tree . cur_fun . ptr , hawk - > tree . cur_fun . len , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EFUNRED , HAWK_T ( " function '%.*js' redefined " ) , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
}
/* check if it conflicts with other local variable names */
2020-04-16 03:42:30 +00:00
n = hawk_arr_search ( hawk - > parse . lcls , nlcls , lcl . ptr , lcl . len ) ;
2019-12-13 04:29:58 +00:00
if ( n ! = HAWK_ARR_NIL )
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EDUPLCL , FMT_EDUPLCL , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
/* check if it conflicts with global variable names */
2020-04-16 03:42:30 +00:00
n = find_global ( hawk , & lcl ) ;
2019-12-13 04:29:58 +00:00
if ( n ! = HAWK_ARR_NIL )
{
2020-04-16 03:42:30 +00:00
if ( n < hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
2020-01-03 10:22:23 +00:00
/* it is a conflict only if it is one of a static global variable */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EDUPLCL , FMT_EDUPLCL , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2020-04-16 03:42:30 +00:00
if ( HAWK_ARR_SIZE ( hawk - > parse . lcls ) > = HAWK_MAX_LCLS )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELCLTM , HAWK_T ( " too many local variables defined - %.*js " ) , lcl . len , lcl . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( hawk_arr_insert ( hawk - > parse . lcls , HAWK_ARR_SIZE ( hawk - > parse . lcls ) , lcl . ptr , lcl . len ) = = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , & hawk - > tok . loc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH_TERMINATOR_NORMAL ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* skip the terminator (;, <NL>) */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
break ;
}
2020-04-16 03:42:30 +00:00
if ( MATCH_TERMINATOR_RBRACE ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* should not skip } */
break ;
}
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ECOMMA , FMT_ECOMMA , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
return hawk ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_if ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * test = HAWK_NULL ;
hawk_nde_t * then_part = HAWK_NULL ;
hawk_nde_t * else_part = HAWK_NULL ;
hawk_nde_if_t * nde ;
hawk_loc_t eloc , tloc ;
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
test = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( test = = HAWK_NULL ) goto oops ;
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/* TODO: optimization. if you know 'test' evaluates to true or false,
* you can drop the ' if ' statement and take either the ' then_part '
* or ' else_part ' . */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
tloc = hawk - > tok . loc ;
then_part = parse_statement ( hawk , & tloc ) ;
2019-12-13 04:29:58 +00:00
if ( then_part = = HAWK_NULL ) goto oops ;
/* skip any new lines before the else block */
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_ELSE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
else_part = parse_statement ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( else_part = = HAWK_NULL ) goto oops ;
}
}
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_if_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = HAWK_NDE_IF ;
nde - > loc = * xloc ;
nde - > test = test ;
nde - > then_part = then_part ;
nde - > else_part = else_part ;
return ( hawk_nde_t * ) nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( else_part ) hawk_clrpt ( hawk , else_part ) ;
if ( then_part ) hawk_clrpt ( hawk , then_part ) ;
if ( test ) hawk_clrpt ( hawk , test ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_while ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * test = HAWK_NULL ;
hawk_nde_t * body = HAWK_NULL ;
hawk_nde_while_t * nde ;
hawk_loc_t ploc ;
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
test = parse_expr_withdc ( hawk , & ploc ) ;
if ( HAWK_UNLIKELY ( ! test ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
body = parse_statement ( hawk , & ploc ) ;
if ( HAWK_UNLIKELY ( ! body ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-11-13 14:56:15 +00:00
nde = ( hawk_nde_while_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = HAWK_NDE_WHILE ;
nde - > loc = * xloc ;
nde - > test = test ;
nde - > body = body ;
return ( hawk_nde_t * ) nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( body ) hawk_clrpt ( hawk , body ) ;
if ( test ) hawk_clrpt ( hawk , test ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_for ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * init = HAWK_NULL , * test = HAWK_NULL ;
hawk_nde_t * incr = HAWK_NULL , * body = HAWK_NULL ;
2024-04-28 19:15:17 +09:00
hawk_nde_for_t * nde_for ;
2020-03-22 18:01:05 +00:00
hawk_nde_forin_t * nde_forin ;
2019-12-13 04:29:58 +00:00
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-13 14:56:15 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_SEMICOLON ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* this line is very ugly. it checks the entire next
2019-12-13 04:29:58 +00:00
* expression or the first element in the expression
* is wrapped by a parenthesis */
2020-04-16 03:42:30 +00:00
int no_forin = MATCH ( hawk , TOK_LPAREN ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
init = parse_expr_withdc ( hawk , & ploc ) ;
2020-04-07 16:16:48 +00:00
if ( HAWK_UNLIKELY ( ! init ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-03-22 18:01:05 +00:00
if ( ! no_forin & & init - > type = = HAWK_NDE_EXP_BIN & &
2019-12-13 04:29:58 +00:00
( ( hawk_nde_exp_t * ) init ) - > opcode = = HAWK_BINOP_IN & &
2020-04-07 16:16:48 +00:00
# if defined(HAWK_ENABLE_GC)
is_var ( ( ( hawk_nde_exp_t * ) init ) - > left ) )
# else
2019-12-13 04:29:58 +00:00
is_plain_var ( ( ( hawk_nde_exp_t * ) init ) - > left ) )
2020-04-07 16:16:48 +00:00
# endif
{
2020-03-22 18:01:05 +00:00
/* switch to forin - for (x in y) */
2020-04-07 16:16:48 +00:00
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
body = parse_statement ( hawk , & ploc ) ;
2020-04-07 16:16:48 +00:00
if ( HAWK_UNLIKELY ( ! body ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
nde_forin = ( hawk_nde_forin_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde_forin ) ) ;
2020-04-07 16:16:48 +00:00
if ( HAWK_UNLIKELY ( ! nde_forin ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-03-22 18:01:05 +00:00
nde_forin - > type = HAWK_NDE_FORIN ;
nde_forin - > loc = * xloc ;
nde_forin - > test = init ;
nde_forin - > body = body ;
2019-12-13 04:29:58 +00:00
2020-03-22 18:01:05 +00:00
return ( hawk_nde_t * ) nde_forin ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_SEMICOLON ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ESCOLON , FMT_ESCOLON , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* skip new lines after the first semicolon */
2024-04-28 19:15:17 +09:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_SEMICOLON ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
test = parse_expr_withdc ( hawk , & ploc ) ;
if ( HAWK_UNLIKELY ( ! test ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_SEMICOLON ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ESCOLON , FMT_ESCOLON , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* skip new lines after the second semicolon */
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
incr = parse_expr_withdc ( hawk , & eloc ) ;
if ( HAWK_UNLIKELY ( ! incr ) ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
body = parse_statement ( hawk , & ploc ) ;
2019-12-13 04:29:58 +00:00
if ( body = = HAWK_NULL ) goto oops ;
2020-11-13 14:56:15 +00:00
nde_for = ( hawk_nde_for_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde_for ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde_for ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde_for - > type = HAWK_NDE_FOR ;
nde_for - > loc = * xloc ;
nde_for - > init = init ;
nde_for - > test = test ;
nde_for - > incr = incr ;
nde_for - > body = body ;
return ( hawk_nde_t * ) nde_for ;
oops :
2020-04-16 03:42:30 +00:00
if ( init ) hawk_clrpt ( hawk , init ) ;
if ( test ) hawk_clrpt ( hawk , test ) ;
if ( incr ) hawk_clrpt ( hawk , incr ) ;
if ( body ) hawk_clrpt ( hawk , body ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_dowhile ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
hawk_nde_t * test = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * body = HAWK_NULL ;
hawk_nde_while_t * nde ;
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_DO ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
body = parse_statement ( hawk , & ploc ) ;
if ( HAWK_UNLIKELY ( ! body ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_WHILE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWWHL , FMT_EKWWHL , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
test = parse_expr_withdc ( hawk , & ploc ) ;
2020-11-13 14:56:15 +00:00
if ( HAWK_UNLIKELY ( ! test ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2020-11-13 14:56:15 +00:00
nde = ( hawk_nde_while_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = HAWK_NDE_DOWHILE ;
nde - > loc = * xloc ;
nde - > test = test ;
nde - > body = body ;
return ( hawk_nde_t * ) nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( body ) hawk_clrpt ( hawk , body ) ;
if ( test ) hawk_clrpt ( hawk , test ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde = = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_break ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_break_t * nde ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_BREAK ) ;
2024-04-28 19:15:17 +09:00
if ( hawk - > parse . depth . loop < = 0 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EBREAK ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-11-13 14:56:15 +00:00
nde = ( hawk_nde_break_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_BREAK ;
nde - > loc = * xloc ;
2020-11-13 14:56:15 +00:00
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_continue ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_continue_t * nde ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_CONTINUE ) ;
2024-04-28 19:15:17 +09:00
if ( hawk - > parse . depth . loop < = 0 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ECONTINUE ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-11-13 14:56:15 +00:00
nde = ( hawk_nde_continue_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_CONTINUE ;
nde - > loc = * xloc ;
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_return ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_return_t * nde ;
hawk_nde_t * val ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_RETURN ) ;
2019-12-13 04:29:58 +00:00
2020-11-13 14:56:15 +00:00
nde = ( hawk_nde_return_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_RETURN ;
nde - > loc = * xloc ;
2020-04-16 03:42:30 +00:00
if ( MATCH_TERMINATOR ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* no return value */
val = HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-11-13 14:56:15 +00:00
val = parse_expr_withdc ( hawk , & eloc ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! val ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
nde - > val = val ;
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_exit ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_exit_t * nde ;
hawk_nde_t * val ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_EXIT | | hawk - > ptok . type = = TOK_XABORT ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_exit_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2019-12-13 04:29:58 +00:00
if ( nde = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_EXIT ;
nde - > loc = * xloc ;
2020-04-16 03:42:30 +00:00
nde - > abort = ( hawk - > ptok . type = = TOK_XABORT ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH_TERMINATOR ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* no exit code */
val = HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
val = parse_expr_withdc ( hawk , & eloc ) ;
2024-04-28 19:15:17 +09:00
if ( val = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
nde - > val = val ;
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_next ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_next_t * nde ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_NEXT ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > parse . id . block = = PARSE_BEGIN_BLOCK )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ENEXTBEG ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( hawk - > parse . id . block = = PARSE_END_BLOCK )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ENEXTEND ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-11-09 16:32:34 +00:00
nde = ( hawk_nde_next_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_NEXT ;
nde - > loc = * xloc ;
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
}
2020-11-09 16:32:34 +00:00
static hawk_nde_t * parse_nextfile ( hawk_t * hawk , const hawk_loc_t * xloc , int out )
2019-12-13 04:29:58 +00:00
{
hawk_nde_nextfile_t * nde ;
2020-04-16 03:42:30 +00:00
if ( ! out & & hawk - > parse . id . block = = PARSE_BEGIN_BLOCK )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ENEXTFBEG ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( ! out & & hawk - > parse . id . block = = PARSE_END_BLOCK )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ENEXTFEND ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-11-09 16:32:34 +00:00
nde = ( hawk_nde_nextfile_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_NEXTFILE ;
nde - > loc = * xloc ;
nde - > out = out ;
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_delete ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_delete_t * nde ;
hawk_nde_t * var = HAWK_NULL ;
hawk_loc_t dloc ;
hawk_nde_type_t type ;
int inparen = 0 ;
2020-11-10 02:56:29 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_DELETE | | hawk - > ptok . type = = TOK_XRESET ) ;
2019-12-13 04:29:58 +00:00
2020-11-10 02:56:29 +00:00
type = ( hawk - > ptok . type = = TOK_DELETE ) ? HAWK_NDE_DELETE : HAWK_NDE_RESET ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
inparen = 1 ;
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EIDENT , FMT_EIDENT , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
dloc = hawk - > tok . loc ;
2020-11-09 16:32:34 +00:00
var = parse_primary_ident ( hawk , & dloc ) ;
if ( HAWK_UNLIKELY ( ! var ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-07 16:16:48 +00:00
if ( ( type = = HAWK_NDE_DELETE & & ! is_var ( var ) ) | |
( type = = HAWK_NDE_RESET & & ! is_plain_var ( var ) ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & dloc , HAWK_EBADARG ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2024-04-28 19:15:17 +09:00
if ( inparen )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-11-09 16:32:34 +00:00
nde = ( hawk_nde_delete_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = type ;
nde - > loc = * xloc ;
nde - > var = var ;
return ( hawk_nde_t * ) nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( var ) hawk_clrpt ( hawk , var ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_print ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_print_t * nde ;
2024-04-28 19:15:17 +09:00
hawk_nde_t * args = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * out = HAWK_NULL ;
2020-12-28 07:10:17 +00:00
hawk_out_type_t out_type ;
2019-12-13 04:29:58 +00:00
hawk_nde_type_t type ;
hawk_loc_t eloc ;
2020-11-09 16:32:34 +00:00
HAWK_ASSERT ( hawk - > ptok . type = = TOK_PRINT | | hawk - > ptok . type = = TOK_PRINTF ) ;
2019-12-13 04:29:58 +00:00
2020-11-09 16:32:34 +00:00
type = ( hawk - > ptok . type = = TOK_PRINT ) ? HAWK_NDE_PRINT : HAWK_NDE_PRINTF ;
2019-12-13 04:29:58 +00:00
2020-11-09 16:32:34 +00:00
if ( ! MATCH_TERMINATOR ( hawk ) & & ! MATCH ( hawk , TOK_GT ) & &
2024-04-28 19:15:17 +09:00
! MATCH ( hawk , TOK_RS ) & & ! MATCH ( hawk , TOK_BOR ) & & ! MATCH ( hawk , TOK_LOR ) )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * args_tail ;
hawk_nde_t * tail_prev ;
int in_parens = 0 , gm_in_parens = 0 ;
hawk_oow_t opening_lparen_seq ;
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* just remember the sequence number of the left
* parenthesis before calling parse_expr_withdc ( )
2019-12-13 04:29:58 +00:00
* that eventually calls parse_primary_lparen ( ) */
2020-04-16 03:42:30 +00:00
opening_lparen_seq = hawk - > parse . lparen_seq ;
2019-12-13 04:29:58 +00:00
in_parens = 1 ; /* maybe. not confirmed yet */
/* print and printf provide weird syntaxs.
2024-04-28 19:15:17 +09:00
*
2019-12-13 04:29:58 +00:00
* 1. print 10 , 20 ;
* 2. print ( 10 , 20 ) ;
* 3. print ( 10 , 20 , 30 ) in a ;
* 4. print ( ( 10 , 20 , 30 ) in a ) ;
*
* Due to case 3 , i can ' t consume LPAREN
2024-04-28 19:15:17 +09:00
* here and expect RPAREN later .
2019-12-13 04:29:58 +00:00
*/
}
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-12-01 10:22:17 +00:00
args = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( args = = HAWK_NULL ) goto oops ;
args_tail = args ;
tail_prev = HAWK_NULL ;
if ( args - > type ! = HAWK_NDE_GRP )
{
2024-04-28 19:15:17 +09:00
/* args->type == HAWK_NDE_GRP when print (a, b, c)
2019-12-13 04:29:58 +00:00
* args - > type ! = HAWK_NDE_GRP when print a , b , c */
hawk_oow_t group_opening_lparen_seq ;
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
/* if it's grouped, i must check if the last group member
* is enclosed in parentheses .
*
* i set the condition to false whenever i see
* a new group member . */
gm_in_parens = 0 ;
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
group_opening_lparen_seq = hawk - > parse . lparen_seq ;
2019-12-13 04:29:58 +00:00
gm_in_parens = 1 ; /* maybe */
}
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-12-01 10:22:17 +00:00
args_tail - > next = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( args_tail - > next = = HAWK_NULL ) goto oops ;
tail_prev = args_tail ;
args_tail = args_tail - > next ;
2020-04-16 03:42:30 +00:00
if ( gm_in_parens = = 1 & & hawk - > ptok . type = = TOK_RPAREN & &
2024-04-28 19:15:17 +09:00
hawk - > parse . lparen_last_closed = = group_opening_lparen_seq )
2019-12-13 04:29:58 +00:00
{
/* confirm that the last group seen so far
* is parenthesized */
gm_in_parens = 2 ;
}
}
}
2024-04-28 19:15:17 +09:00
/* print 1 > 2 would print 1 to the file named 2.
* print ( 1 > 2 ) would print ( 1 > 2 ) on the console
*
2019-12-13 04:29:58 +00:00
* think of all these . . . there are many more possible combinations .
*
2024-04-28 19:15:17 +09:00
* print ( ( 10 , 20 , 30 ) in a ) > " x " ;
2019-12-13 04:29:58 +00:00
* print ( ( 10 , 20 , 30 ) in a )
2024-04-28 19:15:17 +09:00
* print ( ( 10 , 20 , 30 ) in a ) > ( " x " ) ;
* print ( ( 10 , 20 , 30 ) in a ) > ( ( " x " ) ) ;
2019-12-13 04:29:58 +00:00
* function abc ( ) { return " abc " ; } BEGIN { print ( 1 > abc ( ) ) ; }
* function abc ( ) { return " abc " ; } BEGIN { print 1 > abc ( ) ; }
* print 1 , 2 , 3 > 4 ;
* print ( 1 , 2 , 3 ) > 4 ;
* print ( ( 1 , 2 , 3 ) > 4 ) ;
* print 1 , 2 , 3 > 4 + 5 ;
* print 1 , 2 , ( 3 > 4 ) > 5 ;
* print 1 , 2 , ( 3 > 4 ) > 5 + 6 ;
*/
2020-12-01 10:22:17 +00:00
if ( in_parens = = 1 & & hawk - > ptok . type = = TOK_RPAREN & & ( hawk - > ptok . flags & TOK_FLAGS_LPAREN_CLOSER ) & &
2024-04-28 19:15:17 +09:00
hawk - > parse . lparen_last_closed = = opening_lparen_seq )
2019-12-13 04:29:58 +00:00
{
in_parens = 2 ; /* confirmed */
}
if ( in_parens ! = 2 & & gm_in_parens ! = 2 & & args_tail - > type = = HAWK_NDE_EXP_BIN )
{
2020-12-01 10:22:17 +00:00
/* check if the expression ends with an output redirector
* and take out the part after the redirector and make it
* the output target */
2019-12-13 04:29:58 +00:00
int i ;
hawk_nde_exp_t * ep = ( hawk_nde_exp_t * ) args_tail ;
2024-04-28 19:15:17 +09:00
static struct
2019-12-13 04:29:58 +00:00
{
int opc ;
int out ;
int opt ;
} tab [ ] =
{
2024-04-28 19:15:17 +09:00
{
HAWK_BINOP_GT ,
HAWK_OUT_FILE ,
2019-12-13 04:29:58 +00:00
0
} ,
2024-04-28 19:15:17 +09:00
{
HAWK_BINOP_RS ,
2019-12-13 04:29:58 +00:00
HAWK_OUT_APFILE ,
0
} ,
{
HAWK_BINOP_BOR ,
HAWK_OUT_PIPE ,
0
} ,
{
HAWK_BINOP_LOR ,
HAWK_OUT_RWPIPE ,
HAWK_RWPIPE
}
} ;
for ( i = 0 ; i < HAWK_COUNTOF ( tab ) ; i + + )
{
if ( ep - > opcode = = tab [ i ] . opc )
{
hawk_nde_t * tmp ;
2020-04-16 03:42:30 +00:00
if ( tab [ i ] . opt & & ! ( hawk - > opt . trait & tab [ i ] . opt ) ) break ;
2019-12-13 04:29:58 +00:00
tmp = args_tail ;
2020-12-01 10:22:17 +00:00
if ( tail_prev ) tail_prev - > next = ep - > left ;
2019-12-13 04:29:58 +00:00
else args = ep - > left ;
out = ep - > right ;
out_type = tab [ i ] . out ;
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , tmp ) ;
2019-12-13 04:29:58 +00:00
break ;
}
}
}
}
if ( ! out )
{
2020-04-16 03:42:30 +00:00
out_type = MATCH ( hawk , TOK_GT ) ? HAWK_OUT_FILE :
MATCH ( hawk , TOK_RS ) ? HAWK_OUT_APFILE :
MATCH ( hawk , TOK_BOR ) ? HAWK_OUT_PIPE :
( ( hawk - > opt . trait & HAWK_RWPIPE ) & &
MATCH ( hawk , TOK_LOR ) ) ? HAWK_OUT_RWPIPE :
2020-11-09 16:32:34 +00:00
HAWK_OUT_CONSOLE ;
2019-12-13 04:29:58 +00:00
if ( out_type ! = HAWK_OUT_CONSOLE )
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-12-01 10:22:17 +00:00
out = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( out = = HAWK_NULL ) goto oops ;
}
}
if ( type = = HAWK_NDE_PRINTF & & ! args )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ENOARG ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-12-01 10:22:17 +00:00
nde = ( hawk_nde_print_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = type ;
nde - > loc = * xloc ;
nde - > args = args ;
nde - > out_type = out_type ;
nde - > out = out ;
return ( hawk_nde_t * ) nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( args ) hawk_clrpt ( hawk , args ) ;
if ( out ) hawk_clrpt ( hawk , out ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
static hawk_nde_t * parse_statement_nb (
2020-04-16 03:42:30 +00:00
hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
/* parse a non-block statement */
hawk_nde_t * nde ;
/* keywords that don't require any terminating semicolon */
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_IF ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
return parse_if ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_WHILE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . loop + + ;
nde = parse_while ( hawk , xloc ) ;
hawk - > parse . depth . loop - - ;
2019-12-13 04:29:58 +00:00
return nde ;
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_FOR ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . loop + + ;
nde = parse_for ( hawk , xloc ) ;
hawk - > parse . depth . loop - - ;
2019-12-13 04:29:58 +00:00
return nde ;
}
/* keywords that require a terminating semicolon */
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_DO ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . loop + + ;
nde = parse_dowhile ( hawk , xloc ) ;
hawk - > parse . depth . loop - - ;
2019-12-13 04:29:58 +00:00
return nde ;
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_BREAK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_break ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_CONTINUE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_continue ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_RETURN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_return ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_EXIT ) | | MATCH ( hawk , TOK_XABORT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_exit ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_NEXT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_next ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_NEXTFILE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_nextfile ( hawk , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( MATCH ( hawk , TOK_NEXTOFILE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_nextfile ( hawk , xloc , 1 ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_DELETE ) | | MATCH ( hawk , TOK_XRESET ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_delete ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( ! ( hawk - > opt . trait & HAWK_TOLERANT ) )
2019-12-13 04:29:58 +00:00
{
/* in the non-tolerant mode, we treat print and printf
* as a separate statement */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_PRINT ) | | MATCH ( hawk , TOK_PRINTF ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-09 16:32:34 +00:00
nde = parse_print ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2020-11-09 16:32:34 +00:00
else nde = parse_expr_withdc ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-11-09 16:32:34 +00:00
nde = parse_expr_withdc ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2020-11-09 16:32:34 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH_TERMINATOR_NORMAL ( hawk ) )
2019-12-13 04:29:58 +00:00
{
/* check if a statement ends with a semicolon or <NL> */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-11-09 16:32:34 +00:00
if ( nde ) hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2020-04-16 03:42:30 +00:00
else if ( MATCH_TERMINATOR_RBRACE ( hawk ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* do not skip the right brace as a statement terminator.
2019-12-13 04:29:58 +00:00
* is there anything to do here ? */
}
else
{
2020-11-09 16:32:34 +00:00
if ( nde ) hawk_clrpt ( hawk , nde ) ;
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > ptok . loc , HAWK_ESTMEND ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_statement ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
/* skip new lines before a statement */
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_SEMICOLON ) )
2019-12-13 04:29:58 +00:00
{
/* null statement */
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_NULL ;
nde - > loc = * xloc ;
nde - > next = HAWK_NULL ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_LBRACE ) )
2019-12-13 04:29:58 +00:00
{
/* a block statemnt { ... } */
hawk_loc_t tloc ;
2020-04-16 03:42:30 +00:00
tloc = hawk - > ptok . loc ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-11-10 02:56:29 +00:00
nde = parse_block_dc ( hawk , & tloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
/* the statement id held in hawk->parse.id.stmt denotes
2019-12-13 04:29:58 +00:00
* the token id of the statement currently being parsed .
2024-04-28 19:15:17 +09:00
* the current statement id is saved here because the
2019-12-13 04:29:58 +00:00
* statement id can be changed in parse_statement_nb .
* it will , in turn , call parse_statement which will
* eventually change the statement id . */
int old_id ;
hawk_loc_t tloc ;
2020-04-16 03:42:30 +00:00
old_id = hawk - > parse . id . stmt ;
tloc = hawk - > tok . loc ;
2019-12-13 04:29:58 +00:00
/* set the current statement id */
2020-04-16 03:42:30 +00:00
hawk - > parse . id . stmt = hawk - > tok . type ;
2019-12-13 04:29:58 +00:00
/* proceed parsing the statement */
2020-04-16 03:42:30 +00:00
nde = parse_statement_nb ( hawk , & tloc ) ;
2019-12-13 04:29:58 +00:00
/* restore the statement id saved previously */
2020-04-16 03:42:30 +00:00
hawk - > parse . id . stmt = old_id ;
2019-12-13 04:29:58 +00:00
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static int assign_to_opcode ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
/* synchronize it with hawk_assop_type_t in run.h */
static int assop [ ] =
{
HAWK_ASSOP_NONE ,
HAWK_ASSOP_PLUS ,
HAWK_ASSOP_MINUS ,
HAWK_ASSOP_MUL ,
HAWK_ASSOP_DIV ,
HAWK_ASSOP_IDIV ,
HAWK_ASSOP_MOD ,
HAWK_ASSOP_EXP ,
HAWK_ASSOP_CONCAT ,
HAWK_ASSOP_RS ,
HAWK_ASSOP_LS ,
HAWK_ASSOP_BAND ,
HAWK_ASSOP_BXOR ,
HAWK_ASSOP_BOR
} ;
2020-04-16 03:42:30 +00:00
if ( hawk - > tok . type > = TOK_ASSN & &
hawk - > tok . type < = TOK_BOR_ASSN )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
return assop [ hawk - > tok . type - TOK_ASSN ] ;
2019-12-13 04:29:58 +00:00
}
return - 1 ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_expr_basic ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde , * n1 , * n2 ;
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
nde = parse_logical_or ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
if ( nde = = HAWK_NULL ) return HAWK_NULL ;
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_QUEST ) )
if ( MATCH ( hawk , TOK_QUEST ) )
2024-04-28 19:15:17 +09:00
{
2019-12-13 04:29:58 +00:00
hawk_loc_t eloc ;
hawk_nde_cnd_t * cnd ;
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
n1 = parse_expr_withdc ( hawk , & eloc ) ;
2024-04-28 19:15:17 +09:00
if ( n1 = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_COLON ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
hawk_clrpt ( hawk , n1 ) ;
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ECOLON , FMT_ECOLON , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
hawk_clrpt ( hawk , n1 ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
n2 = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( n2 = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
hawk_clrpt ( hawk , n1 ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
cnd = ( hawk_nde_cnd_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * cnd ) ) ;
2019-12-13 04:29:58 +00:00
if ( cnd = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , nde ) ;
hawk_clrpt ( hawk , n1 ) ;
hawk_clrpt ( hawk , n2 ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
cnd - > type = HAWK_NDE_CND ;
cnd - > loc = * xloc ;
cnd - > next = HAWK_NULL ;
cnd - > test = nde ;
cnd - > left = n1 ;
cnd - > right = n2 ;
nde = ( hawk_nde_t * ) cnd ;
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_expr ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * x , * y ;
hawk_nde_ass_t * nde ;
int opcode ;
2020-04-16 03:42:30 +00:00
x = parse_expr_basic ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
if ( x = = HAWK_NULL ) return HAWK_NULL ;
2020-04-16 03:42:30 +00:00
opcode = assign_to_opcode ( hawk ) ;
2024-04-28 19:15:17 +09:00
if ( opcode < = - 1 )
2019-12-13 04:29:58 +00:00
{
/* no assignment operator found. */
return x ;
}
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( x - > next = = HAWK_NULL ) ;
2024-04-28 19:15:17 +09:00
if ( ! is_var ( x ) & & x - > type ! = HAWK_NDE_POS )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , x ) ;
hawk_seterrnum ( hawk , xloc , HAWK_EASSIGN ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , x ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
2020-12-01 10:22:17 +00:00
y = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( y = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , x ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_ass_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( nde = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , x ) ;
hawk_clrpt ( hawk , y ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_ASS ;
nde - > loc = * xloc ;
nde - > next = HAWK_NULL ;
nde - > opcode = opcode ;
nde - > left = x ;
nde - > right = y ;
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_expr_withdc ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
/* perform depth check before parsing expression */
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . expr_parse > 0 & &
hawk - > parse . depth . expr > = hawk - > opt . depth . s . expr_parse )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EEXPRNST ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . expr + + ;
nde = parse_expr ( hawk , xloc ) ;
hawk - > parse . depth . expr - - ;
2019-12-13 04:29:58 +00:00
return nde ;
}
# define INT_BINOP_INT(x,op,y) \
( ( ( hawk_nde_int_t * ) x ) - > val op ( ( hawk_nde_int_t * ) y ) - > val )
# define INT_BINOP_FLT(x,op,y) \
( ( ( hawk_nde_int_t * ) x ) - > val op ( ( hawk_nde_flt_t * ) y ) - > val )
# define FLT_BINOP_INT(x,op,y) \
( ( ( hawk_nde_flt_t * ) x ) - > val op ( ( hawk_nde_int_t * ) y ) - > val )
# define FLT_BINOP_FLT(x,op,y) \
( ( ( hawk_nde_flt_t * ) x ) - > val op ( ( hawk_nde_flt_t * ) y ) - > val )
union folded_t
{
hawk_int_t l ;
hawk_flt_t r ;
} ;
typedef union folded_t folded_t ;
static int fold_constants_for_binop (
2020-04-16 03:42:30 +00:00
hawk_t * hawk , hawk_nde_t * left , hawk_nde_t * right ,
2019-12-13 04:29:58 +00:00
int opcode , folded_t * folded )
{
int fold = - 1 ;
2024-04-28 19:15:17 +09:00
/* TODO: can i shorten various comparisons below?
2019-12-13 04:29:58 +00:00
* i hate to repeat similar code just for type difference */
2020-04-15 15:12:28 +00:00
if ( left - > type = = HAWK_NDE_INT & & right - > type = = HAWK_NDE_INT )
2019-12-13 04:29:58 +00:00
{
fold = HAWK_NDE_INT ;
switch ( opcode )
{
case HAWK_BINOP_PLUS :
folded - > l = INT_BINOP_INT ( left , + , right ) ;
break ;
case HAWK_BINOP_MINUS :
folded - > l = INT_BINOP_INT ( left , - , right ) ;
break ;
case HAWK_BINOP_MUL :
folded - > l = INT_BINOP_INT ( left , * , right ) ;
break ;
case HAWK_BINOP_DIV :
if ( ( ( hawk_nde_int_t * ) right ) - > val = = 0 )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EDIVBY0 ) ;
2019-12-13 04:29:58 +00:00
fold = - 2 ; /* error */
}
else if ( INT_BINOP_INT ( left , % , right ) )
{
2024-04-28 19:15:17 +09:00
folded - > r = ( hawk_flt_t ) ( ( hawk_nde_int_t * ) left ) - > val /
2019-12-13 04:29:58 +00:00
( hawk_flt_t ) ( ( hawk_nde_int_t * ) right ) - > val ;
fold = HAWK_NDE_FLT ;
}
else
{
folded - > l = INT_BINOP_INT ( left , / , right ) ;
}
break ;
case HAWK_BINOP_IDIV :
if ( ( ( hawk_nde_int_t * ) right ) - > val = = 0 )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_EDIVBY0 ) ;
2019-12-13 04:29:58 +00:00
fold = - 2 ; /* error */
}
else
{
folded - > l = INT_BINOP_INT ( left , / , right ) ;
}
break ;
case HAWK_BINOP_MOD :
folded - > l = INT_BINOP_INT ( left , % , right ) ;
break ;
default :
fold = - 1 ; /* no folding */
break ;
}
}
2020-04-15 15:12:28 +00:00
else if ( left - > type = = HAWK_NDE_FLT & & right - > type = = HAWK_NDE_FLT )
2019-12-13 04:29:58 +00:00
{
fold = HAWK_NDE_FLT ;
switch ( opcode )
{
case HAWK_BINOP_PLUS :
folded - > r = FLT_BINOP_FLT ( left , + , right ) ;
break ;
case HAWK_BINOP_MINUS :
folded - > r = FLT_BINOP_FLT ( left , - , right ) ;
break ;
case HAWK_BINOP_MUL :
folded - > r = FLT_BINOP_FLT ( left , * , right ) ;
break ;
case HAWK_BINOP_DIV :
folded - > r = FLT_BINOP_FLT ( left , / , right ) ;
break ;
case HAWK_BINOP_IDIV :
folded - > l = ( hawk_int_t ) FLT_BINOP_FLT ( left , / , right ) ;
fold = HAWK_NDE_INT ;
break ;
case HAWK_BINOP_MOD :
2020-04-16 03:42:30 +00:00
folded - > r = hawk - > prm . math . mod (
2024-04-28 19:15:17 +09:00
hawk ,
( ( hawk_nde_flt_t * ) left ) - > val ,
2019-12-13 04:29:58 +00:00
( ( hawk_nde_flt_t * ) right ) - > val
) ;
break ;
default :
fold = - 1 ;
break ;
}
}
2020-04-15 15:12:28 +00:00
else if ( left - > type = = HAWK_NDE_INT & & right - > type = = HAWK_NDE_FLT )
2019-12-13 04:29:58 +00:00
{
fold = HAWK_NDE_FLT ;
switch ( opcode )
{
case HAWK_BINOP_PLUS :
folded - > r = INT_BINOP_FLT ( left , + , right ) ;
break ;
case HAWK_BINOP_MINUS :
folded - > r = INT_BINOP_FLT ( left , - , right ) ;
break ;
case HAWK_BINOP_MUL :
folded - > r = INT_BINOP_FLT ( left , * , right ) ;
break ;
case HAWK_BINOP_DIV :
folded - > r = INT_BINOP_FLT ( left , / , right ) ;
break ;
case HAWK_BINOP_IDIV :
folded - > l = ( hawk_int_t )
2024-04-28 19:15:17 +09:00
( ( hawk_flt_t ) ( ( hawk_nde_int_t * ) left ) - > val /
2019-12-13 04:29:58 +00:00
( ( hawk_nde_flt_t * ) right ) - > val ) ;
fold = HAWK_NDE_INT ;
break ;
case HAWK_BINOP_MOD :
2020-04-16 03:42:30 +00:00
folded - > r = hawk - > prm . math . mod (
2024-04-28 19:15:17 +09:00
hawk ,
( hawk_flt_t ) ( ( hawk_nde_int_t * ) left ) - > val ,
2019-12-13 04:29:58 +00:00
( ( hawk_nde_flt_t * ) right ) - > val
) ;
break ;
default :
fold = - 1 ;
break ;
}
}
2020-04-15 15:12:28 +00:00
else if ( left - > type = = HAWK_NDE_FLT & & right - > type = = HAWK_NDE_INT )
2019-12-13 04:29:58 +00:00
{
fold = HAWK_NDE_FLT ;
switch ( opcode )
{
case HAWK_BINOP_PLUS :
folded - > r = FLT_BINOP_INT ( left , + , right ) ;
break ;
case HAWK_BINOP_MINUS :
folded - > r = FLT_BINOP_INT ( left , - , right ) ;
break ;
case HAWK_BINOP_MUL :
folded - > r = FLT_BINOP_INT ( left , * , right ) ;
break ;
case HAWK_BINOP_DIV :
folded - > r = FLT_BINOP_INT ( left , / , right ) ;
break ;
case HAWK_BINOP_IDIV :
folded - > l = ( hawk_int_t )
2024-04-28 19:15:17 +09:00
( ( ( hawk_nde_int_t * ) left ) - > val /
2019-12-13 04:29:58 +00:00
( hawk_flt_t ) ( ( hawk_nde_int_t * ) right ) - > val ) ;
fold = HAWK_NDE_INT ;
break ;
case HAWK_BINOP_MOD :
2020-04-16 03:42:30 +00:00
folded - > r = hawk - > prm . math . mod (
2024-04-28 19:15:17 +09:00
hawk ,
( ( hawk_nde_flt_t * ) left ) - > val ,
2019-12-13 04:29:58 +00:00
( hawk_flt_t ) ( ( hawk_nde_int_t * ) right ) - > val
) ;
break ;
default :
fold = - 1 ;
break ;
}
}
return fold ;
}
static hawk_nde_t * new_exp_bin_node (
2020-04-16 03:42:30 +00:00
hawk_t * hawk , const hawk_loc_t * loc ,
2019-12-13 04:29:58 +00:00
int opcode , hawk_nde_t * left , hawk_nde_t * right )
{
hawk_nde_exp_t * tmp ;
2020-04-16 03:42:30 +00:00
tmp = ( hawk_nde_exp_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * tmp ) ) ;
2019-12-13 04:29:58 +00:00
if ( tmp )
{
tmp - > type = HAWK_NDE_EXP_BIN ;
tmp - > loc = * loc ;
2024-04-28 19:15:17 +09:00
tmp - > opcode = opcode ;
2019-12-13 04:29:58 +00:00
tmp - > left = left ;
tmp - > right = right ;
}
2020-04-16 03:42:30 +00:00
else ADJERR_LOC ( hawk , loc ) ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) tmp ;
}
2020-04-15 15:12:28 +00:00
static hawk_nde_t * new_int_node ( hawk_t * hawk , hawk_int_t lv , const hawk_loc_t * loc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_int_t * tmp ;
2020-04-15 15:12:28 +00:00
tmp = ( hawk_nde_int_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * tmp ) ) ;
if ( HAWK_LIKELY ( tmp ) )
2019-12-13 04:29:58 +00:00
{
tmp - > type = HAWK_NDE_INT ;
tmp - > loc = * loc ;
tmp - > val = lv ;
}
2020-04-15 15:12:28 +00:00
else ADJERR_LOC ( hawk , loc ) ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) tmp ;
}
2020-04-15 15:12:28 +00:00
static hawk_nde_t * new_flt_node ( hawk_t * hawk , hawk_flt_t rv , const hawk_loc_t * loc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_flt_t * tmp ;
2020-04-15 15:12:28 +00:00
tmp = ( hawk_nde_flt_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * tmp ) ) ;
if ( HAWK_LIKELY ( tmp ) )
2019-12-13 04:29:58 +00:00
{
tmp - > type = HAWK_NDE_FLT ;
tmp - > loc = * loc ;
tmp - > val = rv ;
}
2020-04-15 15:12:28 +00:00
else ADJERR_LOC ( hawk , loc ) ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) tmp ;
}
2020-04-15 15:12:28 +00:00
static HAWK_INLINE void update_int_node ( hawk_t * hawk , hawk_nde_int_t * node , hawk_int_t lv )
2019-12-13 04:29:58 +00:00
{
node - > val = lv ;
if ( node - > str )
{
2020-04-15 15:12:28 +00:00
hawk_freemem ( hawk , node - > str ) ;
2019-12-13 04:29:58 +00:00
node - > str = HAWK_NULL ;
node - > len = 0 ;
}
}
2020-04-15 15:12:28 +00:00
static HAWK_INLINE void update_flt_node ( hawk_t * hawk , hawk_nde_flt_t * node , hawk_flt_t rv )
2019-12-13 04:29:58 +00:00
{
node - > val = rv ;
if ( node - > str )
{
2020-04-15 15:12:28 +00:00
hawk_freemem ( hawk , node - > str ) ;
2019-12-13 04:29:58 +00:00
node - > str = HAWK_NULL ;
node - > len = 0 ;
}
}
static hawk_nde_t * parse_binary (
2024-04-28 19:15:17 +09:00
hawk_t * hawk , const hawk_loc_t * xloc ,
2019-12-13 04:29:58 +00:00
int skipnl , const binmap_t * binmap ,
hawk_nde_t * ( * next_level_func ) ( hawk_t * , const hawk_loc_t * ) )
{
2024-04-28 19:15:17 +09:00
hawk_nde_t * left = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * right = HAWK_NULL ;
hawk_loc_t rloc ;
2020-04-16 03:42:30 +00:00
left = next_level_func ( hawk , xloc ) ;
2020-04-15 15:12:28 +00:00
if ( HAWK_UNLIKELY ( ! left ) ) goto oops ;
2019-12-13 04:29:58 +00:00
do
{
const binmap_t * p = binmap ;
int matched = 0 ;
int opcode , fold ;
folded_t folded ;
while ( p - > token ! = TOK_EOF )
{
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , p - > token ) )
2019-12-13 04:29:58 +00:00
{
opcode = p - > binop ;
matched = 1 ;
break ;
}
p + + ;
}
if ( ! matched ) break ;
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( skipnl & & MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
rloc = hawk - > tok . loc ;
right = next_level_func ( hawk , & rloc ) ;
2019-12-13 04:29:58 +00:00
if ( right = = HAWK_NULL ) goto oops ;
2020-04-16 03:42:30 +00:00
fold = fold_constants_for_binop ( hawk , left , right , opcode , & folded ) ;
2019-12-13 04:29:58 +00:00
switch ( fold )
{
case HAWK_NDE_INT :
if ( fold = = left - > type )
{
2024-04-28 19:15:17 +09:00
hawk_clrpt ( hawk , right ) ;
2019-12-13 04:29:58 +00:00
right = HAWK_NULL ;
2020-04-16 03:42:30 +00:00
update_int_node ( hawk , ( hawk_nde_int_t * ) left , folded . l ) ;
2019-12-13 04:29:58 +00:00
}
else if ( fold = = right - > type )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
update_int_node ( hawk , ( hawk_nde_int_t * ) right , folded . l ) ;
2019-12-13 04:29:58 +00:00
left = right ;
right = HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , right ) ; right = HAWK_NULL ;
hawk_clrpt ( hawk , left ) ; left = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
left = new_int_node ( hawk , folded . l , xloc ) ;
2019-12-13 04:29:58 +00:00
if ( left = = HAWK_NULL ) goto oops ;
}
break ;
case HAWK_NDE_FLT :
if ( fold = = left - > type )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , right ) ;
2019-12-13 04:29:58 +00:00
right = HAWK_NULL ;
2020-04-16 03:42:30 +00:00
update_flt_node ( hawk , ( hawk_nde_flt_t * ) left , folded . r ) ;
2019-12-13 04:29:58 +00:00
}
else if ( fold = = right - > type )
{
2024-04-28 19:15:17 +09:00
hawk_clrpt ( hawk , left ) ;
2020-04-16 03:42:30 +00:00
update_flt_node ( hawk , ( hawk_nde_flt_t * ) right , folded . r ) ;
2024-04-28 19:15:17 +09:00
left = right ;
2019-12-13 04:29:58 +00:00
right = HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , right ) ; right = HAWK_NULL ;
hawk_clrpt ( hawk , left ) ; left = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
left = new_flt_node ( hawk , folded . r , xloc ) ;
2019-12-13 04:29:58 +00:00
if ( left = = HAWK_NULL ) goto oops ;
}
break ;
case - 2 :
goto oops ;
default :
{
hawk_nde_t * tmp ;
2020-04-16 03:42:30 +00:00
tmp = new_exp_bin_node ( hawk , xloc , opcode , left , right ) ;
2019-12-13 04:29:58 +00:00
if ( tmp = = HAWK_NULL ) goto oops ;
left = tmp ; right = HAWK_NULL ;
break ;
}
}
}
while ( 1 ) ;
return left ;
oops :
2020-04-16 03:42:30 +00:00
if ( right ) hawk_clrpt ( hawk , right ) ;
if ( left ) hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_logical_or ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_LOR , HAWK_BINOP_LOR } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 1 , map , parse_logical_and ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_logical_and ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_LAND , HAWK_BINOP_LAND } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 1 , map , parse_in ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_in ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/*
2019-12-13 04:29:58 +00:00
static binmap_t map [ ] =
{
{ TOK_IN , HAWK_BINOP_IN } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_regex_match ) ;
2019-12-13 04:29:58 +00:00
*/
2024-04-28 19:15:17 +09:00
hawk_nde_t * left = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * right = HAWK_NULL ;
hawk_loc_t rloc ;
2020-04-16 03:42:30 +00:00
left = parse_regex_match ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
if ( left = = HAWK_NULL ) goto oops ;
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * tmp ;
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_IN ) ) break ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
rloc = hawk - > tok . loc ;
right = parse_regex_match ( hawk , & rloc ) ;
2020-04-07 16:16:48 +00:00
if ( HAWK_UNLIKELY ( ! right ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-07 16:16:48 +00:00
# if defined(HAWK_ENABLE_GC)
2024-05-03 14:04:03 +09:00
if ( ! is_var ( right ) & & right - > type ! = HAWK_NDE_XARGV )
2020-04-07 16:16:48 +00:00
# else
2024-05-03 14:04:03 +09:00
if ( ! is_plain_var ( right ) & & right - > type ! = HAWK_NDE_XARGV )
2020-04-07 16:16:48 +00:00
# endif
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & rloc , HAWK_ENOTVAR ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
tmp = new_exp_bin_node ( hawk , xloc , HAWK_BINOP_IN , left , right ) ;
2020-04-07 16:16:48 +00:00
if ( HAWK_UNLIKELY ( ! left ) ) goto oops ;
2019-12-13 04:29:58 +00:00
left = tmp ;
right = HAWK_NULL ;
}
while ( 1 ) ;
return left ;
oops :
2020-04-16 03:42:30 +00:00
if ( right ) hawk_clrpt ( hawk , right ) ;
if ( left ) hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_regex_match ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
static binmap_t map [ ] =
{
2020-03-04 09:54:38 +00:00
{ TOK_TILDE , HAWK_BINOP_MA } ,
2019-12-13 04:29:58 +00:00
{ TOK_NM , HAWK_BINOP_NM } ,
{ TOK_EOF , 0 } ,
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_bitwise_or ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_bitwise_or ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_BOR , HAWK_BINOP_BOR } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_bitwise_xor ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_bitwise_xor ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_BXOR , HAWK_BINOP_BXOR } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_bitwise_and ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_bitwise_and ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_BAND , HAWK_BINOP_BAND } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_equality ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_equality ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_TEQ , HAWK_BINOP_TEQ } ,
{ TOK_TNE , HAWK_BINOP_TNE } ,
{ TOK_EQ , HAWK_BINOP_EQ } ,
{ TOK_NE , HAWK_BINOP_NE } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_relational ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_relational ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_GT , HAWK_BINOP_GT } ,
{ TOK_GE , HAWK_BINOP_GE } ,
{ TOK_LT , HAWK_BINOP_LT } ,
{ TOK_LE , HAWK_BINOP_LE } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_shift ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_shift ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_LS , HAWK_BINOP_LS } ,
{ TOK_RS , HAWK_BINOP_RS } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_concat ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_concat ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
hawk_nde_t * left = HAWK_NULL ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * right = HAWK_NULL ;
hawk_loc_t rloc ;
2020-04-16 03:42:30 +00:00
left = parse_additive ( hawk , xloc ) ;
2020-03-04 13:59:03 +00:00
if ( HAWK_UNLIKELY ( ! left ) ) goto oops ;
2019-12-13 04:29:58 +00:00
do
{
hawk_nde_t * tmp ;
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_CONCAT ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( hawk - > opt . trait & HAWK_BLANKCONCAT )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/*
2020-03-04 13:59:03 +00:00
* [ NOTE ]
* TOK_TILDE has been commented out in the if condition below because
* BINOP_MA has lower precedence than concatenation and it is not certain
* the tilde is an unary bitwise negation operator at this phase .
* You may use ( ~ 10 ) rather than ~ 10 after concatenation to avoid confusion .
*/
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) | | MATCH ( hawk , TOK_DOLLAR ) | |
2019-12-13 04:29:58 +00:00
/* unary operators */
2020-04-16 03:42:30 +00:00
MATCH ( hawk , TOK_PLUS ) | | MATCH ( hawk , TOK_MINUS ) | |
2024-04-28 19:15:17 +09:00
MATCH ( hawk , TOK_LNOT ) | | /* MATCH(hawk,TOK_TILDE) ||*/
2019-12-13 04:29:58 +00:00
/* increment operators */
2020-04-16 03:42:30 +00:00
MATCH ( hawk , TOK_PLUSPLUS ) | | MATCH ( hawk , TOK_MINUSMINUS ) | |
2024-04-28 19:15:17 +09:00
( ( hawk - > opt . trait & HAWK_TOLERANT ) & &
2020-04-16 03:42:30 +00:00
( hawk - > tok . type = = TOK_PRINT | | hawk - > tok . type = = TOK_PRINTF ) ) | |
hawk - > tok . type > = TOK_GETLINE )
2019-12-13 04:29:58 +00:00
{
/* proceed to handle concatenation expression */
/* nothing to to here. just fall through */
}
else break ;
}
else break ;
2020-04-16 03:42:30 +00:00
rloc = hawk - > tok . loc ;
right = parse_additive ( hawk , & rloc ) ;
2020-03-04 13:59:03 +00:00
if ( HAWK_UNLIKELY ( ! right ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
tmp = new_exp_bin_node ( hawk , xloc , HAWK_BINOP_CONCAT , left , right ) ;
2020-03-04 13:59:03 +00:00
if ( HAWK_UNLIKELY ( ! tmp ) ) goto oops ;
2019-12-13 04:29:58 +00:00
left = tmp ; right = HAWK_NULL ;
}
while ( 1 ) ;
return left ;
oops :
2020-04-16 03:42:30 +00:00
if ( right ) hawk_clrpt ( hawk , right ) ;
if ( left ) hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_additive ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_PLUS , HAWK_BINOP_PLUS } ,
{ TOK_MINUS , HAWK_BINOP_MINUS } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_multiplicative ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_multiplicative ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_MUL , HAWK_BINOP_MUL } ,
{ TOK_DIV , HAWK_BINOP_DIV } ,
{ TOK_IDIV , HAWK_BINOP_IDIV } ,
{ TOK_MOD , HAWK_BINOP_MOD } ,
/* { TOK_EXP, HAWK_BINOP_EXP }, */
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_unary ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_unary ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * left ;
hawk_loc_t uloc ;
int opcode ;
int fold ;
folded_t folded ;
2020-04-16 03:42:30 +00:00
opcode = ( MATCH ( hawk , TOK_PLUS ) ) ? HAWK_UNROP_PLUS :
( MATCH ( hawk , TOK_MINUS ) ) ? HAWK_UNROP_MINUS :
( MATCH ( hawk , TOK_LNOT ) ) ? HAWK_UNROP_LNOT :
( MATCH ( hawk , TOK_TILDE ) ) ? HAWK_UNROP_BNOT : - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
/*if (opcode <= -1) return parse_increment(hawk);*/
if ( opcode < = - 1 ) return parse_exponent ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . expr_parse > 0 & &
hawk - > parse . depth . expr > = hawk - > opt . depth . s . expr_parse )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EEXPRNST ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . expr + + ;
uloc = hawk - > tok . loc ;
left = parse_unary ( hawk , & uloc ) ;
hawk - > parse . depth . expr - - ;
2019-12-13 04:29:58 +00:00
if ( left = = HAWK_NULL ) return HAWK_NULL ;
fold = - 1 ;
if ( left - > type = = HAWK_NDE_INT )
{
fold = HAWK_NDE_INT ;
switch ( opcode )
{
case HAWK_UNROP_PLUS :
folded . l = ( ( hawk_nde_int_t * ) left ) - > val ;
break ;
case HAWK_UNROP_MINUS :
folded . l = - ( ( hawk_nde_int_t * ) left ) - > val ;
break ;
case HAWK_UNROP_LNOT :
folded . l = ! ( ( hawk_nde_int_t * ) left ) - > val ;
break ;
case HAWK_UNROP_BNOT :
folded . l = ~ ( ( hawk_nde_int_t * ) left ) - > val ;
break ;
default :
fold = - 1 ;
break ;
}
}
else if ( left - > type = = HAWK_NDE_FLT )
{
fold = HAWK_NDE_FLT ;
switch ( opcode )
{
case HAWK_UNROP_PLUS :
folded . r = ( ( hawk_nde_flt_t * ) left ) - > val ;
break ;
case HAWK_UNROP_MINUS :
folded . r = - ( ( hawk_nde_flt_t * ) left ) - > val ;
break ;
case HAWK_UNROP_LNOT :
folded . r = ! ( ( hawk_nde_flt_t * ) left ) - > val ;
break ;
case HAWK_UNROP_BNOT :
folded . l = ~ ( ( hawk_int_t ) ( ( hawk_nde_flt_t * ) left ) - > val ) ;
fold = HAWK_NDE_INT ;
break ;
default :
fold = - 1 ;
break ;
}
}
switch ( fold )
{
case HAWK_NDE_INT :
if ( left - > type = = fold )
{
2020-04-16 03:42:30 +00:00
update_int_node ( hawk , ( hawk_nde_int_t * ) left , folded . l ) ;
2019-12-13 04:29:58 +00:00
return left ;
}
else
{
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( left - > type = = HAWK_NDE_FLT ) ;
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
return new_int_node ( hawk , folded . l , xloc ) ;
2019-12-13 04:29:58 +00:00
}
case HAWK_NDE_FLT :
if ( left - > type = = fold )
{
2020-04-16 03:42:30 +00:00
update_flt_node ( hawk , ( hawk_nde_flt_t * ) left , folded . r ) ;
2019-12-13 04:29:58 +00:00
return left ;
}
else
{
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( left - > type = = HAWK_NDE_INT ) ;
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
return new_flt_node ( hawk , folded . r , xloc ) ;
2019-12-13 04:29:58 +00:00
}
default :
{
2024-04-28 19:15:17 +09:00
hawk_nde_exp_t * nde ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_exp_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2019-12-13 04:29:58 +00:00
if ( nde = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_EXP_UNR ;
nde - > loc = * xloc ;
nde - > opcode = opcode ;
nde - > left = left ;
/*nde->right = HAWK_NULL;*/
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
}
}
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_exponent ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
static binmap_t map [ ] =
2019-12-13 04:29:58 +00:00
{
{ TOK_EXP , HAWK_BINOP_EXP } ,
{ TOK_EOF , 0 }
} ;
2020-04-16 03:42:30 +00:00
return parse_binary ( hawk , xloc , 0 , map , parse_unary_exp ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_unary_exp ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
hawk_nde_exp_t * nde ;
2019-12-13 04:29:58 +00:00
hawk_nde_t * left ;
hawk_loc_t uloc ;
int opcode ;
2020-04-16 03:42:30 +00:00
opcode = ( MATCH ( hawk , TOK_PLUS ) ) ? HAWK_UNROP_PLUS :
( MATCH ( hawk , TOK_MINUS ) ) ? HAWK_UNROP_MINUS :
( MATCH ( hawk , TOK_LNOT ) ) ? HAWK_UNROP_LNOT :
( MATCH ( hawk , TOK_TILDE ) ) ? HAWK_UNROP_BNOT : - 1 ; /* ~ in the unary context is a bitwise-not operator */
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( opcode < = - 1 ) return parse_increment ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . depth . s . expr_parse > 0 & &
hawk - > parse . depth . expr > = hawk - > opt . depth . s . expr_parse )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EEXPRNST ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk - > parse . depth . expr + + ;
uloc = hawk - > tok . loc ;
left = parse_unary ( hawk , & uloc ) ;
hawk - > parse . depth . expr - - ;
2019-12-13 04:29:58 +00:00
if ( left = = HAWK_NULL ) return HAWK_NULL ;
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_exp_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2019-12-13 04:29:58 +00:00
if ( nde = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_EXP_UNR ;
nde - > loc = * xloc ;
nde - > opcode = opcode ;
nde - > left = left ;
nde - > right = HAWK_NULL ;
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_increment ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_exp_t * nde ;
hawk_nde_t * left ;
int type , opcode , opcode1 , opcode2 ;
hawk_loc_t ploc ;
/* check for prefix increment operator */
2020-04-16 03:42:30 +00:00
opcode1 = MATCH ( hawk , TOK_PLUSPLUS ) ? HAWK_INCOP_PLUS :
MATCH ( hawk , TOK_MINUSMINUS ) ? HAWK_INCOP_MINUS : - 1 ;
2019-12-13 04:29:58 +00:00
if ( opcode1 ! = - 1 )
{
/* there is a prefix increment operator */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2020-11-10 02:56:29 +00:00
left = parse_primary ( hawk , & ploc ) ;
if ( HAWK_UNLIKELY ( ! left ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
/* check for postfix increment operator */
2020-04-16 03:42:30 +00:00
opcode2 = MATCH ( hawk , TOK_PLUSPLUS ) ? HAWK_INCOP_PLUS :
MATCH ( hawk , TOK_MINUSMINUS ) ? HAWK_INCOP_MINUS : - 1 ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_BLANKCONCAT ) )
2024-04-28 19:15:17 +09:00
{
2019-12-13 04:29:58 +00:00
if ( opcode1 ! = - 1 & & opcode2 ! = - 1 )
{
2024-04-28 19:15:17 +09:00
/* both prefix and postfix increment operator.
2019-12-13 04:29:58 +00:00
* not allowed */
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
hawk_seterrnum ( hawk , xloc , HAWK_EPREPST ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
if ( opcode1 = = - 1 & & opcode2 = = - 1 )
{
/* no increment operators */
return left ;
}
2024-04-28 19:15:17 +09:00
if ( opcode1 ! = - 1 )
2019-12-13 04:29:58 +00:00
{
/* prefix increment operator.
* ignore a potential postfix operator */
type = HAWK_NDE_EXP_INCPRE ;
opcode = opcode1 ;
}
else /*if (opcode2 != -1)*/
{
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( opcode2 ! = - 1 ) ;
2019-12-13 04:29:58 +00:00
/* postfix increment operator */
type = HAWK_NDE_EXP_INCPST ;
opcode = opcode2 ;
2024-04-28 19:15:17 +09:00
/* let's do it later
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
*/
}
if ( ! is_var ( left ) & & left - > type ! = HAWK_NDE_POS )
{
if ( type = = HAWK_NDE_EXP_INCPST )
{
/* For an expression like 1 ++y,
* left is 1. so we leave + + for y . */
return left ;
}
else
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
hawk_seterrnum ( hawk , xloc , HAWK_EINCDECOPR ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
if ( type = = HAWK_NDE_EXP_INCPST )
{
/* consume the postfix operator */
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_exp_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2019-12-13 04:29:58 +00:00
if ( nde = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , left ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = type ;
nde - > loc = * xloc ;
nde - > opcode = opcode ;
nde - > left = left ;
nde - > right = HAWK_NULL ;
return ( hawk_nde_t * ) nde ;
}
# define FNTYPE_UNKNOWN 0
# define FNTYPE_FNC 1
# define FNTYPE_FUN 2
2020-04-16 03:42:30 +00:00
static HAWK_INLINE int isfunname ( hawk_t * hawk , const hawk_oocs_t * name , hawk_fun_t * * fun )
2019-12-13 04:29:58 +00:00
{
hawk_htb_pair_t * pair ;
2020-04-16 03:42:30 +00:00
/* check if it is an hawk function being processed currently */
if ( hawk - > tree . cur_fun . ptr )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk_comp_oochars ( hawk - > tree . cur_fun . ptr , hawk - > tree . cur_fun . len , name - > ptr , name - > len , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
/* the current function begin parsed */
return FNTYPE_FUN ;
}
}
/* check the funtion name in the function table */
2020-04-16 03:42:30 +00:00
pair = hawk_htb_search ( hawk - > tree . funs , name - > ptr , name - > len ) ;
2019-12-13 04:29:58 +00:00
if ( pair )
{
/* one of the functions defined previously */
2024-04-28 19:15:17 +09:00
if ( fun )
2019-12-13 04:29:58 +00:00
{
* fun = ( hawk_fun_t * ) HAWK_HTB_VPTR ( pair ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( * fun ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
}
return FNTYPE_FUN ;
}
/* check if it is a function not resolved so far */
2024-04-28 19:15:17 +09:00
if ( hawk_htb_search ( hawk - > parse . funs , name - > ptr , name - > len ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* one of the function calls not resolved so far. */
2019-12-13 04:29:58 +00:00
return FNTYPE_FUN ;
}
return FNTYPE_UNKNOWN ;
}
2020-04-16 03:42:30 +00:00
static HAWK_INLINE int isfnname ( hawk_t * hawk , const hawk_oocs_t * name )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( hawk_findfncwithoocs ( hawk , name ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
/* implicit function */
return FNTYPE_FNC ;
}
2020-04-16 03:42:30 +00:00
return isfunname ( hawk , name , HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
}
2020-12-05 18:55:05 +00:00
static hawk_nde_t * parse_primary_char ( hawk_t * hawk , const hawk_loc_t * xloc )
{
hawk_nde_char_t * nde ;
2020-12-10 16:55:47 +00:00
nde = ( hawk_nde_char_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2020-12-05 18:55:05 +00:00
{
ADJERR_LOC ( hawk , xloc ) ;
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_CHAR ;
nde - > loc = * xloc ;
nde - > val = HAWK_OOECS_CHAR ( hawk - > tok . name , 0 ) ;
if ( get_token ( hawk ) < = - 1 ) goto oops ;
return ( hawk_nde_t * ) nde ;
oops :
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
hawk_freemem ( hawk , nde ) ;
return HAWK_NULL ;
}
2020-12-09 18:07:20 +00:00
static hawk_nde_t * parse_primary_bchr ( hawk_t * hawk , const hawk_loc_t * xloc )
{
hawk_nde_bchr_t * nde ;
2020-12-10 16:55:47 +00:00
nde = ( hawk_nde_bchr_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2020-12-09 18:07:20 +00:00
{
ADJERR_LOC ( hawk , xloc ) ;
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_BCHR ;
nde - > loc = * xloc ;
nde - > val = HAWK_OOECS_CHAR ( hawk - > tok . name , 0 ) ;
if ( get_token ( hawk ) < = - 1 ) goto oops ;
return ( hawk_nde_t * ) nde ;
oops :
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
hawk_freemem ( hawk , nde ) ;
return HAWK_NULL ;
}
2019-12-14 06:11:30 +00:00
static hawk_nde_t * parse_primary_int ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_int_t * nde ;
/* create the node for the literal */
2020-12-10 16:55:47 +00:00
nde = ( hawk_nde_int_t * ) new_int_node (
2024-04-28 19:15:17 +09:00
hawk ,
2020-03-09 08:52:42 +00:00
hawk_oochars_to_int ( HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOCHARS_TO_INT_MAKE_OPTION ( 0 , 0 , 0 ) , HAWK_NULL , HAWK_NULL ) ,
2019-12-13 04:29:58 +00:00
xloc
) ;
2020-03-09 08:52:42 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( HAWK_OOECS_LEN ( hawk - > tok . name ) = = hawk_count_oocstr ( HAWK_OOECS_PTR ( hawk - > tok . name ) ) ) ;
2019-12-13 04:29:58 +00:00
/* remember the literal in the original form */
2019-12-14 06:11:30 +00:00
nde - > len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > str = hawk_dupoocs ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ;
2020-03-09 08:52:42 +00:00
if ( ! nde - > str | | get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
2019-12-14 06:11:30 +00:00
if ( nde - > str ) hawk_freemem ( hawk , nde - > str ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-12-02 18:52:33 +00:00
static hawk_nde_t * parse_primary_flt ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_flt_t * nde ;
/* create the node for the literal */
2019-12-14 06:11:30 +00:00
nde = ( hawk_nde_flt_t * ) new_flt_node (
2024-04-28 19:15:17 +09:00
hawk ,
2020-03-09 08:52:42 +00:00
hawk_oochars_to_flt ( HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_NULL , 0 ) ,
2019-12-13 04:29:58 +00:00
xloc
) ;
2020-03-09 08:52:42 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2019-12-21 16:59:00 +00:00
HAWK_ASSERT (
2019-12-14 06:11:30 +00:00
HAWK_OOECS_LEN ( hawk - > tok . name ) = =
hawk_count_oocstr ( HAWK_OOECS_PTR ( hawk - > tok . name ) ) ) ;
2019-12-13 04:29:58 +00:00
/* remember the literal in the original form */
2019-12-14 06:11:30 +00:00
nde - > len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > str = hawk_dupoocs ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ;
2020-03-09 08:52:42 +00:00
if ( ! nde - > str | | get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
2019-12-14 06:11:30 +00:00
if ( nde - > str ) hawk_freemem ( hawk , nde - > str ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_str ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_str_t * nde ;
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_str_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( nde = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_STR ;
nde - > loc = * xloc ;
2020-04-16 03:42:30 +00:00
nde - > len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > ptr = hawk_dupoocs ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ;
if ( nde - > ptr = = HAWK_NULL | | get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
2020-04-16 03:42:30 +00:00
if ( nde - > ptr ) hawk_freemem ( hawk , nde - > ptr ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_mbs ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_mbs_t * nde ;
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_mbs_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_MBS ;
nde - > loc = * xloc ;
# if defined(HAWK_OOCH_IS_BCH)
2020-04-16 03:42:30 +00:00
nde - > len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > ptr = hawk_dupoocs ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ;
2024-04-28 19:15:17 +09:00
if ( ! nde - > ptr )
2020-01-01 14:02:27 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2020-01-01 14:02:27 +00:00
goto oops ;
}
2019-12-13 04:29:58 +00:00
# else
{
2024-04-28 19:15:17 +09:00
/* the MBS token doesn't include a character greater than 0xFF in hawk->tok.name
2019-12-13 04:29:58 +00:00
* even though it is a unicode string . simply copy over without conversion */
2020-04-16 03:42:30 +00:00
nde - > len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > ptr = hawk_allocmem ( hawk , ( nde - > len + 1 ) * HAWK_SIZEOF ( * nde - > ptr ) ) ;
2019-12-13 04:29:58 +00:00
if ( ! nde - > ptr )
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
hawk_copy_uchars_to_bchars ( nde - > ptr , HAWK_OOECS_PTR ( hawk - > tok . name ) , nde - > len ) ;
2019-12-13 04:29:58 +00:00
nde - > ptr [ nde - > len ] = ' \0 ' ;
}
# endif
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
2020-04-16 03:42:30 +00:00
if ( nde - > ptr ) hawk_freemem ( hawk , nde - > ptr ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_rex ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_rex_t * nde ;
2024-04-28 19:15:17 +09:00
/* the regular expression is tokenized here because
2019-12-13 04:29:58 +00:00
* of the context - sensitivity of the slash symbol .
* if TOK_DIV is seen as a primary , it tries to compile
* it as a regular expression */
2020-04-16 03:42:30 +00:00
hawk_ooecs_clear ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_DIV_ASSN ) & & hawk_ooecs_ccat ( hawk - > tok . name , HAWK_T ( ' = ' ) ) = = ( hawk_oow_t ) - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
SET_TOKEN_TYPE ( hawk , & hawk - > tok , TOK_REX ) ;
if ( get_rexstr ( hawk , & hawk - > tok ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( MATCH ( hawk , TOK_REX ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_rex_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( nde = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_REX ;
nde - > loc = * xloc ;
2020-04-16 03:42:30 +00:00
nde - > str . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
nde - > str . ptr = hawk_dupoocs ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
if ( nde - > str . ptr = = HAWK_NULL ) goto oops ;
2020-04-16 03:42:30 +00:00
if ( hawk_buildrex ( hawk , HAWK_OOECS_PTR ( hawk - > tok . name ) , HAWK_OOECS_LEN ( hawk - > tok . name ) , & nde - > code [ 0 ] , & nde - > code [ 1 ] ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
2020-04-16 03:42:30 +00:00
if ( nde - > code [ 0 ] ) hawk_freerex ( hawk , nde - > code [ 0 ] , nde - > code [ 1 ] ) ;
if ( nde - > str . ptr ) hawk_freemem ( hawk , nde - > str . ptr ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_positional ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_pos_t * nde ;
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_pos_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = HAWK_NDE_POS ;
nde - > loc = * xloc ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
nde - > val = parse_primary ( hawk , & ploc ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! nde - > val ) ) goto oops ;
2019-12-13 04:29:58 +00:00
return ( hawk_nde_t * ) nde ;
oops :
2024-04-28 19:15:17 +09:00
if ( nde )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( nde - > val ) hawk_clrpt ( hawk , nde - > val ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
}
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_lparen ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
hawk_nde_t * last ;
hawk_loc_t eloc ;
hawk_oow_t opening_lparen_seq ;
2020-04-16 03:42:30 +00:00
opening_lparen_seq = hawk - > parse . lparen_seq + + ;
2019-12-13 04:29:58 +00:00
/* eat up the left parenthesis */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
/* parse the sub-expression inside the parentheses */
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
nde = parse_expr_withdc ( hawk , & eloc ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
/* parse subsequent expressions separated by a comma, if any */
last = nde ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( last - > next = = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * tmp ;
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
tmp = parse_expr_withdc ( hawk , & eloc ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! tmp ) ) goto oops ;
2019-12-13 04:29:58 +00:00
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( tmp - > next = = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
last - > next = tmp ;
last = tmp ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
/* ----------------- */
/* check for the closing parenthesis */
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERPAREN , FMT_ERPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
/* remember the sequence number of the left parenthesis
2020-12-01 10:22:17 +00:00
* that ' s been just closed by the matching right parenthesis */
2020-04-16 03:42:30 +00:00
hawk - > parse . lparen_last_closed = opening_lparen_seq ;
2020-12-01 10:22:17 +00:00
hawk - > tok . flags | = TOK_FLAGS_LPAREN_CLOSER ; /* indicate that this RPAREN is closing LPAREN */
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* check if it is a chained node */
if ( nde - > next )
{
/* if so, it is an expression group */
/* (expr1, expr2, expr2) */
hawk_nde_grp_t * tmp ;
2020-04-16 03:42:30 +00:00
if ( ( hawk - > parse . id . stmt ! = TOK_PRINT & & hawk - > parse . id . stmt ! = TOK_PRINTF ) | | hawk - > parse . depth . expr ! = 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_TOLERANT ) & & ! MATCH ( hawk , TOK_IN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EKWIN , FMT_EKWIN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
2020-04-16 03:42:30 +00:00
tmp = ( hawk_nde_grp_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( hawk_nde_grp_t ) ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! tmp ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
tmp - > type = HAWK_NDE_GRP ;
tmp - > loc = * xloc ;
tmp - > body = nde ;
nde = ( hawk_nde_t * ) tmp ;
}
/* ----------------- */
return nde ;
oops :
2020-04-16 03:42:30 +00:00
if ( nde ) hawk_clrpt ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_getline ( hawk_t * hawk , const hawk_loc_t * xloc , int mbs )
2019-12-13 04:29:58 +00:00
{
/* parse the statement-level getline.
* getline after the pipe symbols ( | , | | ) is parsed
2024-04-28 19:15:17 +09:00
* by parse_primary ( ) .
2019-12-13 04:29:58 +00:00
*/
hawk_nde_getline_t * nde ;
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_getline_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! nde ) ) goto oops ;
2019-12-13 04:29:58 +00:00
nde - > type = HAWK_NDE_GETLINE ;
2020-01-16 09:22:59 +00:00
nde - > mbs = mbs ;
2019-12-13 04:29:58 +00:00
nde - > loc = * xloc ;
nde - > in_type = HAWK_IN_CONSOLE ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_IDENT ) | | MATCH ( hawk , TOK_DOLLAR ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* getline var
2019-12-13 04:29:58 +00:00
* getline $ XXX */
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & HAWK_BLANKCONCAT ) & & MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
/* i need to perform some precheck on if the identifier is
* really a variable */
2020-04-16 03:42:30 +00:00
if ( preget_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > ntok . type = = TOK_DBLCOLON ) goto novar ;
if ( hawk - > ntok . type = = TOK_LPAREN )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( hawk - > ntok . loc . line = = hawk - > tok . loc . line & &
2020-04-16 03:42:30 +00:00
hawk - > ntok . loc . colm = = hawk - > tok . loc . colm + HAWK_OOECS_LEN ( hawk - > tok . name ) )
2019-12-13 04:29:58 +00:00
{
/* it's in the form of a function call since
* there is no spaces between the identifier
* and the left parenthesis . */
goto novar ;
}
}
2020-04-16 03:42:30 +00:00
if ( isfnname ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ! = FNTYPE_UNKNOWN ) goto novar ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
nde - > var = parse_primary ( hawk , & ploc ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! nde - > var ) ) goto oops ;
2019-12-13 04:29:58 +00:00
if ( ! is_var ( nde - > var ) & & nde - > var - > type ! = HAWK_NDE_POS )
{
/* this is 'getline' followed by an expression probably.
2024-04-28 19:15:17 +09:00
* getline a ( )
2019-12-13 04:29:58 +00:00
* getline sys : : WNOHANG
*/
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & ploc , HAWK_EBADARG ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
novar :
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LT ) )
2019-12-13 04:29:58 +00:00
{
/* getline [var] < file */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
2019-12-13 04:29:58 +00:00
/* TODO: is this correct? */
2020-04-16 03:42:30 +00:00
/*nde->in = parse_expr_withdc (hawk, &ploc);*/
nde - > in = parse_primary ( hawk , & ploc ) ;
2020-03-12 04:26:28 +00:00
if ( HAWK_UNLIKELY ( ! nde - > in ) ) goto oops ;
2019-12-13 04:29:58 +00:00
nde - > in_type = HAWK_IN_FILE ;
}
return ( hawk_nde_t * ) nde ;
oops :
if ( nde )
{
2020-04-16 03:42:30 +00:00
if ( nde - > in ) hawk_clrpt ( hawk , nde - > in ) ;
if ( nde - > var ) hawk_clrpt ( hawk , nde - > var ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
}
return HAWK_NULL ;
}
2020-11-10 02:56:29 +00:00
static hawk_nde_t * parse_primary_xnil ( hawk_t * hawk , const hawk_loc_t * xloc )
{
hawk_nde_xnil_t * nde ;
nde = ( hawk_nde_xnil_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
{
ADJERR_LOC ( hawk , xloc ) ;
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_XNIL ;
nde - > loc = * xloc ;
if ( get_token ( hawk ) < = - 1 ) goto oops ;
return ( hawk_nde_t * ) nde ;
oops :
HAWK_ASSERT ( nde ! = HAWK_NULL ) ;
hawk_freemem ( hawk , nde ) ;
return HAWK_NULL ;
}
2024-05-02 22:36:50 +09:00
static hawk_nde_t * parse_primary_xarg ( hawk_t * hawk , const hawk_loc_t * xloc )
{
2024-05-03 14:04:03 +09:00
hawk_nde_t * nde = HAWK_NULL ;
2024-05-02 22:36:50 +09:00
hawk_nde_t * pos = HAWK_NULL ;
2024-05-03 14:04:03 +09:00
int nde_type ;
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
/* @argc, @argv, @argv[] look like the standard ARGC and ARGV but form special constructs
* for function arguments . this is useful when combined with the variadic function arguments .
* it can ' t be used in assignment , delete , reset , in many other context , however .
* when used in the main entry point function , @ argc is the number of arguments to the
* function but ARGC is the number of arguments including the program name so ARGC is greater
* than @ argc by 1. */
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
HAWK_ASSERT ( hawk - > tok . type = = TOK_XARGV | | hawk - > tok . type = = TOK_XARGC ) ;
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
if ( hawk - > tok . type = = TOK_XARGV )
2024-05-02 22:36:50 +09:00
{
2024-05-03 14:04:03 +09:00
/* @argv */
nde_type = HAWK_NDE_XARGV ;
if ( get_token ( hawk ) < = - 1 ) goto oops ;
if ( MATCH ( hawk , TOK_LBRACK ) ) /* @argv[, expecting to see @argv[expr] */
{
hawk_loc_t eloc ;
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
eloc = hawk - > tok . loc ;
pos = parse_expr_withdc ( hawk , & eloc ) ;
if ( HAWK_UNLIKELY ( ! pos ) ) goto oops ;
if ( ! MATCH ( hawk , TOK_RBRACK ) )
{
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERBRACK , FMT_ERBRACK , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
goto oops ;
}
if ( get_token ( hawk ) < = - 1 ) goto oops ;
}
}
else
2024-05-02 22:36:50 +09:00
{
2024-05-03 14:04:03 +09:00
nde_type = HAWK_NDE_XARGC ;
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2024-05-02 22:36:50 +09:00
}
2024-05-03 14:04:03 +09:00
if ( pos )
2024-05-02 22:36:50 +09:00
{
2024-05-03 14:04:03 +09:00
hawk_nde_xargvidx_t * xargvidx ;
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
xargvidx = ( hawk_nde_xargvidx_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * xargvidx ) ) ;
if ( HAWK_UNLIKELY ( ! xargvidx ) )
{
ADJERR_LOC ( hawk , xloc ) ;
return HAWK_NULL ;
}
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
xargvidx - > type = HAWK_NDE_XARGVIDX ;
xargvidx - > loc = * xloc ;
xargvidx - > pos = pos ;
nde = ( hawk_nde_t * ) xargvidx ;
2024-05-02 22:36:50 +09:00
}
2024-05-03 14:04:03 +09:00
else
{
nde = hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
if ( HAWK_UNLIKELY ( ! nde ) )
{
ADJERR_LOC ( hawk , xloc ) ;
return HAWK_NULL ;
}
2024-05-02 22:36:50 +09:00
2024-05-03 14:04:03 +09:00
nde - > type = nde_type ;
nde - > loc = * xloc ;
}
2024-05-02 22:36:50 +09:00
return ( hawk_nde_t * ) nde ;
oops :
2024-05-03 14:04:03 +09:00
if ( nde ) hawk_freemem ( hawk , nde ) ; /* tricky to call hawk_clrpt() on nde due to pos */
2024-05-02 22:36:50 +09:00
if ( pos ) hawk_clrpt ( hawk , pos ) ;
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_nopipe ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
switch ( hawk - > tok . type )
2019-12-13 04:29:58 +00:00
{
case TOK_IDENT :
2020-04-16 03:42:30 +00:00
return parse_primary_ident ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
2020-12-05 18:55:05 +00:00
case TOK_CHAR :
return parse_primary_char ( hawk , xloc ) ;
2020-12-09 18:07:20 +00:00
case TOK_BCHR :
return parse_primary_bchr ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_INT :
2020-04-16 03:42:30 +00:00
return parse_primary_int ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_FLT :
2020-04-16 03:42:30 +00:00
return parse_primary_flt ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_STR :
2020-04-16 03:42:30 +00:00
return parse_primary_str ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_MBS :
2020-04-16 03:42:30 +00:00
return parse_primary_mbs ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_DIV :
case TOK_DIV_ASSN :
2020-04-16 03:42:30 +00:00
return parse_primary_rex ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_DOLLAR :
2020-04-16 03:42:30 +00:00
return parse_primary_positional ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
case TOK_LPAREN :
2020-04-16 03:42:30 +00:00
return parse_primary_lparen ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
2020-01-16 09:22:59 +00:00
case TOK_GETBLINE :
2020-04-16 03:42:30 +00:00
return parse_primary_getline ( hawk , xloc , 1 ) ;
2020-01-16 09:22:59 +00:00
2019-12-13 04:29:58 +00:00
case TOK_GETLINE :
2020-04-16 03:42:30 +00:00
return parse_primary_getline ( hawk , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
2020-11-10 02:56:29 +00:00
case TOK_XNIL :
return parse_primary_xnil ( hawk , xloc ) ;
2024-05-02 22:36:50 +09:00
case TOK_XARGV :
case TOK_XARGC :
return parse_primary_xarg ( hawk , xloc ) ;
2020-11-10 02:56:29 +00:00
2019-12-13 04:29:58 +00:00
default :
2020-01-03 07:35:59 +00:00
{
hawk_tok_t * xtok ;
2024-04-28 19:15:17 +09:00
/* in the tolerant mode, we treat print and printf
2019-12-13 04:29:58 +00:00
* as a function like getline */
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & HAWK_TOLERANT ) & &
( MATCH ( hawk , TOK_PRINT ) | | MATCH ( hawk , TOK_PRINTF ) ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) return HAWK_NULL ;
2020-12-01 10:22:17 +00:00
return parse_print ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
/* valid expression introducer is expected */
2020-04-16 03:42:30 +00:00
xtok = MATCH ( hawk , TOK_NEWLINE ) ? & hawk - > ptok : & hawk - > tok ;
hawk_seterrfmt ( hawk , & xtok - > loc , HAWK_EEXPRNR , HAWK_T ( " expression not recognized around '%.*js' " ) , HAWK_OOECS_LEN ( xtok - > name ) , HAWK_OOECS_PTR ( xtok - > name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
2020-01-03 07:35:59 +00:00
}
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * left ;
hawk_nde_getline_t * nde ;
hawk_nde_t * var = HAWK_NULL ;
hawk_loc_t ploc ;
2020-04-16 03:42:30 +00:00
left = parse_primary_nopipe ( hawk , xloc ) ;
2020-12-10 16:55:47 +00:00
if ( ! left ) goto oops ;
2019-12-13 04:29:58 +00:00
/* handle the piping part */
do
{
int intype = - 1 ;
2020-01-16 09:22:59 +00:00
int mbs ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_RIO )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_BOR ) )
2019-12-13 04:29:58 +00:00
{
intype = HAWK_IN_PIPE ;
}
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_LOR ) & & ( hawk - > opt . trait & HAWK_RWPIPE ) )
2019-12-13 04:29:58 +00:00
{
intype = HAWK_IN_RWPIPE ;
}
}
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
if ( intype = = - 1 ) break ;
2020-04-16 03:42:30 +00:00
if ( preget_token ( hawk ) < = - 1 ) goto oops ;
if ( hawk - > ntok . type = = TOK_GETBLINE ) mbs = 1 ;
else if ( hawk - > ntok . type = = TOK_GETLINE ) mbs = 0 ;
2020-01-16 09:22:59 +00:00
else break ;
2019-12-13 04:29:58 +00:00
/* consume ntok('getline') */
2020-04-16 03:42:30 +00:00
get_token ( hawk ) ; /* no error check needed as it's guaranteeded to succeed for preget_token() above */
2019-12-13 04:29:58 +00:00
/* get the next token */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* TODO: is this correct? */
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_IDENT ) | | MATCH ( hawk , TOK_DOLLAR ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* command | getline var
2019-12-13 04:29:58 +00:00
* command | | getline var */
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & HAWK_BLANKCONCAT ) & & MATCH ( hawk , TOK_IDENT ) )
2019-12-13 04:29:58 +00:00
{
/* i need to perform some precheck on if the identifier is
* really a variable */
2020-04-16 03:42:30 +00:00
if ( preget_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > ntok . type = = TOK_DBLCOLON ) goto novar ;
if ( hawk - > ntok . type = = TOK_LPAREN )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( hawk - > ntok . loc . line = = hawk - > tok . loc . line & &
2020-04-16 03:42:30 +00:00
hawk - > ntok . loc . colm = = hawk - > tok . loc . colm + HAWK_OOECS_LEN ( hawk - > tok . name ) )
2019-12-13 04:29:58 +00:00
{
/* it's in the form of a function call since
* there is no spaces between the identifier
* and the left parenthesis . */
goto novar ;
}
}
2020-04-16 03:42:30 +00:00
if ( isfnname ( hawk , HAWK_OOECS_OOCS ( hawk - > tok . name ) ) ! = FNTYPE_UNKNOWN ) goto novar ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
ploc = hawk - > tok . loc ;
var = parse_primary ( hawk , & ploc ) ;
2019-12-13 04:29:58 +00:00
if ( var = = HAWK_NULL ) goto oops ;
if ( ! is_var ( var ) & & var - > type ! = HAWK_NDE_POS )
{
/* fucntion a() {}
* print ( " ls -laF " | getline a ( ) ) */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & ploc , HAWK_EBADARG ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
novar :
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_getline_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2020-12-10 16:55:47 +00:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nde - > type = HAWK_NDE_GETLINE ;
nde - > loc = * xloc ;
nde - > var = var ;
2020-01-16 09:22:59 +00:00
nde - > mbs = mbs ;
2019-12-13 04:29:58 +00:00
nde - > in_type = intype ;
nde - > in = left ;
left = ( hawk_nde_t * ) nde ;
var = HAWK_NULL ;
}
while ( 1 ) ;
return left ;
oops :
2020-04-16 03:42:30 +00:00
if ( var ) hawk_clrpt ( hawk , var ) ;
hawk_clrpt ( hawk , left ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_variable ( hawk_t * hawk , const hawk_loc_t * xloc , hawk_nde_type_t type , const hawk_oocs_t * name , hawk_oow_t idxa )
2019-12-13 04:29:58 +00:00
{
hawk_nde_var_t * nde ;
int is_fcv = 0 ;
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2019-12-13 04:29:58 +00:00
/*
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_LPAREN ) & &
( ! ( hawk - > opt . trait & HAWK_BLANKCONCAT ) | |
( hawk - > tok . loc . line = = xloc - > line & &
2020-04-16 03:42:30 +00:00
hawk - > tok . loc . colm = = xloc - > colm + name - > len ) ) )
2019-12-13 04:29:58 +00:00
*/
2020-04-16 03:42:30 +00:00
if ( hawk - > tok . loc . line = = xloc - > line & & hawk - > tok . loc . colm = = xloc - > colm + name - > len )
2019-12-13 04:29:58 +00:00
{
is_fcv = 1 ;
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
# endif
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_BLANKCONCAT ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* if concatenation by blanks is not allowed, the explicit
* concatenation operator ( % % ) must be used . so it is obvious
* that it is a function call , which is illegal for a variable .
2019-12-13 04:29:58 +00:00
* if implicit , " var_xxx (1) " may be concatenation of
* the value of var_xxx and 1.
*/
/* a variable is not a function */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFUNNAM , HAWK_T ( " '%.*js' not a valid function name " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_var_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = type ;
nde - > loc = * xloc ;
/*nde->id.name.ptr = HAWK_NULL;*/
nde - > id . name . ptr = name - > ptr ;
nde - > id . name . len = name - > len ;
nde - > id . idxa = idxa ;
nde - > idx = HAWK_NULL ;
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2019-12-13 04:29:58 +00:00
if ( ! is_fcv ) return ( hawk_nde_t * ) nde ;
2020-04-16 03:42:30 +00:00
return parse_fncall ( hawk , ( const hawk_oocs_t * ) nde , HAWK_NULL , xloc , FNCALL_FLAG_VAR ) ;
2019-12-13 04:29:58 +00:00
# else
return ( hawk_nde_t * ) nde ;
# endif
}
2020-04-16 03:42:30 +00:00
static int dup_ident_and_get_next ( hawk_t * hawk , const hawk_loc_t * xloc , hawk_oocs_t * name , int max )
2019-12-13 04:29:58 +00:00
{
int nsegs = 0 ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( MATCH ( hawk , TOK_IDENT ) ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
name [ nsegs ] . ptr = HAWK_OOECS_PTR ( hawk - > tok . name ) ;
name [ nsegs ] . len = HAWK_OOECS_LEN ( hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
/* duplicate the identifier */
2020-04-16 03:42:30 +00:00
name [ nsegs ] . ptr = hawk_dupoochars ( hawk , name [ nsegs ] . ptr , name [ nsegs ] . len ) ;
2019-12-13 04:29:58 +00:00
if ( ! name [ nsegs ] . ptr )
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
nsegs + + ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_DBLCOLON ) ) break ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
/* the identifier after ::
2024-04-28 19:15:17 +09:00
* allow reserved words as well since i view the whole name ( mod : : ident )
2019-12-13 04:29:58 +00:00
* as one segment . however , i don ' t want the identifier part to begin
2024-04-28 19:15:17 +09:00
* with @ . some extended keywords begin with @ like @ include .
2019-12-13 04:29:58 +00:00
* TOK_XGLOBAL to TOK_XRESET are excuded from the check for that reason . */
2020-04-16 03:42:30 +00:00
if ( ! MATCH ( hawk , TOK_IDENT ) & & ! ( MATCH_RANGE ( hawk , TOK_BEGIN , TOK_GETLINE ) ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EIDENT , FMT_EIDENT , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
if ( nsegs > = max )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_ESEGTM ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
while ( 1 ) ;
return nsegs ;
oops :
2020-04-16 03:42:30 +00:00
while ( nsegs > 0 ) hawk_freemem ( hawk , name [ - - nsegs ] . ptr ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_fun_as_value ( hawk_t * hawk , const hawk_oocs_t * name , const hawk_loc_t * xloc , hawk_fun_t * funptr )
2019-12-13 04:29:58 +00:00
{
hawk_nde_fun_t * nde ;
/* create the node for the literal */
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_fun_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
nde - > type = HAWK_NDE_FUN ;
nde - > loc = * xloc ;
nde - > name . ptr = name - > ptr ;
nde - > name . len = name - > len ;
nde - > funptr = funptr ;
return ( hawk_nde_t * ) nde ;
}
# endif
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_ident_noseg ( hawk_t * hawk , const hawk_loc_t * xloc , const hawk_oocs_t * name )
2019-12-13 04:29:58 +00:00
{
hawk_fnc_t * fnc ;
hawk_oow_t idxa ;
hawk_nde_t * nde = HAWK_NULL ;
/* check if name is an intrinsic function name */
2020-04-16 03:42:30 +00:00
fnc = hawk_findfncwithoocs ( hawk , name ) ;
2019-12-13 04:29:58 +00:00
if ( fnc )
{
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) | | fnc - > dfl0 )
2019-12-13 04:29:58 +00:00
{
if ( fnc - > spec . arg . min > fnc - > spec . arg . max )
{
/* this intrinsic function is located in the specificed module.
2024-04-28 19:15:17 +09:00
* convert the function call to a module call . i do this to
* exclude some instrinsic functions from the main engine .
2019-12-13 04:29:58 +00:00
* e . g ) sin - > math : : sin
2024-04-28 19:15:17 +09:00
* cos - > math : : cos
2019-12-13 04:29:58 +00:00
*/
hawk_oocs_t segs [ 2 ] ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( fnc - > spec . arg . spec ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
segs [ 0 ] . ptr = ( hawk_ooch_t * ) fnc - > spec . arg . spec ;
segs [ 0 ] . len = hawk_count_oocstr ( fnc - > spec . arg . spec ) ;
segs [ 1 ] = * name ;
2022-06-03 05:20:32 +00:00
return parse_primary_ident_segs ( hawk , xloc , name , segs , 2 ) ;
2019-12-13 04:29:58 +00:00
}
/* fnc->dfl0 means that the function can be called without ().
* i . e . length */
2020-04-16 03:42:30 +00:00
nde = parse_fncall ( hawk , name , fnc , xloc , ( ( ! MATCH ( hawk , TOK_LPAREN ) & & fnc - > dfl0 ) ? FNCALL_FLAG_NOARG : 0 ) ) ;
2019-12-13 04:29:58 +00:00
}
else
{
/* an intrinsic function should be in the form of the function call */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
}
}
/* now we know that name is a normal identifier. */
2024-04-28 19:15:17 +09:00
else if ( MATCH ( hawk , TOK_LBRACK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
nde = parse_hashidx ( hawk , name , xloc ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( ( idxa = hawk_arr_rsearch ( hawk - > parse . lcls , HAWK_ARR_SIZE ( hawk - > parse . lcls ) , name - > ptr , name - > len ) ) ! = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
/* local variable */
2020-04-16 03:42:30 +00:00
nde = parse_variable ( hawk , xloc , HAWK_NDE_LCL , name , idxa ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( ( idxa = hawk_arr_search ( hawk - > parse . params , 0 , name - > ptr , name - > len ) ) ! = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
/* parameter */
2020-04-16 03:42:30 +00:00
nde = parse_variable ( hawk , xloc , HAWK_NDE_ARG , name , idxa ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else if ( ( idxa = get_global ( hawk , name ) ) ! = HAWK_ARR_NIL )
2019-12-13 04:29:58 +00:00
{
/* global variable */
2020-04-16 03:42:30 +00:00
nde = parse_variable ( hawk , xloc , HAWK_NDE_GBL , name , idxa ) ;
2019-12-13 04:29:58 +00:00
}
else
{
int fntype ;
hawk_fun_t * funptr = HAWK_NULL ;
2020-04-16 03:42:30 +00:00
fntype = isfunname ( hawk , name , & funptr ) ;
2019-12-13 04:29:58 +00:00
if ( fntype )
{
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( fntype = = FNTYPE_FUN ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
/* must be a function name */
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk_htb_search ( hawk - > parse . named , name - > ptr , name - > len ) = = HAWK_NULL ) ;
nde = parse_fncall ( hawk , name , HAWK_NULL , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-01-03 10:22:23 +00:00
/* function name appeared without (). used as a value without invocation */
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2020-04-16 03:42:30 +00:00
nde = parse_fun_as_value ( hawk , name , xloc , funptr ) ;
2019-12-13 04:29:58 +00:00
# else
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFUNRED , HAWK_T ( " function '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
# endif
}
}
2020-04-16 03:42:30 +00:00
/*else if (hawk->opt.trait & HAWK_IMPLICIT) */
else if ( hawk - > parse . pragma . trait & HAWK_IMPLICIT )
2019-12-13 04:29:58 +00:00
{
/* if the name is followed by ( without spaces,
2024-04-28 19:15:17 +09:00
* it ' s considered a function call though the name
2019-12-13 04:29:58 +00:00
* has not been seen / resolved .
2024-04-28 19:15:17 +09:00
*
2019-12-13 04:29:58 +00:00
* it is a function call so long as it ' s followed
* by a left parenthesis if concatenation by blanks
* is not allowed .
*/
int is_fncall_var = 0 ;
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_LPAREN ) & &
( ! ( hawk - > opt . trait & HAWK_BLANKCONCAT ) | |
( hawk - > tok . loc . line = = xloc - > line & &
2020-04-16 03:42:30 +00:00
hawk - > tok . loc . colm = = xloc - > colm + name - > len ) ) )
2019-12-13 04:29:58 +00:00
{
/* it is a function call to an undefined function yet */
2020-04-16 03:42:30 +00:00
if ( hawk_htb_search ( hawk - > parse . named , name - > ptr , name - > len ) ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
/* the function call conflicts with a named variable */
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2019-12-13 04:29:58 +00:00
is_fncall_var = 1 ;
goto named_var ;
# else
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EVARRED , HAWK_T ( " variable '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
# endif
}
else
{
2020-04-16 03:42:30 +00:00
nde = parse_fncall ( hawk , name , HAWK_NULL , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
}
else
{
hawk_nde_var_t * tmp ;
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2019-12-13 04:29:58 +00:00
named_var :
# endif
/* if there is a space between the name and the left parenthesis
* while the name is not resolved to anything , we treat the space
2024-04-28 19:15:17 +09:00
* as concatention by blanks . so we handle the name as a named
2019-12-13 04:29:58 +00:00
* variable . */
2020-04-16 03:42:30 +00:00
tmp = ( hawk_nde_var_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * tmp ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! tmp ) ) ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
else
{
2024-04-28 19:15:17 +09:00
/* collect unique instances of a named variable
2019-12-13 04:29:58 +00:00
* for reference */
2020-04-16 03:42:30 +00:00
if ( hawk_htb_upsert ( hawk - > parse . named , name - > ptr , name - > len , HAWK_NULL , 0 ) = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
hawk_freemem ( hawk , tmp ) ;
2019-12-13 04:29:58 +00:00
}
else
{
tmp - > type = HAWK_NDE_NAMED ;
tmp - > loc = * xloc ;
tmp - > id . name . ptr = name - > ptr ;
tmp - > id . name . len = name - > len ;
tmp - > id . idxa = ( hawk_oow_t ) - 1 ;
tmp - > idx = HAWK_NULL ;
nde = ( hawk_nde_t * ) tmp ;
2020-03-25 06:22:25 +00:00
# if defined(HAWK_ENABLE_FUN_AS_VALUE)
2024-04-28 19:15:17 +09:00
if ( is_fncall_var )
2020-04-16 03:42:30 +00:00
nde = parse_fncall ( hawk , ( const hawk_oocs_t * ) nde , HAWK_NULL , xloc , FNCALL_FLAG_VAR ) ;
2019-12-13 04:29:58 +00:00
# endif
}
}
}
}
else
{
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* it is a function call as the name is followed
2019-12-13 04:29:58 +00:00
* by ( with / without spaces and implicit variables are disabled . */
2020-04-16 03:42:30 +00:00
nde = parse_fncall ( hawk , name , HAWK_NULL , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
else
{
/* undefined variable */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
}
}
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_ident_segs ( hawk_t * hawk , const hawk_loc_t * xloc , const hawk_oocs_t * full , const hawk_oocs_t segs [ ] , int nsegs )
2019-12-13 04:29:58 +00:00
{
/* parse xxx::yyy */
hawk_nde_t * nde = HAWK_NULL ;
hawk_mod_t * mod ;
hawk_mod_sym_t sym ;
hawk_fnc_t fnc ;
2020-04-16 03:42:30 +00:00
mod = query_module ( hawk , segs , nsegs , & sym ) ;
2020-12-18 14:43:30 +00:00
if ( ! mod )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
else
{
switch ( sym . type )
{
case HAWK_MOD_FNC :
2020-12-18 14:43:30 +00:00
if ( ( hawk - > opt . trait & sym . u . fnc_ . trait ) ! = sym . u . fnc_ . trait )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , full - > len , full - > ptr ) ;
2019-12-13 04:29:58 +00:00
break ;
}
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LPAREN ) )
2019-12-13 04:29:58 +00:00
{
HAWK_MEMSET ( & fnc , 0 , HAWK_SIZEOF ( fnc ) ) ;
2024-04-28 19:15:17 +09:00
fnc . name . ptr = full - > ptr ;
2019-12-13 04:29:58 +00:00
fnc . name . len = full - > len ;
2020-12-18 14:43:30 +00:00
fnc . spec = sym . u . fnc_ ;
2019-12-13 04:29:58 +00:00
fnc . mod = mod ;
2020-12-18 14:43:30 +00:00
nde = parse_fncall ( hawk , full , & fnc , xloc , 0 ) ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELPAREN , FMT_ELPAREN , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
}
break ;
case HAWK_MOD_INT :
2020-12-18 14:43:30 +00:00
if ( ( hawk - > opt . trait & sym . u . int_ . trait ) ! = sym . u . int_ . trait )
{
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , full - > len , full - > ptr ) ;
break ;
}
nde = new_int_node ( hawk , sym . u . int_ . val , xloc ) ;
2019-12-13 04:29:58 +00:00
/* i don't remember the symbol in the original form */
break ;
case HAWK_MOD_FLT :
2020-12-18 14:43:30 +00:00
if ( ( hawk - > opt . trait & sym . u . flt_ . trait ) ! = sym . u . flt_ . trait )
{
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , full - > len , full - > ptr ) ;
break ;
}
nde = new_flt_node ( hawk , sym . u . flt_ . val , xloc ) ;
2019-12-13 04:29:58 +00:00
/* i don't remember the symbol in the original form */
break ;
default :
/* TODO: support MOD_VAR */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , full - > len , full - > ptr ) ;
2019-12-13 04:29:58 +00:00
break ;
}
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_primary_ident ( hawk_t * hawk , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde = HAWK_NULL ;
hawk_oocs_t name [ 2 ] ; /* TODO: support more than 2 segments??? */
int nsegs ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( MATCH ( hawk , TOK_IDENT ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
nsegs = dup_ident_and_get_next ( hawk , xloc , name , HAWK_COUNTOF ( name ) ) ;
2019-12-13 04:29:58 +00:00
if ( nsegs < = - 1 ) return HAWK_NULL ;
if ( nsegs < = 1 )
{
2020-04-16 03:42:30 +00:00
nde = parse_primary_ident_noseg ( hawk , xloc , & name [ 0 ] ) ;
if ( ! nde ) hawk_freemem ( hawk , name [ 0 ] . ptr ) ;
2019-12-13 04:29:58 +00:00
}
else
{
hawk_oocs_t full ; /* full name including :: */
hawk_oow_t capa ;
int i ;
for ( capa = 0 , i = 0 ; i < nsegs ; i + + ) capa + = name [ i ] . len + 2 ; /* +2 for :: */
2020-04-16 03:42:30 +00:00
full . ptr = hawk_allocmem ( hawk , HAWK_SIZEOF ( * full . ptr ) * ( capa + 1 ) ) ;
2019-12-13 04:29:58 +00:00
if ( full . ptr )
{
capa = hawk_copy_oochars_to_oocstr_unlimited ( & full . ptr [ 0 ] , name [ 0 ] . ptr , name [ 0 ] . len ) ;
2024-04-28 19:15:17 +09:00
for ( i = 1 ; i < nsegs ; i + + )
2019-12-13 04:29:58 +00:00
{
capa + = hawk_copy_oocstr_unlimited ( & full . ptr [ capa ] , HAWK_T ( " :: " ) ) ;
capa + = hawk_copy_oochars_to_oocstr_unlimited ( & full . ptr [ capa ] , name [ i ] . ptr , name [ i ] . len ) ;
}
full . ptr [ capa ] = HAWK_T ( ' \0 ' ) ;
full . len = capa ;
2020-04-16 03:42:30 +00:00
nde = parse_primary_ident_segs ( hawk , xloc , & full , name , nsegs ) ;
2024-04-28 19:15:17 +09:00
if ( ! nde | | nde - > type ! = HAWK_NDE_FNCALL_FNC )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* the FNC node takes the full name but other
2019-12-13 04:29:58 +00:00
* nodes don ' t . so i need to free it . i know it ' s ugly . */
2020-04-16 03:42:30 +00:00
hawk_freemem ( hawk , full . ptr ) ;
2019-12-13 04:29:58 +00:00
}
}
else
{
/* error number is set in hawk_allocmem */
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
}
/* i don't need the name segments */
2020-04-16 03:42:30 +00:00
while ( nsegs > 0 ) hawk_freemem ( hawk , name [ - - nsegs ] . ptr ) ;
2019-12-13 04:29:58 +00:00
}
return nde ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_hashidx ( hawk_t * hawk , const hawk_oocs_t * name , const hawk_loc_t * xloc )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * idx , * tmp , * last ;
hawk_nde_var_t * nde ;
hawk_oow_t idxa ;
idx = HAWK_NULL ;
last = HAWK_NULL ;
2020-03-30 08:54:37 +00:00
# if defined(HAWK_ENABLE_GC)
more_idx :
# endif
2019-12-13 04:29:58 +00:00
do
{
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( idx ) hawk_clrpt ( hawk , idx ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
{
hawk_loc_t eloc ;
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
tmp = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! tmp ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( idx ) hawk_clrpt ( hawk , idx ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-03-30 08:54:37 +00:00
if ( ! idx )
2019-12-13 04:29:58 +00:00
{
2020-03-30 08:54:37 +00:00
/* this is the first item */
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( last = = HAWK_NULL ) ;
2020-03-30 08:54:37 +00:00
idx = tmp ;
last = tmp ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-03-30 08:54:37 +00:00
/* not the first item. append it */
2019-12-13 04:29:58 +00:00
last - > next = tmp ;
last = tmp ;
}
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_COMMA ) ) ;
2019-12-13 04:29:58 +00:00
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( idx ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_RBRACK ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , idx ) ;
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ERBRACK , FMT_ERBRACK , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2024-04-28 19:15:17 +09:00
if ( get_token ( hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , idx ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-03-30 08:54:37 +00:00
# if defined(HAWK_ENABLE_GC)
2020-04-16 03:42:30 +00:00
if ( MATCH ( hawk , TOK_LBRACK ) )
2020-03-30 08:54:37 +00:00
{
2024-04-28 19:15:17 +09:00
/* additional index - a[10][20] ...
2020-03-30 08:54:37 +00:00
* use the NULL node as a splitter */
2020-04-16 03:42:30 +00:00
tmp = ( hawk_nde_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * tmp ) ) ;
2020-03-30 08:54:37 +00:00
if ( HAWK_UNLIKELY ( ! tmp ) )
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , idx ) ;
ADJERR_LOC ( hawk , xloc ) ;
2020-03-30 08:54:37 +00:00
return HAWK_NULL ;
}
tmp - > type = HAWK_NDE_NULL ;
HAWK_ASSERT ( idx ! = HAWK_NULL ) ;
HAWK_ASSERT ( last ! = HAWK_NULL ) ;
last - > next = tmp ;
last = tmp ;
goto more_idx ;
}
# endif
2020-04-16 03:42:30 +00:00
nde = ( hawk_nde_var_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * nde ) ) ;
2024-04-28 19:15:17 +09:00
if ( HAWK_UNLIKELY ( ! nde ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , idx ) ;
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
/* search the local variable list */
2020-04-16 03:42:30 +00:00
idxa = hawk_arr_rsearch ( hawk - > parse . lcls , HAWK_ARR_SIZE ( hawk - > parse . lcls ) , name - > ptr , name - > len ) ;
2019-12-13 04:29:58 +00:00
if ( idxa ! = HAWK_ARR_NIL )
{
nde - > type = HAWK_NDE_LCLIDX ;
nde - > loc = * xloc ;
/*nde->id.name = HAWK_NULL; */
nde - > id . name . ptr = name - > ptr ;
nde - > id . name . len = name - > len ;
nde - > id . idxa = idxa ;
nde - > idx = idx ;
return ( hawk_nde_t * ) nde ;
}
/* search the parameter name list */
2020-04-16 03:42:30 +00:00
idxa = hawk_arr_search ( hawk - > parse . params , 0 , name - > ptr , name - > len ) ;
2019-12-13 04:29:58 +00:00
if ( idxa ! = HAWK_ARR_NIL )
{
nde - > type = HAWK_NDE_ARGIDX ;
nde - > loc = * xloc ;
/*nde->id.name = HAWK_NULL; */
nde - > id . name . ptr = name - > ptr ;
nde - > id . name . len = name - > len ;
nde - > id . idxa = idxa ;
nde - > idx = idx ;
return ( hawk_nde_t * ) nde ;
}
/* gets the global variable index */
2020-04-16 03:42:30 +00:00
idxa = get_global ( hawk , name ) ;
2019-12-13 04:29:58 +00:00
if ( idxa ! = HAWK_ARR_NIL )
{
nde - > type = HAWK_NDE_GBLIDX ;
nde - > loc = * xloc ;
/*nde->id.name = HAWK_NULL;*/
nde - > id . name . ptr = name - > ptr ;
nde - > id . name . len = name - > len ;
nde - > id . idxa = idxa ;
nde - > idx = idx ;
return ( hawk_nde_t * ) nde ;
}
2020-04-16 03:42:30 +00:00
/*if (hawk->opt.trait & HAWK_IMPLICIT) */
if ( hawk - > parse . pragma . trait & HAWK_IMPLICIT )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
int fnname = isfnname ( hawk , name ) ;
2019-12-13 04:29:58 +00:00
switch ( fnname )
{
case FNTYPE_FNC :
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFNCRED , HAWK_T ( " intrinsic function '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
goto exit_func ;
case FNTYPE_FUN :
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EFUNRED , HAWK_T ( " function '%.*js' redefined " ) , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
goto exit_func ;
}
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( fnname = = 0 ) ;
2019-12-13 04:29:58 +00:00
nde - > type = HAWK_NDE_NAMEDIDX ;
nde - > loc = * xloc ;
nde - > id . name . ptr = name - > ptr ;
nde - > id . name . len = name - > len ;
nde - > id . idxa = ( hawk_oow_t ) - 1 ;
nde - > idx = idx ;
return ( hawk_nde_t * ) nde ;
}
/* undefined variable */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , xloc , HAWK_EUNDEF , FMT_EUNDEF , name - > len , name - > ptr ) ;
2019-12-13 04:29:58 +00:00
exit_func :
2020-04-16 03:42:30 +00:00
hawk_clrpt ( hawk , idx ) ;
hawk_freemem ( hawk , nde ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static hawk_nde_t * parse_fncall ( hawk_t * hawk , const hawk_oocs_t * name , hawk_fnc_t * fnc , const hawk_loc_t * xloc , int flags )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * head , * curr , * nde ;
hawk_nde_fncall_t * call ;
hawk_oow_t nargs ;
hawk_loc_t eloc ;
head = curr = HAWK_NULL ;
call = HAWK_NULL ;
nargs = 0 ;
if ( flags & FNCALL_FLAG_NOARG ) goto make_node ;
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
/* no parameters to the function call */
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
/* parse function parameters */
2024-04-28 19:15:17 +09:00
while ( 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
eloc = hawk - > tok . loc ;
nde = parse_expr_withdc ( hawk , & eloc ) ;
2019-12-13 04:29:58 +00:00
if ( ! nde ) goto oops ;
if ( ! head ) head = nde ;
else curr - > next = nde ;
curr = nde ;
nargs + + ;
2024-04-28 19:15:17 +09:00
if ( MATCH ( hawk , TOK_RPAREN ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
break ;
}
2024-04-28 19:15:17 +09:00
if ( ! MATCH ( hawk , TOK_COMMA ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ECOMMA , FMT_ECOMMA , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
do
{
2020-04-16 03:42:30 +00:00
if ( get_token ( hawk ) < = - 1 ) goto oops ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
while ( MATCH ( hawk , TOK_NEWLINE ) ) ;
2019-12-13 04:29:58 +00:00
}
}
make_node :
2020-04-16 03:42:30 +00:00
call = ( hawk_nde_fncall_t * ) hawk_callocmem ( hawk , HAWK_SIZEOF ( * call ) ) ;
2024-05-02 22:36:50 +09:00
if ( HAWK_UNLIKELY ( ! call ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
if ( flags & FNCALL_FLAG_VAR )
{
call - > type = HAWK_NDE_FNCALL_VAR ;
call - > loc = * xloc ;
call - > u . var . var = ( hawk_nde_var_t * ) name ; /* name is a pointer to a variable node */
call - > args = head ;
call - > nargs = nargs ;
}
else if ( fnc )
{
call - > type = HAWK_NDE_FNCALL_FNC ;
call - > loc = * xloc ;
call - > u . fnc . info . name . ptr = name - > ptr ;
call - > u . fnc . info . name . len = name - > len ;
call - > u . fnc . info . mod = fnc - > mod ;
call - > u . fnc . spec = fnc - > spec ;
call - > args = head ;
call - > nargs = nargs ;
if ( nargs > call - > u . fnc . spec . arg . max )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EARGTM ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
else if ( nargs < call - > u . fnc . spec . arg . min )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , xloc , HAWK_EARGTF ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
else
{
call - > type = HAWK_NDE_FNCALL_FUN ;
call - > loc = * xloc ;
2024-04-28 19:15:17 +09:00
call - > u . fun . name . ptr = name - > ptr ;
2019-12-13 04:29:58 +00:00
call - > u . fun . name . len = name - > len ;
call - > args = head ;
call - > nargs = nargs ;
2020-04-16 03:42:30 +00:00
/* store a non-builtin function call into the hawk->parse.funs table */
if ( ! hawk_htb_upsert ( hawk - > parse . funs , name - > ptr , name - > len , call , 0 ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADJERR_LOC ( hawk , xloc ) ;
2019-12-13 04:29:58 +00:00
goto oops ;
}
}
return ( hawk_nde_t * ) call ;
oops :
2020-04-16 03:42:30 +00:00
if ( call ) hawk_freemem ( hawk , call ) ;
if ( head ) hawk_clrpt ( hawk , head ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-04-16 03:42:30 +00:00
static int get_number ( hawk_t * hawk , hawk_tok_t * tok )
2019-12-13 04:29:58 +00:00
{
hawk_ooci_t c ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( HAWK_OOECS_LEN ( tok - > name ) = = 0 ) ;
2020-04-16 03:42:30 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_INT ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
c = hawk - > sio . last . c ;
2019-12-13 04:29:58 +00:00
2020-05-27 09:15:48 +00:00
if ( c = = ' 0 ' )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
2020-05-27 09:15:48 +00:00
if ( c = = ' x ' | | c = = ' X ' )
2019-12-13 04:29:58 +00:00
{
/* hexadecimal number */
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
while ( hawk_is_ooch_xdigit ( c ) ) ;
return 0 ;
}
2020-05-27 09:15:48 +00:00
else if ( c = = ' b ' | | c = = ' B ' )
2019-12-13 04:29:58 +00:00
{
/* binary number */
do
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
}
2020-05-27 09:15:48 +00:00
while ( c = = ' 0 ' | | c = = ' 1 ' ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
else if ( c ! = ' . ' )
{
/* octal number */
2020-05-27 09:15:48 +00:00
while ( c > = ' 0 ' & & c < = ' 7 ' )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
2020-05-27 09:15:48 +00:00
if ( c = = ' 8 ' | | c = = ' 9 ' )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_ELXCHR , HAWK_T ( " invalid digit '%jc' " ) , ( hawk_ooch_t ) c ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
return 0 ;
}
}
2024-04-28 19:15:17 +09:00
while ( hawk_is_ooch_digit ( c ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
2020-05-27 09:15:48 +00:00
if ( c = = ' . ' )
2019-12-13 04:29:58 +00:00
{
/* floating-point number */
2020-04-16 03:42:30 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_FLT ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
while ( hawk_is_ooch_digit ( c ) )
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-05-27 09:15:48 +00:00
if ( c = = ' E ' | | c = = ' e ' )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_FLT ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
2020-05-27 09:15:48 +00:00
if ( c = = ' + ' | | c = = ' - ' )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
while ( hawk_is_ooch_digit ( c ) )
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
}
return 0 ;
}
2024-04-28 19:15:17 +09:00
/* i think allowing only up to 2 hexadigits is more useful though it
2020-04-16 03:42:30 +00:00
* may break compatibilty with other hawk implementations . If you want
2019-12-13 04:29:58 +00:00
* more than 2 , define HEX_DIGIT_LIMIT_FOR_X to HAWK_TYPE_MAX ( hawk_oow_t ) . */
/*#define HEX_DIGIT_LIMIT_FOR_X (HAWK_TYPE_MAX(hawk_oow_t))*/
# define HEX_DIGIT_LIMIT_FOR_X (2)
static int get_string (
2024-04-28 19:15:17 +09:00
hawk_t * hawk , hawk_ooch_t end_char ,
2019-12-13 04:29:58 +00:00
hawk_ooch_t esc_char , int keep_esc_char , int byte_only ,
hawk_oow_t preescaped , hawk_tok_t * tok )
{
hawk_ooci_t c ;
hawk_oow_t escaped = preescaped ;
hawk_oow_t digit_count = 0 ;
hawk_uint32_t c_acc = 0 ;
while ( 1 )
{
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_OOCI_EOF )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > tok . loc , HAWK_ESTRNC ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
/* nothing extra to handle byte_only */
# else
2020-11-08 17:23:25 +00:00
if ( byte_only & & c ! = ' \\ ' & & ! HAWK_BYTE_PRINTABLE ( c ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EMBSCHR , HAWK_T ( " invalid mbs character '%jc' " ) , ( hawk_ooch_t ) c ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# endif
if ( escaped = = 3 )
{
if ( c > = HAWK_T ( ' 0 ' ) & & c < = HAWK_T ( ' 7 ' ) )
{
c_acc = c_acc * 8 + c - HAWK_T ( ' 0 ' ) ;
digit_count + + ;
2024-04-28 19:15:17 +09:00
if ( digit_count > = escaped )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* should i limit the max to 0xFF/0377?
2019-12-13 04:29:58 +00:00
if ( c_acc > 0377 ) c_acc = 0377 ; */
2020-04-16 03:42:30 +00:00
ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
}
continue ;
}
else
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
}
}
else if ( escaped = = HEX_DIGIT_LIMIT_FOR_X | | escaped = = 4 | | escaped = = 8 )
{
if ( c > = HAWK_T ( ' 0 ' ) & & c < = HAWK_T ( ' 9 ' ) )
{
c_acc = c_acc * 16 + c - HAWK_T ( ' 0 ' ) ;
digit_count + + ;
2024-04-28 19:15:17 +09:00
if ( digit_count > = escaped )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
}
continue ;
}
else if ( c > = HAWK_T ( ' A ' ) & & c < = HAWK_T ( ' F ' ) )
{
c_acc = c_acc * 16 + c - HAWK_T ( ' A ' ) + 10 ;
digit_count + + ;
2024-04-28 19:15:17 +09:00
if ( digit_count > = escaped )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
}
continue ;
}
else if ( c > = HAWK_T ( ' a ' ) & & c < = HAWK_T ( ' f ' ) )
{
c_acc = c_acc * 16 + c - HAWK_T ( ' a ' ) + 10 ;
digit_count + + ;
2024-04-28 19:15:17 +09:00
if ( digit_count > = escaped )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
}
continue ;
}
else
{
2024-04-28 19:15:17 +09:00
if ( digit_count = = 0 )
2019-12-13 04:29:58 +00:00
{
2020-03-14 06:09:59 +00:00
hawk_ooch_t ec ;
ec = ( escaped = = HEX_DIGIT_LIMIT_FOR_X ) ? HAWK_T ( ' x ' ) :
( escaped = = 4 ) ? HAWK_T ( ' u ' ) : HAWK_T ( ' U ' ) ;
2019-12-13 04:29:58 +00:00
/* no valid character after the escaper.
* keep the escaper as it is . consider this input :
* \ xGG
* ' c ' is at the first G . this part is to restore the
* \ x part . since \ x is not followed by any hexadecimal
* digits , it ' s literally ' x ' */
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , ec ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
else ADD_TOKEN_UINT32 ( hawk , tok , c_acc ) ;
2019-12-13 04:29:58 +00:00
escaped = 0 ;
2020-03-14 06:09:59 +00:00
/* carray on to handle the current character */
2019-12-13 04:29:58 +00:00
}
}
2020-03-14 06:09:59 +00:00
else if ( escaped = = 99 )
2019-12-13 04:29:58 +00:00
{
2020-03-11 07:13:02 +00:00
escaped = 0 ;
if ( c = = ' \n ' ) continue ; /* backslash \r \n */
2019-12-13 04:29:58 +00:00
}
2020-03-14 06:09:59 +00:00
/* -------------------------------------- */
2020-03-11 07:13:02 +00:00
if ( escaped = = 0 )
2019-12-13 04:29:58 +00:00
{
2020-03-11 07:13:02 +00:00
if ( c = = end_char )
{
/* terminating quote */
2020-04-16 03:42:30 +00:00
/*GET_CHAR_TO (hawk, c);*/
GET_CHAR ( hawk ) ;
2020-03-11 07:13:02 +00:00
break ;
}
else if ( c = = esc_char )
{
escaped = 1 ;
continue ;
}
2020-04-16 03:42:30 +00:00
else if ( ! ( hawk - > parse . pragma . trait & HAWK_MULTILINESTR ) & & ( c = = ' \n ' | | c = = ' \r ' ) )
2020-03-11 07:13:02 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > tok . loc , HAWK_ESTRNC ) ;
2020-03-11 07:13:02 +00:00
return - 1 ;
}
2019-12-13 04:29:58 +00:00
}
2020-03-14 06:09:59 +00:00
else if ( escaped = = 1 )
2019-12-13 04:29:58 +00:00
{
2020-03-11 07:13:02 +00:00
if ( c = = ' \n ' )
{
/* line continuation - a backslash at the end of line */
escaped = 0 ;
continue ;
}
else if ( c = = ' \r ' )
{
escaped = 99 ;
continue ;
}
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_T ( ' n ' ) ) c = HAWK_T ( ' \n ' ) ;
else if ( c = = HAWK_T ( ' r ' ) ) c = HAWK_T ( ' \r ' ) ;
else if ( c = = HAWK_T ( ' t ' ) ) c = HAWK_T ( ' \t ' ) ;
else if ( c = = HAWK_T ( ' f ' ) ) c = HAWK_T ( ' \f ' ) ;
else if ( c = = HAWK_T ( ' b ' ) ) c = HAWK_T ( ' \b ' ) ;
else if ( c = = HAWK_T ( ' v ' ) ) c = HAWK_T ( ' \v ' ) ;
else if ( c = = HAWK_T ( ' a ' ) ) c = HAWK_T ( ' \a ' ) ;
2024-04-28 19:15:17 +09:00
else if ( c > = HAWK_T ( ' 0 ' ) & & c < = HAWK_T ( ' 7 ' ) & & end_char ! = HAWK_T ( ' / ' ) )
2019-12-13 04:29:58 +00:00
{
/* i don't support the octal notation for a regular expression.
* it conflicts with the backreference notation between \ 1 and \ 7 inclusive . */
escaped = 3 ;
digit_count = 1 ;
c_acc = c - HAWK_T ( ' 0 ' ) ;
continue ;
}
2024-04-28 19:15:17 +09:00
else if ( c = = HAWK_T ( ' x ' ) )
2019-12-13 04:29:58 +00:00
{
escaped = HEX_DIGIT_LIMIT_FOR_X ;
digit_count = 0 ;
c_acc = 0 ;
continue ;
}
2024-04-28 19:15:17 +09:00
else if ( ! byte_only & & c = = HAWK_T ( ' u ' ) )
2019-12-13 04:29:58 +00:00
{
/* in the MCHAR mode, the \u letter will get converted to UTF-8 sequences.
* see ADD_TOKEN_UINT32 ( ) . */
escaped = 4 ;
digit_count = 0 ;
c_acc = 0 ;
continue ;
}
2024-04-28 19:15:17 +09:00
else if ( ! byte_only & & c = = HAWK_T ( ' U ' ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* in the MCHAR mode, the \u letter will get converted to UTF-8 sequences
2019-12-13 04:29:58 +00:00
* see ADD_TOKEN_UINT32 ( ) . */
escaped = 8 ;
digit_count = 0 ;
c_acc = 0 ;
continue ;
}
2024-04-28 19:15:17 +09:00
else if ( keep_esc_char )
2019-12-13 04:29:58 +00:00
{
/* if the following character doesn't compose a proper
2024-04-28 19:15:17 +09:00
* escape sequence , keep the escape character .
* an unhandled escape sequence can be handled
* outside this function since the escape character
2019-12-13 04:29:58 +00:00
* is preserved . */
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , esc_char ) ;
2019-12-13 04:29:58 +00:00
}
escaped = 0 ;
}
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
2019-12-13 04:29:58 +00:00
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int get_rexstr ( hawk_t * hawk , hawk_tok_t * tok )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . last . c = = HAWK_T ( ' / ' ) )
2019-12-13 04:29:58 +00:00
{
/* handle an empty regular expression.
*
* this condition is met when the input is //.
* the first / has been tokenized to TOK_DIV already .
* if TOK_DIV is seen as a primary , this function is called .
* as the token buffer has been cleared by the caller and
* the token type is set to TOK_REX , this function can
* just return after reading the next character .
* see parse_primary_rex ( ) . */
2020-04-16 03:42:30 +00:00
GET_CHAR ( hawk ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
else
{
hawk_oow_t preescaped = 0 ;
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . last . c = = HAWK_T ( ' \\ ' ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* for input like /\//, this condition is met.
2019-12-13 04:29:58 +00:00
* the initial escape character is added when the
* second charater is handled in get_string ( ) */
preescaped = 1 ;
}
else
{
/* add other initial characters here as get_string()
* begins with reading the next character */
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , hawk - > sio . last . c ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
return get_string ( hawk , HAWK_T ( ' / ' ) , HAWK_T ( ' \\ ' ) , 1 , 0 , preescaped , tok ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-11-08 17:23:25 +00:00
static int get_raw_string ( hawk_t * hawk , hawk_ooch_t end_char , int byte_only , hawk_tok_t * tok )
2019-12-13 04:29:58 +00:00
{
hawk_ooci_t c ;
while ( 1 )
{
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_OOCI_EOF )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & hawk - > tok . loc , HAWK_ESTRNC ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# if defined(HAWK_OOCH_IS_BCH)
/* nothing extra to handle byte_only */
# else
2020-11-08 17:23:25 +00:00
if ( byte_only & & c ! = ' \\ ' & & ! HAWK_BYTE_PRINTABLE ( c ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EMBSCHR , HAWK_T ( " invalid mbs character '%jc' " ) , ( hawk_ooch_t ) c ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
# endif
2020-11-08 17:23:25 +00:00
if ( c = = end_char )
2019-12-13 04:29:58 +00:00
{
/* terminating quote */
2020-04-16 03:42:30 +00:00
GET_CHAR ( hawk ) ;
2019-12-13 04:29:58 +00:00
break ;
}
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
2019-12-13 04:29:58 +00:00
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int skip_spaces ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_ooci_t c = hawk - > sio . last . c ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_NEWLINE )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
while ( c ! = HAWK_T ( ' \n ' ) & & hawk_is_ooch_space ( c ) )
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_T ( ' \\ ' ) )
{
hawk_sio_lxc_t bs ;
hawk_sio_lxc_t cr ;
int hascr = 0 ;
2020-04-16 03:42:30 +00:00
bs = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
if ( c = = HAWK_T ( ' \r ' ) )
2019-12-13 04:29:58 +00:00
{
hascr = 1 ;
2020-04-16 03:42:30 +00:00
cr = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
if ( c = = HAWK_T ( ' \n ' ) )
{
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
continue ;
}
else
{
/* push back the last character */
2020-04-16 03:42:30 +00:00
unget_char ( hawk , & hawk - > sio . last ) ;
2019-12-13 04:29:58 +00:00
/* push CR if any */
2020-04-16 03:42:30 +00:00
if ( hascr ) unget_char ( hawk , & cr ) ;
2019-12-13 04:29:58 +00:00
/* restore the orginal backslash */
2020-04-16 03:42:30 +00:00
hawk - > sio . last = bs ;
2019-12-13 04:29:58 +00:00
}
}
break ;
}
while ( 1 ) ;
}
else
{
2020-04-16 03:42:30 +00:00
while ( hawk_is_ooch_space ( c ) ) GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int skip_comment ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_ooci_t c = hawk - > sio . last . c ;
2019-12-13 04:29:58 +00:00
hawk_sio_lxc_t lc ;
if ( c = = HAWK_T ( ' # ' ) )
{
/* skip up to \n */
2020-04-16 03:42:30 +00:00
do { GET_CHAR_TO ( hawk , c ) ; }
2019-12-13 04:29:58 +00:00
while ( c ! = HAWK_T ( ' \n ' ) & & c ! = HAWK_OOCI_EOF ) ;
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_NEWLINE ) ) GET_CHAR ( hawk ) ;
2019-12-13 04:29:58 +00:00
return 1 ; /* comment by # */
}
/* handle c-style comment */
if ( c ! = HAWK_T ( ' / ' ) ) return 0 ; /* not a comment */
/* save the last character */
2020-04-16 03:42:30 +00:00
lc = hawk - > sio . last ;
2019-12-13 04:29:58 +00:00
/* read a new character */
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( c = = HAWK_T ( ' * ' ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_OOCI_EOF )
{
hawk_loc_t loc ;
2020-04-16 03:42:30 +00:00
loc . line = hawk - > sio . inp - > line ;
loc . colm = hawk - > sio . inp - > colm ;
loc . file = hawk - > sio . inp - > path ;
hawk_seterrnum ( hawk , & loc , HAWK_ECMTNC ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2024-04-28 19:15:17 +09:00
if ( c = = HAWK_T ( ' * ' ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
if ( c = = HAWK_OOCI_EOF )
{
hawk_loc_t loc ;
2020-04-16 03:42:30 +00:00
loc . line = hawk - > sio . inp - > line ;
loc . colm = hawk - > sio . inp - > colm ;
loc . file = hawk - > sio . inp - > path ;
hawk_seterrnum ( hawk , & loc , HAWK_ECMTNC ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2024-04-28 19:15:17 +09:00
if ( c = = HAWK_T ( ' / ' ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
/*GET_CHAR_TO (hawk, c);*/
GET_CHAR ( hawk ) ;
2019-12-13 04:29:58 +00:00
break ;
}
}
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
while ( 1 ) ;
return 1 ; /* c-style comment */
}
/* unget '*' */
2020-04-16 03:42:30 +00:00
unget_char ( hawk , & hawk - > sio . last ) ;
2019-12-13 04:29:58 +00:00
/* restore the previous state */
2020-04-16 03:42:30 +00:00
hawk - > sio . last = lc ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int get_symbols ( hawk_t * hawk , hawk_ooci_t c , hawk_tok_t * tok )
2019-12-13 04:29:58 +00:00
{
struct ops_t
{
const hawk_ooch_t * str ;
hawk_oow_t len ;
int tid ;
int trait ;
} ;
2024-04-28 19:15:17 +09:00
static struct ops_t ops [ ] =
2019-12-13 04:29:58 +00:00
{
{ HAWK_T ( " === " ) , 3 , TOK_TEQ , 0 } ,
{ HAWK_T ( " == " ) , 2 , TOK_EQ , 0 } ,
{ HAWK_T ( " = " ) , 1 , TOK_ASSN , 0 } ,
{ HAWK_T ( " !== " ) , 3 , TOK_TNE , 0 } ,
{ HAWK_T ( " != " ) , 2 , TOK_NE , 0 } ,
{ HAWK_T ( " !~ " ) , 2 , TOK_NM , 0 } ,
{ HAWK_T ( " ! " ) , 1 , TOK_LNOT , 0 } ,
{ HAWK_T ( " >>= " ) , 3 , TOK_RS_ASSN , 0 } ,
{ HAWK_T ( " >> " ) , 2 , TOK_RS , 0 } ,
{ HAWK_T ( " >= " ) , 2 , TOK_GE , 0 } ,
{ HAWK_T ( " > " ) , 1 , TOK_GT , 0 } ,
{ HAWK_T ( " <<= " ) , 3 , TOK_LS_ASSN , 0 } ,
{ HAWK_T ( " << " ) , 2 , TOK_LS , 0 } ,
{ HAWK_T ( " <= " ) , 2 , TOK_LE , 0 } ,
{ HAWK_T ( " < " ) , 1 , TOK_LT , 0 } ,
{ HAWK_T ( " || " ) , 2 , TOK_LOR , 0 } ,
{ HAWK_T ( " |= " ) , 2 , TOK_BOR_ASSN , 0 } ,
{ HAWK_T ( " | " ) , 1 , TOK_BOR , 0 } ,
{ HAWK_T ( " && " ) , 2 , TOK_LAND , 0 } ,
{ HAWK_T ( " &= " ) , 2 , TOK_BAND_ASSN , 0 } ,
{ HAWK_T ( " & " ) , 1 , TOK_BAND , 0 } ,
{ HAWK_T ( " ^^= " ) , 3 , TOK_BXOR_ASSN , 0 } ,
{ HAWK_T ( " ^^ " ) , 2 , TOK_BXOR , 0 } ,
{ HAWK_T ( " ^= " ) , 2 , TOK_EXP_ASSN , 0 } ,
{ HAWK_T ( " ^ " ) , 1 , TOK_EXP , 0 } ,
{ HAWK_T ( " ++ " ) , 2 , TOK_PLUSPLUS , 0 } ,
{ HAWK_T ( " += " ) , 2 , TOK_PLUS_ASSN , 0 } ,
{ HAWK_T ( " + " ) , 1 , TOK_PLUS , 0 } ,
{ HAWK_T ( " -- " ) , 2 , TOK_MINUSMINUS , 0 } ,
{ HAWK_T ( " -= " ) , 2 , TOK_MINUS_ASSN , 0 } ,
{ HAWK_T ( " - " ) , 1 , TOK_MINUS , 0 } ,
{ HAWK_T ( " **= " ) , 3 , TOK_EXP_ASSN , 0 } ,
{ HAWK_T ( " ** " ) , 2 , TOK_EXP , 0 } ,
{ HAWK_T ( " *= " ) , 2 , TOK_MUL_ASSN , 0 } ,
{ HAWK_T ( " * " ) , 1 , TOK_MUL , 0 } ,
{ HAWK_T ( " /= " ) , 2 , TOK_DIV_ASSN , 0 } ,
{ HAWK_T ( " / " ) , 1 , TOK_DIV , 0 } ,
{ HAWK_T ( " \\ = " ) , 2 , TOK_IDIV_ASSN , 0 } ,
{ HAWK_T ( " \\ " ) , 1 , TOK_IDIV , 0 } ,
{ HAWK_T ( " %%= " ) , 3 , TOK_CONCAT_ASSN , 0 } ,
{ HAWK_T ( " %% " ) , 2 , TOK_CONCAT , 0 } ,
{ HAWK_T ( " %= " ) , 2 , TOK_MOD_ASSN , 0 } ,
{ HAWK_T ( " % " ) , 1 , TOK_MOD , 0 } ,
2020-03-04 09:54:38 +00:00
{ HAWK_T ( " ~ " ) , 1 , TOK_TILDE , 0 } ,
2019-12-13 04:29:58 +00:00
{ HAWK_T ( " ( " ) , 1 , TOK_LPAREN , 0 } ,
{ HAWK_T ( " ) " ) , 1 , TOK_RPAREN , 0 } ,
{ HAWK_T ( " { " ) , 1 , TOK_LBRACE , 0 } ,
{ HAWK_T ( " } " ) , 1 , TOK_RBRACE , 0 } ,
{ HAWK_T ( " [ " ) , 1 , TOK_LBRACK , 0 } ,
{ HAWK_T ( " ] " ) , 1 , TOK_RBRACK , 0 } ,
{ HAWK_T ( " $ " ) , 1 , TOK_DOLLAR , 0 } ,
{ HAWK_T ( " , " ) , 1 , TOK_COMMA , 0 } ,
{ HAWK_T ( " ; " ) , 1 , TOK_SEMICOLON , 0 } ,
{ HAWK_T ( " :: " ) , 2 , TOK_DBLCOLON , 0 } ,
{ HAWK_T ( " : " ) , 1 , TOK_COLON , 0 } ,
{ HAWK_T ( " ? " ) , 1 , TOK_QUEST , 0 } ,
2024-05-02 22:36:50 +09:00
{ HAWK_T ( " ... " ) , 3 , TOK_ELLIPSIS , 0 } ,
{ HAWK_T ( " .. " ) , 2 , TOK_DBLPERIOD , 0 } ,
{ HAWK_T ( " . " ) , 1 , TOK_PERIOD , 0 } ,
2019-12-13 04:29:58 +00:00
{ HAWK_NULL , 0 , 0 , 0 }
} ;
struct ops_t * p ;
int idx = 0 ;
/* note that the loop below is not generaic enough.
* you must keep the operators strings in a particular order */
for ( p = ops ; p - > str ! = HAWK_NULL ; )
{
2020-04-16 03:42:30 +00:00
if ( p - > trait = = 0 | | ( hawk - > opt . trait & p - > trait ) )
2019-12-13 04:29:58 +00:00
{
if ( p - > str [ idx ] = = HAWK_T ( ' \0 ' ) )
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_STR ( hawk , tok , p - > str , p - > len ) ;
SET_TOKEN_TYPE ( hawk , tok , p - > tid ) ;
2019-12-13 04:29:58 +00:00
return 1 ;
}
if ( c = = p - > str [ idx ] )
{
idx + + ;
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
continue ;
}
}
p + + ;
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int get_token_into ( hawk_t * hawk , hawk_tok_t * tok )
2019-12-13 04:29:58 +00:00
{
hawk_ooci_t c ;
int n ;
int skip_semicolon_after_include = 0 ;
retry :
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( skip_spaces ( hawk ) < = - 1 ) return - 1 ;
if ( ( n = skip_comment ( hawk ) ) < = - 1 ) return - 1 ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
while ( n > = 1 ) ;
hawk_ooecs_clear ( tok - > name ) ;
2020-12-01 10:22:17 +00:00
tok - > flags = 0 ;
2020-04-16 03:42:30 +00:00
tok - > loc . file = hawk - > sio . last . file ;
tok - > loc . line = hawk - > sio . last . line ;
tok - > loc . colm = hawk - > sio . last . colm ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
c = hawk - > sio . last . c ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
if ( c = = HAWK_OOCI_EOF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
n = end_include ( hawk ) ;
2019-12-13 04:29:58 +00:00
if ( n < = - 1 ) return - 1 ;
2024-04-28 19:15:17 +09:00
if ( n > = 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
/*hawk->sio.last = hawk->sio.inp->last;*/
2019-12-13 04:29:58 +00:00
/* mark that i'm retrying after end of an included file */
2024-04-28 19:15:17 +09:00
skip_semicolon_after_include = 1 ;
2019-12-13 04:29:58 +00:00
goto retry ;
}
2020-04-16 03:42:30 +00:00
ADD_TOKEN_STR ( hawk , tok , HAWK_T ( " <EOF> " ) , 5 ) ;
SET_TOKEN_TYPE ( hawk , tok , TOK_EOF ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else if ( c = = HAWK_T ( ' \n ' ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
/*ADD_TOKEN_CHAR (hawk, tok, HAWK_T('\n'));*/
ADD_TOKEN_STR ( hawk , tok , HAWK_T ( " <NL> " ) , 4 ) ;
SET_TOKEN_TYPE ( hawk , tok , TOK_NEWLINE ) ;
GET_CHAR ( hawk ) ;
2019-12-13 04:29:58 +00:00
}
else if ( hawk_is_ooch_digit ( c ) /*|| c == HAWK_T('.')*/ )
{
2020-05-04 07:14:32 +00:00
if ( get_number ( hawk , tok ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
else if ( c = = HAWK_T ( ' . ' ) )
{
hawk_sio_lxc_t lc ;
2020-04-16 03:42:30 +00:00
lc = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
unget_char ( hawk , & hawk - > sio . last ) ;
hawk - > sio . last = lc ;
2019-12-13 04:29:58 +00:00
if ( hawk_is_ooch_digit ( c ) )
{
/* for a token such as .123 */
2020-04-16 03:42:30 +00:00
if ( get_number ( hawk , tok ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
c = HAWK_T ( ' . ' ) ;
goto try_get_symbols ;
}
}
else if ( c = = HAWK_T ( ' @ ' ) )
{
int type ;
2020-04-16 03:42:30 +00:00
GET_CHAR_TO ( hawk , c ) ;
2019-12-13 04:29:58 +00:00
2020-05-04 07:14:32 +00:00
if ( c ! = HAWK_T ( ' _ ' ) & & ! hawk_is_ooch_alpha ( c ) )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* this extended keyword is empty,
2019-12-13 04:29:58 +00:00
* not followed by a valid word */
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , & ( hawk ) - > tok . loc , HAWK_EXKWEM ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
2020-11-08 17:23:25 +00:00
if ( c = = ' B ' | | c = = ' b ' )
{
hawk_sio_lxc_t pc1 = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
if ( c = = ' R ' | | c = = ' r ' )
{
hawk_sio_lxc_t pc2 = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
if ( c = = ' \" ' )
{
/* raw byte string */
SET_TOKEN_TYPE ( hawk , tok , TOK_MBS ) ;
if ( get_raw_string ( hawk , c , 1 , tok ) < = - 1 ) return - 1 ;
}
else
{
unget_char ( hawk , & hawk - > sio . last ) ;
unget_char ( hawk , & pc2 ) ;
hawk - > sio . last = pc1 ;
c = pc1 . c ;
goto process_at_identifier ;
}
}
else if ( c = = ' \" ' )
{
2020-12-09 18:07:20 +00:00
/* @B"XXX", @b"XXX" - byte string */
2020-11-08 17:23:25 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_MBS ) ;
if ( get_string ( hawk , c , HAWK_T ( ' \\ ' ) , 0 , 1 , 0 , tok ) < = - 1 ) return - 1 ;
2024-04-28 19:15:17 +09:00
}
2020-11-08 17:23:25 +00:00
else if ( c = = ' \' ' )
{
2020-12-09 18:07:20 +00:00
/* @B'X' @b'x' - byte character */
SET_TOKEN_TYPE ( hawk , tok , TOK_BCHR ) ;
if ( get_string ( hawk , c , ' \\ ' , 0 , 1 , 0 , tok ) < = - 1 ) return - 1 ;
if ( HAWK_OOECS_LEN ( tok - > name ) ! = 1 )
{
hawk_seterrfmt ( hawk , & tok - > loc , HAWK_ELXCHR , HAWK_T ( " invalid byte-character token " ) ) ;
return - 1 ;
}
2020-11-08 17:23:25 +00:00
}
else
{
unget_char ( hawk , & hawk - > sio . last ) ;
hawk - > sio . last = pc1 ;
c = pc1 . c ;
goto process_at_identifier ;
}
}
else if ( c = = ' R ' | | c = = ' r ' )
{
hawk_sio_lxc_t pc1 = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
if ( c = = ' B ' | | c = = ' b ' )
{
hawk_sio_lxc_t pc2 = hawk - > sio . last ;
GET_CHAR_TO ( hawk , c ) ;
if ( c = = ' \" ' )
{
/* raw byte string */
SET_TOKEN_TYPE ( hawk , tok , TOK_MBS ) ;
if ( get_raw_string ( hawk , c , 1 , tok ) < = - 1 ) return - 1 ;
}
else
{
unget_char ( hawk , & hawk - > sio . last ) ;
unget_char ( hawk , & pc2 ) ;
hawk - > sio . last = pc1 ;
c = pc1 . c ;
goto process_at_identifier ;
}
}
else if ( c = = ' \" ' )
{
/* R, r - raw string */
SET_TOKEN_TYPE ( hawk , tok , TOK_STR ) ;
if ( get_raw_string ( hawk , c , 0 , tok ) < = - 1 ) return - 1 ;
}
#if 0
2024-04-28 19:15:17 +09:00
2020-11-08 17:23:25 +00:00
else if ( c = = ' \' ' )
{
/* TODO: character literal when I add a character type?? */
}
# endif
else
{
unget_char ( hawk , & hawk - > sio . last ) ;
hawk - > sio . last = pc1 ;
c = pc1 . c ;
goto process_at_identifier ;
}
}
2019-12-13 04:29:58 +00:00
else
{
2020-11-08 17:23:25 +00:00
process_at_identifier :
ADD_TOKEN_CHAR ( hawk , tok , HAWK_T ( ' @ ' ) ) ;
2019-12-13 04:29:58 +00:00
/* expect normal identifier starting with an alphabet */
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
}
2019-12-13 04:29:58 +00:00
while ( c = = HAWK_T ( ' _ ' ) | | hawk_is_ooch_alpha ( c ) | | hawk_is_ooch_digit ( c ) ) ;
2021-07-19 19:54:01 +00:00
if ( hawk_comp_oochars_bcstr ( HAWK_OOECS_PTR ( tok - > name ) , HAWK_OOECS_LEN ( tok - > name ) , " @SCRIPTNAME " , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
2020-05-04 07:14:32 +00:00
/* special parser-level word @SCRIPTNAME. substitute an actual value for it */
2022-06-16 13:31:34 +00:00
if ( HAWK_UNLIKELY ( hawk_ooecs_cpy ( tok - > name , ( tok - > loc . file ? ( const hawk_ooch_t * ) tok - > loc . file : ( const hawk_ooch_t * ) HAWK_T ( " " ) ) ) = = ( hawk_oow_t ) - 1 ) ) return - 1 ;
2020-05-04 07:14:32 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_STR ) ;
}
2021-07-19 19:54:01 +00:00
else if ( hawk_comp_oochars_bcstr ( HAWK_OOECS_PTR ( tok - > name ) , HAWK_OOECS_LEN ( tok - > name ) , " @SCRIPTLINE " , 0 ) = = 0 )
2020-05-04 07:14:32 +00:00
{
/* special parser-level word @SCRIPTLINE. subsitute an actual value for it */
if ( HAWK_UNLIKELY ( hawk_ooecs_fmt ( tok - > name , HAWK_T ( " %zu " ) , tok - > loc . line ) = = ( hawk_oow_t ) - 1 ) ) return - 1 ;
SET_TOKEN_TYPE ( hawk , tok , TOK_INT ) ;
}
else
{
type = classify_ident ( hawk , HAWK_OOECS_OOCS ( tok - > name ) ) ;
if ( type = = TOK_IDENT )
{
hawk_seterrfmt ( hawk , & hawk - > tok . loc , HAWK_EXKWNR , FMT_EXKWNR , HAWK_OOECS_LEN ( hawk - > tok . name ) , HAWK_OOECS_PTR ( hawk - > tok . name ) ) ;
return - 1 ;
}
SET_TOKEN_TYPE ( hawk , tok , type ) ;
2019-12-13 04:29:58 +00:00
}
}
}
2020-11-08 17:23:25 +00:00
else if ( c = = ' _ ' | | hawk_is_ooch_alpha ( c ) )
2019-12-13 04:29:58 +00:00
{
int type ;
/* identifier */
2024-04-28 19:15:17 +09:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
ADD_TOKEN_CHAR ( hawk , tok , c ) ;
GET_CHAR_TO ( hawk , c ) ;
2024-04-28 19:15:17 +09:00
}
2020-11-08 17:23:25 +00:00
while ( c = = ' _ ' | | hawk_is_ooch_alpha ( c ) | | hawk_is_ooch_digit ( c ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
type = classify_ident ( hawk , HAWK_OOECS_OOCS ( tok - > name ) ) ;
SET_TOKEN_TYPE ( hawk , tok , type ) ;
2019-12-13 04:29:58 +00:00
}
2020-11-08 17:23:25 +00:00
else if ( c = = ' \" ' )
2019-12-13 04:29:58 +00:00
{
/* double-quoted string */
2020-04-16 03:42:30 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_STR ) ;
2020-11-08 17:23:25 +00:00
if ( get_string ( hawk , c , ' \\ ' , 0 , 0 , 0 , tok ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
2020-12-05 18:55:05 +00:00
else if ( c = = ' \' ' )
2019-12-13 04:29:58 +00:00
{
2020-12-05 18:55:05 +00:00
SET_TOKEN_TYPE ( hawk , tok , TOK_CHAR ) ;
if ( get_string ( hawk , c , ' \\ ' , 0 , 0 , 0 , tok ) < = - 1 ) return - 1 ;
if ( HAWK_OOECS_LEN ( tok - > name ) ! = 1 )
{
hawk_seterrfmt ( hawk , & tok - > loc , HAWK_ELXCHR , HAWK_T ( " invalid character token " ) ) ;
return - 1 ;
}
2019-12-13 04:29:58 +00:00
}
else
{
try_get_symbols :
2020-04-16 03:42:30 +00:00
n = get_symbols ( hawk , c , tok ) ;
2019-12-13 04:29:58 +00:00
if ( n < = - 1 ) return - 1 ;
if ( n = = 0 )
{
/* not handled yet */
if ( c = = HAWK_T ( ' \0 ' ) )
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & tok - > loc , HAWK_ELXCHR , HAWK_T ( " invalid character ' \\ 0' " ) ) ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & tok - > loc , HAWK_ELXCHR , HAWK_T ( " invalid character '%jc' " ) , ( hawk_ooch_t ) c ) ;
2019-12-13 04:29:58 +00:00
}
return - 1 ;
}
if ( skip_semicolon_after_include & & ( tok - > type = = TOK_SEMICOLON | | tok - > type = = TOK_NEWLINE ) )
{
2024-04-28 19:15:17 +09:00
/* this handles the optional semicolon after the
2019-12-13 04:29:58 +00:00
* included file named as in @ include " file-name " ; */
skip_semicolon_after_include = 0 ;
goto retry ;
}
}
2020-04-16 03:42:30 +00:00
if ( skip_semicolon_after_include & & ! ( hawk - > opt . trait & HAWK_NEWLINE ) )
2019-12-13 04:29:58 +00:00
{
2020-01-04 04:47:41 +00:00
/* semiclon has not been skipped yet and the newline option is not set. */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , & tok - > loc , HAWK_ESCOLON , FMT_ESCOLON , HAWK_OOECS_LEN ( tok - > name ) , HAWK_OOECS_PTR ( tok - > name ) ) ;
2019-12-13 04:29:58 +00:00
return - 1 ;
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int get_token ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > ptok . type = hawk - > tok . type ;
2020-12-01 10:22:17 +00:00
hawk - > ptok . flags = hawk - > tok . flags ;
2020-04-16 03:42:30 +00:00
hawk - > ptok . loc . file = hawk - > tok . loc . file ;
hawk - > ptok . loc . line = hawk - > tok . loc . line ;
hawk - > ptok . loc . colm = hawk - > tok . loc . colm ;
hawk_ooecs_swap ( hawk - > ptok . name , hawk - > tok . name ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( HAWK_OOECS_LEN ( hawk - > ntok . name ) > 0 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > tok . type = hawk - > ntok . type ;
2020-12-01 10:22:17 +00:00
hawk - > tok . flags = hawk - > ntok . flags ;
2020-04-16 03:42:30 +00:00
hawk - > tok . loc . file = hawk - > ntok . loc . file ;
hawk - > tok . loc . line = hawk - > ntok . loc . line ;
2024-04-28 19:15:17 +09:00
hawk - > tok . loc . colm = hawk - > ntok . loc . colm ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk_ooecs_swap ( hawk - > tok . name , hawk - > ntok . name ) ;
hawk_ooecs_clear ( hawk - > ntok . name ) ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2020-12-01 10:22:17 +00:00
return get_token_into ( hawk , & hawk - > tok ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
static int preget_token ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* LIMITATION: no more than one token can be pre-read in a row
2019-12-13 04:29:58 +00:00
without consumption . */
2024-04-28 19:15:17 +09:00
2020-04-16 03:42:30 +00:00
if ( HAWK_OOECS_LEN ( hawk - > ntok . name ) > 0 )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
/* you can't read more than 1 token in advance.
*
2019-12-13 04:29:58 +00:00
* if there is a token already read in , it is just
2024-04-28 19:15:17 +09:00
* retained .
*
* parsing an expression like ' $ 0 | a ' causes this
2019-12-13 04:29:58 +00:00
* funtion to be called before get_token ( ) consumes the
2024-04-28 19:15:17 +09:00
* pre - read token .
2019-12-13 04:29:58 +00:00
*
2024-04-28 19:15:17 +09:00
* Because the expression like this
2019-12-13 04:29:58 +00:00
* print $ 1 | getline x ;
* must be parsed as
* print $ ( 1 | getline x ) ;
* preget_token ( ) is called from parse_primary ( ) .
*
* For the expression ' $ 0 | $ 2 ' ,
* 1 ) parse_primary ( ) calls parse_primary_positional ( ) if $ is encountered .
* 2 ) parse_primary_positional ( ) calls parse_primary ( ) recursively for the positional part after $ .
* 3 ) parse_primary ( ) in # 2 calls preget_token ( )
* 4 ) parse_primary ( ) in # 1 also calls preget_token ( ) .
*
* this block is reached because no token is consumed between # 3 and # 4.
*
2024-04-28 19:15:17 +09:00
* in short , it happens if getline doesn ' t doesn ' t follow | after the positional .
2019-12-13 04:29:58 +00:00
* $ 1 | $ 2
* $ 1 | abc + 20
*/
return 0 ;
}
else
{
/* if there is no token pre-read, we get a new
2024-04-28 19:15:17 +09:00
* token and place it to hawk - > ntok . */
2020-12-01 10:22:17 +00:00
return get_token_into ( hawk , & hawk - > ntok ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
static int classify_ident ( hawk_t * hawk , const hawk_oocs_t * name )
2019-12-13 04:29:58 +00:00
{
/* perform binary search */
/* declaring left, right, mid to be the int type is ok
* because we know kwtab is small enough . */
int left = 0 , right = HAWK_COUNTOF ( kwtab ) - 1 , mid ;
while ( left < = right )
{
int n ;
kwent_t * kwp ;
/*mid = (left + right) / 2;*/
mid = left + ( right - left ) / 2 ;
kwp = & kwtab [ mid ] ;
n = hawk_comp_oochars ( kwp - > name . ptr , kwp - > name . len , name - > ptr , name - > len , 0 ) ;
2024-04-28 19:15:17 +09:00
if ( n > 0 )
2019-12-13 04:29:58 +00:00
{
/* if left, right, mid were of hawk_oow_t,
2024-04-28 19:15:17 +09:00
* you would need the following line .
2019-12-13 04:29:58 +00:00
if ( mid = = 0 ) break ;
*/
right = mid - 1 ;
}
else if ( n < 0 ) left = mid + 1 ;
else
{
2020-04-16 03:42:30 +00:00
if ( ( hawk - > opt . trait & kwp - > trait ) ! = kwp - > trait ) break ;
2019-12-13 04:29:58 +00:00
return kwp - > type ;
}
}
return TOK_IDENT ;
}
2020-03-05 06:33:58 +00:00
int hawk_isvalidident ( hawk_t * hawk , const hawk_ooch_t * name )
{
hawk_ooch_t c ;
hawk_oocs_t cs ;
cs . ptr = ( hawk_ooch_t * ) name ;
if ( ( c = * name ) = = ' _ ' | | hawk_is_ooch_alpha ( c ) )
{
2024-04-28 19:15:17 +09:00
do
2020-03-05 06:33:58 +00:00
{
c = * + + name ;
2024-04-28 19:15:17 +09:00
}
2020-03-05 06:33:58 +00:00
while ( c = = ' _ ' | | hawk_is_ooch_alpha ( c ) | | hawk_is_ooch_digit ( c ) ) ;
if ( c ! = ' \0 ' ) return 0 ;
cs . len = name - cs . ptr ;
return classify_ident ( hawk , & cs ) = = TOK_IDENT ;
}
return 0 ;
}
2024-04-28 19:15:17 +09:00
struct deparse_func_t
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_t * hawk ;
2019-12-13 04:29:58 +00:00
hawk_ooch_t * tmp ;
hawk_oow_t tmp_len ;
int ret ;
} ;
2020-04-16 03:42:30 +00:00
static int deparse ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_nde_t * nde ;
hawk_chain_t * chain ;
hawk_ooch_t tmp [ HAWK_SIZEOF ( hawk_oow_t ) * 8 + 32 ] ;
struct deparse_func_t df ;
2024-04-28 19:15:17 +09:00
int n = 0 ;
2019-12-13 04:29:58 +00:00
hawk_ooi_t op ;
hawk_oocs_t kw ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > sio . outf ! = HAWK_NULL ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
HAWK_MEMSET ( & hawk - > sio . arg , 0 , HAWK_SIZEOF ( hawk - > sio . arg ) ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
op = hawk - > sio . outf ( hawk , HAWK_SIO_CMD_OPEN , & hawk - > sio . arg , HAWK_NULL , 0 ) ;
2020-01-01 04:46:49 +00:00
if ( op < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
# define EXIT_DEPARSE() do { n = -1; goto exit_deparse; } while(0)
2020-04-16 03:42:30 +00:00
if ( hawk - > parse . pragma . rtx_stack_limit > 0 & & hawk - > parse . pragma . rtx_stack_limit ! = hawk - > opt . rtx_stack_limit )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t len ;
2020-04-16 03:42:30 +00:00
len = hawk_int_to_oocstr ( ( hawk_int_t ) hawk - > parse . pragma . rtx_stack_limit , 10 , HAWK_NULL , tmp , HAWK_COUNTOF ( tmp ) ) ;
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " @pragma stack_limit " ) ) < = - 1 | |
hawk_putsrcoochars ( hawk , tmp , len ) < = - 1 | |
hawk_putsrcoocstr ( hawk , HAWK_T ( " ; \n " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( hawk - > tree . ngbls > hawk - > tree . ngbls_base )
2019-12-13 04:29:58 +00:00
{
hawk_oow_t i , len ;
2020-04-16 03:42:30 +00:00
HAWK_ASSERT ( hawk - > tree . ngbls > 0 ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
hawk_getkwname ( hawk , HAWK_KWID_XGLOBAL , & kw ) ;
if ( hawk_putsrcoochars ( hawk , kw . ptr , kw . len ) < = - 1 | | hawk_putsrcoocstr ( hawk , HAWK_T ( " " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
2024-04-28 19:15:17 +09:00
for ( i = hawk - > tree . ngbls_base ; i < hawk - > tree . ngbls - 1 ; i + + )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_IMPLICIT ) )
2019-12-13 04:29:58 +00:00
{
/* use the actual name if no named variable is allowed */
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( hawk , HAWK_ARR_DPTR ( hawk - > parse . gbls , i ) , HAWK_ARR_DLEN ( hawk - > parse . gbls , i ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
else
{
len = hawk_int_to_oocstr ( ( hawk_int_t ) i , 10 , HAWK_T ( " __g " ) , tmp , HAWK_COUNTOF ( tmp ) ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( len ! = ( hawk_oow_t ) - 1 ) ;
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( hawk , tmp , len ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " , " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( ! ( hawk - > opt . trait & HAWK_IMPLICIT ) )
2019-12-13 04:29:58 +00:00
{
/* use the actual name if no named variable is allowed */
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( hawk , HAWK_ARR_DPTR ( hawk - > parse . gbls , i ) , HAWK_ARR_DLEN ( hawk - > parse . gbls , i ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
else
{
len = hawk_int_to_oocstr ( ( hawk_int_t ) i , 10 , HAWK_T ( " __g " ) , tmp , HAWK_COUNTOF ( tmp ) ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( len ! = ( hawk_oow_t ) - 1 ) ;
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( hawk , tmp , len ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " ; \r \n \r \n " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
else
{
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " ; \n \n " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
}
2020-04-16 03:42:30 +00:00
df . hawk = hawk ;
2019-12-13 04:29:58 +00:00
df . tmp = tmp ;
df . tmp_len = HAWK_COUNTOF ( tmp ) ;
df . ret = 0 ;
2020-04-16 03:42:30 +00:00
hawk_htb_walk ( hawk - > tree . funs , deparse_func , & df ) ;
2019-12-13 04:29:58 +00:00
if ( df . ret < = - 1 ) EXIT_DEPARSE ( ) ;
2020-04-16 03:42:30 +00:00
for ( nde = hawk - > tree . begin ; nde ! = HAWK_NULL ; nde = nde - > next )
2019-12-13 04:29:58 +00:00
{
hawk_oocs_t kw ;
2020-04-16 03:42:30 +00:00
hawk_getkwname ( hawk , HAWK_KWID_BEGIN , & kw ) ;
2019-12-13 04:29:58 +00:00
2020-11-08 17:23:25 +00:00
if ( hawk_putsrcoochars ( hawk , kw . ptr , kw . len ) < = - 1 ) EXIT_DEPARSE ( ) ;
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2020-11-12 08:02:36 +00:00
2020-11-08 17:23:25 +00:00
if ( hawk_prnnde ( hawk , nde ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \r ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \n ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
chain = hawk - > tree . chain ;
2024-04-28 19:15:17 +09:00
while ( chain )
2019-12-13 04:29:58 +00:00
{
2024-04-28 19:15:17 +09:00
if ( chain - > pattern ! = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( hawk_prnptnpt ( hawk , chain - > pattern ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
if ( chain - > action = = HAWK_NULL )
2019-12-13 04:29:58 +00:00
{
/* blockless pattern */
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \r ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \n ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2024-04-28 19:15:17 +09:00
else
2019-12-13 04:29:58 +00:00
{
2020-11-12 08:02:36 +00:00
if ( chain - > pattern )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( hawk_prnpt ( hawk , chain - > action ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \r ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \n ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
chain = chain - > next ;
}
2020-04-16 03:42:30 +00:00
for ( nde = hawk - > tree . end ; nde ! = HAWK_NULL ; nde = nde - > next )
2019-12-13 04:29:58 +00:00
{
hawk_oocs_t kw ;
2020-04-16 03:42:30 +00:00
hawk_getkwname ( hawk , HAWK_KWID_END , & kw ) ;
2019-12-13 04:29:58 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( hawk , kw . ptr , kw . len ) < = - 1 ) EXIT_DEPARSE ( ) ;
if ( hawk_putsrcoocstr ( hawk , HAWK_T ( " " ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2020-11-12 08:02:36 +00:00
2020-04-16 03:42:30 +00:00
if ( hawk_prnnde ( hawk , nde ) < = - 1 ) EXIT_DEPARSE ( ) ;
2024-04-28 19:15:17 +09:00
2019-12-13 04:29:58 +00:00
/*
2020-04-16 03:42:30 +00:00
if ( hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \r ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
if ( put_char ( hawk , HAWK_T ( ' \n ' ) ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
*/
}
2020-12-10 16:55:47 +00:00
if ( flush_out ( hawk ) < = - 1 ) EXIT_DEPARSE ( ) ;
2019-12-13 04:29:58 +00:00
exit_deparse :
2020-04-16 03:42:30 +00:00
if ( hawk - > sio . outf ( hawk , HAWK_SIO_CMD_CLOSE , & hawk - > sio . arg , HAWK_NULL , 0 ) ! = 0 & & n = = 0 ) n = - 1 ;
2019-12-13 04:29:58 +00:00
return n ;
}
static hawk_htb_walk_t deparse_func ( hawk_htb_t * map , hawk_htb_pair_t * pair , void * arg )
{
struct deparse_func_t * df = ( struct deparse_func_t * ) arg ;
hawk_fun_t * fun = ( hawk_fun_t * ) HAWK_HTB_VPTR ( pair ) ;
hawk_oow_t i , n ;
hawk_oocs_t kw ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( hawk_comp_oochars ( HAWK_HTB_KPTR ( pair ) , HAWK_HTB_KLEN ( pair ) , fun - > name . ptr , fun - > name . len , 0 ) = = 0 ) ;
2019-12-13 04:29:58 +00:00
# define PUT_C(x,c) \
2020-04-16 03:42:30 +00:00
if ( put_char ( x - > hawk , c ) = = - 1 ) { \
2019-12-13 04:29:58 +00:00
x - > ret = - 1 ; return HAWK_HTB_WALK_STOP ; \
}
# define PUT_S(x,str) \
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoocstr ( x - > hawk , str ) < = - 1 ) { \
2019-12-13 04:29:58 +00:00
x - > ret = - 1 ; return HAWK_HTB_WALK_STOP ; \
}
# define PUT_SX(x,str,len) \
2020-04-16 03:42:30 +00:00
if ( hawk_putsrcoochars ( x - > hawk , str , len ) < = - 1 ) { \
2019-12-13 04:29:58 +00:00
x - > ret = - 1 ; return HAWK_HTB_WALK_STOP ; \
}
2020-04-16 03:42:30 +00:00
hawk_getkwname ( df - > hawk , HAWK_KWID_FUNCTION , & kw ) ;
2019-12-13 04:29:58 +00:00
PUT_SX ( df , kw . ptr , kw . len ) ;
PUT_C ( df , HAWK_T ( ' ' ) ) ;
PUT_SX ( df , fun - > name . ptr , fun - > name . len ) ;
PUT_S ( df , HAWK_T ( " ( " ) ) ;
2024-04-28 19:15:17 +09:00
for ( i = 0 ; i < fun - > nargs ; )
2019-12-13 04:29:58 +00:00
{
2024-05-01 13:24:08 +09:00
if ( fun - > argspec & & i < fun - > argspeclen & & fun - > argspec [ i ] = = ' r ' ) PUT_S ( df , HAWK_T ( " & " ) ) ;
n = hawk_int_to_oocstr ( i + + , 10 , HAWK_T ( " __p " ) , df - > tmp , df - > tmp_len ) ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( n ! = ( hawk_oow_t ) - 1 ) ;
2019-12-13 04:29:58 +00:00
PUT_SX ( df , df - > tmp , n ) ;
if ( i > = fun - > nargs ) break ;
PUT_S ( df , HAWK_T ( " , " ) ) ;
}
2024-05-03 14:04:03 +09:00
if ( fun - > variadic )
{
if ( fun - > nargs > 0 ) PUT_S ( df , HAWK_T ( " , " ) ) ;
PUT_S ( df , HAWK_T ( " ... " ) ) ;
}
2024-05-02 22:36:50 +09:00
2019-12-13 04:29:58 +00:00
PUT_S ( df , HAWK_T ( " ) " ) ) ;
2020-04-16 03:42:30 +00:00
if ( df - > hawk - > opt . trait & HAWK_CRLF ) PUT_C ( df , HAWK_T ( ' \r ' ) ) ;
2019-12-13 04:29:58 +00:00
PUT_C ( df , HAWK_T ( ' \n ' ) ) ;
2020-04-16 03:42:30 +00:00
if ( hawk_prnpt ( df - > hawk , fun - > body ) < = - 1 ) return - 1 ;
if ( df - > hawk - > opt . trait & HAWK_CRLF )
2019-12-13 04:29:58 +00:00
{
PUT_C ( df , HAWK_T ( ' \r ' ) ) ;
}
PUT_C ( df , HAWK_T ( ' \n ' ) ) ;
return HAWK_HTB_WALK_FORWARD ;
# undef PUT_C
# undef PUT_S
# undef PUT_SX
}
2020-04-16 03:42:30 +00:00
static int put_char ( hawk_t * hawk , hawk_ooch_t c )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk - > sio . arg . b . buf [ hawk - > sio . arg . b . len + + ] = c ;
if ( hawk - > sio . arg . b . len > = HAWK_COUNTOF ( hawk - > sio . arg . b . buf ) )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
if ( flush_out ( hawk ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
}
return 0 ;
}
2020-04-16 03:42:30 +00:00
static int flush_out ( hawk_t * hawk )
2019-12-13 04:29:58 +00:00
{
hawk_ooi_t n ;
2020-04-16 03:42:30 +00:00
while ( hawk - > sio . arg . b . pos < hawk - > sio . arg . b . len )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
n = hawk - > sio . outf (
hawk , HAWK_SIO_CMD_WRITE , & hawk - > sio . arg ,
2024-04-28 19:15:17 +09:00
& hawk - > sio . arg . b . buf [ hawk - > sio . arg . b . pos ] ,
2020-04-16 03:42:30 +00:00
hawk - > sio . arg . b . len - hawk - > sio . arg . b . pos
2019-12-13 04:29:58 +00:00
) ;
2020-01-01 04:46:49 +00:00
if ( n < = 0 ) return - 1 ;
2020-04-16 03:42:30 +00:00
hawk - > sio . arg . b . pos + = n ;
2019-12-13 04:29:58 +00:00
}
2020-04-16 03:42:30 +00:00
hawk - > sio . arg . b . pos = 0 ;
hawk - > sio . arg . b . len = 0 ;
2019-12-13 04:29:58 +00:00
return 0 ;
}
2019-12-25 16:01:43 +00:00
int hawk_putsrcoocstr ( hawk_t * hawk , const hawk_ooch_t * str )
2019-12-13 04:29:58 +00:00
{
2020-11-08 17:23:25 +00:00
while ( * str ! = ' \0 ' )
2019-12-13 04:29:58 +00:00
{
2019-12-25 16:01:43 +00:00
if ( put_char ( hawk , * str ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
str + + ;
}
return 0 ;
}
2019-12-25 16:01:43 +00:00
int hawk_putsrcoochars ( hawk_t * hawk , const hawk_ooch_t * str , hawk_oow_t len )
2019-12-13 04:29:58 +00:00
{
const hawk_ooch_t * end = str + len ;
while ( str < end )
{
2019-12-25 16:01:43 +00:00
if ( put_char ( hawk , * str ) < = - 1 ) return - 1 ;
2019-12-13 04:29:58 +00:00
str + + ;
}
return 0 ;
}
# if defined(HAWK_ENABLE_STATIC_MODULE)
/* let's hardcode module information */
2020-03-28 08:04:37 +00:00
# include "mod-hawk.h"
2019-12-13 04:29:58 +00:00
# include "mod-math.h"
# include "mod-str.h"
2019-12-16 08:57:43 +00:00
# include "mod-sys.h"
2019-12-13 04:29:58 +00:00
2020-12-17 10:12:57 +00:00
# if defined(HAWK_ENABLE_MOD_FFI)
# include "../mod/mod-ffi.h"
# endif
2019-12-13 04:29:58 +00:00
# if defined(HAWK_ENABLE_MOD_MYSQL)
2020-01-04 05:21:00 +00:00
# include "../mod/mod-mysql.h"
2019-12-13 04:29:58 +00:00
# endif
2022-04-05 14:26:21 +00:00
# if defined(HAWK_ENABLE_MOD_SED)
# include "../mod/mod-sed.h"
# endif
2019-12-13 04:29:58 +00:00
# if defined(HAWK_ENABLE_MOD_UCI)
2020-01-04 05:21:00 +00:00
# include "../mod/mod-uci.h"
2019-12-13 04:29:58 +00:00
# endif
2024-04-25 16:42:32 +09:00
# if defined(HAWK_ENABLE_MOD_MEMC)
# include "../mod/mod-memc.h"
# endif
2024-04-28 19:15:17 +09:00
/*
2020-04-16 03:42:30 +00:00
* if modules are linked statically into the main hawk module ,
2019-12-13 04:29:58 +00:00
* this table is used to find the entry point of the modules .
2024-04-28 19:15:17 +09:00
* you must update this table if you add more modules
2019-12-13 04:29:58 +00:00
*/
static struct
{
hawk_ooch_t * modname ;
2020-04-16 03:42:30 +00:00
int ( * modload ) ( hawk_mod_t * mod , hawk_t * hawk ) ;
2024-04-28 19:15:17 +09:00
} static_modtab [ ] =
2019-12-13 04:29:58 +00:00
{
2020-12-20 17:50:30 +00:00
# if defined(HAWK_ENABLE_MOD_FFI)
{ HAWK_T ( " ffi " ) , hawk_mod_ffi } ,
# endif
2020-03-28 08:04:37 +00:00
{ HAWK_T ( " hawk " ) , hawk_mod_hawk } ,
2019-12-13 04:29:58 +00:00
{ HAWK_T ( " math " ) , hawk_mod_math } ,
# if defined(HAWK_ENABLE_MOD_MYSQL)
{ HAWK_T ( " mysql " ) , hawk_mod_mysql } ,
2022-04-05 14:26:21 +00:00
# endif
# if defined(HAWK_ENABLE_MOD_SED)
{ HAWK_T ( " sed " ) , hawk_mod_sed } ,
2019-12-13 04:29:58 +00:00
# endif
{ HAWK_T ( " str " ) , hawk_mod_str } ,
2019-12-20 14:55:10 +00:00
{ HAWK_T ( " sys " ) , hawk_mod_sys } ,
2019-12-13 04:29:58 +00:00
# if defined(HAWK_ENABLE_MOD_UCI)
{ HAWK_T ( " uci " ) , hawk_mod_uci }
# endif
2024-04-25 16:42:32 +09:00
# if defined(HAWK_ENABLE_MOD_MEMC)
{ HAWK_T ( " memc " ) , hawk_mod_memc }
# endif
2019-12-13 04:29:58 +00:00
} ;
# endif
2020-04-16 03:42:30 +00:00
static hawk_mod_t * query_module ( hawk_t * hawk , const hawk_oocs_t segs [ ] , int nsegs , hawk_mod_sym_t * sym )
2019-12-13 04:29:58 +00:00
{
hawk_rbt_pair_t * pair ;
hawk_mod_data_t * mdp ;
int n ;
2019-12-21 16:59:00 +00:00
HAWK_ASSERT ( nsegs = = 2 ) ;
2019-12-13 04:29:58 +00:00
2020-12-28 07:10:17 +00:00
pair = hawk_rbt_search ( hawk - > modtab , segs [ 0 ] . ptr , segs [ 0 ] . len ) ;
2019-12-13 04:29:58 +00:00
if ( pair )
{
mdp = ( hawk_mod_data_t * ) HAWK_RBT_VPTR ( pair ) ;
}
else
{
hawk_mod_data_t md ;
hawk_mod_load_t load = HAWK_NULL ;
hawk_mod_spec_t spec ;
hawk_oow_t buflen ;
/*hawk_ooch_t buf[64 + 12] = HAWK_T("_hawk_mod_");*/
/* maximum module name length is 64. 15 is decomposed to 13 + 1 + 1.
* 10 for _hawk_mod_
* 1 for _ at the end when hawk_mod_xxx_ is attempted .
* 1 for the terminating ' \0 '
*/
2024-04-28 19:15:17 +09:00
hawk_ooch_t buf [ 64 + 12 ] ;
2019-12-13 04:29:58 +00:00
/* the terminating null isn't needed in buf here */
2024-04-28 19:15:17 +09:00
HAWK_MEMCPY ( buf , HAWK_T ( " _hawk_mod_ " ) , HAWK_SIZEOF ( hawk_ooch_t ) * 10 ) ;
2019-12-13 04:29:58 +00:00
if ( segs [ 0 ] . len > HAWK_COUNTOF ( buf ) - 15 )
{
/* module name too long */
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ESEGTL , FMT_ESEGTL , segs [ 0 ] . len , segs [ 0 ] . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
# if defined(HAWK_ENABLE_STATIC_MODULE)
/* attempt to find a statically linked module */
/* TODO: binary search ... */
for ( n = 0 ; n < HAWK_COUNTOF ( static_modtab ) ; n + + )
{
2021-07-19 19:54:01 +00:00
if ( hawk_comp_oochars_oocstr ( segs [ 0 ] . ptr , segs [ 0 ] . len , static_modtab [ n ] . modname , 0 ) = = 0 )
2019-12-13 04:29:58 +00:00
{
load = static_modtab [ n ] . modload ;
break ;
}
}
/*if (n >= HAWK_COUNTOF(static_modtab))
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , HAWK_T ( " '%.*js' not found " ) , segs [ 0 ] . len , segs [ 0 ] . ptr ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
} */
if ( load )
{
/* found the module in the staic module table */
HAWK_MEMSET ( & md , 0 , HAWK_SIZEOF ( md ) ) ;
/* Note md.handle is HAWK_NULL for a static module */
/* i copy-insert 'md' into the table before calling 'load'.
* to pass the same address to load ( ) , query ( ) , etc */
2020-04-16 03:42:30 +00:00
pair = hawk_rbt_insert ( hawk - > modtab , segs [ 0 ] . ptr , segs [ 0 ] . len , & md , HAWK_SIZEOF ( md ) ) ;
2020-12-28 07:10:17 +00:00
if ( ! pair ) return HAWK_NULL ;
2019-12-13 04:29:58 +00:00
mdp = ( hawk_mod_data_t * ) HAWK_RBT_VPTR ( pair ) ;
2020-04-16 03:42:30 +00:00
if ( load ( & mdp - > mod , hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_rbt_delete ( hawk - > modtab , segs [ 0 ] . ptr , segs [ 0 ] . len ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
goto done ;
}
# endif
2020-04-15 15:12:28 +00:00
/* attempt to find an external module */
HAWK_MEMSET ( & spec , 0 , HAWK_SIZEOF ( spec ) ) ;
2022-06-16 13:31:34 +00:00
spec . prefix = ( hawk - > opt . mod [ 1 ] . len > 0 ) ? ( const hawk_ooch_t * ) hawk - > opt . mod [ 1 ] . ptr : ( const hawk_ooch_t * ) HAWK_T ( HAWK_DEFAULT_MODPREFIX ) ;
spec . postfix = ( hawk - > opt . mod [ 2 ] . len > 0 ) ? ( const hawk_ooch_t * ) hawk - > opt . mod [ 2 ] . ptr : ( const hawk_ooch_t * ) HAWK_T ( HAWK_DEFAULT_MODPOSTFIX ) ;
2022-06-03 05:20:32 +00:00
spec . name = segs [ 0 ] . ptr ; /* the caller must ensure that this segment is null-terminated */
2020-04-16 03:42:30 +00:00
if ( ! hawk - > prm . modopen | | ! hawk - > prm . modgetsym | | ! hawk - > prm . modclose )
2020-04-15 08:35:07 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_EINVAL , HAWK_T ( " module callbacks not set properly " ) ) ;
2020-04-15 08:35:07 +00:00
goto open_fail ;
}
2022-06-16 13:31:34 +00:00
spec . libdir = ( hawk - > opt . mod [ 0 ] . len > 0 ) ? ( const hawk_ooch_t * ) hawk - > opt . mod [ 0 ] . ptr : ( const hawk_ooch_t * ) HAWK_T ( HAWK_DEFAULT_MODLIBDIRS ) ;
2020-04-15 08:35:07 +00:00
do
2019-12-13 04:29:58 +00:00
{
2020-04-15 15:12:28 +00:00
# if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define LIBDIR_SEPARATOR ';'
# else
# define LIBDIR_SEPARATOR ':'
# endif
2020-04-15 08:35:07 +00:00
hawk_ooch_t * colon ;
2020-04-15 15:12:28 +00:00
colon = hawk_find_oochar_in_oocstr ( spec . libdir , LIBDIR_SEPARATOR ) ;
2020-04-15 08:35:07 +00:00
if ( colon ) * colon = ' \0 ' ;
2020-04-15 15:12:28 +00:00
HAWK_MEMSET ( & md , 0 , HAWK_SIZEOF ( md ) ) ;
2020-04-16 03:42:30 +00:00
md . handle = hawk - > prm . modopen ( hawk , & spec ) ;
2020-04-15 08:35:07 +00:00
if ( ! colon ) break ;
2020-04-15 15:12:28 +00:00
* colon = LIBDIR_SEPARATOR ;
spec . libdir = colon + 1 ;
# undef LIBDIR_SEPARATOR
2020-01-02 08:33:24 +00:00
}
2020-04-15 08:35:07 +00:00
while ( ! md . handle ) ;
2019-12-13 04:29:58 +00:00
2020-04-15 08:35:07 +00:00
if ( ! md . handle )
2019-12-13 04:29:58 +00:00
{
2020-04-15 08:35:07 +00:00
const hawk_ooch_t * bem ;
open_fail :
2020-04-16 03:42:30 +00:00
bem = hawk_backuperrmsg ( hawk ) ;
2024-04-28 19:15:17 +09:00
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , HAWK_T ( " '%js%js%js' for module '%js' not found - %js " ) ,
( spec . prefix ? ( const hawk_ooch_t * ) spec . prefix : ( const hawk_ooch_t * ) HAWK_T ( " " ) ) ,
2022-06-16 13:31:34 +00:00
spec . name ,
2024-04-28 19:15:17 +09:00
( spec . postfix ? ( const hawk_ooch_t * ) spec . postfix : ( const hawk_ooch_t * ) HAWK_T ( " " ) ) ,
2022-06-03 05:20:32 +00:00
spec . name , bem ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
2020-01-02 08:33:24 +00:00
buflen = hawk_copy_oocstr_unlimited ( & buf [ 10 ] , segs [ 0 ] . ptr ) ;
2019-12-13 04:29:58 +00:00
/* attempt hawk_mod_xxx */
2020-04-16 03:42:30 +00:00
load = hawk - > prm . modgetsym ( hawk , md . handle , & buf [ 1 ] ) ;
2024-04-28 19:15:17 +09:00
if ( ! load )
2019-12-13 04:29:58 +00:00
{
/* attempt _hawk_mod_xxx */
2020-04-16 03:42:30 +00:00
load = hawk - > prm . modgetsym ( hawk , md . handle , & buf [ 0 ] ) ;
2019-12-13 04:29:58 +00:00
if ( ! load )
{
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_ENOERR ) ;
2019-12-13 04:29:58 +00:00
/* attempt hawk_mod_xxx_ */
2020-01-02 08:33:24 +00:00
buf [ 10 + buflen ] = HAWK_T ( ' _ ' ) ;
buf [ 10 + buflen + 1 ] = HAWK_T ( ' \0 ' ) ;
2020-04-16 03:42:30 +00:00
load = hawk - > prm . modgetsym ( hawk , md . handle , & buf [ 1 ] ) ;
2019-12-13 04:29:58 +00:00
if ( ! load )
{
2020-04-16 03:42:30 +00:00
const hawk_ooch_t * bem = hawk_backuperrmsg ( hawk ) ;
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , HAWK_T ( " module symbol '%.*js' not found - %js " ) , ( 10 + buflen ) , & buf [ 1 ] , bem ) ;
2020-01-02 08:33:24 +00:00
2020-04-16 03:42:30 +00:00
hawk - > prm . modclose ( hawk , md . handle ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
}
/* i copy-insert 'md' into the table before calling 'load'.
* to pass the same address to load ( ) , query ( ) , etc */
2020-04-16 03:42:30 +00:00
pair = hawk_rbt_insert ( hawk - > modtab , segs [ 0 ] . ptr , segs [ 0 ] . len , & md , HAWK_SIZEOF ( md ) ) ;
2019-12-13 04:29:58 +00:00
if ( pair = = HAWK_NULL )
{
2020-04-16 03:42:30 +00:00
hawk - > prm . modclose ( hawk , md . handle ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
mdp = ( hawk_mod_data_t * ) HAWK_RBT_VPTR ( pair ) ;
2020-04-16 03:42:30 +00:00
if ( load ( & mdp - > mod , hawk ) < = - 1 )
2019-12-13 04:29:58 +00:00
{
2020-04-16 03:42:30 +00:00
hawk_rbt_delete ( hawk - > modtab , segs [ 0 ] . ptr , segs [ 0 ] . len ) ;
hawk - > prm . modclose ( hawk , mdp - > handle ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
}
done :
2020-04-16 03:42:30 +00:00
hawk_seterrnum ( hawk , HAWK_NULL , HAWK_ENOERR ) ;
n = mdp - > mod . query ( & mdp - > mod , hawk , segs [ 1 ] . ptr , sym ) ;
2019-12-13 04:29:58 +00:00
if ( n < = - 1 )
{
2020-04-16 03:42:30 +00:00
const hawk_ooch_t * olderrmsg = hawk_backuperrmsg ( hawk ) ;
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_ENOENT , HAWK_T ( " unable to find '%.*js' in module '%.*js' - %js " ) , segs [ 1 ] . len , segs [ 1 ] . ptr , segs [ 0 ] . len , segs [ 0 ] . ptr , olderrmsg ) ;
2019-12-13 04:29:58 +00:00
return HAWK_NULL ;
}
return & mdp - > mod ;
}
2020-12-28 07:10:17 +00:00
2022-06-03 06:01:52 +00:00
hawk_mod_t * hawk_querymodulewithname ( hawk_t * hawk , hawk_ooch_t * name , hawk_mod_sym_t * sym )
2020-12-28 07:10:17 +00:00
{
const hawk_ooch_t * dc ;
2024-04-28 19:15:17 +09:00
hawk_oocs_t segs [ 2 ] ;
2022-06-03 05:20:32 +00:00
hawk_mod_t * mod ;
2022-06-03 06:01:52 +00:00
hawk_oow_t name_len ;
2022-06-03 05:20:32 +00:00
hawk_ooch_t tmp ;
2020-12-28 07:10:17 +00:00
/*TOOD: non-module builtin function? fnc? */
2022-06-03 06:01:52 +00:00
name_len = hawk_count_oocstr ( name ) ;
dc = hawk_find_oochars_in_oochars ( name , name_len , HAWK_T ( " :: " ) , 2 , 0 ) ;
2024-04-28 19:15:17 +09:00
if ( ! dc )
2020-12-28 07:10:17 +00:00
{
hawk_seterrfmt ( hawk , HAWK_NULL , HAWK_EINVAL , HAWK_T ( " invalid module name - %js " ) , name ) ;
return HAWK_NULL ;
}
2022-06-03 06:01:52 +00:00
segs [ 0 ] . len = dc - name ;
segs [ 0 ] . ptr = name ;
tmp = name [ segs [ 0 ] . len ] ;
name [ segs [ 0 ] . len ] = ' \0 ' ;
2020-12-28 07:10:17 +00:00
2022-06-03 06:01:52 +00:00
segs [ 1 ] . len = name_len - segs [ 0 ] . len - 2 ;
segs [ 1 ] . ptr = ( hawk_ooch_t * ) name + segs [ 0 ] . len + 2 ;
2022-06-03 05:20:32 +00:00
mod = query_module ( hawk , segs , 2 , sym ) ;
2022-06-03 06:01:52 +00:00
name [ segs [ 0 ] . len ] = tmp ;
2022-06-03 05:20:32 +00:00
return mod ;
2020-12-28 07:10:17 +00:00
}