Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | more changes in topcua for type handling |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
416a0ae7c1fc7fafd90830dca5d13f5c |
User & Date: | chw 2020-07-30 04:58:24.888 |
Context
2020-08-02
| ||
16:54 | heavy refactoring in topcua incl. beginning of a nodeset loader check-in: 01b7d7cc94 user: chw tags: trunk | |
2020-07-30
| ||
04:58 | more changes in topcua for type handling check-in: 416a0ae7c1 user: chw tags: trunk | |
2020-07-28
| ||
04:39 | update topcua for some open62541 1.x diffs in type handling etc. check-in: 15e21d4fcc user: chw tags: trunk | |
Changes
Changes to jni/topcua/doc/opcua.n.
︙ | ︙ | |||
484 485 486 487 488 489 490 | \fBopcua endpoints\fR ?\fIurl\fR? . Queries the local OPC/UA server \fBopc.tcp://localhost:4840\fR or the server specified by the \fIurl\fR parameter for endpoints and returns a list of deserialized dictionaries based on the \fBUA_EndpointDescription\fR structure. Consult the \fBopen62541\fR documentation for more information. .TP | | > > | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | \fBopcua endpoints\fR ?\fIurl\fR? . Queries the local OPC/UA server \fBopc.tcp://localhost:4840\fR or the server specified by the \fIurl\fR parameter for endpoints and returns a list of deserialized dictionaries based on the \fBUA_EndpointDescription\fR structure. Consult the \fBopen62541\fR documentation for more information. .TP \fBopcua genstubs\fR \fIhandle\fR ?\fIstrip substs ...\fR? . Generates stubs for methods in the handle specific address space derived from the client or server object \fIhandle\fR. The address space is traversed and browse paths and node class paths are accumulated. The resulting browse paths optionally get the prefix \fIstrip\fR stripped off from the beginning and optionally filtered using the glob patterns following the \fIsubsts\fR parameter. If \fIsubsts\fR is not empty it specifies pairwise regexps and substitutions which are applied on the browse paths for the final procedure names. For all nodes matching the node class path pattern \fIObject/Method\fR the optional \fIInputArguments\fR and \fIOutputArguments\fR child nodes are retrieved and stub procedures are written using the browse path and argument information. .TP \fBopcua gentypes\fR \fIhandle\fR . Generates custom data type mappings using information obtained from analyzing |
︙ | ︙ |
Changes to jni/topcua/library/topcua.tcl.
︙ | ︙ | |||
152 153 154 155 156 157 158 | break } return $ret } # Generate stubs for methods in sub-namespace derived from # client or server name. Argument "strip" is cut off from the begin | > > | | | | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | break } return $ret } # Generate stubs for methods in sub-namespace derived from # client or server name. Argument "strip" is cut off from the begin # of browse paths. Argument "substs" is a list of regexp/substitution # elements which are applied in order on the browse path. All following # arguments are glob patterns for matching in browse paths before the # substitutions are applied. The entire address space is processed # by using the root node as base for retrieving the tree of names. # Example: # # opcua::new client Pumps # opcua::connect Pumps ... # opcua::genstubs Pumps /Root/Objects/2:Pumps/2: # # writes these procs (assuming there are Pump_1 and Pump_2 objects # each having a Start and a Stop method with zero input arguments): # # proc opcua::Pumps::Pump_1/Start {} ... # proc opcua::Pumps::Pump_1/Stop {} ... # proc opcua::Pumps::Pump_2/Start {} ... # proc opcua::Pumps::Pump_2/Stop {} ... proc genstubs {handle {strip {}} {substs {}} args} { ::namespace eval ::opcua::$handle {} set all [expr {[llength $args] == 0}] set root [root] if {$all && ([string first /Root/Objects $strip] == 0)} { # speed up for common place set strip [string range $strip 5 end] set root [lindex [translate $handle $root / Objects] 0] |
︙ | ︙ | |||
197 198 199 200 201 202 203 | if {[string match $pat $b]} { set found 1 break } } } if {$found} { | | > > > > > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | if {[string match $pat $b]} { set found 1 break } } } if {$found} { # procname will be method path with prefix stripped ... set b [string range $b [string length $strip] end] # ... and mangled by substitutions set st {} foreach {re st} $substs { regsub -all -- $re $b $st b } # the opcua::call object is the method's parent set o [parent $handle $n] # parameter list for proc set plist {} # arguments (type and name pairs) for opcua::call set alist {} if {![catch {translate $handle $n / InputArguments} ia]} { |
︙ | ︙ | |||
250 251 252 253 254 255 256 | # namespaces { prefix uri ... } # enums { enumname { bit-width itemname value ... } ... } # structs { structname { type fieldname ... } ... } # # This function needs tDOM for XML processing! proc _readbsd {string} { | > > > > | | > > > | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | # namespaces { prefix uri ... } # enums { enumname { bit-width itemname value ... } ... } # structs { structname { type fieldname ... } ... } # # This function needs tDOM for XML processing! proc _readbsd {string} { dict set out namespaces {} dict set out enums {} dict set out structs {} if {[catch { package require tdom set doc [dom parse $string] }]} { return $out } set root [$doc documentElement] # process namespaces array set ns {} foreach attr [$root attributes] { if {[llength $attr] == 3} { lassign $attr loc pfx uri } |
︙ | ︙ | |||
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | # must be ua:ExtensionObject, otherwise skip if {[$struct getAttribute BaseType] ne "ua:ExtensionObject"} { continue } } set stf {} foreach field [$struct childNodes] { if {[$field hasAttribute SwitchField]} { # cannot process this struct set stf {} break } # TBD: handle attribute LengthField set nstype [$field getAttribute TypeName] lassign [split $nstype :] fns type if {$type ne ""} { switch -- $fns { opc - ua { lappend stf $type } tns { lappend stf $nstype } default { # cannot process this struct set stf {} break } } } else { lappend stf $nstype } lappend stf [$field getAttribute Name] } | > > > > > > > > > > > > > | > > > > | | | | > | > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | # must be ua:ExtensionObject, otherwise skip if {[$struct getAttribute BaseType] ne "ua:ExtensionObject"} { continue } } set stf {} foreach field [$struct childNodes] { if {[$field nodeName] ne "opc:Field"} { continue } if {[$field hasAttribute SwitchField]} { # cannot process this struct set stf {} break } # TBD: handle attribute LengthField if {![$field hasAttribute TypeName]} { # cannot process this struct set stf {} break } set nstype [$field getAttribute TypeName] lassign [split $nstype :] fns type if {$type ne ""} { switch -- $fns { opc - ua { lappend stf $type } tns { lappend stf $nstype } default { # cannot process this struct set stf {} break } } } else { lappend stf $nstype } if {![$field hasAttribute Name]} { # cannot process this struct set stf {} break } lappend stf [$field getAttribute Name] } if {[llength $stf] && [$struct hasAttribute Name]} { set st([$struct getAttribute Name]) $stf } } # structs need further checking later set stl [array names st] # process enums array set en {} foreach enum [$typedict selectNodes opc:EnumeratedType] { set enf {} foreach value [$enum childNodes] { if {[$value nodeName] ne "opc:EnumeratedValue"} { continue } if {[$value hasAttribute Name] && [$value hasAttribute Value]} { lappend enf \ [$value getAttribute Name] \ [$value getAttribute Value] } } if {[llength $enf] && [$enum hasAttribute Name] && [$enum hasAttribute LengthInBits]} { set en([$enum getAttribute Name]) \ [concat [$enum getAttribute LengthInBits] $enf] } } dict set out enums [array get en] set enl [array names en] # cross check type names in structs |
︙ | ︙ |
Changes to jni/topcua/topcua.c.
︙ | ︙ | |||
164 165 166 167 168 169 170 | void *ctx, UA_StatusChangeNotification *ntf); static void ReleaseSubs(UAH *uah); static void ReleaseMethodsEtc(UAH *uah, int killProcs); static void ReleaseTypes(UAH *uah, int all); static void DisconnectClient(UAH *uah); static void FreeHandle(char *clientData); | | > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | void *ctx, UA_StatusChangeNotification *ntf); static void ReleaseSubs(UAH *uah); static void ReleaseMethodsEtc(UAH *uah, int killProcs); static void ReleaseTypes(UAH *uah, int all); static void DisconnectClient(UAH *uah); static void FreeHandle(char *clientData); static const UA_DataType *FindType(UAI *uai, UAH *uah, int inDef, const char *name); static UA_NodeId * ParseNodeId(Tcl_Interp *interp, UA_NodeId *nodein, const char *string); static UA_NodeId * ParseTypeOrNodeId(Tcl_Interp *interp, UAH *uah, UA_NodeId *nodein, const char *string); static UA_NodeId * ParseRefTypeOrNodeId(Tcl_Interp *interp, UAI *uai, UA_NodeId *nodein, |
︙ | ︙ | |||
1137 1138 1139 1140 1141 1142 1143 | * Side effects: * None. * *------------------------------------------------------------------------- */ static const UA_DataType * | | > > > > | | | | | | | | | > | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 | * Side effects: * None. * *------------------------------------------------------------------------- */ static const UA_DataType * FindType(UAI *uai, UAH *uah, int inDef, const char *name) { size_t j; Tcl_HashEntry *hPtr; const UA_DataType *type = NULL; hPtr = Tcl_FindHashEntry(&uai->types, name); if (hPtr != NULL) { type = (UA_DataType *) Tcl_GetHashValue(hPtr); } else { for (j = 0; j < UA_TYPES_COUNT; j++) { if (strcmp(UA_TYPES[j].typeName, name) == 0) { type = &UA_TYPES[j]; break; } } if ((type == NULL) && (uah != NULL)) { size_t typesSize; UA_DataType *types; if (inDef) { types = uah->types; typesSize = uah->typesSize; } else { #if (UA_OPEN62541_VER_MAJOR < 1) if (uah->client != NULL) { UA_Client_getCustomDataTypes(uah->client, &types, &typesSize); } else { UA_Server_getCustomDataTypes(uah->server, &types, &typesSize); } #else types = (UA_DataType *) uah->typesArray.types; typesSize = uah->typesArray.typesSize; #endif } for (j = 0; j < typesSize; j++) { if ((types[j].typeName != NULL) && (strcmp(types[j].typeName, name) == 0)) { type = &types[j]; break; } } |
︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 | static UA_NodeId * ParseTypeOrNodeId(Tcl_Interp *interp, UAH *uah, UA_NodeId *nodein, const char *string) { if ((strchr(string, ';') == NULL) && (strchr(string, '=') == NULL)) { | | | 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 | static UA_NodeId * ParseTypeOrNodeId(Tcl_Interp *interp, UAH *uah, UA_NodeId *nodein, const char *string) { if ((strchr(string, ';') == NULL) && (strchr(string, '=') == NULL)) { const UA_DataType *type = FindType(uah->uai, uah, 0, string); if (type != NULL) { *nodein = type->typeId; return nodein; } } return ParseNodeId(interp, nodein, string); |
︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 | errstr = "no result buffer"; goto error; } namein->name = UA_STRING_NULL; if (len > 2) { char *p = NULL, *q = strchr(string, ':'); | | | 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 | errstr = "no result buffer"; goto error; } namein->name = UA_STRING_NULL; if (len > 2) { char *p = NULL, *q = strchr(string, ':'); if ((q != NULL) && (q != string)) { nsindex = strtol(string, &p, 10); if ((p == q) && (p - string < len)) { string = p + 1; } else { nsindex = 0; } } |
︙ | ︙ | |||
2986 2987 2988 2989 2990 2991 2992 | } if (n == 1) { Tcl_SetResult(interp, "zero, two, or more elements required", TCL_STATIC); goto error; } if (n) { | | | 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 | } if (n == 1) { Tcl_SetResult(interp, "zero, two, or more elements required", TCL_STATIC); goto error; } if (n) { vtype = FindType(uai, uah, 0, Tcl_GetString(elem[0])); if ((vtype == NULL) || (vtype == &UA_TYPES[UA_TYPES_VARIANT])) { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); goto error; } /* Now skip type element. */ elem += 1; n -= 1; |
︙ | ︙ | |||
3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 | value = NULL; goto error; } UA_delete(subval, subtype); data = (char *) data + subtype->memSize; } } } else { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); } error: return value; } | > > > > > > > > > > > > > | 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 | value = NULL; goto error; } UA_delete(subval, subtype); data = (char *) data + subtype->memSize; } } #if (UA_OPEN62541_VER_MAJOR >= 1) } else if ((type->membersSize == 0) && (type->typeKind == UA_DATATYPEKIND_ENUM) && (type->typeIndex == UA_TYPES_INT32)) { /* Map scalar enum types to wide integer. */ Tcl_WideInt v; if (Tcl_GetWideIntFromObj(interp, obj, &v) != TCL_OK) { goto error; } value = UA_new(type); ((UA_Int64 *) value)[0] = v; #endif } else { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); } error: return value; } |
︙ | ︙ | |||
3484 3485 3486 3487 3488 3489 3490 | goto error; } else if (n < 2) { Tcl_SetResult(interp, "need two or more elements, type and data", TCL_STATIC); ret = TCL_ERROR; goto error; } | | | 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 | goto error; } else if (n < 2) { Tcl_SetResult(interp, "need two or more elements, type and data", TCL_STATIC); ret = TCL_ERROR; goto error; } type = FindType(uai, uah, 0, Tcl_GetString(elem[0])); if (type == NULL) { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); ret = TCL_ERROR; goto error; } if (n > 2) { Tcl_SetObjResult(interp, Tcl_NewListObj(n - 1, &elem[1])); |
︙ | ︙ | |||
5553 5554 5555 5556 5557 5558 5559 | attr += 1; idx = 4; } else { /* By default, write the "value" attribute. */ attr = UA_ATTRIBUTEID_VALUE; idx = 3; } | | | 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 | attr += 1; idx = 4; } else { /* By default, write the "value" attribute. */ attr = UA_ATTRIBUTEID_VALUE; idx = 3; } type = FindType(uai, uah, 0, Tcl_GetString(objv[idx])); if (type == NULL) { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); goto error; } idx++; value = EncodeFromObj(interp, uai, uah, type, NULL, objv[idx], 0); if (value == NULL) { |
︙ | ︙ | |||
5644 5645 5646 5647 5648 5649 5650 | } nInArgs = (objc - 4) / 2; inArgs = (UA_Variant *) UA_Array_new(nInArgs, &UA_TYPES[UA_TYPES_VARIANT]); for (i = 0; i < nInArgs; i++) { int idx = i * 2 + 4; void *value; | | | 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 | } nInArgs = (objc - 4) / 2; inArgs = (UA_Variant *) UA_Array_new(nInArgs, &UA_TYPES[UA_TYPES_VARIANT]); for (i = 0; i < nInArgs; i++) { int idx = i * 2 + 4; void *value; type = FindType(uai, uah, 0, Tcl_GetString(objv[idx])); if (type == NULL) { Tcl_SetResult(interp, "unsupported type", TCL_STATIC); goto argsError; } idx++; if (objv[idx]->typePtr == uai->listObjType) { int j, n; |
︙ | ︙ | |||
6572 6573 6574 6575 6576 6577 6578 | { UAI *uai = (UAI *) clientData; UAH *uah; Tcl_HashEntry *hPtr; UA_StatusCode uaret; int flag; | | | 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 | { UAI *uai = (UAI *) clientData; UAH *uah; Tcl_HashEntry *hPtr; UA_StatusCode uaret; int flag; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "handle"); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&uai->handles, Tcl_GetString(objv[1])); if (hPtr == NULL) { Tcl_SetResult(interp, "handle not found", TCL_STATIC); ReportError(interp, uai, NULL, 0); |
︙ | ︙ | |||
7669 7670 7671 7672 7673 7674 7675 | { UAI *uai = (UAI *) clientData; UAH *uah; Tcl_HashEntry *hPtr; UA_NodeId nodeid, encid; int cmd, i, j; Tcl_Obj *obj; | | | 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 | { UAI *uai = (UAI *) clientData; UAH *uah; Tcl_HashEntry *hPtr; UA_NodeId nodeid, encid; int cmd, i, j; Tcl_Obj *obj; const UA_DataType *type; size_t max; static const char *cmdNames[] = { "begin", "commit", "enum", "struct", NULL }; enum cmdTag { CMD_begin, CMD_commit, CMD_enum, CMD_struct }; |
︙ | ︙ | |||
7798 7799 7800 7801 7802 7803 7804 | } if ((nodeid.identifierType != UA_NODEIDTYPE_NUMERIC) || (encid.identifierType != UA_NODEIDTYPE_NUMERIC)) { Tcl_SetResult(interp, "need numeric node identifier", TCL_STATIC); ReportError(interp, uai, NULL, 0); return TCL_ERROR; } | | | > | | > > > > | 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 | } if ((nodeid.identifierType != UA_NODEIDTYPE_NUMERIC) || (encid.identifierType != UA_NODEIDTYPE_NUMERIC)) { Tcl_SetResult(interp, "need numeric node identifier", TCL_STATIC); ReportError(interp, uai, NULL, 0); return TCL_ERROR; } type = FindType(uai, uah, 1, Tcl_GetString(objv[6])); if (type == NULL) { Tcl_SetResult(interp, "unsupported type for enum", TCL_STATIC); ReportError(interp, uai, NULL, 0); return TCL_ERROR; } if ( #if (UA_OPEN62541_VER_MAJOR < 1) (type->membersSize != 1) || !type->pointerFree #else (type->membersSize != 0) || !type->pointerFree #endif ) { Tcl_SetResult(interp, "unsupported type for enum", TCL_STATIC); ReportError(interp, uai, NULL, 0); return TCL_ERROR; } max = nodeid.identifier.numeric; if (max < encid.identifier.numeric) { max = encid.identifier.numeric; |
︙ | ︙ | |||
7837 7838 7839 7840 7841 7842 7843 | } obj = GetSymObj(uai, Tcl_GetString(objv[3]), (char **) &uah->types[i].typeName); Tcl_IncrRefCount(obj); uah->types[i].typeId = nodeid; uah->types[i].memSize = type->memSize; uah->types[i].typeIndex = i; | < < < < < < > > > > > > > > | < < | < < < < < < < < < < < < < < < < < < < < | | | > | 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 | } obj = GetSymObj(uai, Tcl_GetString(objv[3]), (char **) &uah->types[i].typeName); Tcl_IncrRefCount(obj); uah->types[i].typeId = nodeid; uah->types[i].memSize = type->memSize; uah->types[i].typeIndex = i; uah->types[i].pointerFree = 1; uah->types[i].overlayable = UA_BINARY_OVERLAYABLE_INTEGER; uah->types[i].binaryEncodingId = 0; #if (UA_OPEN62541_VER_MAJOR < 1) uah->types[i].builtin = 0; uah->types[i].membersSize = 1; uah->types[i].members = ckalloc(sizeof(UA_DataTypeMember)); uah->types[i].members[0] = type->members[0]; obj = GetSymObj(uai, "", (char **) &uah->types[i].members[0].memberName); Tcl_IncrRefCount(obj); #else uah->types[i].typeKind = UA_DATATYPEKIND_ENUM; uah->types[i].membersSize = 0; uah->types[i].members = NULL; #endif break; case CMD_struct: if ((objc < 8) || (objc % 2 != 0)) { Tcl_WrongNumArgs(interp, 1, objv, "handle struct name nodeid encid type member ..."); return TCL_ERROR; } if (ParseNodeId(interp, &nodeid, Tcl_GetString(objv[4])) == NULL) { return TCL_ERROR; } if (ParseNodeId(interp, &encid, Tcl_GetString(objv[5])) == NULL) { return TCL_ERROR; } /* Validate member types. */ for (i = 6; i < objc; i += 2) { type = FindType(uai, uah, 1, Tcl_GetString(objv[i])); if (type == NULL) { Tcl_SetResult(interp, "unknown type in struct", TCL_STATIC); ReportError(interp, uai, NULL, 0); return TCL_ERROR; } } max = nodeid.identifier.numeric; if (max < encid.identifier.numeric) { max = encid.identifier.numeric; } max += 64; if (uah->types == NULL) { |
︙ | ︙ | |||
7935 7936 7937 7938 7939 7940 7941 | uah->types[i].pointerFree = 1; uah->types[i].overlayable = 0; uah->types[i].binaryEncodingId = encid.identifier.numeric; j = sizeof(UA_DataTypeMember) * uah->types[i].membersSize; uah->types[i].members = ckalloc(j); memset(uah->types[i].members, 0, j); for (j = 6; j < objc; j += 2) { | | < | < > | < < < < < < < < < < < < < | < < < < | 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 | uah->types[i].pointerFree = 1; uah->types[i].overlayable = 0; uah->types[i].binaryEncodingId = encid.identifier.numeric; j = sizeof(UA_DataTypeMember) * uah->types[i].membersSize; uah->types[i].members = ckalloc(j); memset(uah->types[i].members, 0, j); for (j = 6; j < objc; j += 2) { int k, isZero; type = FindType(uai, uah, 1, Tcl_GetString(objv[j])); if ((type >= &UA_TYPES[0]) && (type < &UA_TYPES[UA_TYPES_COUNT])) { isZero = 1; } else { isZero = 0; } k = (j - 6) / 2; obj = GetSymObj(uai, Tcl_GetString(objv[j + 1]), (char **) &uah->types[i].members[k].memberName); Tcl_IncrRefCount(obj); uah->types[i].members[k].memberTypeIndex = type->typeIndex; uah->types[i].members[k].padding = |
︙ | ︙ |