source: trunk/lang/tcl/src/RpLibraryTclInterface.cc @ 6697

Last change on this file since 6697 was 5673, checked in by ldelgass, 9 years ago

Fix line endings, set eol-style to native on all C/C++ sources.

  • Property svn:eol-style set to native
File size: 32.2 KB
Line 
1
2/*
3 * ----------------------------------------------------------------------
4 *  Rappture::library
5 *
6 *  This is an interface to the rappture library module.
7 *  It allows you to create rappture library objects.
8 * ======================================================================
9 *  AUTHOR:  Derrick Kearney, Purdue University
10 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
11 *
12 *  See the file "license.terms" for information on usage and
13 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * ======================================================================
15 */
16#include <tcl.h>
17#include <sstream>
18#include "RpLibrary.h"
19
20#define RAPPTURE_OBJ_TYPE "::Rappture::LibraryObj"
21
22extern "C" Tcl_AppInitProc RpLibrary_Init;
23
24#include "RpOp.h"
25
26static Tcl_ObjCmdProc LibraryCmd;
27static Tcl_ObjCmdProc LibCallCmd;
28static Tcl_ObjCmdProc ChildOp;
29static Tcl_ObjCmdProc CopyOp;
30static Tcl_ObjCmdProc DiffOp;
31static Tcl_ObjCmdProc ElemOp;
32static Tcl_ObjCmdProc GetOp;
33static Tcl_ObjCmdProc InfoOp;
34static Tcl_ObjCmdProc IsaOp;
35static Tcl_ObjCmdProc ParentOp;
36static Tcl_ObjCmdProc PutOp;
37static Tcl_ObjCmdProc RemoveOp;
38static Tcl_ObjCmdProc ResultOp;
39static Tcl_ObjCmdProc ValueOp;
40static Tcl_ObjCmdProc XmlOp;
41static Tcl_ObjCmdProc ResultCmd;
42
43static std::string rpLib2command _ANSI_ARGS_((Tcl_Interp *interp,
44    RpLibrary* newRpLibObj));
45static int rpGetLibraryFromObj _ANSI_ARGS_((Tcl_Interp *interp,
46    Tcl_Obj* obj, RpLibrary **rval));
47
48// member function, function pointer mainly used in 'element' implementation
49typedef std::string (RpLibrary::*rpMbrFxnPtr) _ANSI_ARGS_(());
50
51static Rp_OpSpec rpLibOps[] = {
52    {"children", 2, (void *)ChildOp, 2, 7,
53        "?-as <fval>? ?-type <name>? ?<path>?",},
54    {"copy",     2, (void *)CopyOp, 5, 6,
55        "<path> from ?<xmlobj>? <path>",},
56    {"diff",     1, (void *)DiffOp, 3, 3, "<xmlobj>",},
57    {"element",  1, (void *)ElemOp, 2, 5, "?-as <fval>? ?<path>?",},
58    {"get",      1, (void *)GetOp, 2, 3, "?<path>?",},
59    {"info",     1, (void *)InfoOp, 3, 3, "<objType>",},
60    {"isa",      1, (void *)IsaOp, 3, 3, "<objType>",},
61    {"parent",   2, (void *)ParentOp, 2, 5, "?-as <fval>? ?<path>?",},
62    {"put",      2, (void *)PutOp, 2, 8,
63        "?-append yes? ?-id num? ?<path>? <string>",},
64    {"remove",   3, (void *)RemoveOp, 2, 3, "?<path>?",},
65    {"xml",      1, (void *)XmlOp, 2, 2, "",},
66};
67
68static int nRpLibOps = sizeof(rpLibOps) / sizeof(Rp_OpSpec);
69
70/*
71 * ------------------------------------------------------------------------
72 *  rpLib2command()
73 *
74 *  dsk defined helper function for creating a new command out of a
75 *  rappture library
76 *
77 * ------------------------------------------------------------------------
78 */
79std::string
80rpLib2command (Tcl_Interp *interp, RpLibrary* newRpLibObj)
81{
82    static int libCount = 0;
83    std::stringstream libName;
84
85    libName << "::libraryObj" << libCount++;
86
87    Tcl_CreateObjCommand(interp, libName.str().c_str(),
88        LibCallCmd, (ClientData)newRpLibObj, (Tcl_CmdDeleteProc*)NULL);
89
90    return libName.str();
91}
92
93/*
94 * ------------------------------------------------------------------------
95 *  rpGetLibraryFromObj()
96 *
97 *  Tries to decode the given argument as a Rappture Library object.
98 *  Returns TCL_OK if successful, along with a pointer to the library
99 *  in rval.  Otherwise, it returns TCL_ERROR, along with an error
100 *  message in the interp.
101 * ------------------------------------------------------------------------
102 */
103static int
104rpGetLibraryFromObj(Tcl_Interp *interp, Tcl_Obj* objPtr, RpLibrary **rval)
105{
106    Tcl_CmdInfo info;
107    char *cmdname = Tcl_GetString(objPtr);
108    if (Tcl_GetCommandInfo(interp, cmdname, &info)) {
109        if (info.objProc == RpLibCallCmd) {
110            *rval = (RpLibrary*)(info.objClientData);
111            return TCL_OK;
112        }
113    }
114    Tcl_AppendResult(interp, "bad value \"", cmdname,
115        "\": should be a Rappture library object", (char*)NULL);
116    return TCL_ERROR;
117}
118
119/*
120 * ------------------------------------------------------------------------
121 *  RpLibrary_Init()
122 *
123 *  Called in Rappture_Init() to initialize the commands defined
124 *  in this file.
125 * ------------------------------------------------------------------------
126 */
127int
128RpLibrary_Init(Tcl_Interp *interp)
129{
130
131    Tcl_CreateObjCommand(interp, "::Rappture::library",
132        LibraryCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
133
134    Tcl_CreateObjCommand(interp, "::Rappture::result",
135        ResultCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
136
137    /*
138    Tcl_CreateObjCommand(interp, "::Rappture::LibraryObj::value",
139        LibValueOp, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
140    */
141
142    return TCL_OK;
143}
144
145/*
146 * USAGE: library <file>
147 * USAGE: library standard
148 * USAGE: library isvalid <object>
149 */
150static int
151LibraryCmd(ClientData clientData, Tcl_Interp *interp, int objc,
152           Tcl_Obj* const *objv)
153{
154    const char *flag = Tcl_GetString(objv[1]);
155    if (objc > 2 && strcmp(flag,"isvalid") == 0) {
156        if (objc != 3) {
157            Tcl_AppendResult(interp, "wrong # args: should be \"",
158                Tcl_GetString(objv[0]), "\": isvalid object",
159                (char*)NULL);
160            return TCL_ERROR;
161        }
162
163        //
164        // Check to see if the object is valid.  It should be a
165        // recognized Tcl command with the appropriate handler
166        // function.
167        //
168        int found = 0;
169        RpLibrary *rlib;
170        if (rpGetLibraryFromObj(interp, objv[2], &rlib) == TCL_OK && rlib) {
171            found = 1;
172        }
173        Tcl_SetObjResult(interp, Tcl_NewIntObj(found));
174        return TCL_OK;
175    }
176
177    if (objc != 2) {
178        Tcl_AppendResult(interp, "usage: ", Tcl_GetString(objv[0]),
179            " <xmlfile>",(char*)NULL);
180        return TCL_ERROR;
181    }
182
183    // create a new command
184    RpLibrary *rpptr = new RpLibrary( Tcl_GetString(objv[1]) );
185    std::string libName = rpLib2command(interp,rpptr);
186
187    Tcl_AppendResult(interp, libName.c_str(), (char*)NULL);
188    return TCL_OK;
189}
190
191
192static int
193LibCallCmd(ClientData clientData, Tcl_Interp *interp, int objc,
194           Tcl_Obj *const *objv)
195{
196    Tcl_ObjCmdProc *proc;
197
198    proc = (Tcl_ObjCmdProc *)Rp_GetOpFromObj(interp, nRpLibOps, rpLibOps,
199        RP_OP_ARG1, objc, objv, 0);
200
201    if (proc == NULL) {
202        return TCL_ERROR;
203    }
204    return (*proc)(clientData, interp, objc, objv);
205}
206
207/**********************************************************************/
208// FUNCTION: ChildOp()
209/// children function in Tcl, retrieves a list of children for a given path
210/**
211 * Returns a list of children of the node located at <path>
212 * Full function call:
213 *
214 * children ?-as <fval>? ?-type <name>? ?<path>?
215 *
216 * -as option specifies how to return the result
217 * <fval> is one of the following:
218 *     component - return the component name of child node, ex: type(id)
219 *     id        - return the id attribute of child node
220 *     type      - return the type attribute of child node
221 *     path      - return the full path of child node
222 *     object    - return a Rappture Library Object
223 *
224 * -type option tells function to only look for nodes of type <name>
225 *
226 * <path> is the path of the parent node you are requesting the children of
227 *        if <path> is left blank, the current node will be considered the
228 *        parent node and all its children will be returned.
229 */
230static int
231ChildOp (ClientData clientData, Tcl_Interp *interp, int objc,
232         Tcl_Obj *const *objv)
233{
234    std::string path   = "";    // path of where to place data inside xml tree
235    std::string type   = "";    // type of nodes to be returned
236    std::string retStr = "";    // path of where to place data inside xml tree
237    int nextarg        = 2;     // start parsing using the '2'th argument
238    int opt_objc       = 2;     // max number of optional parameters
239
240    RpLibrary* node    = NULL;
241    rpMbrFxnPtr asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
242
243    // parse through -'d arguments
244    while (opt_objc--) {
245        char *opt = Tcl_GetString(objv[nextarg]);
246        if (nextarg < objc && *opt == '-') {
247            if (strcmp(opt,"-as") == 0) {
248                nextarg++;
249                if (nextarg < objc) {
250                    if (*opt == 'c' && strcmp(opt,"component") == 0) {
251                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
252                        nextarg++;
253                    }
254                    else if (*opt == 'i' && strcmp(opt,"id") == 0) {
255                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeId;
256                        nextarg++;
257                    }
258                    else if (*opt == 't' && strcmp(opt,"type") == 0) {
259                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeType;
260                        nextarg++;
261                    }
262                    else if (*opt == 'p' && strcmp(opt,"path") == 0) {
263                        asProc = (rpMbrFxnPtr)&RpLibrary::nodePath;
264                        nextarg++;
265                    }
266                    else if (*opt == 'o' && strcmp(opt,"object") == 0) {
267                        asProc = (rpMbrFxnPtr)NULL;
268                        nextarg++;
269                    }
270                    else {
271                        Tcl_AppendResult(interp, "bad flavor \"", opt,
272                            "\" for -as: should be component, id, type,",
273                            " path, object", (char*)NULL);
274                        return TCL_ERROR;
275                    }
276                }
277                else {
278                    Tcl_AppendResult(interp, "bad flavor \"\" for -as",
279                        ": should be component, id, type, path, object",
280                        (char*)NULL);
281                    return TCL_ERROR;
282                }
283            }
284            else if (strcmp(opt,"-type") == 0) {
285                nextarg++;
286                if (nextarg < objc) {
287                    type = std::string(opt);
288                    nextarg++;
289                }
290                else {
291                    Tcl_AppendResult(interp, "bad flavor \"\" for -type ",
292                        "option: should be a type of node within the xml",
293                        (char*)NULL);
294                    return TCL_ERROR;
295                }
296            }
297            else {
298                Tcl_AppendResult(interp, "bad option \"", opt,
299                    "\": should be -as, -type", (char*)NULL);
300                return TCL_ERROR;
301            }
302        }
303    }
304
305    int argsLeft = (objc-nextarg);
306    if (argsLeft > 1) {
307        Tcl_AppendResult(interp,
308                "wrong # args: should be ",
309                "\"children ?-as <fval>? ?-type <name>? ?<path>?\"",
310                (char*)NULL);
311        return TCL_ERROR;
312    }
313    else if (argsLeft == 1) {
314        path = std::string( Tcl_GetString(objv[nextarg++]) );
315    }
316    else {
317        path = "";
318    }
319
320    // call the rappture library children function
321    while ( (node = ((RpLibrary*) clientData)->children(path,node,type)) ) {
322        if (node) {
323            if (asProc) {
324                // evaluate the "-as" flag on the returned node
325                retStr = (node->*asProc)();
326            }
327            else {
328                // create a new command for the new rappture object
329                retStr = rpLib2command(interp, node);
330            }
331
332            // store the new result string in the interpreter
333            Tcl_AppendElement(interp,retStr.c_str());
334        }
335    }
336    return TCL_OK;
337}
338
339static int
340CopyOp (ClientData clientData, Tcl_Interp *interp, int objc,
341        Tcl_Obj *const *objv)
342{
343    std::string fromPath = "";    // path of where to copy data from
344    std::string toPath   = "";    // path of where to copy data to
345    std::string from     = "";    // string that should == "from"
346    RpLibrary* fromObj   = NULL;
347    int nextarg          = 2;     // start parsing using the '2'th argument
348    int argsLeft         = 0;     // temp variable for calculation
349
350    if (nextarg+2 < objc) {
351        toPath = std::string( Tcl_GetString(objv[nextarg++]) );
352        from = std::string( Tcl_GetString(objv[nextarg++]) );
353    }
354    else {
355        Tcl_AppendResult(interp,
356            "wrong # args: should be \"",
357            Tcl_GetString(objv[0]), " path from ?<xmlobj>? path\"",
358            (char*)NULL);
359        return TCL_ERROR;
360    }
361
362    argsLeft = (objc-nextarg);
363    if (argsLeft == 2) {
364        if (rpGetLibraryFromObj(interp, objv[nextarg++], &fromObj) != TCL_OK) {
365            return TCL_ERROR;
366        }
367        fromPath = std::string( Tcl_GetString(objv[nextarg++]) );
368    }
369    else if (argsLeft == 1) {
370        fromPath = std::string( Tcl_GetString(objv[nextarg++]) );
371    }
372    else {
373        Tcl_ResetResult(interp);
374        Tcl_AppendResult(interp,
375            "wrong # args: should be \"copy path from ?xmlobj? path\"",
376            (char*)NULL);
377        return TCL_ERROR;
378    }
379
380    if (from != "from") {
381        Tcl_ResetResult(interp);
382        Tcl_AppendResult(interp,
383R            "bad syntax: should be \"copy path from ?xmlobj? path\"",
384            (char*)NULL);
385        return TCL_ERROR;
386    }
387
388    // call the rappture library copy function
389    RpLibrary *libPtr   = (RpLibrary *)clientData;
390    libPtr->copy(toPath, fromObj, fromPath);
391
392    // clear any previous result in the interpreter
393    Tcl_ResetResult(interp);
394    return TCL_OK;
395}
396
397/**********************************************************************/
398// FUNCTION: DiffOp()
399/// diff function in Tcl, used to find the difference between two xml objects
400/**
401 * Returns a list of differences between two xml objects.
402 * Full function call:
403 * diff <xmlobj>
404 */
405
406static int
407DiffOp (ClientData clientData, Tcl_Interp *interp, int objc,
408        Tcl_Obj *const *objv)
409{
410    RpLibrary* otherLibPtr = NULL;
411
412    // parse input arguments
413    if (rpGetLibraryFromObj(interp, objv[2], &otherLibPtr) != TCL_OK) {
414        return TCL_ERROR;
415    }
416    RpLibrary *libPtr   = (RpLibrary *)clientData;
417
418    std::list<std::string> diffList; // list to store the return value
419                                     // from diff command
420    // perform the diff command
421    diffList = libPtr->diff(otherLibPtr,"input");
422
423    std::list<std::string>::iterator diffListIter;
424    diffListIter = diffList.begin();
425
426    Tcl_ResetResult(interp);
427
428    // parse through the output of the diff command
429    // put it into the return result
430    while (diffListIter != diffList.end()) {
431        Tcl_AppendElement(interp,(*diffListIter).c_str());
432
433        // increment the iterator
434        diffListIter++;
435    }
436    return TCL_OK;
437}
438
439/**********************************************************************/
440// FUNCTION: ElemOp()
441/// element function in Tcl, used to retrieve a xml objects
442/**
443 * Returns a xml object.
444 * Full function call:
445 * element ?-as <fval>? ?<path>?
446 */
447static int
448ElemOp (ClientData clientData, Tcl_Interp *interp, int objc,
449        Tcl_Obj *const *objv)
450{
451    std::string path   = "";    // path of where to place data inside xml tree
452    std::string retStr = "";    // path of where to place data inside xml tree
453    int nextarg        = 2;     // start parsing using the '2'th argument
454    int opt_objc       = 1;     // max number of optional parameters
455
456    RpLibrary* node    = NULL;
457    rpMbrFxnPtr asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
458
459    // parse through -'d arguments
460    while (opt_objc--) {
461        char *opt = Tcl_GetString(objv[nextarg]);
462        if (nextarg < objc && *opt == '-') {
463            if (strcmp(opt,"-as") == 0) {
464                nextarg++;
465                if (nextarg < objc) {
466                    if (*opt == 'c' && strcmp(opt,"component") == 0) {
467                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
468                        nextarg++;
469                    }
470                    else if (*opt == 'i' && strcmp(opt,"id") == 0) {
471                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeId;
472                        nextarg++;
473                    }
474                    else if (*opt == 't' && strcmp(opt,"type") == 0) {
475                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeType;
476                        nextarg++;
477                    }
478                    else if (*opt == 'p' && strcmp(opt,"path") == 0) {
479                        asProc = (rpMbrFxnPtr)&RpLibrary::nodePath;
480                        nextarg++;
481                    }
482                    else if (*opt == 'o' && strcmp(opt,"object") == 0) {
483                        asProc = NULL;
484                        nextarg++;
485                    }
486                    else {
487                        Tcl_AppendResult(interp, "bad flavor \"",
488                            Tcl_GetString(objv[nextarg]),
489                            "\" for -as: should be component, id, type,"
490                            " path, object", (char*)NULL);
491                        return TCL_ERROR;
492                    }
493                }
494                else {
495                    Tcl_AppendResult(interp, "bad flavor \"\" for -as:",
496                           " should be component, id, type, path, object",
497                            (char*)NULL);
498                    return TCL_ERROR;
499                }
500            }
501            else {
502                Tcl_AppendResult(interp, "bad option \"", opt,
503                    "\": should be -as", (char*)NULL);
504                return TCL_ERROR;
505            }
506        }
507    }
508
509    int argsLeft = (objc-nextarg);
510    if (argsLeft > 1) {
511        Tcl_AppendResult(interp,
512            "wrong # args: should be \"element ?-as <fval>? ?<path>?\"",
513            (char*)NULL);
514        return TCL_ERROR;
515    }
516    else if (argsLeft == 1) {
517        path = std::string( Tcl_GetString(objv[nextarg++]) );
518    }
519    else {
520        path = "";
521    }
522
523    // call the rappture library element function
524    node = ((RpLibrary*) clientData)->element(path);
525    if (node) {
526        // clear any previous result in the interpreter
527        Tcl_ResetResult(interp);
528
529        if (asProc) {
530            // evaluate the "-as" flag on the returned node
531            retStr = (node->*asProc)();
532        }
533        else {
534            // create a new command for the new rappture object
535            retStr = rpLib2command(interp, node);
536        }
537        // store the new result string in the interpreter
538        Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
539    }
540    return TCL_OK;
541}
542
543/**********************************************************************/
544// FUNCTION: GetOp()
545/// get function in Tcl, used to retrieve the value of a xml object
546/**
547 * Returns the value of a xml object.
548 * Full function call:
549 * get ?<path>?
550 */
551static int
552GetOp (ClientData clientData, Tcl_Interp *interp, int objc,
553       Tcl_Obj *const *objv)
554{
555
556    std::string retStr = ""; // return value of rappture get fxn
557    std::string path = "";
558
559    if (objc == 3) {
560        path = std::string( Tcl_GetString(objv[2]) );
561    }
562    else if (objc != 2) {
563        Tcl_ResetResult(interp);
564        Tcl_AppendResult(interp,
565            "wrong # args: should be \"get ?path?\"",
566            "\":", (char*)NULL);
567        return TCL_ERROR;
568    }
569
570    // call the Rappture Library Get Function
571    retStr = ((RpLibrary*) clientData)->getString(path);
572
573    // clear any previous result in the interpreter
574    // store the new result in the interpreter
575    Tcl_ResetResult(interp);
576    Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
577
578    return TCL_OK;
579}
580
581/**********************************************************************/
582// FUNCTION: InfoOp()
583/// info function in Tcl, return specific information about this object's type
584/**
585 * Query the object about its data type.
586 * This function is available for compatibility with old itcl
587 * Rappture::LibraryObj's
588 *
589 * Full function call:
590 * info <infoType>
591 *
592 * <infoType> must be one of the following:
593 *     class
594 *
595 * Return Values:
596 * class -> ::Rappture::LibraryObj
597 */
598
599static int
600InfoOp (ClientData clientData, Tcl_Interp *interp, int objc,
601        Tcl_Obj *const *objv)
602{
603
604    std::string infoType = ""; // string value of type of info being requested
605    std::string retStr   = ""; // return value of rappture get fxn
606
607    if (objc == 3) {
608        infoType = std::string( Tcl_GetString(objv[2]) );
609    }
610    else {
611        Tcl_ResetResult(interp);
612        Tcl_AppendResult(interp,
613            "wrong # args: should be \"info <infoType>\"",
614            (char*)NULL);
615        return TCL_ERROR;
616    }
617
618    if ("class" == infoType) {
619        retStr = RAPPTURE_OBJ_TYPE;
620    }
621    else {
622        retStr = "";
623        Tcl_AppendResult(interp,
624            "bad flavor: \"", infoType.c_str(), "\" should be \"class\"",
625            (char*)NULL);
626        return TCL_ERROR;
627    }
628
629    // store the new result in the interpreter
630    Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
631
632    return TCL_OK;
633}
634
635/**********************************************************************/
636// FUNCTION: IsaOp()
637/// isa function in Tcl, check this objects type against a provided <objType>
638/**
639 * Query the object about its data type.
640 * This function is available for compatibility with old itcl
641 * Rappture::LibraryObj's
642 *
643 * Full function call:
644 * isa <objType>
645 *
646 * <infoType> must be one of the following:
647 *     class
648 *
649 * Return Value:
650 * if "::Rappture::LibraryObj" == <objType> returns "1"
651 * else returns "0"
652 */
653
654static int
655IsaOp (ClientData clientData, Tcl_Interp *interp, int objc,
656       Tcl_Obj *const *objv)
657{
658
659    std::string compVal = ""; // string value of object being compared to
660    std::string retStr  = ""; // return value of rappture get fxn
661
662    if (objc == 3) {
663        compVal = std::string( Tcl_GetString(objv[2]) );
664    }
665    else {
666        Tcl_ResetResult(interp);
667        Tcl_AppendResult(interp,
668            "wrong # args: should be \"isa <objType>\"",
669            (char*)NULL);
670        return TCL_ERROR;
671    }
672
673    if (compVal == RAPPTURE_OBJ_TYPE) {
674        retStr = "1";
675    }
676    else {
677        retStr = "0";
678    }
679
680    // clear any previous result in the interpreter
681    // store the new result in the interpreter
682    Tcl_ResetResult(interp);
683    Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
684
685    return TCL_OK;
686}
687
688static int
689ParentOp (ClientData clientData, Tcl_Interp *interp, int objc,
690          Tcl_Obj *const *objv)
691{
692    std::string path   = "";    // path of where to place data inside xml tree
693    std::string retStr = "";    // path of where to place data inside xml tree
694    int nextarg        = 2;     // start parsing using the '2'th argument
695    int opt_objc       = 1;     // max number of optional parameters
696
697    RpLibrary* node    = NULL;
698    rpMbrFxnPtr asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
699
700    // parse through -'d arguments
701    while (opt_objc--) {
702        char *opt = Tcl_GetString(objv[nextarg]);
703        if (nextarg < objc && *opt == '-') {
704            if (strcmp(opt,"-as") == 0) {
705                nextarg++;
706                if (nextarg < objc) {
707                    if (*opt == 'c' && strcmp(opt,"component") == 0) {
708                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeComp;
709                        nextarg++;
710                    }
711                    else if (*opt == 'i' && strcmp(opt,"id") == 0) {
712                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeId;
713                        nextarg++;
714                    }
715                    else if (*opt == 't' && strcmp(opt,"type") == 0) {
716                        asProc = (rpMbrFxnPtr)&RpLibrary::nodeType;
717                        nextarg++;
718                    }
719                    else if (*opt == 'p' && strcmp(opt,"path") == 0) {
720                        asProc = (rpMbrFxnPtr)&RpLibrary::nodePath;
721                        nextarg++;
722                    }
723                    else if (*opt == 'o' && strcmp(opt,"object") == 0) {
724                        asProc = NULL;
725                        nextarg++;
726                    }
727                    else {
728                        Tcl_AppendResult(interp, "bad flavor \"",
729                            Tcl_GetString(objv[nextarg]),
730                            "\": should be component, id, type, path, object",
731                            (char*)NULL);
732                        return TCL_ERROR;
733                    }
734                }
735                else {
736                    Tcl_AppendResult(interp, "bad flavor \"\" for -as: ",
737                            "should be component, id, type, path, object",
738                            (char*)NULL);
739                    return TCL_ERROR;
740                }
741            }
742            else {
743                Tcl_AppendResult(interp, "bad option \"", opt,
744                    "\": should be -as", (char*)NULL);
745                return TCL_ERROR;
746            }
747        }
748    }
749
750    int argsLeft = (objc-nextarg);
751    if ( argsLeft > 1) {
752        Tcl_AppendResult(interp,
753            "wrong # args: should be \"parent ?-as <fval>? ?<path>?\"",
754            (char*)NULL);
755        return TCL_ERROR;
756    }
757    else if (argsLeft == 1) {
758        path = std::string( Tcl_GetString(objv[nextarg++]) );
759    }
760    else {
761        path = "";
762    }
763
764    // call the rappture library parent function
765    node = ((RpLibrary*) clientData)->parent(path);
766    if (node) {
767        // clear any previous result in the interpreter
768        Tcl_ResetResult(interp);
769
770        if (asProc) {
771            // evaluate the "-as" flag on the returned node
772            retStr = (node->*asProc)();
773        }
774        else {
775            // create a new command for the new rappture object
776            retStr = rpLib2command(interp, node);
777        }
778        // store the new result string in the interpreter
779        Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
780    }
781    return TCL_OK;
782}
783
784/**********************************************************************/
785// FUNCTION: PutOp()
786/// put function in Tcl, put a value into a xml node at location <path>
787/**
788 * Put a value into a xml node at location <path>
789 *
790 * Full function call:
791 * put <path>
792 *
793 * Return Value:
794 * On success, None.
795 * On failure, an error message is returned
796 */
797static int
798PutOp (ClientData clientData, Tcl_Interp *interp, int objc,
799       Tcl_Obj *const *objv)
800{
801    std::string id     = "";    // id tag for the given path
802    std::string path   = "";    // path of where to place data inside xml tree
803    std::string addStr = "";    // string to be added to data inside xml tree
804    int nextarg        = 2;     // start parsing using the '2'th argument
805    int append         = 0;     // append flag - 0 means no, 1 means yes
806    int opt_objc       = 2;     // max number of optional parameters
807
808    while (opt_objc--) {
809        char *opt = Tcl_GetString(objv[nextarg]);
810        if (nextarg < objc && *opt == '-') {
811            if (strcmp(opt,"-append") == 0) {
812                ++nextarg;
813                if (nextarg < objc) {
814                    if (Tcl_GetBooleanFromObj(interp, objv[nextarg],
815                          &append) != TCL_OK) {
816                        return TCL_ERROR;
817                    }
818                }
819                else {
820                    Tcl_AppendResult(interp, "missing value for -append",
821                        (char*)NULL);
822                    return TCL_ERROR;
823                }
824            }
825            else if (strcmp(opt,"-id") == 0) {
826                id = std::string( Tcl_GetString(objv[++nextarg]) );
827                nextarg++;
828            }
829            else {
830                Tcl_AppendResult(interp, "bad option \"", opt,
831                    "\": should be -append or -id", (char*)NULL);
832                return TCL_ERROR;
833            }
834        }
835    }
836
837    int argsLeft = (objc-nextarg);
838    if (argsLeft == 2) {
839        path = std::string( Tcl_GetString(objv[nextarg++]) );
840        addStr = std::string( Tcl_GetString(objv[nextarg++]) );
841    }
842    else if (argsLeft == 1) {
843        path = "";
844        addStr = std::string( Tcl_GetString(objv[nextarg++]) );
845    }
846    else {
847        Tcl_AppendResult(interp, "wrong # args: should be ",
848            "\"put ?-append yes? ?-id num? ?<path>? <string>\"",
849            (char*)NULL);
850        return TCL_ERROR;
851    }
852
853    // call the rappture library put function
854    ((RpLibrary*) clientData)->put(path, addStr, id, append);
855
856    // return nothing for this operation
857    Tcl_ResetResult(interp);
858    return TCL_OK;
859}
860
861/**********************************************************************/
862// FUNCTION: RemoveOp()
863/// remove function in Tcl, used to remove a xml node at location <path>
864/**
865 * Removes the xml node at location <path>, if it exists. Does nothing
866 * if the node does not exist.
867 *
868 * Full function call:
869 * remove ?<path>?
870 *
871 * Return Value:
872 * On success, None.
873 * On failure, an error message is returned
874 */
875static int
876RemoveOp (ClientData clientData, Tcl_Interp *interp, int objc,
877          Tcl_Obj *const *objv)
878{
879    std::string path = std::string("");  // path of where to remove data from
880
881    if (objc == 3) {
882        path = std::string( Tcl_GetString(objv[2]) );
883    }
884
885    // call the rappture library remove function
886    ((RpLibrary*) clientData)->remove(path);
887
888    // clear any previous result in the interpreter
889    Tcl_ResetResult(interp);
890    return TCL_OK;
891}
892
893static int
894ResultOp(ClientData clientData, Tcl_Interp *interp, int objc,
895         Tcl_Obj *const *objv)
896{
897    // call the rappture library result function
898    ((RpLibrary*) clientData)->result();
899
900    // clear any previous result in the interpreter
901    Tcl_ResetResult(interp);
902    return TCL_OK;
903}
904
905/**********************************************************************/
906// FUNCTION: ValueOp()
907/// Rappture::LibraryObj::value function in Tcl, used to normalize a number.
908/**
909 * Normalizes values located at <path> in <xmlobj>.
910 *
911 * Full function call:
912 * Rappture::LibraryObj::value <xmlobj> <path>
913 *
914 * Return Value:
915 * 2 element list
916 *   - first element is the original value at location <path>
917 *   - second element is the normalization of the value at location <path>
918 */
919static int
920ValueOp (ClientData clientData, Tcl_Interp *interp, int objc,
921         Tcl_Obj *const *objv)
922{
923    std::list<std::string> valList;  // list to store the return value
924                                     // from diff command
925    std::list<std::string>::iterator valListIter;
926
927    if (objc != 3) {
928        Tcl_AppendResult(interp,
929            "wrong # args: should be \"", Tcl_GetString(objv[0]),
930            " <xmlobj> <path>\"", (char*)NULL);
931        return TCL_ERROR;
932    }
933
934    // parse input arguments
935    RpLibrary* lib;
936    if (rpGetLibraryFromObj(interp, objv[1], &lib) != TCL_OK) {
937        return TCL_ERROR;
938    }
939    std::string path = std::string(Tcl_GetString(objv[2]));
940
941    // perform the value command
942    valList = lib->value(path);
943    valListIter = valList.begin();
944
945    // parse through the output of the diff command
946    // put it into the return result
947    while (valListIter != valList.end()) {
948        Tcl_AppendElement(interp,(*valListIter).c_str());
949
950        // increment the iterator
951        valListIter++;
952    }
953    return TCL_OK;
954}
955
956/**********************************************************************/
957// FUNCTION: XmlOp()
958/// xml function in Tcl, returns the xml data that this object represents
959/**
960 * Prints the xml text for this object.
961 *
962 * Full function call:
963 * xml
964 *
965 * Return Value:
966 * xml text as a string
967 */
968
969static int
970XmlOp(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
971{
972
973    std::string retStr = ""; // return value of rappture get fxn
974
975    if (objc != 2) {
976        Tcl_AppendResult(interp, "wrong # args: should be \"",
977            Tcl_GetString(objv[0]), " xml\"", (char*)NULL);
978        return TCL_ERROR;
979    }
980
981    // call the Rappture Library xml Function
982    retStr = ((RpLibrary*) clientData)->xml();
983
984    // clear any previous result in the interpreter
985    // store the new result in the interpreter
986    Tcl_ResetResult(interp);
987    Tcl_AppendResult(interp, retStr.c_str(), (char*)NULL);
988
989    return TCL_OK;
990}
991
992/**********************************************************************/
993// FUNCTION: ResultCmd()
994/// Rappture::result function in Tcl, prints xml to file and signals gui.
995/**
996 * Prints xml text representing provided object to a runXXXX.xml file
997 * and sends the '=RAPTURE=RUN=>runXXXX.xml' signal to the graphical
998 * user interface so the data can be visualized.
999 *
1000 * Full function call:
1001 * Rappture::result <rpObj>
1002 *
1003 * <rpObj> is a valid rappture object
1004 *
1005 * Return Value:
1006 * None
1007 */
1008static int
1009ResultCmd(ClientData clientData, Tcl_Interp *interp, int objc,
1010          Tcl_Obj *const *objv)
1011{
1012    // parse through command line options
1013    if (objc != 2) {
1014        Tcl_AppendResult(interp, "wrong # args: should be \"",
1015            Tcl_GetString(objv[0]), " <xmlobj>\"", (char*)NULL);
1016        return TCL_ERROR;
1017    }
1018
1019    RpLibrary* lib;
1020    if (rpGetLibraryFromObj(interp, objv[1], &lib) != TCL_OK) {
1021        return TCL_ERROR;
1022    }
1023    lib->result();
1024
1025    // returns nothing
1026    Tcl_ResetResult(interp);
1027    return TCL_OK;
1028}
Note: See TracBrowser for help on using the repository browser.