From: larrybr Date: Sat, 19 Mar 2022 14:27:57 +0000 (+0000) Subject: macro-ize extension boiler-plate, improve exit processing X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ff98736baf31623e3727b8c0bc22efaeeef9312e;p=thirdparty%2Fsqlite.git macro-ize extension boiler-plate, improve exit processing FossilOrigin-Name: 7996d3a359ab90ef9f42f501e0ddb2efa964a906739116836cb1eafe2a96a0ed --- diff --git a/manifest b/manifest index 6be225a162..9ca7448206 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\smigration\sto\scentralized\serror\sreporting -D 2022-03-18T16:00:07.658 +C macro-ize\sextension\sboiler-plate,\simprove\sexit\sprocessing +D 2022-03-19T14:27:57.463 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -555,8 +555,8 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 4890a3cfee0bc60ff231c3a44db37968859ab0be156983dbcc0c096109832cdd -F src/shell.c.in e1214665c269fad77b3cb6cb679939337a7259fecf189276b398a88d4653d4d6 -F src/shext_linkage.h 7c8ac3970d81c20c752e58860cc1a0f4521889152766a6cbcbd2734fcba6232d +F src/shell.c.in acb97f8ad071498a35748d31b86d5797745ba236e042d54ae31adb8c23a27581 +F src/shext_linkage.h 6c75ac9690965ae6968b5b246f83bde6bac9f13a248e5ac0f5775d2ad8a35496 F src/sqlite.h.in 5845213799feca09cd69d18ff841a85fe0df31021f46aaa1797e703e80dc1d70 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 @@ -605,7 +605,7 @@ F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe -F src/test_shellext.c 049533eae21ff0c041ff97d2681f3005e612fc33b3824ef7b6525a719180115e +F src/test_shellext.c 0d07a78ac1487532f39ac93eafff0240e861f8f3430205af62b937136b6dbd49 F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939 @@ -1949,8 +1949,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3457f87c5db7a28eb6a47223f7853cd066245edfe1882feabbdb8ce9555f872e 72029cf7cdb266703cc8716102dbba8e6f2666e1f47409f42c39528795757b73 -R e4977d7e43e565456c0cd3ce58d731ce +P 898088008e2d15f89941db433f743594aea1351f353c12ce3932a39902dfb161 +R 129774c9c2e8cac58d8036d38701569e U larrybr -Z 7cb1fae332b9ca509f4fbb346c55037d +Z 76b79faefcf881b072c961370ce1a08d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4f13331843..9c7218fc0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -898088008e2d15f89941db433f743594aea1351f353c12ce3932a39902dfb161 \ No newline at end of file +7996d3a359ab90ef9f42f501e0ddb2efa964a906739116836cb1eafe2a96a0ed \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 4823c234ff..c8e80184b0 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1574,7 +1574,7 @@ static int failIfSafeMode( va_end(ap); raw_printf(STD_ERR, "line %d: ", ISS(psx)->pInSource->lineno); utf8_printf(STD_ERR, "%s\n", zMsg); - psx->shellAbruptExit = 3; + psx->shellAbruptExit = 0x202; return 1; } return 0; @@ -8498,20 +8498,39 @@ DISPATCHABLE_COMMAND( eqp ? 0 0 ){ } /***************** - * The .exit and .quit commands - * These are together so that their subtle differences are apparent. + * The .cease, .exit and .quit commands + * These are together so that their differing effects are apparent. */ +CONDITION_COMMAND(cease defined(SHELL_CEASE)); COLLECT_HELP_TEXT[ - ".exit ?CODE? Exit this program with return-code CODE", - ".quit Exit this program or script", + ".cease ?CODE? Cease shell operation, with optional return code", + " Return code defaults to 0, otherwise is limited to non-signal values", + ".exit ?CODE? Exit shell program, maybe with return-code CODE", + " Exit immediately if CODE != 0, else functions as \"quit this input\"", + ".quit Quit processing this input or script", ]; +DISPATCHABLE_COMMAND( cease 4 1 2 ){ + /* .cease effects an exit, always. Only the exit code is variable. */ + int rc = 0; + if( nArg>1 ){ + rc = (int)integerValue(azArg[1]); + if( rc>0x7f ) rc = 0x7f; + } + p->shellAbruptExit = 0x100|rc; + return DCR_Exit; +} DISPATCHABLE_COMMAND( exit 3 1 0 ){ + /* .exit acts like .quit with no argument or a zero argument, + * only returning. With a non-zero argument, it effects an exit. */ int rc; - if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) - p->shellAbruptExit = rc; + if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ){ + rc &= 0xff; /* Mimic effect of legacy call to exit(). */ + p->shellAbruptExit = 0x100|rc; + } return DCR_Return; } DISPATCHABLE_COMMAND( quit 1 1 0 ){ + /* .quit would be more aptly named .return, as it does nothing more. */ return DCR_Return; } @@ -13204,7 +13223,8 @@ static DotCmdRC do_meta_command(char *zLine, ShellExState *psx){ dispatchResult = dispatchCommand(azArg, nArg, psx, &zErr); if( psx->shellAbruptExit!=0 ){ - dispatchResult = DCR_AbortError; + if( psx->shellAbruptExit>0x1ff ) dispatchResult = DCR_AbortError; + else dispatchResult = DCR_Exit | (dispatchResult&DCR_Error); } if( dispatchResult==DCR_CmdErred ){ /* Error message(s) already emitted. Just translate to execute error. */ @@ -13297,13 +13317,13 @@ static DotCmdRC do_meta_command(char *zLine, ShellExState *psx){ /* Handle execution errors. */ if( dispatchResult==DCR_AbortError ){ if( zErr!=0 ){ - utf8_printf(STD_ERR, "Error: \".%s\" may not %s in --safe mode\n", + utf8_printf(STD_ERR, "Error: \".%s\" may not %s in -safe mode\n", azArg[0], zErr); }else { - utf8_printf(STD_ERR, "Error: \".%s\" forbidden in --safe mode\n", + utf8_printf(STD_ERR, "Error: \".%s\" forbidden in -safe mode\n", azArg[0]); } - psx->shellAbruptExit = 3; + psx->shellAbruptExit = 0x203; }else{ int error = dispatchResult & DCR_Error; int action = dispatchResult & ~DCR_Error; @@ -13905,7 +13925,7 @@ static DotCmdRC process_input(ShellInState *psi){ break; } if( XSS(psi)->shellAbruptExit!=0 ){ - termKind = XSS(psi)->shellAbruptExit; + termKind = DCR_Exit; } break; case Erroneous: @@ -14017,7 +14037,7 @@ static int run_single_query(ShellExState *psx, char *zSql){ }else{ utf8_printf(STD_ERR,"Error: unable to process SQL \"%s\"\n", zSql); } - psx->shellAbruptExit = (rc==0)? 1 : rc; + psx->shellAbruptExit = (rc==0)? 0x100 : 0x102; rc = 2; } return rc; @@ -14061,7 +14081,9 @@ static void process_sqliterc( rc = process_input(psi); fclose(inUse); psi->pInSource = inSourceRedir.pFrom; - if( rc>DCR_Ok && bail_on_error ) XSS(psi)->shellAbruptExit = rc; + if( rc>DCR_Ok && bail_on_error ){ + XSS(psi)->shellAbruptExit = 0x100|((rc>>1)&0x3); + } }else if( sqliterc_override!=0 ){ utf8_printf(STD_ERR,"cannot open: \"%s\"\n", sqliterc); if( bail_on_error ) exit(1); /* Future: Exit shell rather than process. */ @@ -14843,10 +14865,9 @@ int SQLITE_CDECL SHELL_MAIN(int argc, wchar_t **wargv){ * exit code or an abnormal exit code. Its abnormal values take priority. */ /* Check for an abnormal exit, and issue error if so. */ - if( rc>2 || aec>1 ){ - rc = (rc255 ) rc = 255; /* Clamp to valid error exit range. */ - raw_printf(STD_ERR, "Abnormal exit (%d)\n", rc); + if( aec!=0 ){ + rc = aec & 0xff; + if( aec>0x1ff ) raw_printf(STD_ERR, "Abnormal exit (%d)\n", rc); }else{ /* rc is one of 0,1,2, mapping to 0,1,0 shellexit codes. */ rc &= ~2; diff --git a/src/shext_linkage.h b/src/shext_linkage.h index db12ec42f4..b1d33c4751 100644 --- a/src/shext_linkage.h +++ b/src/shext_linkage.h @@ -41,10 +41,11 @@ typedef struct ShellExState { /* Output stream to which shell's text output to be written (reference) */ FILE **ppCurrentOutput; - /* Whether to exit as command completes. + /* Shell abrupt exit indicator with return code in LS-byte * 0 => no exit - * ~0 => a non-error (0) exit - * other => exit with process exit code other + * 0x100 => a non-error (0) exit + * 0x100|other => exit with process exit code other + * Any value greater than 0x1ff indicates an abnormal exit. * For embedded shell, "exit" means "return from REPL function". */ int shellAbruptExit; @@ -170,6 +171,25 @@ PURE_VMETHOD(void, closeDataInStream, ImportHandler, 2,( ShellExState *pSES, char **pzErr )); INTERFACE_END( ImportHandlerVtable ); +/* Define an implementation's v-table matching the MetaCommand interface. + * Method signatures are copied and pasted from above interface declaration. + */ +#define MetaCommand_IMPLEMENT_VTABLE(Derived, vtname) \ +CONCRETE_BEGIN(MetaCommand, Derived); \ +CONCRETE_METHOD(const char *, name, MetaCommand, 0,()); \ +CONCRETE_METHOD(const char *, help, MetaCommand, 1,(int more)); \ +CONCRETE_METHOD(DotCmdRC, argsCheck, MetaCommand, 3, \ + (char **pzErrMsg, int nArgs, char *azArgs[])); \ +CONCRETE_METHOD(DotCmdRC, execute, MetaCommand, 4, \ + (ShellExState *, char **pzErrMsg, int nArgs, char *azArgs[])); \ +CONCRETE_END(Derived) vtname = { \ + DECORATE_METHOD(Derived,destruct), \ + DECORATE_METHOD(Derived,name), \ + DECORATE_METHOD(Derived,help), \ + DECORATE_METHOD(Derived,argsCheck), \ + DECORATE_METHOD(Derived,execute) \ +} + /* This function pointer has the same signature as the sqlite3_X_init() * function that is called as SQLite3 completes loading an extension. */ diff --git a/src/test_shellext.c b/src/test_shellext.c index 1db2b5da28..981e865120 100644 --- a/src/test_shellext.c +++ b/src/test_shellext.c @@ -20,9 +20,12 @@ SQLITE_EXTENSION_INIT1; static struct ShExtAPI *pShExtApi = 0; static struct ExtHelpers *pExtHelpers = 0; +typedef struct BatBeing BatBeing; +static void sayHowMany( BatBeing *pbb, FILE *out, ShellExState *psx ); + /* These DERIVED_METHOD(...) macro calls' arguments were copied and * pasted from the MetaCommand interface declaration in shext_linkage.h , - * but with Interface,Derived substituted for the interface typename. + * but with "Interface,Derived" substituted for the interface typename. * The function bodies are not so easily written, of course. */ DERIVED_METHOD(void, destruct, MetaCommand,BatBeing, 0, ()){ @@ -47,9 +50,6 @@ DERIVED_METHOD(DotCmdRC, argsCheck, MetaCommand,BatBeing, 3, return DCR_Ok; } -typedef struct BatBeing BatBeing; -static void sayHowMany( struct BatBeing *pbb, FILE *out, ShellExState *psx ); - DERIVED_METHOD(DotCmdRC, execute, MetaCommand,BatBeing, 4, (ShellExState *psx, char **pzErrMsg, int nArgs, char *azArgs[])){ FILE *out = pExtHelpers->currentOutputFile(psx); @@ -58,45 +58,37 @@ DERIVED_METHOD(DotCmdRC, execute, MetaCommand,BatBeing, 4, case 2: fprintf(out, "The Dynamic Duo arrives, and ... "); case 1: fprintf(out, "@#$ KaPow! $#@\n"); } - sayHowMany((struct BatBeing *)pThis, out, psx); + sayHowMany((BatBeing *)pThis, out, psx); return DCR_Ok; } -/* Note that these CONCRETE_METHOD... macro calls' arguments were copied and - * pasted from the MetaCommand interface declaration in shext_linkage.h . - * In a future version of shext_linkage.h, this will all be a mondo maco. */ -CONCRETE_BEGIN(MetaCommand, BatBeing); -CONCRETE_METHOD(const char *, name, MetaCommand, 0,()); -CONCRETE_METHOD(const char *, help, MetaCommand, 1,(int more)); -CONCRETE_METHOD(DotCmdRC, argsCheck, MetaCommand, 3, - (char **pzErrMsg, int nArgs, char *azArgs[])); -CONCRETE_METHOD(DotCmdRC, execute, MetaCommand, 4, - (ShellExState *, char **pzErrMsg, int nArgs, char *azArgs[])); -CONCRETE_END(BatBeing) batty_methods = { - DECORATE_METHOD(BatBeing,destruct), - DECORATE_METHOD(BatBeing,name), - DECORATE_METHOD(BatBeing,help), - DECORATE_METHOD(BatBeing,argsCheck), - DECORATE_METHOD(BatBeing,execute) -}; +/* Define a MetaCommand v-table initialized to reference above methods. */ +MetaCommand_IMPLEMENT_VTABLE(BatBeing, batty_methods); +/* Define/initialize BatBeing as a MetaCommand subclass using above v-table. + * This compiles in a type-safe manner because the batty_methods v-table + * and methods it incorporates strictly match the MetaCommand interface. + */ INSTANCE_BEGIN(BatBeing); int numCalls; - MetaCommand * pShow; + MetaCommand * pPrint; INSTANCE_END(BatBeing) batty = { &batty_methods, 0, 0 }; -static void sayHowMany( struct BatBeing *pbb, FILE *out, ShellExState *psx ){ - fprintf(out, "This execute has been called %d times.\n", ++pbb->numCalls); - if( pbb->pShow ){ - char *az[] = { "show" }; +static void sayHowMany( BatBeing *pbb, FILE *out, ShellExState *psx ){ + if( pbb->pPrint ){ + char *az[] = { "print", 0 }; char *zErr = 0; - MetaCommand * pmcShow = (MetaCommand *)pbb->pShow; - DotCmdRC rc = pmc->pMethods->execute(pmc, psx, &zErr, 1, az); + MetaCommand * pmcPrint = pbb->pPrint; + DotCmdRC rc; + az[1] = sqlite3_mprintf("This execute has been called %d times.\n", + ++pbb->numCalls); + rc = pmcPrint->pMethods->execute(pmcPrint, psx, &zErr, 2, az); + sqlite3_free(az[1]); if( rc!= DCR_Ok ){ - fprintf(out, "show() failed: %d\n", rc); + fprintf(out, "print() failed: %d\n", rc); } } } @@ -126,7 +118,7 @@ int sqlite3_testshellext_init( pShExtApi = & pShExtLink->pShellExtensionAPI->api.named; pExtHelpers = & pShExtLink->pShellExtensionAPI->pExtHelpers->helpers.named; - batty.pShow = pExtHelpers->findMetaCommand("show", psx, &rc); + batty.pPrint = pExtHelpers->findMetaCommand("print", psx, &rc); rc = pShExtApi->registerMetaCommand(psx, sqlite3_testshellext_init,pmc); if( rc!=0 ) ++nErr; }