File: | d/tclobj.c |
Warning: | line 104, column 32 Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * The contents of this file are subject to the Mozilla Public License | |||
3 | * Version 1.1 (the "License"); you may not use this file except in | |||
4 | * compliance with the License. You may obtain a copy of the License at | |||
5 | * http://mozilla.org/. | |||
6 | * | |||
7 | * Software distributed under the License is distributed on an "AS IS" | |||
8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | |||
9 | * the License for the specific language governing rights and limitations | |||
10 | * under the License. | |||
11 | * | |||
12 | * The Original Code is AOLserver Code and related documentation | |||
13 | * distributed by AOL. | |||
14 | * | |||
15 | * The Initial Developer of the Original Code is America Online, | |||
16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, | |||
17 | * Inc. All Rights Reserved. | |||
18 | * | |||
19 | * Alternatively, the contents of this file may be used under the terms | |||
20 | * of the GNU General Public License (the "GPL"), in which case the | |||
21 | * provisions of GPL are applicable instead of those above. If you wish | |||
22 | * to allow use of your version of this file only under the terms of the | |||
23 | * GPL and not to allow others to use your version of this file under the | |||
24 | * License, indicate your decision by deleting the provisions above and | |||
25 | * replace them with the notice and other provisions required by the GPL. | |||
26 | * If you do not delete the provisions above, a recipient may use your | |||
27 | * version of this file under either the License or the GPL. | |||
28 | */ | |||
29 | ||||
30 | ||||
31 | /* | |||
32 | * tclobj.c -- | |||
33 | * | |||
34 | * Helper routines for managing Tcl_Obj types. | |||
35 | */ | |||
36 | ||||
37 | #include "nsd.h" | |||
38 | ||||
39 | /* | |||
40 | * Local functions defined in this file. | |||
41 | */ | |||
42 | ||||
43 | static Tcl_UpdateStringProc UpdateStringOfAddr; | |||
44 | static Tcl_SetFromAnyProc SetAddrFromAny; | |||
45 | ||||
46 | /* | |||
47 | * Local variables defined in this file. | |||
48 | */ | |||
49 | ||||
50 | static const Tcl_ObjType addrType = { | |||
51 | "ns:addr", | |||
52 | NULL((void*)0), | |||
53 | NULL((void*)0), | |||
54 | UpdateStringOfAddr, | |||
55 | SetAddrFromAny | |||
56 | }; | |||
57 | ||||
58 | static const Tcl_ObjType *byteArrayTypePtr; /* For NsTclObjIsByteArray(). */ | |||
59 | static const Tcl_ObjType *properByteArrayTypePtr; /* For NsTclObjIsByteArray(). */ | |||
60 | ||||
61 | /* | |||
62 | *---------------------------------------------------------------------- | |||
63 | * | |||
64 | * NsTclInitAddrType -- | |||
65 | * | |||
66 | * Initialize the Tcl address object type and cache the bytearray Tcl | |||
67 | * built-in type. Starting with Tcl 8.7a1, Tcl has actually two different | |||
68 | * types for bytearrays, the old "tclByteArrayType" and a new | |||
69 | * "properByteArrayType", where both have the string name "bytearray". | |||
70 | * | |||
71 | * Results: | |||
72 | * None. | |||
73 | * | |||
74 | * Side effects: | |||
75 | * None. | |||
76 | * | |||
77 | *---------------------------------------------------------------------- | |||
78 | */ | |||
79 | ||||
80 | void | |||
81 | NsTclInitAddrType(void) | |||
82 | { | |||
83 | Tcl_Obj *newByteObj; | |||
84 | ||||
85 | Tcl_RegisterObjType(&addrType); | |||
86 | /* | |||
87 | * Get the "tclByteArrayType" via name "bytearray". | |||
88 | */ | |||
89 | byteArrayTypePtr = Tcl_GetObjType("bytearray"); | |||
90 | ||||
91 | /* | |||
92 | * Get the "properByteArrayType" via a TclObj. | |||
93 | * In versions before Tcl 8.7, both values will be the same. | |||
94 | */ | |||
95 | newByteObj = Tcl_NewByteArrayObj(NULL((void*)0), 0); | |||
96 | properByteArrayTypePtr = newByteObj->typePtr; | |||
97 | if (properByteArrayTypePtr == byteArrayTypePtr) { | |||
| ||||
98 | /* | |||
99 | * When both values are the same, we are in a Tcl version before 8.7, | |||
100 | * where we have no properByteArrayTypePtr. So set it to an invalid | |||
101 | * value to avoid potential confusions. Without this stunt, we would | |||
102 | * need several ifdefs. | |||
103 | */ | |||
104 | properByteArrayTypePtr = (Tcl_ObjType *)INT2PTR(0xffffff)((void *)(intptr_t)(0xffffff)); | |||
| ||||
105 | } | |||
106 | Tcl_DecrRefCount(newByteObj)do { Tcl_Obj *_objPtr = (newByteObj); if (_objPtr->refCount -- <= 1) { TclFreeObj(_objPtr); } } while(0); | |||
107 | } | |||
108 | ||||
109 | ||||
110 | /* | |||
111 | *---------------------------------------------------------------------- | |||
112 | * | |||
113 | * Ns_TclResetObjType -- | |||
114 | * | |||
115 | * Reset the given Tcl_Obj type, freeing any type specific | |||
116 | * internal representation. The new Tcl_Obj type might be NULL. | |||
117 | * | |||
118 | * Results: | |||
119 | * None. | |||
120 | * | |||
121 | * Side effects: | |||
122 | * Depends on object type. | |||
123 | * | |||
124 | *---------------------------------------------------------------------- | |||
125 | */ | |||
126 | ||||
127 | void | |||
128 | Ns_TclResetObjType(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr) | |||
129 | { | |||
130 | const Tcl_ObjType *typePtr; | |||
131 | ||||
132 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
133 | ||||
134 | typePtr = objPtr->typePtr; | |||
135 | if (typePtr != NULL((void*)0) && typePtr->freeIntRepProc != NULL((void*)0)) { | |||
136 | (*typePtr->freeIntRepProc)(objPtr); | |||
137 | } | |||
138 | objPtr->typePtr = newTypePtr; | |||
139 | } | |||
140 | ||||
141 | ||||
142 | /* | |||
143 | *---------------------------------------------------------------------- | |||
144 | * | |||
145 | * Ns_TclSetTwoPtrValue -- | |||
146 | * | |||
147 | * Reset the given objects type and values, freeing any existing | |||
148 | * internal rep. | |||
149 | * | |||
150 | * Results: | |||
151 | * None. | |||
152 | * | |||
153 | * Side effects: | |||
154 | * Depends on object type. | |||
155 | * | |||
156 | *---------------------------------------------------------------------- | |||
157 | */ | |||
158 | ||||
159 | void | |||
160 | Ns_TclSetTwoPtrValue(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr, | |||
161 | void *ptr1, void *ptr2) | |||
162 | { | |||
163 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
164 | ||||
165 | Ns_TclResetObjType(objPtr, newTypePtr); | |||
166 | objPtr->internalRep.twoPtrValue.ptr1 = ptr1; | |||
167 | objPtr->internalRep.twoPtrValue.ptr2 = ptr2; | |||
168 | } | |||
169 | ||||
170 | ||||
171 | /* | |||
172 | *---------------------------------------------------------------------- | |||
173 | * | |||
174 | * Ns_TclSetOtherValuePtr -- | |||
175 | * | |||
176 | * Reset the given objects type and value, freeing any existing | |||
177 | * internal rep. | |||
178 | * | |||
179 | * Results: | |||
180 | * None. | |||
181 | * | |||
182 | * Side effects: | |||
183 | * Depends on object type. | |||
184 | * | |||
185 | *---------------------------------------------------------------------- | |||
186 | */ | |||
187 | ||||
188 | void | |||
189 | Ns_TclSetOtherValuePtr(Tcl_Obj *objPtr, const Tcl_ObjType *newTypePtr, void *value) | |||
190 | { | |||
191 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
192 | NS_NONNULL_ASSERT(newTypePtr != NULL)((void) (0)); | |||
193 | NS_NONNULL_ASSERT(value != NULL)((void) (0)); | |||
194 | ||||
195 | Ns_TclResetObjType(objPtr, newTypePtr); | |||
196 | objPtr->internalRep.otherValuePtr = value; | |||
197 | } | |||
198 | ||||
199 | ||||
200 | /* | |||
201 | *---------------------------------------------------------------------- | |||
202 | * | |||
203 | * Ns_TclSetStringRep -- | |||
204 | * | |||
205 | * Copy length bytes and set objects string rep. The objects | |||
206 | * existing string rep *must* have already been freed. Tcl uses | |||
207 | * as well "int" and not "size" (internally and via interface) | |||
208 | * | |||
209 | * Results: | |||
210 | * None. | |||
211 | * | |||
212 | * Side effects: | |||
213 | * Memory is allocated. | |||
214 | * | |||
215 | *---------------------------------------------------------------------- | |||
216 | */ | |||
217 | ||||
218 | void | |||
219 | Ns_TclSetStringRep(Tcl_Obj *objPtr, const char *bytes, int length) | |||
220 | { | |||
221 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
222 | NS_NONNULL_ASSERT(bytes != NULL)((void) (0)); | |||
223 | ||||
224 | if (length < 1) { | |||
225 | length = (int)strlen(bytes); | |||
226 | } | |||
227 | objPtr->length = length; | |||
228 | objPtr->bytes = ckalloc((unsigned) length + 1u)((void *) Tcl_Alloc((unsigned)((unsigned) length + 1u))); | |||
229 | memcpy(objPtr->bytes, bytes, (size_t) length + 1u); | |||
230 | } | |||
231 | ||||
232 | ||||
233 | ||||
234 | /* | |||
235 | *---------------------------------------------------------------------- | |||
236 | * | |||
237 | * Ns_TclSetFromAnyError -- | |||
238 | * | |||
239 | * This procedure is registered as the setFromAnyProc for an | |||
240 | * object type when it doesn't make sense to generate its internal | |||
241 | * form from the string representation alone. | |||
242 | * | |||
243 | * Results: | |||
244 | * The return value is always TCL_ERROR, and an error message is | |||
245 | * left in interp's result if interp isn't NULL. | |||
246 | * | |||
247 | * Side effects: | |||
248 | * None. | |||
249 | * | |||
250 | *---------------------------------------------------------------------- | |||
251 | */ | |||
252 | ||||
253 | int | |||
254 | Ns_TclSetFromAnyError(Tcl_Interp *interp, Tcl_Obj *UNUSED(objPtr)UNUSED_objPtr __attribute__((__unused__))) | |||
255 | { | |||
256 | Tcl_AppendToObj(Tcl_GetObjResult(interp), | |||
257 | "can't convert value to requested type except via prescribed API", | |||
258 | -1); | |||
259 | return TCL_ERROR1; | |||
260 | } | |||
261 | ||||
262 | ||||
263 | /* | |||
264 | *---------------------------------------------------------------------- | |||
265 | * | |||
266 | * Ns_TclGetAddrFromObj -- | |||
267 | * | |||
268 | * Return the internal pointer of an address Tcl_Obj. | |||
269 | * | |||
270 | * Results: | |||
271 | * TCL_OK or TCL_ERROR if conversion failed or not the correct type. | |||
272 | * | |||
273 | * Side effects: | |||
274 | * Object may be converted to address type. | |||
275 | * | |||
276 | *---------------------------------------------------------------------- | |||
277 | */ | |||
278 | ||||
279 | int | |||
280 | Ns_TclGetAddrFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, | |||
281 | const char *type, void **addrPtrPtr) | |||
282 | { | |||
283 | int result = TCL_OK0; | |||
284 | ||||
285 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
286 | NS_NONNULL_ASSERT(type != NULL)((void) (0)); | |||
287 | NS_NONNULL_ASSERT(addrPtrPtr != NULL)((void) (0)); | |||
288 | ||||
289 | if (Tcl_ConvertToType(interp, objPtr, &addrType) != TCL_OK0) { | |||
290 | result = TCL_ERROR1; | |||
291 | ||||
292 | } else if (objPtr->internalRep.twoPtrValue.ptr1 != (void *) type) { | |||
293 | Ns_TclPrintfResult(interp, "incorrect type: %s", Tcl_GetString(objPtr)); | |||
294 | result = TCL_ERROR1; | |||
295 | ||||
296 | } else { | |||
297 | *addrPtrPtr = objPtr->internalRep.twoPtrValue.ptr2; | |||
298 | } | |||
299 | ||||
300 | return result; | |||
301 | } | |||
302 | ||||
303 | ||||
304 | /* | |||
305 | *---------------------------------------------------------------------- | |||
306 | * | |||
307 | * Ns_TclSetAddrObj -- | |||
308 | * | |||
309 | * Convert the given object to the ns:addr type. | |||
310 | * | |||
311 | * Results: | |||
312 | * None. | |||
313 | * | |||
314 | * Side effects: | |||
315 | * None. | |||
316 | * | |||
317 | *---------------------------------------------------------------------- | |||
318 | */ | |||
319 | ||||
320 | void | |||
321 | Ns_TclSetAddrObj(Tcl_Obj *objPtr, const char *type, void *addr) | |||
322 | { | |||
323 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
324 | NS_NONNULL_ASSERT(type != NULL)((void) (0)); | |||
325 | NS_NONNULL_ASSERT(addr != NULL)((void) (0)); | |||
326 | ||||
327 | if (Tcl_IsShared(objPtr)((objPtr)->refCount > 1)) { | |||
328 | Tcl_Panic("Ns_TclSetAddrObj called with shared object"); | |||
329 | } | |||
330 | Ns_TclSetTwoPtrValue(objPtr, &addrType, (void *) type, addr); | |||
331 | Tcl_InvalidateStringRep(objPtr); | |||
332 | } | |||
333 | ||||
334 | ||||
335 | /* | |||
336 | *---------------------------------------------------------------------- | |||
337 | * | |||
338 | * Ns_TclGetOpaqueFromObj -- | |||
339 | * | |||
340 | * Get the internal pointer of an address Tcl_Obj. | |||
341 | * | |||
342 | * Results: | |||
343 | * TCL_OK or TCL_ERROR if object was not of the ns:addr type. | |||
344 | * | |||
345 | * Side effects: | |||
346 | * None. | |||
347 | * | |||
348 | *---------------------------------------------------------------------- | |||
349 | */ | |||
350 | ||||
351 | int | |||
352 | Ns_TclGetOpaqueFromObj(const Tcl_Obj *objPtr, const char *type, void **addrPtrPtr) | |||
353 | { | |||
354 | int result = TCL_OK0; | |||
355 | ||||
356 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
357 | NS_NONNULL_ASSERT(type != NULL)((void) (0)); | |||
358 | NS_NONNULL_ASSERT(addrPtrPtr != NULL)((void) (0)); | |||
359 | ||||
360 | if (objPtr->typePtr == &addrType | |||
361 | && objPtr->internalRep.twoPtrValue.ptr1 == (void *) type) { | |||
362 | *addrPtrPtr = objPtr->internalRep.twoPtrValue.ptr2; | |||
363 | } else { | |||
364 | char s[33] = {0}; | |||
365 | uintptr_t t = 0u, a = 0u; | |||
366 | ||||
367 | if ((sscanf(Tcl_GetString((Tcl_Obj *) objPtr), "t%20" SCNxPTR"l" "x" "-a%20" SCNxPTR"l" "x" "-%32s", &t, &a, s) != 3) | |||
368 | || (strcmp(s, type) != 0) | |||
369 | || (t != (uintptr_t)type) | |||
370 | ) { | |||
371 | result = TCL_ERROR1; | |||
372 | } else { | |||
373 | *addrPtrPtr = (void *)a; | |||
374 | } | |||
375 | } | |||
376 | ||||
377 | return result; | |||
378 | } | |||
379 | ||||
380 | ||||
381 | /* | |||
382 | *---------------------------------------------------------------------- | |||
383 | * | |||
384 | * Ns_TclSetOpaqueObj -- | |||
385 | * | |||
386 | * Convert the given object to the ns:addr type without | |||
387 | * invalidating the current string rep. It is OK if the object | |||
388 | * is shared. | |||
389 | * | |||
390 | * Results: | |||
391 | * None. | |||
392 | * | |||
393 | * Side effects: | |||
394 | * None. | |||
395 | * | |||
396 | *---------------------------------------------------------------------- | |||
397 | */ | |||
398 | ||||
399 | void | |||
400 | Ns_TclSetOpaqueObj(Tcl_Obj *objPtr, const char *type, void *addr) | |||
401 | { | |||
402 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
403 | NS_NONNULL_ASSERT(type != NULL)((void) (0)); | |||
404 | ||||
405 | Ns_TclSetTwoPtrValue(objPtr, &addrType, (void *) type, addr); | |||
406 | } | |||
407 | ||||
408 | ||||
409 | /* | |||
410 | *---------------------------------------------------------------------- | |||
411 | * | |||
412 | * NsTclObjIsByteArray -- | |||
413 | * | |||
414 | * Does the given Tcl_Obj have a byte array internal rep? The | |||
415 | * function determines when it is safe to interpret a string as a | |||
416 | * byte array directly. | |||
417 | * | |||
418 | * Results: | |||
419 | * Boolean. | |||
420 | * | |||
421 | * Side effects: | |||
422 | * None. | |||
423 | * | |||
424 | *---------------------------------------------------------------------- | |||
425 | */ | |||
426 | ||||
427 | bool_Bool | |||
428 | NsTclObjIsByteArray(const Tcl_Obj *objPtr) | |||
429 | { | |||
430 | bool_Bool result; | |||
431 | ||||
432 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
433 | ||||
434 | /* | |||
435 | * This function resembles the tclInt.h function for testing pure byte | |||
436 | * arrays. In versions up to at least on Tcl 8.6, a pure byte array was | |||
437 | * defined as a byte array without a string rep. Starting with Tcl | |||
438 | * 8.7a1, Tcl has introduced the properByteArrayTypePtr, which allows as | |||
439 | * well a string rep. | |||
440 | */ | |||
441 | #ifdef NS_TCL_PRE87 | |||
442 | result = ((objPtr->typePtr == byteArrayTypePtr) && (objPtr->bytes == NULL((void*)0))); | |||
443 | #else | |||
444 | result = (objPtr->typePtr == properByteArrayTypePtr); | |||
445 | #endif | |||
446 | ||||
447 | #if 0 | |||
448 | fprintf(stderr, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n",__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
449 | (void*)objPtr,__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
450 | (void*)(objPtr->typePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
451 | (objPtr->typePtr == properByteArrayTypePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
452 | (objPtr->typePtr == byteArrayTypePtr),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
453 | (void*)(objPtr->bytes),__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
454 | objPtr->typePtr == NULL ? "string" : objPtr->typePtr->name,__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result) | |||
455 | result)__fprintf_chk (stderr, 2 - 1, "NsTclObjIsByteArray? %p type %p proper %d old %d bytes %p name %s => %d\n" , (void*)objPtr, (void*)(objPtr->typePtr), (objPtr->typePtr == properByteArrayTypePtr), (objPtr->typePtr == byteArrayTypePtr ), (void*)(objPtr->bytes), objPtr->typePtr == ((void*)0 ) ? "string" : objPtr->typePtr->name, result); | |||
456 | #endif | |||
457 | ||||
458 | return result; | |||
459 | } | |||
460 | ||||
461 | ||||
462 | /* | |||
463 | *---------------------------------------------------------------------- | |||
464 | * | |||
465 | * NsTclObjIsEncodedByteArray -- | |||
466 | * | |||
467 | * This function is true, when we encounter a bytearray with a string | |||
468 | * rep. In this cases, it is necessary to use Tcl_UtfToExternalDString() | |||
469 | * to obtain the proper byte array. | |||
470 | * | |||
471 | * Results: | |||
472 | * Boolean. | |||
473 | * | |||
474 | * Side effects: | |||
475 | * None. | |||
476 | * | |||
477 | *---------------------------------------------------------------------- | |||
478 | */ | |||
479 | ||||
480 | bool_Bool | |||
481 | NsTclObjIsEncodedByteArray(const Tcl_Obj *objPtr) | |||
482 | { | |||
483 | NS_NONNULL_ASSERT(objPtr != NULL)((void) (0)); | |||
484 | ||||
485 | return ((objPtr->typePtr == byteArrayTypePtr) && (objPtr->bytes != NULL((void*)0))); | |||
486 | } | |||
487 | ||||
488 | ||||
489 | /* | |||
490 | *---------------------------------------------------------------------- | |||
491 | * | |||
492 | * UpdateStringOfAddr -- | |||
493 | * | |||
494 | * Update the string representation for an address object. | |||
495 | * Note: This procedure does not free an existing old string rep | |||
496 | * so storage will be lost if this has not already been done. | |||
497 | * | |||
498 | * Results: | |||
499 | * None. | |||
500 | * | |||
501 | * Side effects: | |||
502 | * None. | |||
503 | * | |||
504 | *---------------------------------------------------------------------- | |||
505 | */ | |||
506 | ||||
507 | static void | |||
508 | UpdateStringOfAddr(Tcl_Obj *objPtr) | |||
509 | { | |||
510 | const char *type = objPtr->internalRep.twoPtrValue.ptr1; | |||
511 | const void *addr = objPtr->internalRep.twoPtrValue.ptr2; | |||
512 | char buf[128]; | |||
513 | int len; | |||
514 | ||||
515 | len = snprintf(buf, sizeof(buf), "t%" PRIxPTR "-a%" PRIxPTR "-%s", (uintptr_t)type, (uintptr_t)addr, type)__builtin___snprintf_chk (buf, sizeof(buf), 2 - 1, __builtin_object_size (buf, 2 > 1), "t%" "l" "x" "-a%" "l" "x" "-%s", (uintptr_t )type, (uintptr_t)addr, type); | |||
516 | Ns_TclSetStringRep(objPtr, buf, len); | |||
517 | } | |||
518 | ||||
519 | ||||
520 | /* | |||
521 | *---------------------------------------------------------------------- | |||
522 | * | |||
523 | * SetAddrFromAny -- | |||
524 | * | |||
525 | * Attempt to generate an address internal form for the Tcl_Obj. | |||
526 | * | |||
527 | * Results: | |||
528 | * The return value is a standard Tcl result. If an error occurs | |||
529 | * during conversion, an error message is left in the interpreter's | |||
530 | * result unless interp is NULL. | |||
531 | * | |||
532 | * Side effects: | |||
533 | * None. | |||
534 | * | |||
535 | *---------------------------------------------------------------------- | |||
536 | */ | |||
537 | ||||
538 | static int | |||
539 | SetAddrFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) | |||
540 | { | |||
541 | int result = TCL_OK0; | |||
542 | void *type, *addr; | |||
543 | char *chars; | |||
544 | ||||
545 | chars = Tcl_GetString(objPtr); | |||
546 | if ((sscanf(chars, "t%20p-a%20p", &type, &addr) != 2) | |||
547 | || (type == NULL((void*)0)) | |||
548 | || (addr == NULL((void*)0)) | |||
549 | ) { | |||
550 | Ns_TclPrintfResult(interp, "invalid address \"%s\"", chars); | |||
551 | result = TCL_ERROR1; | |||
552 | } else { | |||
553 | Ns_TclSetTwoPtrValue(objPtr, &addrType, type, addr); | |||
554 | } | |||
555 | ||||
556 | return result; | |||
557 | } | |||
558 | ||||
559 | ||||
560 | /* | |||
561 | * Local Variables: | |||
562 | * mode: c | |||
563 | * c-basic-offset: 4 | |||
564 | * fill-column: 78 | |||
565 | * indent-tabs-mode: nil | |||
566 | * End: | |||
567 | */ |