Index: generic/nsf.c =================================================================== diff -u -rdc4e227d31df104be7df072ee78f2779ff387b9e -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- generic/nsf.c (.../nsf.c) (revision dc4e227d31df104be7df072ee78f2779ff387b9e) +++ generic/nsf.c (.../nsf.c) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -862,7 +862,7 @@ } #endif - if (unlikely(status)) { + if (unlikely(status != 0)) { if (status & NSF_PC_STATUS_MUST_DECR) { int i; /*fprintf(stderr, "ParseContextRelease %p loop from 0 to %d\n", pcPtr, pcPtr->objc-1);*/ @@ -21027,7 +21027,7 @@ object = tcd->object; tcd->object = NULL; - + Nsf_PushFrameObj(interp, object, framePtr); result = Tcl_NRCallObjProc(interp, tcd->objProc, tcd->clientData, objc, objv); Nsf_PopFrameObj(interp, framePtr); @@ -21716,7 +21716,7 @@ * ArgumentParse -- * * Parse the provided ist of argument against the given definition. The - * result is returned in the parameter context structure. + * result is returned in the parse context structure. * * Results: * Standard Tcl result. @@ -25138,6 +25138,62 @@ } /* +cmd parseargs NsfParseArgsCmd { + {-argName "argspec" -required 1 -type tclobj} + {-argName "arglist" -required 1 -type tclobj} +} {-nxdoc 0} +*/ +static int +NsfParseArgsCmd(Tcl_Interp *interp, Tcl_Obj *argspecObj, Tcl_Obj *arglistObj) { + NsfParsedParam parsedParam; + unsigned int processFlags = 0u; + Tcl_Obj **objv; + int result, objc; + + result = ParamDefsParse(interp, NsfGlobalObjs[NSF_PARSE_ARGS], argspecObj, + NSF_DISALLOWED_ARG_METHOD_PARAMETER, 0, + &parsedParam); + + if (unlikely(result != TCL_OK)) { + return result; + } + + result = Tcl_ListObjGetElements(interp, arglistObj, &objc, &objv); + if (likely(result == TCL_OK)) { + ParseContext pc; + NsfParamDefs *paramDefs = parsedParam.paramDefs; + + result = ArgumentParse(interp, objc, objv, NULL, NsfGlobalObjs[NSF_PARSE_ARGS], + paramDefs->paramsPtr, paramDefs->nrParams, paramDefs->serial, + processFlags|NSF_ARGPARSE_START_ZERO|RUNTIME_STATE(interp)->doCheckArguments, + &pc); + + if (result == TCL_OK) { + Nsf_Param *paramPtr; + Tcl_Obj *resultObj; + int i; + + for (i = 0, paramPtr = paramDefs->paramsPtr; paramPtr->name; paramPtr++, i++) { + Tcl_Obj *valueObj = pc.objv[i]; + + if (valueObj != NsfGlobalObjs[NSF___UNKNOWN__]) { + /*fprintf(stderr, "param %s -> <%s>\n", paramPtr->name, ObjStr(valueObj));*/ + resultObj = Tcl_ObjSetVar2(interp, paramPtr->nameObj, NULL, valueObj, TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); + if (resultObj == NULL) { + result = TCL_ERROR; + break; + } + } + } + + ParseContextRelease(&pc); + } + + } + return result; +} + +/* cmd method::alias NsfMethodAliasCmd { {-argName "object" -type object} {-argName "-per-object"} @@ -25667,7 +25723,7 @@ cl = withPer_object == 0 && NsfObjectIsClass(object) ? (NsfClass *)object : NULL; fromClassNS = (cl != NULL); - + cmd = ResolveMethodName(interp, (cl != NULL) ? cl->nsPtr : object->nsPtr, methodObj, NULL, NULL, &defObject, NULL, &fromClassNS); /*fprintf(stderr, "methodProperty for method '%s' prop %d value %s => cl %p cmd %p\n", Index: generic/nsfAPI.decls =================================================================== diff -u -r4fa580aed7f0c54c8e09ec6bb1fc1b46789334ed -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision 4fa580aed7f0c54c8e09ec6bb1fc1b46789334ed) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -110,7 +110,6 @@ {-argName "value" -required 1 -type tclobj} } {-nxdoc 1} - cmd parameter::info NsfParameterInfoCmd { {-argName "subcmd" -typeName "parametersubcmd" -type "default|list|name|syntax|type" -required 1} {-argName "spec" -required 1 -type tclobj} @@ -131,6 +130,11 @@ {-argName "slotobjs" -required 1 -type tclobj} } +cmd parseargs NsfParseArgsCmd { + {-argName "argspec" -required 1 -type tclobj} + {-argName "arglist" -required 1 -type tclobj} +} {-nxdoc 0} + # # cmd cmds (maybe more later) # Index: generic/nsfAPI.h =================================================================== diff -u -rdadf28efd0707ae40076f49837e6b45ad5b2a989 -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- generic/nsfAPI.h (.../nsfAPI.h) (revision dadf28efd0707ae40076f49837e6b45ad5b2a989) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -295,7 +295,7 @@ /* just to define the symbol */ -static Nsf_methodDefinition method_definitions[113]; +static Nsf_methodDefinition method_definitions[114]; static const char *method_command_namespace_names[] = { "::nsf::methods::object::info", @@ -417,6 +417,8 @@ NSF_nonnull(2) NSF_nonnull(4); static int NsfParameterSpecsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) NSF_nonnull(2) NSF_nonnull(4); +static int NsfParseArgsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) + NSF_nonnull(2) NSF_nonnull(4); static int NsfProcCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) NSF_nonnull(2) NSF_nonnull(4); static int NsfProfileClearDataStubStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) @@ -642,6 +644,8 @@ NSF_nonnull(1) NSF_nonnull(3); static int NsfParameterSpecsCmd(Tcl_Interp *interp, int withConfigure, int withNonposargs, Tcl_Obj *slotobjs) NSF_nonnull(1) NSF_nonnull(4); +static int NsfParseArgsCmd(Tcl_Interp *interp, Tcl_Obj *argspec, Tcl_Obj *arglist) + NSF_nonnull(1) NSF_nonnull(2) NSF_nonnull(3); static int NsfProcCmd(Tcl_Interp *interp, int withAd, int withCheckalways, int withDebug, int withDeprecated, Tcl_Obj *procName, Tcl_Obj *arguments, Tcl_Obj *body) NSF_nonnull(1) NSF_nonnull(6) NSF_nonnull(7) NSF_nonnull(8); static int NsfProfileClearDataStub(Tcl_Interp *interp) @@ -811,6 +815,7 @@ NsfParameterCacheObjectInvalidateCmdIdx, NsfParameterInfoCmdIdx, NsfParameterSpecsCmdIdx, + NsfParseArgsCmdIdx, NsfProcCmdIdx, NsfProfileClearDataStubIdx, NsfProfileGetDataStubIdx, @@ -2239,6 +2244,27 @@ } static int +NsfParseArgsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) { + ParseContext pc; + (void)clientData; + + if (likely(ArgumentParse(interp, objc, objv, NULL, objv[0], + method_definitions[NsfParseArgsCmdIdx].paramDefs, + method_definitions[NsfParseArgsCmdIdx].nrParameters, 0, NSF_ARGPARSE_BUILTIN, + &pc) == TCL_OK)) { + Tcl_Obj *argspec = (Tcl_Obj *)pc.clientData[0]; + Tcl_Obj *arglist = (Tcl_Obj *)pc.clientData[1]; + + assert(pc.status == 0); + return NsfParseArgsCmd(interp, argspec, arglist); + + } else { + + return TCL_ERROR; + } +} + +static int NsfProcCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST* objv) { ParseContext pc; (void)clientData; @@ -3476,7 +3502,7 @@ } } -static Nsf_methodDefinition method_definitions[113] = { +static Nsf_methodDefinition method_definitions[114] = { {"::nsf::methods::class::alloc", NsfCAllocMethodStub, 1, { {"objectName", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, @@ -3753,6 +3779,10 @@ {"-nonposargs", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"slotobjs", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, +{"::nsf::parseargs", NsfParseArgsCmdStub, 2, { + {"argspec", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, + {"arglist", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} +}, {"::nsf::proc", NsfProcCmdStub, 7, { {"-ad", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"-checkalways", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, Index: generic/nsfAPI.nxdocindex =================================================================== diff -u -r5a162b098b6a9550218646d470b274769bda8da1 -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- generic/nsfAPI.nxdocindex (.../nsfAPI.nxdocindex) (revision 5a162b098b6a9550218646d470b274769bda8da1) +++ generic/nsfAPI.nxdocindex (.../nsfAPI.nxdocindex) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -19,6 +19,7 @@ set ::nxdoc::include(::nsf::parameter::cache::classinvalidate) 0 set ::nxdoc::include(::nsf::parameter::cache::objectinvalidate) 0 set ::nxdoc::include(::nsf::parameter::specs) 0 +set ::nxdoc::include(::nsf::parseargs) 0 set ::nxdoc::include(::nsf::cmd::info) 1 set ::nxdoc::include(::nsf::method::alias) 1 set ::nxdoc::include(::nsf::method::assertion) 1 Index: generic/nsfInt.h =================================================================== diff -u -rdc4e227d31df104be7df072ee78f2779ff387b9e -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- generic/nsfInt.h (.../nsfInt.h) (revision dc4e227d31df104be7df072ee78f2779ff387b9e) +++ generic/nsfInt.h (.../nsfInt.h) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -705,6 +705,7 @@ NSF_METHOD, NSF_OBJECT, NSF_SETTER, NSF_SETTERNAME, NSF_VALUECHECK, NSF_GUARD_OPTION, NSF___UNKNOWN__, NSF_ARRAY, NSF_GET, NSF_SET, NSF_OPTION_STRICT, NSF_OBJECT_UNKNOWN_HANDLER, NSF_ARGUMENT_UNKNOWN_HANDLER, + NSF_PARSE_ARGS, /* Partly redefined Tcl commands; leave them together at the end */ NSF_EXPR, NSF_FORMAT, NSF_INFO_BODY, NSF_INFO_FRAME, NSF_INTERP, NSF_STRING_IS, NSF_EVAL, @@ -731,6 +732,7 @@ /* nsf tcl commands */ "::nsf::object::unknown", "::nsf::argument::unknown", + "::nsf::parseargs", /* tcl commands */ "expr", "format", "::tcl::info::body", "::tcl::info::frame", "interp", "::tcl::string::is", "::eval", Index: tests/parameters.test =================================================================== diff -u -rdadf28efd0707ae40076f49837e6b45ad5b2a989 -r546f8ddb033b81b5a4f9836d4f5541c9f68ac306 --- tests/parameters.test (.../parameters.test) (revision dadf28efd0707ae40076f49837e6b45ad5b2a989) +++ tests/parameters.test (.../parameters.test) (revision 546f8ddb033b81b5a4f9836d4f5541c9f68ac306) @@ -3149,7 +3149,28 @@ ? {::f1 cget -x} "3" } + # +# Testing nsf::parseargs +# + +nx::test case parseargs { + + ? {nsf::parseargs {a:int} {1}; info exists a} "1" + ? {nsf::parseargs {a:int} {1}; info exists b} "0" + ? {nsf::parseargs {a:int} {a}} {expected integer but got "a" for parameter "a"} + + ? { + nsf::parseargs {-foo:int {-bar:int 2} baz} {hi} + list [info exists foo] [info exists bar] [info exists baz] + } "0 1 1" + + ? {set bar} 2 + ? {set baz} hi +} + + +# # Local variables: # mode: tcl # tcl-indent-level: 2