source: trunk/packages/vizservers/nanovis/CmdProc.cpp @ 1109

Last change on this file since 1109 was 931, checked in by dkearney, 16 years ago

adding new Rappture::DX class which interacts with libdx to produce positions and data as read from the dx file. moved some common functions needed by open dx and nanovis dx to the dxReaderCommon header file. this version allows the user to visualize some dx files from abinit.

File size: 6.4 KB
Line 
1#include <tcl.h>
2#include "CmdProc.h"
3#include <string.h>
4
5/*
6 *-------------------------------------------------------------------------------
7 *
8 * BinaryOpSearch --
9 *
10 *      Performs a binary search on the array of command operation
11 *      specifications to find a partial, anchored match for the given
12 *      operation string.
13 *
14 * Results:
15 *  If the string matches unambiguously the index of the specification in
16 *  the array is returned.  If the string does not match, even as an
17 *  abbreviation, any operation, -1 is returned.  If the string matches,
18 *  but ambiguously -2 is returned.
19 *
20 *-------------------------------------------------------------------------------
21 */
22static int
23BinaryOpSearch(
24    Rappture::CmdSpec *specs,
25    int nSpecs,
26    char *string)       /* Name of minor operation to search for */
27{
28    char c;
29    int high, low;
30    size_t length;
31
32    low = 0;
33    high = nSpecs - 1;
34    c = string[0];
35    length = strlen(string);
36    while (low <= high) {
37    Rappture::CmdSpec *specPtr;
38    int compare;
39    int median;
40   
41    median = (low + high) >> 1;
42    specPtr = specs + median;
43
44    /* Test the first character */
45    compare = c - specPtr->name[0];
46    if (compare == 0) {
47        /* Now test the entire string */
48        compare = strncmp(string, specPtr->name, length);
49        if (compare == 0) {
50        if ((int)length < specPtr->minChars) {
51            return -2;  /* Ambiguous operation name */
52        }
53        }
54    }
55    if (compare < 0) {
56        high = median - 1;
57    } else if (compare > 0) {
58        low = median + 1;
59    } else {
60        return median;  /* Op found. */
61    }
62    }
63    return -1;          /* Can't find operation */
64}
65
66
67/*
68 *-------------------------------------------------------------------------------
69 *
70 * LinearOpSearch --
71 *
72 *      Performs a binary search on the array of command operation
73 *      specifications to find a partial, anchored match for the given
74 *      operation string.
75 *
76 * Results:
77 *  If the string matches unambiguously the index of the specification in
78 *  the array is returned.  If the string does not match, even as an
79 *  abbreviation, any operation, -1 is returned.  If the string matches,
80 *  but ambiguously -2 is returned.
81 *
82 *-------------------------------------------------------------------------------
83 */
84static int
85LinearOpSearch(
86    Rappture::CmdSpec *specs,
87    int nSpecs,
88    char *string)       /* Name of minor operation to search for */
89{
90    Rappture::CmdSpec *specPtr;
91    char c;
92    size_t length;
93    int nMatches, last;
94    int i;
95
96    c = string[0];
97    length = strlen(string);
98    nMatches = 0;
99    last = -1;
100    for (specPtr = specs, i = 0; i < nSpecs; i++, specPtr++) {
101    if ((c == specPtr->name[0]) &&
102        (strncmp(string, specPtr->name, length) == 0)) {
103        last = i;
104        nMatches++;
105        if ((int)length == specPtr->minChars) {
106        break;
107        }
108    }
109    }
110    if (nMatches > 1) {
111    return -2;      /* Ambiguous operation name */
112    }
113    if (nMatches == 0) {
114    return -1;      /* Can't find operation */
115    }
116    return last;        /* Op found. */
117}
118
119/*
120 *-------------------------------------------------------------------------------
121 *
122 * GetOpFromObj --
123 *
124 *      Find the command operation given a string name.  This is useful where
125 *      a group of command operations have the same argument signature.
126 *
127 * Results:
128 *      If found, a pointer to the procedure (function pointer) is returned.
129 *      Otherwise NULL is returned and an error message containing a list of
130 *      the possible commands is returned in interp->result.
131 *
132 *-------------------------------------------------------------------------------
133 */
134Tcl_ObjCmdProc *
135Rappture::GetOpFromObj(
136    Tcl_Interp *interp,     /* Interpreter to report errors to */
137    int nSpecs,         /* Number of specifications in array */
138    CmdSpec *specs,     /* Op specification array */
139    int operPos,        /* Position of operation in argument list. */
140    int objc,           /* Number of arguments in the argument vector.
141                 * This includes any prefixed arguments */
142    Tcl_Obj *CONST *objv,   /* Argument vector */
143    int flags)
144{
145    CmdSpec *specPtr;
146    char *string;
147    int n;
148
149    if (objc <= operPos) {  /* No operation argument */
150    Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
151      usage:
152    Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
153    for (n = 0; n < nSpecs; n++) {
154        int i;
155
156        Tcl_AppendResult(interp, "\n  ", (char *)NULL);
157        for (i = 0; i < operPos; i++) {
158        Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
159             (char *)NULL);
160        }
161        specPtr = specs + n;
162        Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
163        (char *)NULL);
164    }
165    return NULL;
166    }
167    string = Tcl_GetString(objv[operPos]);
168    if (flags & CMDSPEC_LINEAR_SEARCH) {
169    n = LinearOpSearch(specs, nSpecs, string);
170    } else {
171    n = BinaryOpSearch(specs, nSpecs, string);
172    }
173    if (n == -2) {
174    char c;
175    size_t length;
176
177    Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
178    if (operPos > 2) {
179        Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
180        (char *)NULL);
181    }
182    Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
183        (char *)NULL);
184
185    c = string[0];
186    length = strlen(string);
187    for (n = 0; n < nSpecs; n++) {
188        specPtr = specs + n;
189        if ((c == specPtr->name[0]) &&
190        (strncmp(string, specPtr->name, length) == 0)) {
191        Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
192        }
193    }
194    return NULL;
195
196    } else if (n == -1) {   /* Can't find operation, display help */
197    Tcl_AppendResult(interp, "bad", (char *)NULL);
198    if (operPos > 2) {
199        Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
200        (char *)NULL);
201    }
202    Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
203    goto usage;
204    }
205    specPtr = specs + n;
206    if ((objc < specPtr->minArgs) ||
207    ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
208    int i;
209
210    Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
211    for (i = 0; i < operPos; i++) {
212        Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
213        (char *)NULL);
214    }
215    Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
216        (char *)NULL);
217    return NULL;
218    }
219    return specPtr->proc;
220}
Note: See TracBrowser for help on using the repository browser.