Added configure script.
[tclrobot.git] / hswitch.c
1 /*
2  * $Id: hswitch.c,v 1.2 1998/10/15 12:31:01 adam Exp $
3  */
4 #include <assert.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8
9 #include "tclrobot.h"
10
11 #define TAG_MAX_LEN 32
12
13 #define SPACECHR " \t\r\n\f"
14
15 #define DEBUG(x) 
16
17 static int skipSpace (const char *cp)
18 {
19     int i = 0;
20     while (strchr (SPACECHR, cp[i]))
21         i++;
22     return i;
23 }
24
25 static int skipTag (const char *cp, char *dst)
26 {
27     int i;
28     int j = 0;
29
30     for (i=0; cp[i] && !strchr (SPACECHR "/>=", cp[i]); i++)
31         if (j < TAG_MAX_LEN-1)
32         {
33             dst[j] = tolower(cp[j]);
34             j++;
35         }
36     dst[j] = '\0';
37     return i;
38 }
39
40 static int skipParm (const char *cp, char *name, char **value)
41 {
42     int i = skipTag (cp, name);   
43     *value = NULL;
44     if (!i)
45         return skipSpace (cp);
46     i += skipSpace (cp + i);
47     if (cp[i] == '=')
48     {
49         int v0, v1;
50         i++;
51         i += skipSpace (cp + i);
52         if (cp[i] == '\"')
53         {
54             v0 = ++i;
55             while (cp[i] != '\"' && cp[i])
56                 i++; 
57             v1 = i;
58             if (cp[i])
59                 i++;
60         }
61         else
62         {
63             v0 = i;
64             while (cp[i] && !strchr (SPACECHR ">", cp[i]))
65                 i++;
66             v1 = i;
67         }
68         *value = malloc (v1 - v0 + 1);
69         memcpy (*value, cp + v0, v1-v0);
70         (*value)[v1-v0] = '\0';
71     }
72     i += skipSpace (cp + i);
73     return i;
74 }
75
76 struct tagParm {
77     char name[TAG_MAX_LEN];
78     char *value;
79     struct tagParm *next;
80 };
81
82 struct tagInfo {
83     int level;
84     char *pattern;
85     char *code;
86
87     char name[TAG_MAX_LEN];
88     const char *body_start;
89     struct tagParm *tagParms;
90 };
91
92 static int tagLookup (struct tagInfo *tags, int tagNo, const char *tagString)
93 {
94     int i;
95     for (i = 0; i<tagNo; i++)
96         if (!strcmp (tags[i].pattern, tagString))
97              return i;
98     return -1;
99 }
100
101 static int tagStart (struct tagInfo *tag, const char *tagString,
102                      const char *cp)
103 {
104     int i;
105     char parm_name[TAG_MAX_LEN];
106     char *parm_value;
107     struct tagParm **nParms;
108
109     if (tag && !tag->level)
110     {
111         strcpy (tag->name, tagString);
112         DEBUG(printf ("------ consuming this %s\n", tag->name));
113         tag->tagParms = NULL;
114         nParms = &tag->tagParms;
115     }
116
117     i = skipSpace (cp);
118     while (cp[i] && cp[i] != '>')
119     {
120         int nor = skipParm (cp+i, parm_name, &parm_value);
121         i += nor;
122         if (nor && tag)
123         {
124             DEBUG(printf ("parm_name=%s parm_value=%s\n", parm_name, parm_value));
125         }
126         if (nor && tag && !tag->level)
127         {
128             *nParms = malloc (sizeof(**nParms));
129             assert (*nParms);
130             strcpy ((*nParms)->name, parm_name);
131             (*nParms)->value = parm_value;
132             (*nParms)->next = NULL;
133             nParms = &(*nParms)->next;
134         }
135         else
136         {
137             if (!nor)
138                 i++;
139             free (parm_value);
140         }
141     }
142     if (cp[i])
143         i++;
144     if (tag)
145     {
146         if (!tag->level)
147             tag->body_start = cp+i;
148         ++(tag->level);
149     }
150     return i;
151 }
152
153 static int tagEnd (Tcl_Interp *interp, struct tagInfo *tag,
154                    const char *tagString, const char *cp, const char *body_end)
155 {
156     int i = 0;
157
158     if (cp[i] == '>')
159         i++;
160
161     if (tag && tag->level)
162     {
163         -- (tag->level);
164         if (!tag->level)
165         {
166             struct tagParm *tp = tag->tagParms;
167             char *value = malloc (body_end - tag->body_start + 1);
168
169             assert (value);
170             memcpy (value, tag->body_start, body_end - tag->body_start);
171             value[body_end - tag->body_start] = '\0';
172             Tcl_SetVar (interp, "body", value, 0);
173             free (value);
174             while (tp)
175             {
176                 char vname[TAG_MAX_LEN+30];
177                 struct tagParm *tp0 = tp;
178                 
179                 sprintf (vname, "parm(%s)", tp->name);
180                 DEBUG(printf ("vname=%s\n", vname));
181
182                 Tcl_SetVar (interp, vname, tp->value ? tp->value : "",0);
183                 tp = tp->next;
184                 free (tp0);
185             }
186             Tcl_Eval (interp, tag->code);
187         }
188     }
189     return i;
190 }
191
192 int htmlSwitch (ClientData clientData, Tcl_Interp *interp,
193                 int argc, char **argv)
194 {
195     struct tagInfo *tags;
196     int noTags;
197     const char *cp;
198     int i, argi = 1;
199
200     cp = argv[argi++];
201     noTags = (argc - argi)/2;
202     if (noTags < 1)
203     {
204         interp->result =
205             "wrong # args: should be ?switches? string pattern body ...";
206         return TCL_ERROR;
207     }
208     tags = malloc (sizeof(*tags) * noTags);
209     assert (tags);
210     for (i = 0; i<noTags; i++)
211     {
212         tags[i].level = 0;
213         tags[i].pattern = argv[argi++];
214         tags[i].code = argv[argi++];
215     }
216     while (*cp)
217     {
218         if (cp[0] == '<' && cp[1] != '/')     /* start tag */
219         {
220             char tagStr[TAG_MAX_LEN];
221             int tagI;
222
223             cp++;
224             cp += skipTag (cp, tagStr);
225             tagI = tagLookup (tags, noTags, tagStr);
226             DEBUG(printf ("tagStr = %s tagI = %d\n", tagStr, tagI));
227             cp += tagStart (tagI >= 0 ? tags+tagI : NULL, tagStr, cp);
228         }
229         else if (cp[0] == '<' && cp[1] == '/')/* end tag */
230         {
231             char tagStr[TAG_MAX_LEN];
232             const char *body_end = cp;
233             int tagI;
234
235             cp += 2;
236             cp += skipTag (cp, tagStr);
237             tagI = tagLookup (tags, noTags, tagStr);
238             cp += tagEnd (interp, tagI >= 0 ? tags+tagI : NULL,
239                           tagStr, cp, body_end);
240         }
241         else                                  /* no tag */
242             cp++;
243     }
244     free (tags);
245     return TCL_OK;
246 }
247
248