There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.19 - (show annotations) (download) (as text)
Mon Aug 1 20:27:35 2005 UTC (12 years, 5 months ago) by jgdavidson
Branch: MAIN
CVS Tags: aolserver_v45_r0, aolserver_v45_r2_rc0, HEAD
Branch point for: aolserver_v45_r1, aolserver_v45_r2, aolserver_v45_bp
Changes since 1.18: +1 -18 lines
File MIME type: text/x-chdr
Use of <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsTclGetServer">NsTclGetServer</a> call to verify when a server is required for a command.
1 /*
2 * The contents of this file are subject to the AOLserver 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://aolserver.com/.
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 * tclset.c --
32 *
33 * Implements the tcl ns_set commands
34 */
35
36 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsd/tclset.c,v 1.19 2005/08/01 20:27:35 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__;
37
38 #include "nsd.h"
39
40 /*
41 * The following represent the valid combinations of
42 * NS_TCL_SET flags
43 */
44
45 #define SET_DYNAMIC 'd'
46 #define SET_STATIC 't'
47 #define SET_SHARED_DYNAMIC 's'
48 #define SET_SHARED_STATIC 'p'
49
50 #define IS_DYNAMIC(id) \
51 (*(id) == SET_DYNAMIC || *(id) == SET_SHARED_DYNAMIC)
52 #define IS_SHARED(id) \
53 (*(id) == SET_SHARED_DYNAMIC || *(id) == SET_SHARED_STATIC)
54
55 /*
56 * Local functions defined in this file
57 */
58
59 static int <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a>(NsInterp *itPtr, char *id, int delete, Ns_Set **setPtr);
60 static int <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(NsInterp *itPtr, Tcl_Obj *idPtr, int delete,
61 Ns_Set **setPtr);
62 static int <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupInterpSet">LookupInterpSet</a>(Tcl_Interp *interp, char *id, int delete,
63 Ns_Set **setPtr);
64 static int <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(NsInterp *itPtr, Ns_Set *set, int flags);
65
66
67 /*
68 *----------------------------------------------------------------------
69 *
70 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclEnterSet">Ns_TclEnterSet</a> --
71 *
72 * Give this Tcl interpreter access to an existing Ns_Set.
73 *
74 * Results:
75 * TCL_OK or TCL_ERROR.
76 *
77 * Side effects:
78 * A pointer to the Ns_Set is added to the interpreter's list of
79 * sets; a new handle is generated and appended to interp result.
80 *
81 *----------------------------------------------------------------------
82 */
83
84 int
85 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclEnterSet">Ns_TclEnterSet</a>(Tcl_Interp *interp, Ns_Set *set, int flags)
86 {
87 NsInterp *itPtr = <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsGetInterpData">NsGetInterpData</a>(interp);
88
89 if (itPtr == NULL) {
90 Tcl_SetResult(interp, "ns_set not supported", TCL_STATIC);
91 return TCL_ERROR;
92 }
93 return <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(itPtr, set, flags);
94 }
95
96
97 /*
98 *----------------------------------------------------------------------
99 *
100 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclGetSet">Ns_TclGetSet</a> --
101 *
102 * Given a Tcl ns_set handle, return a pointer to the Ns_Set.
103 *
104 * Results:
105 * An Ns_Set pointer, or NULL if error.
106 *
107 * Side effects:
108 * None.
109 *
110 *----------------------------------------------------------------------
111 */
112
113 Ns_Set *
114 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclGetSet">Ns_TclGetSet</a>(Tcl_Interp *interp, char *id)
115 {
116 Ns_Set *set;
117
118 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupInterpSet">LookupInterpSet</a>(interp, id, 0, &set) != TCL_OK) {
119 return NULL;
120 }
121 return set;
122 }
123
124
125 /*
126 *----------------------------------------------------------------------
127 *
128 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclGetSet2">Ns_TclGetSet2</a> --
129 *
130 * Like <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclGetSet">Ns_TclGetSet</a>, but sends errors to the tcl interp.
131 *
132 * Results:
133 * TCL result.
134 *
135 * Side effects:
136 * None.
137 *
138 *----------------------------------------------------------------------
139 */
140
141 int
142 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclGetSet2">Ns_TclGetSet2</a>(Tcl_Interp *interp, char *id, Ns_Set **setPtr)
143 {
144 return <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupInterpSet">LookupInterpSet</a>(interp, id, 0, setPtr);
145 }
146
147
148 /*
149 *----------------------------------------------------------------------
150 *
151 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclFreeSet">Ns_TclFreeSet</a> --
152 *
153 * Free a set id, and if own by Tcl, the underlying Ns_Set.
154 *
155 * Results:
156 * NS_OK/NS_ERROR.
157 *
158 * Side effects:
159 * Will free the set matching the passed-in set id, and all of
160 * its associated data.
161 *
162 *----------------------------------------------------------------------
163 */
164
165 int
166 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclFreeSet">Ns_TclFreeSet</a>(Tcl_Interp *interp, char *id)
167 {
168 Ns_Set *set;
169
170 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupInterpSet">LookupInterpSet</a>(interp, id, 1, &set) != TCL_OK) {
171 return TCL_ERROR;
172 }
173 if (IS_DYNAMIC(id)) {
174 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetFree">Ns_SetFree</a>(set);
175 }
176 return TCL_OK;
177 }
178
179
180 /*
181 *----------------------------------------------------------------------
182 *
183 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_NsTclSetObjCmd">NsTclSetObjCmd</a> --
184 *
185 * Implelments ns_set.
186 *
187 * Results:
188 * Tcl result.
189 *
190 * Side effects:
191 * See docs.
192 *
193 *----------------------------------------------------------------------
194 */
195
196 int
197 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_NsTclSetObjCmd">NsTclSetObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv)
198 {
199 Ns_Set *set, *set2Ptr, **sets;
200 int locked, i, flags;
201 char *key, *val, *name, *split;
202 Tcl_DString ds;
203 Tcl_HashTable *tablePtr;
204 Tcl_HashEntry *hPtr;
205 Tcl_HashSearch search;
206 NsInterp *itPtr = arg;
207 Tcl_Obj *objPtr;
208 static CONST char *opts[] = {
209 "array", "cleanup", "copy", "cput", "create", "delete",
210 "delkey", "find", "free", "get", "icput", "idelete",
211 "idelkey", "ifind", "iget", "isnull", "iunique", "key",
212 "list", "merge", "move", "name", "new", "print", "purge",
213 "put", "size", "split", "<a href="/cvs/aolserver/aolserver/nsd/nswin32.c#A_truncate">truncate</a>", "unique", "update",
214 "value", NULL,
215 };
216 enum {
217 SArrayIdx, SCleanupIdx, SCopyIdx, SCPutIdx, SCreateidx,
218 SDeleteIdx, SDelkeyIdx, SFindIdx, SFreeIdx, SGetIdx,
219 SICPutIdx, SIDeleteIdx, SIDelkeyIdx, SIFindIdx, SIGetIdx,
220 SIsNullIdx, SIUniqueIdx, SKeyIdx, SListIdx, SMergeIdx,
221 SMoveIdx, sINameIdx, SNewIdx, SPrintIdx, spurgeidx, SPutIdx,
222 SSizeIdx, SSplitIdx, STruncateIdx, SUniqueIdx, SUpdateIdx,
223 SValueIdx
224 };
225 int opt;
226
227 if (objc < 2) {
228 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
229 return TCL_ERROR;
230 }
231 if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0,
232 &opt) != TCL_OK) {
233 return TCL_ERROR;
234 }
235 if (opt == SCreateidx) {
236 opt = SNewIdx;
237 }
238
239 switch (opt) {
240 case SCleanupIdx:
241 tablePtr = &itPtr->sets;
242 hPtr = Tcl_FirstHashEntry(tablePtr, &search);
243 while (hPtr != NULL) {
244 key = Tcl_GetHashKey(tablePtr, hPtr);
245 if (IS_DYNAMIC(key)) {
246 set = Tcl_GetHashValue(hPtr);
247 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetFree">Ns_SetFree</a>(set);
248 }
249 hPtr = Tcl_NextHashEntry(&search);
250 }
251 Tcl_DeleteHashTable(tablePtr);
252 Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
253 break;
254
255 case SListIdx:
256 if (objc == 2) {
257 tablePtr = &itPtr->sets;
258 locked = 0;
259 } else if (STREQ(Tcl_GetString(objv[2]), "-shared")) {
260 tablePtr = &itPtr->servPtr->sets.table;
261 locked = 1;
262 Ns_MutexLock(&itPtr->servPtr->sets.lock);
263 } else {
264 Tcl_WrongNumArgs(interp, 2, objv, "?-shared?");
265 return TCL_ERROR;
266 }
267 if (tablePtr != NULL) {
268 hPtr = Tcl_FirstHashEntry(tablePtr, &search);
269 while (hPtr != NULL) {
270 Tcl_AppendElement(interp, Tcl_GetHashKey(tablePtr, hPtr));
271 hPtr = Tcl_NextHashEntry(&search);
272 }
273 }
274 if (locked) {
275 Ns_MutexUnlock(&itPtr->servPtr->sets.lock);
276 }
277 break;
278
279 case SNewIdx:
280 case SCopyIdx:
281 case SSplitIdx:
282 /*
283 * The following commands create new sets.
284 */
285
286 flags = NS_TCL_SET_DYNAMIC;
287 i = 2;
288 if (objc > 2) {
289 char *oflag = Tcl_GetString(objv[2]);
290 if (STREQ(oflag, "-shared") || STREQ(oflag, "-persist")) {
291 flags |= NS_TCL_SET_SHARED;
292 ++i;
293 }
294 }
295
296 switch (opt) {
297 case SNewIdx:
298 name = (i < objc) ? Tcl_GetString(objv[i++]) : NULL;
299 set = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetCreate">Ns_SetCreate</a>(name);
300 while (i < objc) {
301 key = Tcl_GetString(objv[i++]);
302 val = (i < objc) ? Tcl_GetString(objv[i++]) : NULL;
303 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPut">Ns_SetPut</a>(set, key, val);
304 }
305 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(itPtr, set, flags);
306 break;
307
308 case SCopyIdx:
309 if (i >= objc) {
310 Tcl_WrongNumArgs(interp, 2, objv, "?-shared? setId");
311 return TCL_ERROR;
312 }
313 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(itPtr, objv[i], 0, &set) != TCL_OK) {
314 return TCL_ERROR;
315 }
316 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(itPtr, <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetCopy">Ns_SetCopy</a>(set), flags);
317 break;
318
319 case SSplitIdx:
320 if ((objc - i) < 1) {
321 Tcl_WrongNumArgs(interp, 2, objv, "?-shared? setId ?splitChar");
322 return TCL_ERROR;
323 }
324 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(itPtr, objv[i++], 0, &set) != TCL_OK) {
325 return TCL_ERROR;
326 }
327 split = (i < objc) ? Tcl_GetString(objv[i]) : ".";
328 sets = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetSplit">Ns_SetSplit</a>(set, *split);
329 for (i = 0; sets[i] != NULL; i++) {
330 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(itPtr, sets[i], flags);
331 }
332 ns_free(sets);
333 break;
334 }
335 break;
336
337 default:
338 /*
339 * All futher commands require a valid set.
340 */
341
342 if (objc < 3) {
343 Tcl_WrongNumArgs(interp, 2, objv, "setId ?args?");
344 return TCL_ERROR;
345 }
346 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(itPtr, objv[2], 0, &set) != TCL_OK) {
347 return TCL_ERROR;
348 }
349
350 switch (opt) {
351 case SArrayIdx:
352 case SSizeIdx:
353 case sINameIdx:
354 case SPrintIdx:
355 case SFreeIdx:
356 /*
357 * These commands require only the set.
358 */
359
360 if (objc != 3) {
361 Tcl_WrongNumArgs(interp, 2, objv, "setId");
362 return TCL_ERROR;
363 }
364 switch (opt) {
365 case SArrayIdx:
366 Tcl_DStringInit(&ds);
367 for (i = 0; i < Ns_SetSize(set); ++i) {
368 Tcl_DStringAppendElement(&ds, Ns_SetKey(set, i));
369 Tcl_DStringAppendElement(&ds, Ns_SetValue(set, i));
370 }
371 Tcl_DStringResult(interp, &ds);
372 break;
373
374 case SSizeIdx:
375 objPtr = Tcl_NewIntObj(Ns_SetSize(set));
376 Tcl_SetObjResult(interp, objPtr);
377 break;
378
379 case sINameIdx:
380 Tcl_SetResult(interp, set->name, TCL_VOLATILE);
381 break;
382
383 case SPrintIdx:
384 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPrint">Ns_SetPrint</a>(set);
385 break;
386
387 case SFreeIdx:
388 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_Ns_TclFreeSet">Ns_TclFreeSet</a>(interp, Tcl_GetString(objv[2]));
389 break;
390 }
391 break;
392
393 case SFindIdx:
394 case SIFindIdx:
395 case SGetIdx:
396 case SIGetIdx:
397 case SDelkeyIdx:
398 case SIDelkeyIdx:
399 case SUniqueIdx:
400 case SIUniqueIdx:
401 /*
402 * These commands require a set and string key.
403 */
404
405 if (objc != 4) {
406 Tcl_WrongNumArgs(interp, 2, objv, "setId key");
407 return TCL_ERROR;
408 }
409 key = Tcl_GetString(objv[3]);
410 switch (opt) {
411 case SFindIdx:
412 objPtr = Tcl_NewIntObj(<a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetFind">Ns_SetFind</a>(set, key));
413 Tcl_SetObjResult(interp, objPtr);
414 break;
415
416 case SGetIdx:
417 Tcl_SetResult(interp, <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetGet">Ns_SetGet</a>(set, key), TCL_VOLATILE);
418 break;
419
420 case SDeleteIdx:
421 case SDelkeyIdx:
422 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetDeleteKey">Ns_SetDeleteKey</a>(set, key);
423 break;
424
425 case SUniqueIdx:
426 objPtr = Tcl_NewIntObj(<a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetUnique">Ns_SetUnique</a>(set, key));
427 Tcl_SetObjResult(interp, objPtr);
428 break;
429
430 case SIFindIdx:
431 objPtr = Tcl_NewIntObj(<a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIFind">Ns_SetIFind</a>(set, key));
432 Tcl_SetObjResult(interp, objPtr);
433 break;
434
435 case SIGetIdx:
436 Tcl_SetResult(interp, <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(set, key), TCL_VOLATILE);
437 break;
438
439 case SIDeleteIdx:
440 case SIDelkeyIdx:
441 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIDeleteKey">Ns_SetIDeleteKey</a>(set, key);
442 break;
443
444 case SIUniqueIdx:
445 objPtr = Tcl_NewIntObj(<a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIUnique">Ns_SetIUnique</a>(set, key));
446 Tcl_SetObjResult(interp, objPtr);
447 break;
448 }
449 break;
450
451 case SValueIdx:
452 case SIsNullIdx:
453 case SKeyIdx:
454 case SDeleteIdx:
455 case STruncateIdx:
456 /*
457 * These commands require a set and key/value index.
458 */
459
460 if (objc != 4) {
461 Tcl_WrongNumArgs(interp, 2, objv, "setId index");
462 return TCL_ERROR;
463 }
464 if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) {
465 return TCL_ERROR;
466 }
467 if (i < 0) {
468 Tcl_AppendResult(interp, "invalid index \"",
469 Tcl_GetString(objv[3]), "\": must be >= 0", NULL);
470 return TCL_ERROR;
471 }
472 if (i >= Ns_SetSize(set)) {
473 Tcl_AppendResult(interp, "invalid index \"",
474 Tcl_GetString(objv[3]),
475 "\": beyond range of set fields", NULL);
476 return TCL_ERROR;
477 }
478 switch (opt) {
479 case SValueIdx:
480 val = Ns_SetValue(set, i);
481 Tcl_SetResult(interp, val, TCL_VOLATILE);
482 break;
483
484 case SIsNullIdx:
485 val = Ns_SetValue(set, i);
486 objPtr = Tcl_NewBooleanObj(val ? 0 : 1);
487 Tcl_SetObjResult(interp, objPtr);
488 break;
489
490 case SKeyIdx:
491 key = Ns_SetKey(set, i);
492 Tcl_SetResult(interp, key, TCL_VOLATILE);
493 break;
494
495 case SDeleteIdx:
496 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetDelete">Ns_SetDelete</a>(set, i);
497 break;
498
499 case STruncateIdx:
500 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetTrunc">Ns_SetTrunc</a>(set, i);
501 break;
502 }
503 break;
504
505 case SPutIdx:
506 case SUpdateIdx:
507 case SCPutIdx:
508 case SICPutIdx:
509 /*
510 * These commands require a set, key, and value.
511 */
512
513 if (objc != 5) {
514 Tcl_WrongNumArgs(interp, 2, objv, "setId key value");
515 return TCL_ERROR;
516 }
517 key = Tcl_GetString(objv[3]);
518 val = Tcl_GetString(objv[4]);
519 switch (opt) {
520 case SUpdateIdx:
521 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetDeleteKey">Ns_SetDeleteKey</a>(set, key);
522 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPut">Ns_SetPut</a>(set, key, val);
523 break;
524
525 case SICPutIdx:
526 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIFind">Ns_SetIFind</a>(set, key);
527 if (i < 0) {
528 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPut">Ns_SetPut</a>(set, key, val);
529 }
530 break;
531
532 case SCPutIdx:
533 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetFind">Ns_SetFind</a>(set, key);
534 if (i < 0) {
535 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPut">Ns_SetPut</a>(set, key, val);
536 }
537 break;
538
539 case SPutIdx:
540 i = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetPut">Ns_SetPut</a>(set, key, val);
541 break;
542 }
543 objPtr = Tcl_NewIntObj(i);
544 Tcl_SetObjResult(interp, objPtr);
545 break;
546
547 case SMergeIdx:
548 case SMoveIdx:
549 /*
550 * These commands require two sets.
551 */
552
553 if (objc != 4) {
554 Tcl_WrongNumArgs(interp, 2, objv, "setTo setFrom");
555 return TCL_ERROR;
556 }
557 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(itPtr, objv[3], 0, &set2Ptr) != TCL_OK) {
558 return TCL_ERROR;
559 }
560 if (opt == SMergeIdx) {
561 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetMerge">Ns_SetMerge</a>(set, set2Ptr);
562 } else {
563 <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetMove">Ns_SetMove</a>(set, set2Ptr);
564 }
565 Tcl_SetObjResult(interp, objv[2]);
566 break;
567 }
568 }
569
570 return TCL_OK;
571 }
572
573
574
575 /*
576 *----------------------------------------------------------------------
577 *
578 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_NsTclParseHeaderCmd">NsTclParseHeaderCmd</a> --
579 *
580 * This wraps <a href="/cvs/aolserver/aolserver/nsd/request.c#A_Ns_ParseHeader">Ns_ParseHeader</a>.
581 *
582 * Results:
583 * Tcl result.
584 *
585 * Side effects:
586 * <a href="/cvs/aolserver/aolserver/nsd/adpparse.c#A_Parse">Parse</a> an HTTP header and add it to an existing set; see
587 * <a href="/cvs/aolserver/aolserver/nsd/request.c#A_Ns_ParseHeader">Ns_ParseHeader</a>.
588 *
589 *----------------------------------------------------------------------
590 */
591
592 int
593 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_NsTclParseHeaderCmd">NsTclParseHeaderCmd</a>(ClientData arg, Tcl_Interp *interp, int argc, char **argv)
594 {
595 NsInterp *itPtr = arg;
596 Ns_Set *set;
597 Ns_HeaderCaseDisposition disp;
598
599 if (argc != 3 && argc != 4) {
600 Tcl_AppendResult(interp, "wrong # of args: should be \"",
601 argv[0], " set header ?tolower|toupper|preserve?\"", NULL);
602 return TCL_ERROR;
603 }
604 if (<a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a>(itPtr, argv[1], 0, &set) != TCL_OK) {
605 return TCL_ERROR;
606 }
607 if (argc < 4) {
608 disp = ToLower;
609 } else if (STREQ(argv[3], "toupper")) {
610 disp = ToUpper;
611 } else if (STREQ(argv[3], "tolower")) {
612 disp = ToLower;
613 } else if (STREQ(argv[3], "preserve")) {
614 disp = Preserve;
615 } else {
616 Tcl_AppendResult(interp, "unknown case disposition \"", argv[3],
617 "\": should be toupper, tolower, or preserve", NULL);
618 return TCL_ERROR;
619 }
620 if (<a href="/cvs/aolserver/aolserver/nsd/request.c#A_Ns_ParseHeader">Ns_ParseHeader</a>(set, argv[2], disp) != NS_OK) {
621 Tcl_AppendResult(interp, "invalid header: ", argv[2], NULL);
622 return TCL_ERROR;
623 }
624 return TCL_OK;
625 }
626
627
628 /*
629 *----------------------------------------------------------------------
630 *
631 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a> --
632 *
633 * Add an Ns_Set to an interp, creating a new unique id.
634 *
635 * Results:
636 * TCL_OK or TCL_ERROR.
637 *
638 * Side effects:
639 * Set will be entered in the shared or private table.
640 *
641 *----------------------------------------------------------------------
642 */
643
644 static int
645 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_EnterSet">EnterSet</a>(NsInterp *itPtr, Ns_Set *set, int flags)
646 {
647 Tcl_HashTable *tablePtr;
648 Tcl_HashEntry *hPtr;
649 int new, next;
650 unsigned char type;
651 char buf[20];
652
653 if (flags & NS_TCL_SET_SHARED) {
654 /*
655 * Lock the global mutex and use the shared sets.
656 */
657
658 if (flags & NS_TCL_SET_DYNAMIC) {
659 type = SET_SHARED_DYNAMIC;
660 } else {
661 type = SET_SHARED_STATIC;
662 }
663 tablePtr = &itPtr->servPtr->sets.table;
664 Ns_MutexLock(&itPtr->servPtr->sets.lock);
665 } else {
666 tablePtr = &itPtr->sets;
667 if (flags & NS_TCL_SET_DYNAMIC) {
668 type = SET_DYNAMIC;
669 } else {
670 type = SET_STATIC;
671 }
672 }
673
674 /*
675 * Allocate a new set IDs until we find an unused one.
676 */
677
678 next = tablePtr->numEntries;
679 do {
680 sprintf(buf, "%c%u", type, next);
681 ++next;
682 hPtr = Tcl_CreateHashEntry(tablePtr, buf, &new);
683 } while (!new);
684 Tcl_SetHashValue(hPtr, set);
685 Tcl_AppendElement(itPtr->interp, buf);
686
687 /*
688 * Unlock the global mutex (locked above) if it's a persistent set.
689 */
690 if (flags & NS_TCL_SET_SHARED) {
691 Ns_MutexUnlock(&itPtr->servPtr->sets.lock);
692 }
693 return TCL_OK;
694 }
695
696
697 /*
698 *----------------------------------------------------------------------
699 *
700 * <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a> --
701 *
702 * Take a tcl set handle and return a matching Set. This
703 * takes both persistent and dynamic set handles.
704 *
705 * Results:
706 * TCL_OK or TCL_ERROR.
707 *
708 * Side effects:
709 * If delete is set, then the hash entry will be removed.
710 * Set will be returned in given setPtr.
711 *
712 *----------------------------------------------------------------------
713 */
714
715 static int
716 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupObjSet">LookupObjSet</a>(NsInterp *itPtr, Tcl_Obj *idPtr, int delete, Ns_Set **setPtr)
717 {
718 return <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a>(itPtr, Tcl_GetString(idPtr), delete, setPtr);
719 }
720
721 static int
722 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupInterpSet">LookupInterpSet</a>(Tcl_Interp *interp, char *id, int delete, Ns_Set **setPtr)
723 {
724 NsInterp *itPtr;
725
726 itPtr = <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsGetInterpData">NsGetInterpData</a>(interp);
727 if (itPtr == NULL) {
728 Tcl_SetResult(interp, "ns_set not supported", TCL_STATIC);
729 return TCL_ERROR;
730 }
731 return <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a>(itPtr, id, delete, setPtr);
732 }
733
734 static int
735 <a href="/cvs/aolserver/aolserver/nsd/tclset.c#A_LookupSet">LookupSet</a>(NsInterp *itPtr, char *id, int delete, Ns_Set **setPtr)
736 {
737 Tcl_HashTable *tablePtr;
738 Tcl_HashEntry *hPtr;
739 Ns_Set *set;
740
741 /*
742 * If it's a persistent set, use the shared table, otherwise
743 * use the private table.
744 */
745
746 set = NULL;
747 if (IS_SHARED(id)) {
748 tablePtr = &itPtr->servPtr->sets.table;
749 Ns_MutexLock(&itPtr->servPtr->sets.lock);
750 } else {
751 tablePtr = &itPtr->sets;
752 }
753 hPtr = Tcl_FindHashEntry(tablePtr, id);
754 if (hPtr != NULL) {
755 set = (Ns_Set *) Tcl_GetHashValue(hPtr);
756 if (delete) {
757 Tcl_DeleteHashEntry(hPtr);
758 }
759 }
760 if (IS_SHARED(id)) {
761 Ns_MutexUnlock(&itPtr->servPtr->sets.lock);
762 }
763 if (set == NULL) {
764 Tcl_AppendResult(itPtr->interp, "no such set: ", id, NULL);
765 return TCL_ERROR;
766 }
767 *setPtr = set;
768 return TCL_OK;
769 }