1 /* -*-c-*- */
2 /*
3  * ParseComand.c was originally part of FvwmForm.c.
4  *
5  * Turned into separate file 02/27/99, Dan Espen.
6  *
7  * FvwmForm is original work of Thomas Zuwei Feng.
8  *
9  * Copyright Feb 1995, Thomas Zuwei Feng.  No guarantees or warantees are
10  * provided or implied in any way whatsoever.  Use this program at your own
11  * risk.  Permission to use, modify, and redistribute this program is hereby
12  * given, provided that this copyright is kept intact.
13  */
14 
15 /* This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, see: <http://www.gnu.org/licenses/>
27  */
28 
29 #include "config.h"
30 #include "libs/fvwmlib.h"
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <FvwmForm.h>                   /* common FvwmForm stuff */
35 
36 static char *buf;
37 static int N = 8;
38 
39 /* Macro used in following functions */
40 #define AddChar(chr) \
41  { if (dn >= N) {\
42      N *= 2;\
43      buf = fxrealloc(buf, N, sizeof(buf));\
44    }\
45    buf[dn++] = (chr);\
46  }
47 
48 /* do var substitution for command string */
ParseCommand(int dn,char * sp,char end,int * dn1,char ** sp1)49 char * ParseCommand (int dn, char *sp, char end, int *dn1, char **sp1)
50 {
51   static char var[256];
52   char c, x, *cp, *vp;
53   int j, dn2;
54   int added_sel;
55   Item *item;
56 
57   if (buf == 0) {                       /* if no buffer yet */
58     buf = (char *)malloc(N);
59   }
60   while (1) {
61     c = *(sp++);
62     if (c == '\0' || c == end) {  /* end of substitution */
63       *dn1 = dn;
64       *sp1 = sp;
65       if (end == 0) {                   /* if end of command reached */
66 	AddChar('\0');                  /* make sure theres a null */
67       }
68       return(buf);
69     }
70     if (c == '$') {  /* variable */
71       if (*sp != '(')
72 	goto normal_char;
73       ++sp;
74       vp = var;
75       while (1) {
76 	x = *(sp++);
77 	if (x == '\\') {
78 	  *(vp++) = '\\';
79 	  *(vp++) = *(sp++);
80 	}
81 	else if (x == ')' || x == '?' || x == '!') {
82 	  *(vp++) = '\0';
83 	  break;
84 	}
85 	else if (!isspace(x))
86 	  *(vp++) = x;
87       }
88       for (item = root_item_ptr; item != 0;
89 	   item = item->header.next) {/* all items */
90 	if (strcmp(var, item->header.name) == 0) {
91 	  switch (item->type) {
92 	  case I_INPUT:
93 	    if (x == ')') {
94 	      for (cp = item->input.value; *cp != '\0'; cp++) {
95 		AddChar(*cp);
96 	      }
97 	    } else {
98 	      ParseCommand(dn, sp, ')', &dn2, &sp);
99 	      if ((x == '?' && strlen(item->input.value) > 0) ||
100 		  (x == '!' && strlen(item->input.value) == 0))
101 		dn = dn2;
102 	    }
103 	    break;
104 	  case I_CHOICE:
105 	    if (x == ')') {
106 	      for (cp = item->choice.value; *cp != '\0'; cp++)
107 		AddChar(*cp);
108 	    } else {
109 	      ParseCommand(dn, sp, ')', &dn2, &sp);
110 	      if ((x == '?' && item->choice.on) ||
111 		  (x == '!' && !item->choice.on))
112 		dn = dn2;
113 	    }
114 	    break;
115 	  case I_SELECT:
116 	    if (x != ')')
117 	      ParseCommand(dn, sp, ')', &dn2, &sp);
118 	    added_sel=0;
119 	    for (j = 0; j < item->selection.n; j++) {
120 	      if (item->selection.choices[j]->choice.on) {
121 		if (added_sel) {        /* if not first sel added */
122 		  AddChar(' ');         /* insert space before next value */
123 		}
124 		added_sel=1;
125 		for (cp = item->selection.choices[j]->choice.value;
126 		     *cp != '\0'; cp++) {
127 		  AddChar(*cp);
128 		}
129 	      }
130 	    }
131 	    break;
132 	  }
133 	  goto next_loop;
134 	}
135       }
136       goto next_loop;
137     } /* end char is $, not followed by ( */
138     /* if char is \, followed by ), want to pass thru the paren literally */
139     if (c == '\\' && *sp == ')') {
140       c = *(sp++);                      /* skip to the paren */
141     }
142   normal_char:
143     AddChar(c);
144   next_loop:
145       ;
146   }
147 }
148