root/trunk/ARB_GDE/GDE_ParseMenu.cxx

Revision 8660, 18.6 KB (checked in by westram, 4 weeks ago)
  • workaround quoting error in ARB_GDEmenus (clang)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include "GDE_extglob.h"
2#include <cctype>
3
4static int getline(FILE *file, char *string)
5{
6    int c;
7    int i;
8    for (i=0; (c=getc(file))!='\n'; i++) {
9        if (c == EOF) break;
10        if (i >= GBUFSIZ -2) break;
11        string[i]=c;
12    }
13    string[i] = '\0';
14    if (i==0 && c==EOF) return (EOF);
15    else return (0);
16}
17
18
19/*
20  ParseMenus(): Read in the menu config file, and generate the internal
21  menu structures used by the window system.
22
23  Copyright (c) 1989, University of Illinois board of trustees.  All rights
24  reserved.  Written by Steven Smith at the Center for Prokaryote Genome
25  Analysis.  Design and implementation guidance by Dr. Gary Olsen and Dr.
26  Carl Woese.
27
28  Copyright (c) 1990,1991,1992 Steven Smith at the Harvard Genome Laboratory.
29  All rights reserved.
30
31  Changed to fit into ARB by ARB development team.
32*/
33
34void ParseMenu() {
35    int           j, curmenu  = -1, curitem = 0;
36    int           curchoice  = 0, curarg = 0, curinput = 0, curoutput = 0;
37    char          in_line[GBUFSIZ], temp[GBUFSIZ], head[GBUFSIZ];
38    char          tail[GBUFSIZ];
39    const char   *home;
40    Gmenu        *thismenu   = NULL;
41    GmenuItem    *thisitem   = NULL;
42    GmenuItemArg *thisarg    = NULL;
43    GfileFormat  *thisinput  = NULL;
44    GfileFormat  *thisoutput = NULL;
45    char         *resize;
46
47    /*  Open the menu configuration file "$ARBHOME/GDEHELP/ARB_GDEmenus"
48     *  First search the local directory, then the home directory.
49     */
50    memset((char*)&menu[0], 0, sizeof(Gmenu)*GDEMAXMENU);
51    home = GB_getenvARBHOME();
52
53    strcpy(temp, home);
54    strcat(temp, "/GDEHELP/ARB_GDEmenus");
55   
56    FILE *file = fopen(temp, "r");
57    if (file == NULL) Error("ARB_GDEmenus file not in the home, local, or $ARBHOME/GDEHELP directory");
58
59    /*  Read the ARB_GDEmenus file, and assemble an internal representation
60     *  of the menu/menu-item hierarchy.
61     */
62
63    for (; getline(file, in_line) != EOF;)
64    {
65        // menu: chooses menu to use
66        if (in_line[0] == '#' || (in_line[0] && in_line[1] == '#')) {
67            ; // skip line
68        }
69        else if (Find(in_line, "menu:"))
70        {
71            crop(in_line, head, temp);
72            curmenu = -1;
73            for (j=0; j<num_menus; j++) {
74                if (Find(temp, menu[j].label)) curmenu=j;
75            }
76            // If menu not found, make a new one
77            if (curmenu == -1)
78            {
79                curmenu         = num_menus++;
80                thismenu        = &menu[curmenu];
81                thismenu->label = (char*)calloc(strlen(temp)+1, sizeof(char));
82
83                if (thismenu->label == NULL) Error("Calloc");
84                (void)strcpy(thismenu->label, temp);
85                thismenu->numitems = 0;
86            }
87        }
88        // item: chooses menu item to use
89        else if (Find(in_line, "item:"))
90        {
91            curarg    = -1;
92            curinput  = -1;
93            curoutput = -1;
94            crop(in_line, head, temp);
95            curitem   = thismenu->numitems++;
96
97            // Resize the item list for this menu (add one item);
98            if (curitem == 0) {
99                resize = (char*)GB_calloc(1, sizeof(GmenuItem)); // @@@ calloc->GB_calloc avoids (rui)
100            }
101            else {
102                resize = (char *)realloc((char *)thismenu->item, thismenu->numitems*sizeof(GmenuItem));
103            }
104
105            if (resize == NULL) Error ("Calloc");
106            thismenu->item = (GmenuItem*)resize;
107
108            thisitem              = &(thismenu->item[curitem]);
109            thisitem->label       = strdup(temp);
110            thisitem->meta        = '\0';
111            thisitem->numinputs   = 0;
112            thisitem->numoutputs  = 0;
113            thisitem->numargs     = 0;
114            thisitem->help        = NULL;
115            thisitem->parent_menu = thismenu;
116            thisitem->aws         = NULL; // no window opened yet
117        }
118
119        // itemmethod: generic command line generated by this item
120        else if (Find(in_line, "itemmethod:"))
121        {
122            crop(in_line, head, temp);
123            thisitem->method =
124                (char*)calloc(strlen(temp)+1, sizeof(char));
125            if (thisitem->method == NULL) Error("Calloc");
126
127            {
128                char *to = thisitem->method;
129                char *from = temp;
130                char last = 0;
131                char c;
132
133                do {
134                    c = *from++;
135                    if (c == '@' && last == '@') {
136                        // replace "@@" with "'"
137                        // [WHY_USE_DOUBLE_AT]
138                        // - cant use 1 single quote  ("'"). Things inside will not be preprocessed correctly.
139                        // - cant use 2 single quotes ("''") any longer. clang fails on OSX.
140                        to[-1] = '\'';
141                    }
142                    else {
143                        *to++ = c;
144                    }
145                    last = c;
146                } while (c!=0);
147            }
148
149        }
150        // Help file
151        else if (Find(in_line, "itemhelp:"))
152        {
153            crop(in_line, head, temp);
154            thisitem->help = (char*)calloc(strlen(temp)+1, sizeof(char));
155            if (thisitem->method == NULL) Error("Calloc");
156            (void)strcpy(thisitem->help, temp);
157        }
158        // Meta key equiv
159        else if (Find(in_line, "itemmeta:"))
160        {
161            crop(in_line, head, temp);
162            thisitem->meta = temp[0];
163        }
164        else if (Find(in_line, "menumeta:"))
165        {
166            crop(in_line, head, temp);
167            thismenu->meta = temp[0];
168        }
169        // Sequence type restriction
170        else if (Find(in_line, "seqtype:"))
171        {
172            crop(in_line, head, temp);
173            thisitem->seqtype = toupper(temp[0]);
174            /* 'A' -> amino acids,
175             * 'N' -> nucleotides,
176             * '-' -> don't select sequences,
177             * otherwise any alignment
178             */
179        }
180        /* arg: defines the symbol for a command line argument.
181         *      this is used for substitution into the itemmethod
182         *      definition.
183         */
184
185        else if (Find(in_line, "arg:"))
186        {
187            crop(in_line, head, temp);
188            curarg=thisitem->numargs++;
189            if (curarg == 0) resize = (char*)calloc(1, sizeof(GmenuItemArg));
190            else resize = (char *)realloc((char *)thisitem->arg, thisitem->numargs*sizeof(GmenuItemArg));
191
192            if (resize == NULL) Error("arg: Realloc");
193            memset((char *)resize + (thisitem->numargs-1)*sizeof(GmenuItemArg), 0, sizeof(GmenuItemArg));
194
195            (thisitem->arg) = (GmenuItemArg*)resize;
196            thisarg         = &(thisitem->arg[curarg]);
197            thisarg->symbol = (char*)calloc(strlen(temp)+1, sizeof(char));
198            if (thisarg->symbol == NULL) Error("Calloc");
199            (void)strcpy(thisarg->symbol, temp);
200
201            thisarg->optional   = FALSE;
202            thisarg->type       = 0;
203            thisarg->min        = 0.0;
204            thisarg->max        = 0.0;
205            thisarg->numchoices = 0;
206            thisarg->choice     = NULL;
207            thisarg->textvalue  = NULL;
208            thisarg->ivalue     = 0;
209            thisarg->fvalue     = 0.0;
210            thisarg->label      = 0;
211        }
212        // argtype: Defines the type of argument (menu,chooser, text, slider)
213        else if (Find(in_line, "argtype:"))
214        {
215            crop(in_line, head, temp);
216
217            int arglen = -1;
218            if (strncmp(temp, "text", (arglen = 4)) == 0) {
219                thisarg->type         = TEXTFIELD;
220                freedup(thisarg->textvalue, "");
221
222                if (temp[arglen] == 0) thisarg->textwidth = TEXTFIELDWIDTH; // only 'text'
223                else {
224                    if (temp[arglen] != '(' || temp[strlen(temp)-1] != ')') {
225                        sprintf(head, "Unknown argtype '%s' -- syntax: text(width) e.g. text(20)", temp);
226                        Error(head);
227                    }
228                    thisarg->textwidth = atoi(temp+arglen+1);
229                    if (thisarg->textwidth<1) {
230                        sprintf(head, "Illegal textwidth specified in '%s'", temp);
231                        Error(head);
232                    }
233                }
234            }
235            else if (strcmp(temp, "choice_list") == 0) thisarg->type = CHOICE_LIST;
236            else if (strcmp(temp, "choice_menu") == 0) thisarg->type = CHOICE_MENU;
237            else if (strcmp(temp, "chooser")     == 0) thisarg->type = CHOOSER;
238            else if (strcmp(temp, "filename")    == 0) {
239                thisarg->type = FILE_SELECTOR;
240                freedup(thisarg->textvalue, "");
241            }
242            else if (strcmp(temp, "sai")         == 0) thisarg->type = CHOICE_SAI;
243            else if (strcmp(temp, "slider")      == 0) thisarg->type = SLIDER;
244            else if (strcmp(temp, "tree")        == 0) thisarg->type = CHOICE_TREE;
245            else if (strcmp(temp, "weights")     == 0) thisarg->type = CHOICE_WEIGHTS;
246            else {
247                sprintf(head, "Unknown argtype '%s'", temp);
248                Error(head);
249            }
250        }
251        /* argtext: The default text value of the symbol.
252         *          $argument is replaced by this value if it is not
253         *           changed in the dialog box by the user.
254         */
255        else if (Find(in_line, "argtext:"))
256        {
257            crop(in_line, head, temp);
258            freedup(thisarg->textvalue, temp);
259        }
260        /* arglabel: Text label displayed in the dialog box for
261         *           this argument. It should be a descriptive label.
262         */
263        else if (Find(in_line, "arglabel:"))
264        {
265            crop(in_line, head, temp);
266            thisarg->label = GBS_string_eval(temp, "\\\\n=\\n", 0);
267        }
268        /* Argument choice values use the following notation:
269         *
270         * argchoice:Displayed value:Method
271         *
272         * Where "Displayed value" is the label displayed in the dialog box
273         * and "Method" is the value passed back on the command line.
274         */
275        else if (Find(in_line, "argchoice:"))
276        {
277            crop(in_line, head, temp);
278            crop(temp, head, tail);
279            curchoice = thisarg->numchoices++;
280
281            if (curchoice == 0) resize = (char*)calloc(1, sizeof(GargChoice));
282            else resize               = (char *)realloc((char *)thisarg->choice, thisarg->numchoices*sizeof(GargChoice));
283            if (resize == NULL) Error("argchoice: Realloc");
284            thisarg->choice           = (GargChoice*)resize;
285
286            (thisarg->choice[curchoice].label)  = NULL;
287            (thisarg->choice[curchoice].method) = NULL;
288            (thisarg->choice[curchoice].label)  = (char*)calloc(strlen(head)+1, sizeof(char));
289            (thisarg->choice[curchoice].method) = (char*)calloc(strlen(tail)+1, sizeof(char));
290
291            if (thisarg->choice[curchoice].method == NULL || thisarg->choice[curchoice].label == NULL) Error("Calloc");
292
293            (void)strcpy(thisarg->choice[curchoice].label, head);
294            (void)strcpy(thisarg->choice[curchoice].method, tail);
295        }
296        // argmin: Minimum value for a slider
297        else if (Find(in_line, "argmin:"))
298        {
299            crop(in_line, head, temp);
300            (void)sscanf(temp, "%lf", &(thisarg->min));
301        }
302        // argmax: Maximum value for a slider
303        else if (Find(in_line, "argmax:"))
304        {
305            crop(in_line, head, temp);
306            (void)sscanf(temp, "%lf", &(thisarg->max));
307        }
308        /* argmethod: Command line flag associated with this argument.
309         *            Replaces argument in itemmethod description.
310         */
311        else if (Find(in_line, "argmethod:"))
312        {
313            crop(in_line, head, temp);
314            thisarg->method = (char*)calloc(GBUFSIZ, strlen(temp));
315            if (thisarg->method == NULL) Error("Calloc");
316            (void)strcpy(thisarg->method, tail);
317        }
318        // argvalue: default value for a slider
319        else if (Find(in_line, "argvalue:"))
320        {
321            crop(in_line, head, temp);
322            if (thisarg->type == TEXT) {
323                freedup(thisarg->textvalue, temp);
324            }
325            else {
326                (void)sscanf(temp, "%lf", &(thisarg->fvalue));
327                thisarg->ivalue = (int) thisarg->fvalue;
328            }
329        }
330        // argoptional: Flag specifying that an argument is optional
331        else if (Find(in_line, "argoptional:")) {
332            gde_assert(thisarg);
333            thisarg->optional = TRUE;
334        }
335        // in: Input file description
336        else if (Find(in_line, "in:"))
337        {
338            crop(in_line, head, temp);
339            curinput                 = (thisitem->numinputs)++;
340            if (curinput == 0) resize = (char*)calloc(1, sizeof(GfileFormat));
341            else resize              = (char *)realloc((char *)thisitem->input, (thisitem->numinputs)*sizeof(GfileFormat));
342            if (resize == NULL) Error("in: Realloc");
343
344            thisitem->input      = (GfileFormat*)resize;
345            thisinput            = &(thisitem->input)[curinput];
346            thisinput->save      = FALSE;
347            thisinput->overwrite = FALSE;
348            thisinput->maskable  = FALSE;
349            thisinput->format    = 0;
350            thisinput->symbol    = strdup(temp);
351            thisinput->name      = NULL;
352            thisinput->select    = SELECTED;
353        }
354        // out: Output file description
355        else if (Find(in_line, "out:"))
356        {
357            crop(in_line, head, temp);
358            gde_assert(thisitem);
359            curoutput = (thisitem->numoutputs)++;
360
361            if (curoutput == 0) resize = (char*)calloc(1, sizeof(GfileFormat));
362            else resize               = (char *)realloc((char *)thisitem->output, (thisitem->numoutputs)*sizeof(GfileFormat));
363            if (resize == NULL) Error("out: Realloc");
364
365            thisitem->output      = (GfileFormat*)resize;
366            thisoutput            = &(thisitem->output)[curoutput];
367            thisitem->output      = (GfileFormat*)resize;
368            thisoutput            = &(thisitem->output)[curoutput];
369            thisoutput->save      = FALSE;
370            thisoutput->overwrite = FALSE;
371            thisoutput->format    = 0;
372            thisoutput->symbol    = strdup(temp);
373            thisoutput->name      = NULL;
374        }
375        else if (Find(in_line, "informat:")) {
376            if (thisinput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
377            crop(in_line, head, tail);
378
379            if (Find(tail, "genbank")) thisinput->format        = GENBANK;
380            else if (Find(tail, "gde")) thisinput->format       = GDE;
381            else if (Find(tail, "na_flat")) thisinput->format   = NA_FLAT;
382            else if (Find(tail, "colormask")) thisinput->format = COLORMASK;
383            else if (Find(tail, "flat")) thisinput->format      = NA_FLAT;
384            else if (Find(tail, "status")) thisinput->format    = STATUS_FILE;
385            else fprintf(stderr, "Warning, unknown file format %s\n", tail);
386        }
387        else if (Find(in_line, "insave:")) {
388            if (thisinput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
389            thisinput->save = TRUE;
390        }
391        else if (Find(in_line, "inselect:")) {
392            if (thisinput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
393            crop(in_line, head, tail);
394
395            if (Find(tail, "one")) thisinput->select         = SELECT_ONE;
396            else if (Find(tail, "region")) thisinput->select = SELECT_REGION;
397            else if (Find(tail, "all")) thisinput->select    = ALL;
398        }
399        else if (Find(in_line, "inmask:")) {
400            if (thisinput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
401            thisinput->maskable = TRUE;
402        }
403        else if (Find(in_line, "outformat:")) {
404            if (thisoutput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
405            crop(in_line, head, tail);
406
407            if (Find(tail, "genbank")) thisoutput->format        = GENBANK;
408            else if (Find(tail, "gde")) thisoutput->format       = GDE;
409            else if (Find(tail, "na_flat")) thisoutput->format   = NA_FLAT;
410            else if (Find(tail, "flat")) thisoutput->format      = NA_FLAT;
411            else if (Find(tail, "status")) thisoutput->format    = STATUS_FILE;
412            else if (Find(tail, "colormask")) thisoutput->format = COLORMASK;
413            else fprintf(stderr, "Warning, unknown file format %s\n", tail);
414        }
415        else if (Find(in_line, "outsave:")) {
416            if (thisoutput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
417            thisoutput->save = TRUE;
418        }
419        else if (Find(in_line, "outoverwrite:")) {
420            if (thisoutput == NULL) Error("Problem with $ARBHOME/GDEHELP/ARB_GDEmenus");
421            thisoutput->overwrite = TRUE;
422        }
423    }
424
425    fclose(file);
426    gde_assert(num_menus>0); // if this fails, the file ARB_GDEmenus contained no menus (maybe file has zero size)
427    return;
428}
429
430
431
432/*
433  Find(): Search the target string for the given key
434*/
435int Find(const char *target, const char *key)
436{
437    int i, j, len1, dif, flag = FALSE;
438    dif = (strlen(target)) - (len1 = strlen(key)) + 1;
439
440    if (len1>0)
441        for (j=0; j<dif && flag == FALSE; j++)
442        {
443            flag = TRUE;
444            for (i=0; i<len1 && flag; i++)
445                flag = (key[i] == target[i+j]) ? TRUE : FALSE;
446
447        }
448    return (flag);
449}
450
451
452int Find2(const char *target, const char *key) {
453    /* Like find, but returns the index of the leftmost
454     * occurrence, and -1 if not found.
455     */
456    int i, j, len1, dif, flag = FALSE;
457    dif = (strlen(target)) - (len1 = strlen(key)) + 1;
458
459    if (len1>0) {
460        for (j=0; j<dif && flag == FALSE; j++) {
461            flag = TRUE;
462            for (i=0; i<len1 && flag; i++)
463                flag = (key[i] == target[i+j]) ? TRUE : FALSE;
464        }
465
466        return (flag ? j-1 : -1);
467    }
468
469    return -1;
470}
471
472
473void Error(const char *msg) {
474    // goes to header: __ATTR__NORETURN
475    (void)fprintf(stderr, "Error in ARB_GDE: %s\n", msg);
476    fflush(stderr);
477    gde_assert(0);
478    exit(1);
479}
480
481
482/*
483  Crop():
484  Split "this:that[:the_other]"
485  into: "this" and "that[:the_other]"
486*/
487
488void crop(char *input, char *head, char *tail)
489{
490    // @@@ Crop needs to be fixed so that whitespace is compressed off the end of tail
491
492    int offset, end, i, j, length;
493
494    length=strlen(input);
495    for (offset=0; offset<length && input[offset] != ':'; offset++) {
496        head[offset]=input[offset];
497    }
498    head[offset++] = '\0';
499    for (; offset<length && isspace(input[offset]); offset++) ;
500    for (end=length-1; end>offset && isspace(input[end]); end--) ;
501
502    for (j=0, i=offset; i<=end; i++, j++) {
503        tail[j]=input[i];
504    }
505    tail[j] = '\0';
506    return;
507}
Note: See TracBrowser for help on using the browser.