From d3b90da1e7368ac8db26ae02ebc79e4a9cd77dc8 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 13 Dec 2025 22:09:05 +0900 Subject: [PATCH] added a new pragma pedantic to make syntax check stricter - for now. it flags about unused local and global variables --- bin/hawk.c | 42 +++++++++--------- bin/hawkgo.go | 5 +-- lib/arr.c | 39 +++++++++-------- lib/err.c | 1 + lib/hawk-arr.h | 4 +- lib/hawk-cmn.h | 1 + lib/hawk-prv.h | 8 ++++ lib/hawk.c | 26 ++++++------ lib/hawk.h | 36 +++++++++------- lib/parse.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++-- t/t-001.c | 2 +- 11 files changed, 203 insertions(+), 74 deletions(-) diff --git a/bin/hawk.c b/bin/hawk.c index 5ff3ac31..342c2d2a 100644 --- a/bin/hawk.c +++ b/bin/hawk.c @@ -333,22 +333,23 @@ struct opttab_t const hawk_bch_t* desc; } opttab[] = { - { "implicit", HAWK_IMPLICIT, "allow undeclared variables" }, - { "multilinestr", HAWK_MULTILINESTR, "allow raw multiline string and regular expression literals" }, - { "nextofile", HAWK_NEXTOFILE, "enable nextofile & OFILENAME" }, - { "rio", HAWK_RIO, "enable builtin I/O including getline & print" }, - { "rwpipe", HAWK_RWPIPE, "allow a dual-directional pipe" }, - { "newline", HAWK_NEWLINE, "enable a newline to terminate a statement" }, - { "striprecspc", HAWK_STRIPRECSPC, "strip spaces in splitting a record" }, - { "stripstrspc", HAWK_STRIPSTRSPC, "strip spaces in string-to-number conversion" }, { "blankconcat", HAWK_BLANKCONCAT, "enable concatenation by blanks" }, { "crlf", HAWK_CRLF, "use CRLF for a newline" }, { "flexmap", HAWK_FLEXMAP, "allow a map to be assigned or returned" }, - { "pablock", HAWK_PABLOCK, "enable pattern-action loop" }, - { "rexbound", HAWK_REXBOUND, "enable {n,m} in a regular expression" }, + { "implicit", HAWK_IMPLICIT, "allow undeclared variables" }, + { "multilinestr", HAWK_MULTILINESTR, "allow raw multiline string and regular expression literals" }, { "ncmponstr", HAWK_NCMPONSTR, "perform numeric comparsion on numeric strings" }, + { "newline", HAWK_NEWLINE, "enable a newline to terminate a statement" }, + { "nextofile", HAWK_NEXTOFILE, "enable nextofile & OFILENAME" }, { "numstrdetect", HAWK_NUMSTRDETECT, "detect a numeric string and convert it to a number" }, + { "pablock", HAWK_PABLOCK, "enable pattern-action loop" }, + { "pedantic", HAWK_PEDANTIC, "enable pedantic mode" }, + { "rexbound", HAWK_REXBOUND, "enable {n,m} in a regular expression" }, + { "rio", HAWK_RIO, "enable builtin I/O including getline & print" }, + { "rwpipe", HAWK_RWPIPE, "allow a dual-directional pipe" }, { "strictnaming", HAWK_STRICTNAMING, "enable the strict naming rule" }, + { "striprecspc", HAWK_STRIPRECSPC, "strip spaces in splitting a record" }, + { "stripstrspc", HAWK_STRIPSTRSPC, "strip spaces in string-to-number conversion" }, { "tolerant", HAWK_TOLERANT, "make more fault-tolerant" }, { HAWK_NULL, 0, HAWK_NULL } }; @@ -408,22 +409,23 @@ static int process_argv (int argc, hawk_bch_t* argv[], const hawk_bch_t* real_ar { static hawk_bcli_lng_t lng[] = { - { ":implicit", '\0' }, - { ":multilinestr", '\0' }, - { ":nextofile", '\0' }, - { ":rio", '\0' }, - { ":rwpipe", '\0' }, - { ":newline", '\0' }, - { ":striprecspc", '\0' }, - { ":stripstrspc", '\0' }, { ":blankconcat", '\0' }, { ":crlf", '\0' }, { ":flexmap", '\0' }, - { ":pablock", '\0' }, - { ":rexbound", '\0' }, + { ":implicit", '\0' }, + { ":multilinestr", '\0' }, { ":ncmponstr", '\0' }, + { ":newline", '\0' }, + { ":nextofile", '\0' }, { ":numstrdetect", '\0' }, + { ":pablock", '\0' }, + { ":pedantic", '\0' }, + { ":rexbound", '\0' }, + { ":rio", '\0' }, + { ":rwpipe", '\0' }, { ":strictnaming", '\0' }, + { ":striprecspc", '\0' }, + { ":stripstrspc", '\0' }, { ":tolerant", '\0' }, { ":call", 'c' }, diff --git a/bin/hawkgo.go b/bin/hawkgo.go index 39904a6e..267f7761 100644 --- a/bin/hawkgo.go +++ b/bin/hawkgo.go @@ -7,7 +7,6 @@ import "io" //import "net/http" //import _ "net/http/pprof" import "os" -import "path/filepath" import "runtime" import "runtime/debug" import "strconv" @@ -144,13 +143,13 @@ func run_script(h *hawk.Hawk, fs_idx int, data_idx int, cfg* Config, wg *sync.Wa if wg != nil { defer wg.Done() } if data_idx <= -1 { - rtx, err = h.NewRtx(filepath.Base(os.Args[0]), cfg.data_in_files, nil) + rtx, err = h.NewRtx(os.Args[0], cfg.data_in_files, nil) } else { var out_idx_end int = data_idx if cfg.data_out_files[data_idx] != "" { out_idx_end++ } rtx, err = h.NewRtx( - fmt.Sprintf("%s.%d", filepath.Base(os.Args[0]), data_idx), + fmt.Sprintf("%s.%d", os.Args[0], data_idx), cfg.data_in_files[data_idx: data_idx + 1], cfg.data_out_files[data_idx: out_idx_end], ) diff --git a/lib/arr.c b/lib/arr.c index 659a2068..95c1f9a3 100644 --- a/lib/arr.c +++ b/lib/arr.c @@ -33,7 +33,7 @@ #define keeper_t hawk_arr_keeper_t #define walker_t hawk_arr_walker_t -#define TOB(arr,len) ((len)*(arr)->scale) +#define TOB(arr,len) ((len) * (arr)->scale) #define DPTR(slot) ((slot)->val.ptr) #define DLEN(slot) ((slot)->val.len) @@ -71,11 +71,13 @@ static HAWK_INLINE slot_t* alloc_slot (hawk_arr_t* arr, void* dptr, hawk_oow_t d } else if (arr->style->copier == HAWK_ARR_COPIER_INLINE) { - n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t) + TOB(arr,dlen)); + hawk_oow_t nbytes = TOB(arr, dlen); + n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t) + nbytes + arr->inline_slot_xtnsize); if (HAWK_UNLIKELY(!n)) return HAWK_NULL; - - HAWK_MEMCPY (n + 1, dptr, TOB(arr,dlen)); /* copy data contents */ + HAWK_MEMCPY(n + 1, dptr, nbytes); /* copy data contents */ DPTR(n) = n + 1; + if (arr->inline_slot_xtnsize > 0) + HAWK_MEMSET((hawk_uint8_t*)DPTR(n) + nbytes, 0, arr->inline_slot_xtnsize); } else { @@ -103,17 +105,17 @@ hawk_arr_t* hawk_arr_open (hawk_gem_t* gem, hawk_oow_t xtnsize, hawk_oow_t capa) if (hawk_arr_init(arr, gem, capa) <= -1) { - hawk_gem_freemem (gem, arr); + hawk_gem_freemem(gem, arr); return HAWK_NULL; } - HAWK_MEMSET (arr + 1, 0, xtnsize); + HAWK_MEMSET(arr + 1, 0, xtnsize); return arr; } void hawk_arr_close (hawk_arr_t* arr) { - hawk_arr_fini (arr); + hawk_arr_fini(arr); hawk_gem_freemem(arr->gem, arr); } @@ -160,7 +162,7 @@ int hawk_arr_init (hawk_arr_t* arr, hawk_gem_t* gem, hawk_oow_t capa) void hawk_arr_fini (hawk_arr_t* arr) { - hawk_arr_clear (arr); + hawk_arr_clear(arr); if (arr->slot) { @@ -181,7 +183,7 @@ void hawk_arr_setscale (hawk_arr_t* arr, int scale) { /* The scale should be larger than 0 and less than or equal to the * maximum value that the hawk_uint8_t type can hold */ - HAWK_ASSERT (scale > 0 && scale <= HAWK_TYPE_MAX(hawk_uint8_t)); + HAWK_ASSERT(scale > 0 && scale <= HAWK_TYPE_MAX(hawk_uint8_t)); if (scale <= 0) scale = 1; if (scale > HAWK_TYPE_MAX(hawk_uint8_t)) scale = HAWK_TYPE_MAX(hawk_uint8_t); @@ -196,7 +198,7 @@ const hawk_arr_style_t* hawk_arr_getstyle (hawk_arr_t* arr) void hawk_arr_setstyle (hawk_arr_t* arr, const hawk_arr_style_t* style) { - HAWK_ASSERT (style != HAWK_NULL); + HAWK_ASSERT(style != HAWK_NULL); arr->style = style; } @@ -238,8 +240,8 @@ hawk_arr_t* hawk_arr_setcapa (hawk_arr_t* arr, hawk_oow_t capa) tmp = HAWK_NULL; - HAWK_ASSERT (arr->size == 0); - HAWK_ASSERT (arr->tally == 0); + HAWK_ASSERT(arr->size == 0); + HAWK_ASSERT(arr->tally == 0); } arr->slot = tmp; @@ -287,6 +289,7 @@ hawk_oow_t hawk_arr_upsert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo return hawk_arr_insert(arr, pos, dptr, dlen); } + hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oow_t dlen) { hawk_oow_t i; @@ -314,7 +317,7 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo { if (arr->capa <= 0) { - HAWK_ASSERT (arr->size <= 0); + HAWK_ASSERT(arr->size <= 0); capa = HAWK_ALIGN_POW2(pos + 1, 64); } else @@ -692,7 +695,7 @@ hawk_oow_t hawk_arr_pushheap (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) if (hawk_arr_insert(arr, index, dptr, dlen) == HAWK_ARR_NIL) return HAWK_ARR_NIL; HEAP_UPDATE_POS(arr, index); - HAWK_ASSERT (arr->size == index + 1); + HAWK_ASSERT(arr->size == index + 1); /* move the item upto the top if it's greater than the parent items */ sift_up(arr, index); @@ -701,7 +704,7 @@ hawk_oow_t hawk_arr_pushheap (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) void hawk_arr_popheap (hawk_arr_t* arr) { - HAWK_ASSERT (arr->size > 0); + HAWK_ASSERT(arr->size > 0); hawk_arr_deleteheap(arr, 0); } @@ -709,8 +712,8 @@ void hawk_arr_deleteheap (hawk_arr_t* arr, hawk_oow_t index) { slot_t* tmp; - HAWK_ASSERT (arr->size > 0); - HAWK_ASSERT (index < arr->size); + HAWK_ASSERT(arr->size > 0); + HAWK_ASSERT(index < arr->size); /* remember the item to destroy */ tmp = arr->slot[index]; @@ -746,7 +749,7 @@ hawk_oow_t hawk_arr_updateheap (hawk_arr_t* arr, hawk_oow_t index, void* dptr, h int n; tmp = arr->slot[index]; - HAWK_ASSERT (tmp != HAWK_NULL); + HAWK_ASSERT(tmp != HAWK_NULL); n = arr->style->comper(arr, dptr, dlen, DPTR(tmp), DLEN(tmp)); if (n) diff --git a/lib/err.c b/lib/err.c index e417f723..02da607a 100644 --- a/lib/err.c +++ b/lib/err.c @@ -129,6 +129,7 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum) HAWK_T("include level too deep"), HAWK_T("word after @ not recognized"), HAWK_T("@ not followed by a valid word"), + HAWK_T("unused element"), HAWK_T("stack full"), HAWK_T("divide by zero"), diff --git a/lib/hawk-arr.h b/lib/hawk-arr.h index 5e76ba26..26ee088e 100644 --- a/lib/hawk-arr.h +++ b/lib/hawk-arr.h @@ -180,6 +180,7 @@ struct hawk_arr_t hawk_gem_t* gem; const hawk_arr_style_t* style; hawk_uint8_t scale; /* scale factor */ + hawk_uint16_t inline_slot_xtnsize; hawk_oow_t heap_pos_offset; /* offset in the data element where position * is stored when heap operation is performed. */ hawk_oow_t size; /* number of items */ @@ -262,14 +263,13 @@ HAWK_EXPORT int hawk_arr_getscale ( */ HAWK_EXPORT void hawk_arr_setscale ( hawk_arr_t* arr /**< array */, - int scale /**< scale factor - 1 to 255 */ + int scale /**< scale factor - 1 to 255 */ ); HAWK_EXPORT hawk_arr_copier_t hawk_arr_getcopier ( hawk_arr_t* arr /* array */ ); - HAWK_EXPORT void hawk_arr_setstyle ( hawk_arr_t* arr, const hawk_arr_style_t* style diff --git a/lib/hawk-cmn.h b/lib/hawk-cmn.h index 8c06aa16..9e890b07 100644 --- a/lib/hawk-cmn.h +++ b/lib/hawk-cmn.h @@ -1014,6 +1014,7 @@ enum hawk_errnum_t HAWK_EINCLTD, /**< include level too deep */ HAWK_EXKWNR, /**< word after @ not recognized */ HAWK_EXKWEM, /**< @ not followed by a valid word */ + HAWK_EUNUSED, /**< unused element */ /* hawk run time error */ HAWK_ESTACK, /**< stack error */ diff --git a/lib/hawk-prv.h b/lib/hawk-prv.h index 16685024..1f8034e6 100644 --- a/lib/hawk-prv.h +++ b/lib/hawk-prv.h @@ -395,6 +395,14 @@ struct hawk_bctos_b_t hawk_bchu_t c[2]; /* ensure the unsigned type to hold not only a byte character but also a free slot index */ }; + +typedef struct hawk_var_xinfo_t hawk_var_xinfo_t; +struct hawk_var_xinfo_t +{ + hawk_uint8_t used; + hawk_loc_t loc; +}; + struct hawk_rtx_t { HAWK_RTX_HDR; diff --git a/lib/hawk.c b/lib/hawk.c index cefbc3cb..95ebd5d4 100644 --- a/lib/hawk.c +++ b/lib/hawk.c @@ -239,30 +239,32 @@ int hawk_init (hawk_t* hawk, hawk_mmgr_t* mmgr, hawk_cmgr_t* cmgr, const hawk_pr } *(hawk_t**)(hawk->tree.funs + 1) = hawk; - hawk_htb_setstyle (hawk->tree.funs, &treefuncbs); + hawk_htb_setstyle(hawk->tree.funs, &treefuncbs); *(hawk_t**)(hawk->parse.funs + 1) = hawk; - hawk_htb_setstyle (hawk->parse.funs, hawk_get_htb_style(HAWK_HTB_STYLE_INLINE_KEY_COPIER)); + hawk_htb_setstyle(hawk->parse.funs, hawk_get_htb_style(HAWK_HTB_STYLE_INLINE_KEY_COPIER)); *(hawk_t**)(hawk->parse.named + 1) = hawk; - hawk_htb_setstyle (hawk->parse.named, hawk_get_htb_style(HAWK_HTB_STYLE_INLINE_KEY_COPIER)); + hawk_htb_setstyle(hawk->parse.named, hawk_get_htb_style(HAWK_HTB_STYLE_INLINE_KEY_COPIER)); *(hawk_t**)(hawk->parse.gbls + 1) = hawk; - hawk_arr_setscale (hawk->parse.gbls, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setstyle (hawk->parse.gbls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); + hawk_arr_setscale(hawk->parse.gbls, HAWK_SIZEOF(hawk_ooch_t)); + hawk_arr_setstyle(hawk->parse.gbls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); + hawk->parse.gbls->inline_slot_xtnsize = HAWK_SIZEOF(hawk_var_xinfo_t); *(hawk_t**)(hawk->parse.lcls + 1) = hawk; - hawk_arr_setscale (hawk->parse.lcls, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setstyle (hawk->parse.lcls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); + hawk_arr_setscale(hawk->parse.lcls, HAWK_SIZEOF(hawk_ooch_t)); + hawk_arr_setstyle(hawk->parse.lcls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); + hawk->parse.lcls->inline_slot_xtnsize = HAWK_SIZEOF(hawk_var_xinfo_t); *(hawk_t**)(hawk->parse.params + 1) = hawk; - hawk_arr_setscale (hawk->parse.params, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setstyle (hawk->parse.params, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); + hawk_arr_setscale(hawk->parse.params, HAWK_SIZEOF(hawk_ooch_t)); + hawk_arr_setstyle(hawk->parse.params, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); *(hawk_t**)(hawk->fnc.user + 1) = hawk; - hawk_htb_setstyle (hawk->fnc.user, &fncusercbs); + hawk_htb_setstyle(hawk->fnc.user, &fncusercbs); - hawk_rbt_setstyle (hawk->modtab, hawk_get_rbt_style(HAWK_RBT_STYLE_INLINE_COPIERS)); + hawk_rbt_setstyle(hawk->modtab, hawk_get_rbt_style(HAWK_RBT_STYLE_INLINE_COPIERS)); if (hawk_initgbls(hawk) <= -1) goto oops; return 0; @@ -417,7 +419,7 @@ void hawk_clear (hawk_t* hawk) hawk->parse.depth.loop = 0; hawk->parse.depth.expr = 0; hawk->parse.depth.incl = 0; - hawk->parse.pragma.trait = (hawk->opt.trait & (HAWK_IMPLICIT | HAWK_MULTILINESTR | HAWK_RWPIPE | HAWK_STRIPRECSPC | HAWK_STRIPSTRSPC)); /* implicit on if you didn't mask it off in hawk->opt.trait with hawk_setopt */ + hawk->parse.pragma.trait = (hawk->opt.trait & (HAWK_IMPLICIT | HAWK_MULTILINESTR | HAWK_PEDANTIC | HAWK_RWPIPE | HAWK_STRIPRECSPC | HAWK_STRIPSTRSPC)); /* implicit on if you didn't mask it off in hawk->opt.trait with hawk_setopt */ hawk->parse.pragma.rtx_stack_limit = 0; hawk->parse.pragma.entry[0] = '\0'; diff --git a/lib/hawk.h b/lib/hawk.h index cb147c17..e91dd857 100644 --- a/lib/hawk.h +++ b/lib/hawk.h @@ -38,7 +38,7 @@ #include /** \file - * An embeddable AWK interpreter is defined in this header file. + * An embeddable HAWK interpreter is defined in this header file. * * \todo * - make enhancement to treat a function as a value @@ -47,11 +47,11 @@ */ /** \struct hawk_t - * The #hawk_t type defines an AWK interpreter. It provides an interface - * to parse an AWK script and run it to manipulate input and output data. + * The #hawk_t type defines an HAWK interpreter. It provides an interface + * to parse an HAWK script and run it to manipulate input and output data. * * In brief, you need to call APIs with user-defined handlers to run a typical - * AWK script as shown below: + * HAWK script as shown below: * * \code * hawk_t* hawk; @@ -61,7 +61,7 @@ * hawk = hawk_open(mmgr, 0, hawk_get_cmgr_by_id(HAWK_CMGR_UTF8), prm, HAWK_NULL); // create an interpreter * hawk_parse(hawk, &sio); // parse a script * rtx = hawk_rtx_open(hawk, 0, &rio); // create a runtime context - * retv = hawk_rtx_loop(rtx); // run a standard AWK loop + * retv = hawk_rtx_loop(rtx); // run a standard HAWK loop * if (retv) hawk_rtx_refdownval(rtx, retv); // free return value * hawk_rtx_close(rtx); // destroy the runtime context * hawk_close(hawk); // destroy the interpreter @@ -88,7 +88,7 @@ struct hawk_alt_t /** \struct hawk_rtx_t * The #hawk_rtx_t type defines a runtime context. A runtime context * maintains runtime state for a running script. You can create multiple - * runtime contexts out of a single AWK interpreter; in other words, you + * runtime contexts out of a single HAWK interpreter; in other words, you * can run the same script with different input and output data by providing * customized I/O handlers when creating a runtime context with * hawk_rtx_open(). @@ -1365,7 +1365,7 @@ enum hawk_trait_t HAWK_STRICTNAMING = (1 << 15), /** - * makes AWK more fault-tolerant. + * makes HAWK more fault-tolerant. * - prevents termination due to print and printf failure. * - achieves this by handling print and printf as if * they are functions like getline. @@ -1377,12 +1377,18 @@ enum hawk_trait_t */ HAWK_TOLERANT = (1 << 17), - /* - * detect a numeric string and convert to a numeric type + /** + * detects a numeric string and convert to a numeric type * automatically */ HAWK_NUMSTRDETECT = (1 << 18), + /** + * makes HAWK more picky about the syntax: + * - it complains about unused local variables + */ + HAWK_PEDANTIC = (1 << 19), + /** * makes #hawk_t to behave compatibly with classical AWK * implementations @@ -1394,7 +1400,7 @@ enum hawk_trait_t HAWK_MODERN = HAWK_CLASSIC | HAWK_FLEXMAP | HAWK_REXBOUND | - HAWK_RWPIPE | HAWK_TOLERANT | HAWK_NEXTOFILE | HAWK_NUMSTRDETECT /*| HAWK_NCMPONSTR*/ + HAWK_RWPIPE | HAWK_TOLERANT | HAWK_NEXTOFILE | HAWK_NUMSTRDETECT /*| HAWK_NCMPONSTR*/ }; typedef enum hawk_trait_t hawk_trait_t; @@ -1446,7 +1452,7 @@ enum hawk_gbl_id_t typedef enum hawk_gbl_id_t hawk_gbl_id_t; /** - * The hawk_val_type_t type defines types of AWK values. Each value + * The hawk_val_type_t type defines types of HAWK values. Each value * allocated is tagged with a value type in the \a type field. * \sa hawk_val_t HAWK_VAL_HDR */ @@ -2476,7 +2482,7 @@ static HAWK_INLINE void hawk_rtx_setcmgr (hawk_rtx_t* rtx, hawk_cmgr_t* cmgr) { /** * The hawk_rtx_loop() function executes the BEGIN block, pattern-action - * blocks and the END blocks in an AWK program. It returns the global return + * blocks and the END blocks in an HAWK program. It returns the global return * value of which the reference count must be decremented when not necessary. * Multiple invocations of the function for the lifetime of a runtime context * is not desirable. @@ -2525,7 +2531,7 @@ HAWK_EXPORT hawk_fun_t* hawk_rtx_findfunwithucstr ( #endif /** - * The hawk_rtx_callfun() function invokes an AWK function described by + * The hawk_rtx_callfun() function invokes an HAWK function described by * the structure pointed to by \a fun. * \sa hawk_rtx_call */ @@ -2537,7 +2543,7 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_callfun ( ); /** - * The hawk_rtx_callwithucstr() function invokes an AWK function named \a name. + * The hawk_rtx_callwithucstr() function invokes an HAWK function named \a name. * However, it is not able to invoke an intrinsic function such as split(). * The #HAWK_PABLOCK option can be turned off to make illegal the BEGIN * blocks, the pattern-action blocks, and the END blocks. @@ -2565,7 +2571,7 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_callwithucstr ( ); /** - * The hawk_rtx_callwithbcstr() function invokes an AWK function named \a name. + * The hawk_rtx_callwithbcstr() function invokes an HAWK function named \a name. * However, it is not able to invoke an intrinsic function such as split(). * The #HAWK_PABLOCK option can be turned off to make illegal the BEGIN * blocks, the pattern-action blocks, and the END blocks. diff --git a/lib/parse.c b/lib/parse.c index fe34b875..510bdc6f 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -606,6 +606,25 @@ static int parse (hawk_t* hawk) } } + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + hawk_oow_t i; + for (i = hawk->tree.ngbls_base ; i < HAWK_ARR_SIZE(hawk->parse.gbls); i++) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t vxi; + + ptl = HAWK_ARR_DPTL(hawk->parse.gbls, i); + HAWK_MEMCPY(&vxi, (const hawk_ooch_t*)ptl->ptr + ptl->len, HAWK_SIZEOF(vxi)); + + if (!vxi.used) + { + hawk_seterrbfmt(hawk, &vxi.loc, HAWK_EUNUSED, "unused global variable '%.*js'", ptl->len, ptl->ptr); + goto oops; + } + } + } + HAWK_ASSERT(hawk->tree.ngbls == HAWK_ARR_SIZE(hawk->parse.gbls)); HAWK_ASSERT(hawk->sio.inp == &hawk->sio.arg); ret = 0; @@ -879,7 +898,7 @@ static int begin_include (hawk_t* hawk, int once) arg->pragma_trait = hawk->parse.pragma.trait; /* but don't change hawk->parse.pragma.trait. it means the included file inherits * the existing progma values. - hawk->parse.pragma.trait = (hawk->opt.trait & (HAWK_IMPLICIT | HAWK_MULTILINESTR | HAWK_STRIPRECSPC | HAWK_STRIPSTRSPC)); + hawk->parse.pragma.trait = (hawk->opt.trait & (HAWK_IMPLICIT | HAWK_MULTILINESTR | HAWK_PEDANTIC | HAWK_RWPIPE | HAWK_STRIPRECSPC | HAWK_STRIPSTRSPC)); */ /* update the current pointer after opening is successful */ @@ -1022,12 +1041,15 @@ static int parse_progunit (hawk_t* hawk) /* 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) || + ((trait = HAWK_PEDANTIC) && hawk_comp_oochars_oocstr(name.ptr, name.len, HAWK_T("pedantic"), 0) == 0) || ((trait = HAWK_RWPIPE) && hawk_comp_oochars_oocstr(name.ptr, name.len, HAWK_T("rwpipe"), 0) == 0)) { /* @pragma implicit on * @pragma implicit off * @pragma multilinestr on * @pragma multilinestr off + * @pragma pedantic on + * @pragma pedantic off * @pragma rwpipe on * @pragma rwpipe off * @@ -1835,6 +1857,27 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags) } } + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + hawk_oow_t i; + for (i = nlcls_outer ; i < HAWK_ARR_SIZE(hawk->parse.lcls); i++) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t vxi; + + ptl = HAWK_ARR_DPTL(hawk->parse.lcls, i); + HAWK_MEMCPY(&vxi, (const hawk_ooch_t*)ptl->ptr + ptl->len, HAWK_SIZEOF(vxi)); + + if (!vxi.used) + { + hawk_seterrbfmt(hawk, &vxi.loc, HAWK_EUNUSED, "unused local variable '%.*js'", ptl->len, ptl->ptr); + hawk_arr_delete(hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); + hawk_clrpt(hawk, head); + return HAWK_NULL; + } + } + } + block = (hawk_nde_blk_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*block)); if (HAWK_UNLIKELY(!block)) { @@ -1980,6 +2023,7 @@ static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name) static int add_global (hawk_t* hawk, const hawk_oocs_t* name, hawk_loc_t* xloc, int disabled) { hawk_oow_t ngbls; + hawk_oow_t n; /* check if it is a keyword */ if (classify_ident(hawk, name) != TOK_IDENT) @@ -2042,7 +2086,8 @@ static int add_global (hawk_t* hawk, const hawk_oocs_t* name, hawk_loc_t* xloc, return -1; } - if (hawk_arr_insert(hawk->parse.gbls, HAWK_ARR_SIZE(hawk->parse.gbls), (hawk_ooch_t*)name->ptr, name->len) == HAWK_ARR_NIL) + n = hawk_arr_insert(hawk->parse.gbls, HAWK_ARR_SIZE(hawk->parse.gbls), (hawk_ooch_t*)name->ptr, name->len); + if (n == HAWK_ARR_NIL) { const hawk_ooch_t* bem = hawk_backuperrmsg(hawk); hawk_seterrfmt(hawk, xloc, hawk_geterrnum(hawk), @@ -2050,6 +2095,16 @@ static int add_global (hawk_t* hawk, const hawk_oocs_t* name, hawk_loc_t* xloc, name->len, name->ptr, bem); return -1; } + else if (hawk->parse.pragma.trait & HAWK_PEDANTIC) /* a variable collected when pendatic on will xinfo */ + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + /* remember location information of each local variable collected */ + ptl = HAWK_ARR_DPTL(hawk->parse.gbls, n); /* n is the position of the inserted name */ + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + if (xloc) vxi->loc = *xloc; + else vxi->used = 1; /* if xloc is not given, it's not declared with @global. set used to 1 for simple check */ + } HAWK_ASSERT(ngbls == HAWK_ARR_SIZE(hawk->parse.gbls) - 1); @@ -2459,11 +2514,21 @@ static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int flags) return HAWK_NULL; } - if (hawk_arr_insert(hawk->parse.lcls, HAWK_ARR_SIZE(hawk->parse.lcls), lcl.ptr, lcl.len) == HAWK_ARR_NIL) + n = hawk_arr_insert(hawk->parse.lcls, HAWK_ARR_SIZE(hawk->parse.lcls), lcl.ptr, lcl.len); + if (n == HAWK_ARR_NIL) { ADJERR_LOC(hawk, &hawk->tok.loc); return HAWK_NULL; } + else if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + /* remember location information of each local variable collected */ + ptl = HAWK_ARR_DPTL(hawk->parse.lcls, n); /* n is the position of the inserted name */ + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + vxi->loc = hawk->tok.loc; + } if (get_token(hawk) <= -1) return HAWK_NULL; @@ -5943,6 +6008,17 @@ static hawk_nde_t* parse_primary_ident_noseg (hawk_t* hawk, const hawk_loc_t* xl else if ((idxa = hawk_arr_rsearch(hawk->parse.lcls, HAWK_ARR_SIZE(hawk->parse.lcls), name->ptr, name->len)) != HAWK_ARR_NIL) { /* local variable */ + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + /* note an extra space has been reserved in each slot value + * when initializing hawk->parser.lcls */ + ptl = HAWK_ARR_DPTL(hawk->parse.lcls, idxa); + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + vxi->used = 1; /* mark that the variable has been referenced */ + } + nde = parse_variable(hawk, xloc, HAWK_NDE_LCL, name, idxa); } else if ((idxa = hawk_arr_search(hawk->parse.params, 0, name->ptr, name->len)) != HAWK_ARR_NIL) @@ -5953,6 +6029,17 @@ static hawk_nde_t* parse_primary_ident_noseg (hawk_t* hawk, const hawk_loc_t* xl else if ((idxa = get_global(hawk, name)) != HAWK_ARR_NIL) { /* global variable */ + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + /* note an extra space has been reserved in each slot value + * when initializing hawk->parser.gbls */ + ptl = HAWK_ARR_DPTL(hawk->parse.gbls, idxa); + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + vxi->used = 1; /* mark that the variable has been referenced */ + } + nde = parse_variable(hawk, xloc, HAWK_NDE_GBL, name, idxa); } else @@ -6309,6 +6396,16 @@ more_idx: nde->id.idxa = idxa; nde->idx = idx; + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + ptl = HAWK_ARR_DPTL(hawk->parse.lcls, idxa); + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + vxi->used = 1; + if (xloc) vxi->loc = *xloc; + } + return (hawk_nde_t*)nde; } @@ -6339,6 +6436,16 @@ more_idx: nde->id.idxa = idxa; nde->idx = idx; + if (hawk->parse.pragma.trait & HAWK_PEDANTIC) + { + const hawk_ptl_t* ptl; + hawk_var_xinfo_t* vxi; + ptl = HAWK_ARR_DPTL(hawk->parse.gbls, idxa); + vxi = (hawk_var_xinfo_t*)((hawk_ooch_t*)ptl->ptr + ptl->len); + vxi->used = 1; + if (xloc) vxi->loc = *xloc; + } + return (hawk_nde_t*)nde; } diff --git a/t/t-001.c b/t/t-001.c index 5a3bf553..307fdf39 100644 --- a/t/t-001.c +++ b/t/t-001.c @@ -109,7 +109,7 @@ int main () hawk_uint128_t u128; hawk_uint8_t arr[16]; } x; - hawk_uint128_t tmp; + /*hawk_uint128_t tmp;*/ x.arr[0] = 0x11; x.arr[1] = 0x22;