earlybrowserreborn - Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 roytam 1 #include <Mrm/MrmAppl.h>                        /* Motif Toolkit and MRM */
2 #include "midaslist.h"
3 #include "midaserrors.h"
4 #include "midasoperand.h"
5 #include "midasconvert.h"
6 #include <ctype.h>
7  
8 MidasOperand MidasEvaluateExpression();
9 ConvertBlock *MidasFindStringConverter();
10  
11 struct ActionBlock {
12     void (*ActionRtn)();
13 };
14  
15 typedef struct ActionBlock ActionBlock;
16  
17  
18 struct ConvertLink {
19    List         *CList;
20    ConvertBlock *CLink;
21 };
22  
23 typedef struct ConvertLink ConvertLink;
24  
25 static List TopLevelCommandList;
26 static List FunctionList;
27 static List QualifierList;
28  
29 static List *QualifierLists[20];
30 static List **CurrentQualifierList = QualifierLists;
31  
32 static char *MidasRemoveSpuriousJunk(in)
33     char *in;
34 {
35 /*
36  *   BUG: This should also support {&*aaa}
37  */
38     int l = strlen(in);
39     if (*in == '&') { in++; l--; }
40     if (*in == '*') { in++; l--; }
41  
42     if (*in == '{')
43       {
44         char *p = strncpy(XtMalloc(l-1),++in,l-2);
45         *(p+l-2) = '\0';
46         return p;
47       }
48     else if (l > 3 && strcmp("...",in+l-3) == 0)
49       {
50         char *p = strncpy(XtMalloc(l-2),in,l-3);
51         *(p+l-3) = '\0';
52         return p;
53       }
54     else return XtNewString(in);
55 }
56 static char *MidasRestOfLine(i,VerbVector,VerbCount)
57 int i;
58 char *VerbVector[];
59 int VerbCount;
60 {
61     char *p;
62     for (p = VerbVector[i]; p < VerbVector[VerbCount-1]; p++) if (*p == '\0') *p = ' ';
63     return VerbVector[i];
64 }
65 void MidasTokenizeCommand(command,verbVector,verbCount,maxVerbs,delimiters)
66     char  *command;
67     char  *verbVector[];
68     int   *verbCount;
69     int   maxVerbs;
70     char  *delimiters;
71 {
72     char *p;
73     *verbCount = 0;
74  
75     for (p=command;;)
76       {
77         int quotes = 0, paren = 0;
78         for (; *p == ' '; p++);
79         if (*p == '\0') break;
80         if (*verbCount == maxVerbs) MidasError("Too many tokens found in line");
81         verbVector[(*verbCount)++] = p;
82         for (; (paren > 0 || quotes || strchr(delimiters,*p) == 0) && *p != '\0'; p++)
83           if      (*p == '"') quotes = !quotes;
84           else if (*p == '(') paren++;
85           else if (*p == ')') paren--;
86         if (*p == '\0') break;
87         *p++ = '\0';
88       }
89 }
90 void MidasDeclareInit()
91 {
92     TopLevelCommandList = NullList;
93     FunctionList = NullList;
94     QualifierList = NullList;
95 }
96 void MidasDeclare(CList,command,ActionRtn,delimiters)
97     List *CList;
98     char *command;
99     void (*ActionRtn)();
100     char *delimiters;
101 {
102     ActionBlock *ab;
103     ConvertLink *cl;
104     ListItem *item;
105     int verbCount , i;
106     char *verbVector[20];
107  
108     MidasTokenizeCommand(command,verbVector,&verbCount,
109                          XtNumber(verbVector),delimiters);
110  
111     for (i=0; i < verbCount; i++)
112       {
113         char *token = verbVector[i];
114         Boolean allupper = TRUE;
115         char *p = token;
116  
117         if (*token == '\0') continue;
118  
119         for (; *p != '\0'; p++) if (islower(*p)) { allupper = FALSE; break; }
120  
121         item = MidasFindItemInList(CList,token);
122         if (item == 0)
123           {
124             item = MidasAddItemToList(CList,token);
125             cl = XtNew(ConvertLink);
126             item->Pointer = cl;
127             cl->CList = MidasCreateEmptyList("");
128  
129             if (allupper) cl->CLink = 0;
130             else
131               {
132                 MidasType type = MidasRemoveSpuriousJunk(token);
133                 cl->CLink = MidasFindStringConverter(type);
134                 XtFree(type);
135               }
136           }
137         cl = item->Pointer;
138         CList = cl->CList;
139       }
140  
141      item = MidasFindItemInList(CList,"endofcommand");
142      if (item == 0)
143        {
144          item = MidasAddItemToList(CList,"endofcommand");
145          item->Pointer = XtNew(ActionBlock);
146        }
147      ab = item->Pointer;
148      ab->ActionRtn = ActionRtn;
149 }
150 void MidasDeclareVerb(command,ActionRtn)
151     char *command;
152     void (*ActionRtn)();
153 {
154     char *buffer = XtNewString(command);
155     MidasDeclare(&TopLevelCommandList,buffer,ActionRtn," ");
156     XtFree(buffer);
157 }
158 void MidasDeclareFunction(command,ActionRtn)
159     char *command;
160     void (*ActionRtn)();
161 {
162     char *buffer = XtNewString(command);
163     MidasDeclare(&FunctionList,buffer,ActionRtn,"(,)");
164     XtFree(buffer);
165 }
166 MidasDeclareQualifier(qualifier,type)
167      char *qualifier;
168      MidasType type;
169 {
170      ListItem *item;
171      ConvertBlock *ab,*cab;
172  
173      item = MidasAddItemToList(&QualifierList,qualifier);
174  
175      if (*type == '\0') item->Pointer = 0;
176      else
177        {
178          cab = MidasFindStringConverter(type);
179          ab = XtNew(ConvertBlock);
180          *ab = *cab;
181          item->Pointer = ab;
182        }
183 }
184 ActionBlock *MidasPrepareToDispatch(CList,command,delimiters,Argv,Argi,ArgC)
185      List *CList;
186      char *command;
187      char *delimiters;
188      MidasOperand Argv[10];
189      Boolean Argi[10];
190      int  *ArgC;
191 {
192      int verbCount , i, Argc = 0;
193      char *verbVector[100];
194      ListItem *item = 0;
195      void *result = 0;
196      char *rest = 0;
197  
198      MidasTokenizeCommand(command,verbVector,&verbCount,
199                           XtNumber(verbVector),delimiters);
200  
201      for (i=0; i < verbCount; i++)
202        {
203          char *c , *token = XtNewString(verbVector[i]);
204  
205          for (c=token ; *c != '\0' ; c++ ) *c = toupper(*c);
206  
207          item = MidasFindItemInList(CList,token);
208          XtFree(token);
209  
210          if (item != 0)
211            {
212              ConvertLink *cl = item->Pointer;
213              CList = cl->CList;
214            }
215          else
216            {
217              for (item = CList->First; item != 0; item = item->Next )
218                {
219                  ConvertLink *cl = item->Pointer;
220                  ConvertBlock *ab = cl->CLink;
221                  char *entry = item->Entry;
222                  Boolean indirect = (*entry == '&');
223  
224                  if (indirect) entry++;
225  
226                  if (ab != 0)
227                    {
228                      MidasOperand Temp;
229                      if (strcmp("...",item->Entry+strlen(entry)-3))
230                        {
231                          if (*entry == '*')
232                            {
233                              char *p = verbVector[i];
234                              if (*p == '"')
235                                {
236                                  p++;
237                                  *(p + strlen(p) - 1) = '\0';
238                                }
239                              Temp.Value.P = (XtPointer) p;
240                              Temp.Dynamic = FALSE;
241                              Temp.Type = MString;
242                            }
243                          else Temp = MidasEvaluateExpression(verbVector[i]);
244                        }
245                      else
246                        {
247                          rest = MidasRestOfLine(i,verbVector,verbCount);
248                          if (*entry == '*')
249                            {
250                              char *p = rest;
251                              if (*p == '"')
252                                {
253                                  p++;
254                                  *(p + strlen(p) - 1) = '\0';
255                                }      
256                              Temp.Value.P = (XtPointer) p;
257                              Temp.Dynamic = FALSE;
258                              Temp.Type = MString;
259                            }
260                          else Temp = MidasEvaluateExpression(rest);
261                          i = verbCount;
262                        }
263 /*
264  *                   if (strcmp(ab->FromType,Temp.Type) == 0) ab->ConvertRtn(&Temp);
265  *
266  */
267                      if (strcmp(ab->ToType,Temp.Type)) MidasConvertOperand(&Temp,ab->ToType);
268                      Argv[Argc  ] = Temp;
269                      Argi[Argc++] = indirect;
270                      CList = cl->CList;
271                      break;
272                    }
273                }
274            }
275        }
276  
277      /* Skip optional arguments until end of command */
278  
279      if (item != 0)
280        {
281          for (; (item = MidasFindItemInList(CList,"endofcommand")) == 0;)
282            {
283              for (item = CList->First; item != 0; item = item->Next )
284                if (*item->Entry == '{')
285                  {
286                    ConvertLink *cl = item->Pointer;
287                    Argv[Argc].Value.P = NULL;
288                    Argv[Argc].Dynamic = FALSE;
289                    Argv[Argc].Type = MInt;
290                    Argi[Argc] = FALSE;
291                    Argc++;
292                    CList = cl->CList;
293                    break;    
294                  }
295              if (item == 0) MidasError("Premature end of command found");
296            }
297        }
298      if (item == 0)
299        {
300          for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *)Argv[i].Value.P);
301          MidasError("Syntax error in expression");
302        }
303      *ArgC = Argc;
304      return item->Pointer;
305 }
306 MidasOperand MidasCallFunction(in)
307      char **in;
308 {
309      MidasOperand result;
310      if (setjmp(JmpEnv[NumJump++]) == 0)
311        {
312          char buffer[2000];
313          char *p = *in, *q = buffer;
314          int n=0 , m=0;
315          for (; *p != '\0'; p++)
316            {
317              *q = *p;
318              if      (*p == '"') m = !m;
319              else if (!m && *p == '(') { if (++n == 1) *q = ' '; }
320              else if (!m && *p == ')') { if (--n == 0) break;    }
321              q++;
322            }
323          if (n != 0) MidasError("Parentheses error in expression: %s",*in+1);
324          if (m != 0) MidasError("Mismatched quotes in expression: %s",*in+1);
325          *q = '\0';
326          {
327            MidasOperand Argv[10];
328            Boolean Argi[10];
329            int Argc, i;
330  
331            ActionBlock *ab = MidasPrepareToDispatch(&FunctionList,buffer," ,",Argv,Argi,&Argc);
332            MidasOperand (*routine)() = (MidasOperand (*)()) ab->ActionRtn;
333            XtPointer A[10];
334            for (i=0; i<Argc; i++)
335              if (Argi[i]) A[i]=(XtPointer) &Argv[i].Value.P;
336              else         A[i]=Argv[i].Value.P;
337  
338  
339            switch (Argc)
340              {
341                case  0: result = routine();
342                         break;
343                case  1: result = routine(A[0]);
344                         break;
345                case  2: result = routine(A[0],A[1]);
346                         break;
347                case  3: result = routine(A[0],A[1],A[2]);
348                         break;
349                case  4: result = routine(A[0],A[1],A[2],A[3]);
350                         break;
351                case  5: result = routine(A[0],A[1],A[2],A[3],A[4]);
352                         break;
353                case  6: result = routine(A[0],A[1],A[2],A[3],A[4],A[5]);
354                         break;
355                case  7: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6]);
356                         break;
357                case  8: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7]);
358                         break;
359                case  9: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8]);
360                         break;
361                case 10: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8],A[9]);
362            }
363            for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *)Argv[i].Value.P);
364          }
365          *in = p;
366          NumJump--;
367        }
368      else
369        {
370          MidasError("Error invoking function: %s",*in);
371        }
372   return result;
373 }
374 static List *MidasFindCommandQualifiers(QL,command)
375 List *QL;
376 char *command;
377 {
378   char *p, *q, *r, delim;
379   int Quotes = 0, paren = 0;
380   ListItem *item;
381   ListItem *new;
382   List *CurrentQualifierList = NULL;
383  
384   for (p=command; *p != '\0'; p++)
385     if (*p == '"') Quotes = 1 - Quotes;
386     else if (!Quotes && *p == '(') paren++;
387     else if (!Quotes && *p == ')') paren--;
388     else if (!Quotes && paren == 0 && *p == ':')
389       {
390         for (q = p+1 ; *q != ' ' && *q != ':' && *q != '=' && *q != '\0'; q++)
391           *q = toupper(*q);
392  
393         delim = *q;
394         *q = '\0';
395  
396         item = MidasFindItemInList(QL,p+1);
397         if (item == 0) MidasError("Unrecognized qualifier %s",p+1);
398  
399         if (!CurrentQualifierList) CurrentQualifierList = MidasCreateEmptyList("CurrentQualifiers");
400         new = MidasAddItemToList(CurrentQualifierList,p+1);
401  
402         if (delim == '=')
403           {
404             MidasOperand *Temp = XtNew(MidasOperand);
405             for (r = q + 1; *r != ':' && *r != '\0' && *r != ' '; r++);
406             delim = *r;
407             *r = '\0';
408             new->Pointer = Temp;
409             Temp->Type = MString;
410             Temp->Dynamic = TRUE;
411             Temp->Value.P = (XtPointer) XtNewString(q+1);
412           }
413         else
414           {
415             r = q;
416             new->Pointer = 0;
417           }
418         for (; p < r ; p++) *p=' ';
419         *p = delim;
420         p--;
421       }
422   return CurrentQualifierList;
423 }
424 void MidasDispatchCommand(command)
425      char *command;
426 {
427      char *p;
428      char *buffer = XtNewString(command);
429      List *QL = 0;
430      ListItem *item;  
431  
432      if (setjmp(JmpEnv[NumJump++]) == 0)
433        {
434          QL = MidasFindCommandQualifiers(&QualifierList,buffer);
435          *++CurrentQualifierList = QL;
436          {
437            MidasOperand Argv[10];
438            Boolean Argi[10];
439            int Argc, i;
440            ActionBlock *ab = MidasPrepareToDispatch(&TopLevelCommandList,buffer," ",Argv,Argi,&Argc);
441            XtPointer A[10];
442            for (i=0; i<Argc; i++)
443              if (Argi[i]) A[i]=(XtPointer) &Argv[i].Value.P;
444              else         A[i]=Argv[i].Value.P;
445  
446            switch (Argc)
447              {
448                case  0: ab->ActionRtn();
449                         break;
450                case  1: ab->ActionRtn(A[0]);
451                         break;
452                case  2: ab->ActionRtn(A[0],A[1]);
453                         break;
454                case  3: ab->ActionRtn(A[0],A[1],A[2]);
455                         break;
456                case  4: ab->ActionRtn(A[0],A[1],A[2],A[3]);
457                         break;
458                case  5: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4]);
459                         break;
460                case  6: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5]);
461                         break;
462                case  7: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6]);
463                         break;
464                case  8: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7]);
465                         break;
466                case  9: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8]);
467                         break;
468                case 10: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8],A[9]);
469            }
470            for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *) Argv[i].Value.P);
471          }
472        if (QL)
473          {
474            for (item = QL->First; item != 0; item = item->Next)
475              {
476                MidasOperand *Temp = item->Pointer;
477                if (Temp != 0 && Temp->Dynamic) XtFree((char *) Temp->Value.P);
478              }
479            MidasDestroyList(QL);
480          }
481        CurrentQualifierList--;
482        XtFree(buffer);
483        NumJump--;
484        }
485      else
486        {
487          if (QL != 0)
488            {  
489              for (item = QL->First; item != 0; item = item->Next)
490                {
491                  MidasOperand *Temp = item->Pointer;
492                  if (Temp != 0 && Temp->Dynamic) XtFree((char *) Temp->Value.P);
493                }
494              if (*CurrentQualifierList) MidasDestroyList(*CurrentQualifierList);
495              CurrentQualifierList--;
496            }
497          XtFree(buffer);
498          MidasError("Illegal command");
499        }
500 }
501 Boolean MidasGetQualifier(Qualifier,Result)
502 char *Qualifier;
503 XtPointer *Result;
504 {
505    ConvertBlock *ab;
506    ListItem *qitem, *item;
507  
508    if (*CurrentQualifierList == 0) return FALSE;
509  
510    item = MidasFindItemInList(*CurrentQualifierList, Qualifier);
511    if (item == 0) return FALSE;
512  
513    qitem = MidasFindItemInList(&QualifierList,Qualifier);
514    ab = qitem->Pointer;
515    if (ab != 0)
516      {
517        MidasOperand *Temp = item->Pointer;
518 /*
519  * Speed up temporarily removed.  
520  *      if (strcmp(Temp->Type,ab->FromType) == 0) ab->ConvertRtn(Temp);
521  *
522  */
523        if (strcmp(Temp->Type,ab->ToType)) MidasConvertOperand(Temp,ab->ToType);
524        *Result = Temp->Value.P;
525      }
526    return TRUE;
527 }
528 void MidasSetQualifier(Qualifier,Value)
529 char *Qualifier;
530 char *Value;
531 {
532    ActionBlock *ab;
533    ListItem *qitem, *item;
534  
535    if (*CurrentQualifierList == 0)
536      *CurrentQualifierList = MidasCreateEmptyList("CurrentQualifiers");  
537  
538    item = MidasFindItemInList(*CurrentQualifierList, Qualifier);
539    if (item == 0)
540      {
541        item = MidasAddItemToList(*CurrentQualifierList, Qualifier);
542      }
543    else
544      {
545        if (item->Pointer != 0) XtFree(item->Pointer);
546      }
547  
548    if (Value == NULL) item->Pointer = NULL;
549    else
550      {
551        MidasOperand *Operand = XtNew(MidasOperand);
552        item->Pointer = Operand;
553        Operand->Type = MString;
554        Operand->Dynamic = TRUE;
555        Operand->Value.P = (XtPointer) XtNewString(Value);
556      }
557 }