1 %{
2 /* This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, see: <http://www.gnu.org/licenses/>
14  */
15 #include "config.h"
16 #include "types.h"
17 #include "libs/FGettext.h"
18 
19 #define MAX_VARS 5120
20 extern int numligne;
21 ScriptProp *scriptprop;
22 int nbobj=-1;			/* Number of objects */
23 int HasPosition,HasType=0;
24 TabObj *tabobj;		/* Array of objects, limit=1000 */
25 int TabIdObj[1001]; 	/* Array of object IDs */
26 Bloc **TabIObj;		/* TabIObj[Obj][Case] -> block linked to case */
27 Bloc *PileBloc[10];	/* 10 imbrications max of conditional loops */
28 int TopPileB=0;		/* Top of block stack */
29 CaseObj *TabCObj;	/* Structure to store cases values and their ID */
30 int CurrCase;
31 int i;
32 char **TabNVar;		/* Array of variable names */
33 char **TabVVar;		/* Array of variable values */
34 int NbVar;
35 long BuffArg[6][20];	/* Arguments are added by layers for each function */
36 int NbArg[6];		/* Array: number of arguments for each layer */
37 int SPileArg;		/* Size of argument stack */
38 long l;
39 extern char* ScriptName;
40 
41 /* Global Initialization */
InitVarGlob(void)42 void InitVarGlob(void)
43 {
44  scriptprop=fxcalloc(1, sizeof(ScriptProp));
45  scriptprop->x=-1;
46  scriptprop->y=-1;
47  scriptprop->colorset = -1;
48  scriptprop->initbloc=NULL;
49 
50  tabobj=fxcalloc(1, sizeof(TabObj));
51  for (i=0;i<1001;i++)
52   TabIdObj[i]=-1;
53  TabNVar=NULL;
54  TabVVar=NULL;
55  NbVar=-1;
56 
57  SPileArg=-1;
58  scriptprop->usegettext = False;
59  scriptprop->periodictasks=NULL;
60  scriptprop->quitfunc=NULL;
61 }
62 
63 /* Object Initialization */
InitObjTabCase(int HasMainLoop)64 void InitObjTabCase(int HasMainLoop)
65 {
66  if (nbobj==0)
67  {
68   TabIObj=fxcalloc(1, sizeof(long));
69   TabCObj=fxcalloc(1, sizeof(CaseObj));
70  }
71  else
72  {
73   TabIObj=(Bloc**)realloc(TabIObj,sizeof(long)*(nbobj+1));
74   TabCObj=(CaseObj*)realloc(TabCObj,sizeof(CaseObj)*(nbobj+1));
75  }
76 
77  if (!HasMainLoop)
78   TabIObj[nbobj]=NULL;
79  CurrCase=-1;
80  TabCObj[nbobj].NbCase=-1;
81 }
82 
83 /* Add a case into TabCase array */
84 /* Initialization of a case: increase array size */
InitCase(int cond)85 void InitCase(int cond)
86 {
87  CurrCase++;
88 
89  /* We store the case condition */
90  TabCObj[nbobj].NbCase++;
91  if (TabCObj[nbobj].NbCase==0)
92   TabCObj[nbobj].LstCase=fxcalloc(1, sizeof(int));
93  else
94   TabCObj[nbobj].LstCase=(int*)realloc(TabCObj[nbobj].LstCase,sizeof(int)*(CurrCase+1));
95  TabCObj[nbobj].LstCase[CurrCase]=cond;
96 
97  if (CurrCase==0)
98   TabIObj[nbobj]=fxcalloc(1, sizeof(Bloc));
99  else
100   TabIObj[nbobj]=(Bloc*)realloc(TabIObj[nbobj],sizeof(Bloc)*(CurrCase+1));
101 
102  TabIObj[nbobj][CurrCase].NbInstr=-1;
103  TabIObj[nbobj][CurrCase].TabInstr=NULL;
104 
105  /* This case is for the current instruction block: we stack it */
106  PileBloc[0]=&TabIObj[nbobj][CurrCase];
107  TopPileB=0;
108 }
109 
110 /* Remove a level of args in BuffArg stack */
RmLevelBufArg(void)111 void RmLevelBufArg(void)
112 {
113   SPileArg--;
114 }
115 
116 /* Function to concatenate the n latest levels of stack */
117 /* Returns the sorted and unstacked elements and size */
Depile(int NbLevelArg,int * s)118 long *Depile(int NbLevelArg, int *s)
119 {
120  long *Temp;
121  int j;
122  int i;
123  int size;
124 
125  if (NbLevelArg>0)
126  {
127   Temp=fxcalloc(1, sizeof(long));
128   size=0;
129   for (i=SPileArg-NbLevelArg+1;i<=SPileArg;i++)
130   {
131    size=NbArg[i]+size+1;
132    Temp=(long*)realloc (Temp,sizeof(long)*size);
133    for (j=0;j<=NbArg[i];j++)
134    {
135     Temp[j+size-NbArg[i]-1]=BuffArg[i][j];
136    }
137   }
138   *s=size;
139   for (i=0;i<NbLevelArg;i++)	/* Unstack the argument layers */
140    RmLevelBufArg();
141   return Temp;
142  }
143  else
144  {
145   *s=0;
146   return NULL;
147  }
148 }
149 
150 /* Add a command */
AddCom(int Type,int NbLevelArg)151 void AddCom(int Type, int NbLevelArg)
152 {
153  int CurrInstr;
154 
155 
156  PileBloc[TopPileB]->NbInstr++;
157  CurrInstr=PileBloc[TopPileB]->NbInstr;
158 
159  if (CurrInstr==0)
160   PileBloc[TopPileB]->TabInstr=fxcalloc(1, sizeof(Instr) * (CurrInstr + 1));
161  else
162   PileBloc[TopPileB]->TabInstr=(Instr*)realloc(PileBloc[TopPileB]->TabInstr,
163 				sizeof(Instr)*(CurrInstr+1));
164  /* Put instructions into block */
165  PileBloc[TopPileB]->TabInstr[CurrInstr].Type=Type;
166  /* We remove the last arguments layer and put it in command */
167 
168  PileBloc[TopPileB]->TabInstr[CurrInstr].TabArg=Depile(NbLevelArg,
169 		&PileBloc[TopPileB]->TabInstr[CurrInstr].NbArg);
170 }
171 
172 /* Initialization of the buffer containing the current command arguments */
173 /* Add a layer of arguments into stack */
AddLevelBufArg(void)174 void AddLevelBufArg(void)
175 {
176  /* Increase stack size */
177  SPileArg++;
178  NbArg[SPileArg]=-1;
179 }
180 
181 /* Add an argument into the argument layer on top of TabArg stack */
AddBufArg(long * TabLong,int NbLong)182 void AddBufArg(long *TabLong,int NbLong)
183 {
184  int i;
185 
186  for (i=0;i<NbLong;i++)
187  {
188   BuffArg[SPileArg][i+NbArg[SPileArg]+1]=TabLong[i];
189  }
190  NbArg[SPileArg]=NbArg[SPileArg]+NbLong;
191 }
192 
193 /* Search for a variable name in TabVar, create it if nonexistant */
194 /* Returns an ID */
AddVar(char * Name)195 void AddVar(char *Name)		/* add a variable at the end of last pointed command */
196 {
197  int i;
198 
199  /* Comparison with already existing variables */
200  for (i=0;i<=NbVar;i++)
201   if (strcmp(TabNVar[i],Name)==0)
202   {
203    l=(long)i;
204    AddBufArg(&l,1);
205    return ;
206   }
207 
208  if (NbVar>MAX_VARS-2)
209  {
210   fprintf(stderr,
211     "[%s] Line %d: too many variables (>5120)\n",ScriptName,numligne);
212   exit(1);
213  }
214 
215  /* Variable not found: create it */
216  NbVar++;
217 
218  if (NbVar==0)
219  {
220   TabNVar=fxcalloc(1, sizeof(long));
221   TabVVar=fxcalloc(1, sizeof(long));
222  }
223  else
224  {
225   TabNVar=(char**)realloc(TabNVar,sizeof(long)*(NbVar+1));
226   TabVVar=(char**)realloc(TabVVar,sizeof(long)*(NbVar+1));
227  }
228 
229  TabNVar[NbVar]=fxstrdup(Name);
230  TabVVar[NbVar]=fxcalloc(1, sizeof(char));
231  TabVVar[NbVar][0]='\0';
232 
233 
234  /* Add variable into argument buffer */
235  l=(long)NbVar;
236  AddBufArg(&l,1);
237  return ;
238 }
239 
240 /* Add a string constant as argument */
AddConstStr(char * Name)241 void AddConstStr(char *Name)
242 {
243  /* We create a new variable and put constant in it */
244  NbVar++;
245  if (NbVar==0)
246  {
247   TabVVar=fxcalloc(1, sizeof(long));
248   TabNVar=fxcalloc(1, sizeof(long));
249  }
250  else
251  {
252   TabVVar=(char**)realloc(TabVVar,sizeof(long)*(NbVar+1));
253   TabNVar=(char**)realloc(TabNVar,sizeof(long)*(NbVar+1));
254  }
255 
256  TabNVar[NbVar]=fxcalloc(1, sizeof(char));
257  TabNVar[NbVar][0]='\0';
258  TabVVar[NbVar]=fxstrdup(Name);
259 
260  /* Add the constant ID into the current arguments list */
261  l=(long)NbVar;
262  AddBufArg(&l,1);
263 }
264 
265 /* Add a number constant as argument */
AddConstNum(long num)266 void AddConstNum(long num)
267 {
268 
269  /* We don't create a new variable */
270  /* We code the number value to form an ID */
271  l=num+200000;
272  /* Add the constant into the current arguments list */
273  AddBufArg(&l,1);
274 }
275 
276 /* Add a functon as argument */
277 /* Remove function arguments from stack, */
278 /* concatene them, and put them into stack */
AddFunct(int code,int NbLevelArg)279 void AddFunct(int code,int NbLevelArg)
280 {
281  int size;
282  long *l;
283  int i;
284 
285  /* Method: unstack BuffArg and complete the bottom level of BuffArg */
286  l=Depile(NbLevelArg, &size);
287 
288  size++;
289  if (size==1)
290   l=fxcalloc(1, sizeof(long));
291  else
292  {
293   l=(long*)realloc(l,sizeof(long)*(size));
294   for (i=size-2;i>-1;i--)	/* Move arguments */
295   {
296    l[i+1]=l[i];
297   }
298  }
299  l[0]=(long)code-150000;
300 
301  AddBufArg(l,size);
302 }
303 
304 /* Add a test instruction to execute one block or more */
305 /* store the instruction, and these blocks field becomes NULL */
AddComBloc(int TypeCond,int NbLevelArg,int NbBloc)306 void AddComBloc(int TypeCond, int NbLevelArg, int NbBloc)
307 {
308  int i;
309  int OldNA;
310  int CurrInstr;
311 
312  /* Add the test instruction as a command */
313  AddCom(TypeCond, NbLevelArg);
314 
315  /* We then initialize both reserved fields bloc1 and bloc2 */
316  CurrInstr=PileBloc[TopPileB]->NbInstr;
317  /* Caution: NbArg can change if we use a function as argument */
318  OldNA=PileBloc[TopPileB]->TabInstr[CurrInstr].NbArg;
319 
320  PileBloc[TopPileB]->TabInstr[CurrInstr].TabArg=(long*)realloc(
321 		PileBloc[TopPileB]->TabInstr[CurrInstr].TabArg,sizeof(long)*(OldNA+NbBloc));
322  for (i=0;i<NbBloc;i++)
323  {
324   PileBloc[TopPileB]->TabInstr[CurrInstr].TabArg[OldNA+i]=0;
325  }
326  PileBloc[TopPileB]->TabInstr[CurrInstr].NbArg=OldNA+NbBloc;
327 }
328 
329 /* Create a new block, and stack it: it's becoming the current block */
EmpilerBloc(void)330 void EmpilerBloc(void)
331 {
332  Bloc *TmpBloc;
333 
334  TmpBloc=fxcalloc(1, sizeof(Bloc));
335  TmpBloc->NbInstr=-1;
336  TmpBloc->TabInstr=NULL;
337  TopPileB++;
338  PileBloc[TopPileB]=TmpBloc;
339 
340 }
341 
342 /* Unstack the script initialization block and put it into its special location */
DepilerBloc(int IdBloc)343 void DepilerBloc(int IdBloc)
344 {
345  Bloc *Bloc1;
346  Instr *IfInstr;
347 
348  Bloc1=PileBloc[TopPileB];
349  TopPileB--;
350  IfInstr=&PileBloc[TopPileB]->TabInstr[PileBloc[TopPileB]->NbInstr];
351  IfInstr->TabArg[IfInstr->NbArg-IdBloc]=(long)Bloc1;
352 }
353 
354 /* Syntax error management */
yyerror(char * errmsg)355 int yyerror(char *errmsg)
356 {
357  fprintf(stderr,"[%s] Line %d: %s\n",ScriptName,numligne,errmsg);
358  return 0;
359 }
360 
361 
362 %}
363 
364 /* Declaration of token types, all types are in union */
365 /* Type is the one of yyval, yyval being used in lex */
366 /* In bison, it's implicitly used with $1, $2... */
367 %union {  char *str;
368           int number;
369        }
370 
371 /* Declaration of terminal symbols */
372 %token <str> STR GSTR VAR FONT
373 %token <number> NUMBER	/* Number to give dimensions */
374 
375 %token WINDOWTITLE WINDOWLOCALETITLE WINDOWSIZE WINDOWPOSITION USEGETTEXT
376 %token FORECOLOR BACKCOLOR SHADCOLOR LICOLOR COLORSET
377 %token OBJECT INIT PERIODICTASK QUITFUNC MAIN END PROP
378 %token TYPE SIZE POSITION VALUE VALUEMIN VALUEMAX TITLE SWALLOWEXEC ICON FLAGS WARP WRITETOFILE LOCALETITLE
379 %token HIDDEN NOFOCUS NORELIEFSTRING CENTER LEFT RIGHT
380 %token CASE SINGLECLIC DOUBLECLIC BEG POINT
381 %token EXEC HIDE SHOW CHFONT CHFORECOLOR CHBACKCOLOR CHCOLORSET CHWINDOWTITLE CHWINDOWTITLEFARG KEY
382 %token GETVALUE GETMINVALUE GETMAXVALUE GETFORE GETBACK GETHILIGHT GETSHADOW CHVALUE CHVALUEMAX CHVALUEMIN
383 %token ADD DIV MULT GETTITLE GETOUTPUT STRCOPY NUMTOHEX HEXTONUM QUIT
384 %token LAUNCHSCRIPT GETSCRIPTFATHER SENDTOSCRIPT RECEIVFROMSCRIPT
385 %token GET SET SENDSIGN REMAINDEROFDIV GETTIME GETSCRIPTARG
386 %token GETPID SENDMSGANDGET PARSE LASTSTRING GETTEXT
387 %token IF THEN ELSE FOR TO DO WHILE
388 %token BEGF ENDF
389 %token EQUAL INFEQ SUPEQ INF SUP DIFF
390 
391 %%
392 script: initvar head initbloc periodictask quitfunc object ;
393 
394 /* Variables Initialization */
395 initvar: 			{ InitVarGlob(); }
396        ;
397 
398 /* Script header for default options */
399 head:
400 | head USEGETTEXT GSTR
401 {
402 	FGettextInit("FvwmScript", LOCALEDIR, "FvwmScript");
403 	FGettextSetLocalePath($3);
404 }
405 | head USEGETTEXT
406 {
407 	fprintf(stderr,"UseGettext!\n");
408 	FGettextInit("FvwmScript", LOCALEDIR, "FvwmScript");
409 }
410 /* empty: we use default values */
411 | head WINDOWTITLE GSTR
412 {
413 	/* Window Title */
414 	scriptprop->titlewin=$3;
415 }
416 | head WINDOWLOCALETITLE GSTR
417 {
418 	/* Window Title */
419 	scriptprop->titlewin=(char *)FGettext($3);
420 }
421 | head ICON STR
422 {
423 	scriptprop->icon=$3;
424 }
425 | head WINDOWPOSITION NUMBER NUMBER
426 {
427 	/* Window Position and Size */
428 	scriptprop->x=$3;
429 	scriptprop->y=$4;
430 }
431 | head WINDOWSIZE NUMBER NUMBER
432 {
433 	/* Window Width and Height */
434 	scriptprop->width=$3;
435 	scriptprop->height=$4;
436 }
437 | head BACKCOLOR GSTR
438 {
439 	/* Background Color */
440 	scriptprop->backcolor=$3;
441 	scriptprop->colorset = -1;
442 }
443 | head FORECOLOR GSTR
444 {
445 	/* Foreground Color */
446 	scriptprop->forecolor=$3;
447 	scriptprop->colorset = -1;
448 }
449 | head SHADCOLOR GSTR
450 {
451 	/* Shaded Color */
452 	scriptprop->shadcolor=$3;
453 	scriptprop->colorset = -1;
454 }
455 | head LICOLOR GSTR
456 {
457 	/* Highlighted Color */
458 	scriptprop->hilicolor=$3;
459 	scriptprop->colorset = -1;
460 }
461 | head COLORSET NUMBER
462 {
463 	scriptprop->colorset = $3;
464 	AllocColorset($3);
465 }
466 | head FONT
467 {
468 	scriptprop->font=$2;
469 }
470 
471 /* Script initialization block */
472 initbloc:		/* case where there's no script initialization block */
473 	| INIT creerbloc BEG instr END {
474 				 scriptprop->initbloc=PileBloc[TopPileB];
475 				 TopPileB--;
476 				}
477 
478 periodictask:		/* case where there's no periodic task */
479 	    | PERIODICTASK creerbloc BEG instr END {
480 				 scriptprop->periodictasks=PileBloc[TopPileB];
481 				 TopPileB--;
482 				}
483 
484 quitfunc:		/* case where there are no QuitFunc */
485 	    | QUITFUNC creerbloc BEG instr END {
486 				 scriptprop->quitfunc=PileBloc[TopPileB];
487 				 TopPileB--;
488 				}
489 
490 	    ;
491 
492 
493 /* Object Desciption */
494 object :			/* Empty */
495     | object OBJECT id PROP init verify mainloop
496     ;
497 
498 id: NUMBER			{ nbobj++;
499 				  if (nbobj>1000)
500 				  { yyerror("Too many items\n");
501 				    exit(1);}
502 				  if (($1<1)||($1>1000))
503 				  { yyerror("Choose item id between 1 and 1000\n");
504 				    exit(1);}
505 				  if (TabIdObj[$1]!=-1)
506 				  { i=$1; fprintf(stderr,"Line %d: item id %d already used:\n",numligne,$1);
507 				    exit(1);}
508 			          TabIdObj[$1]=nbobj;
509 				  (*tabobj)[nbobj].id=$1;
510 				  (*tabobj)[nbobj].colorset = -1;
511 				}
512   ;
513 
514 init:				/* vide */
515     | init TYPE STR		{
516 				 (*tabobj)[nbobj].type=$3;
517 				 HasType=1;
518 				}
519     | init SIZE NUMBER NUMBER	{
520 				 (*tabobj)[nbobj].width=$3;
521 				 (*tabobj)[nbobj].height=$4;
522 				}
523     | init POSITION NUMBER NUMBER {
524 				 (*tabobj)[nbobj].x=$3;
525 				 (*tabobj)[nbobj].y=$4;
526 				 HasPosition=1;
527 				}
528     | init VALUE NUMBER		{
529 				 (*tabobj)[nbobj].value=$3;
530 				}
531     | init VALUEMIN NUMBER		{
532 				 (*tabobj)[nbobj].value2=$3;
533 				}
534     | init VALUEMAX NUMBER		{
535 				 (*tabobj)[nbobj].value3=$3;
536 				}
537     | init TITLE GSTR		{
538 				 (*tabobj)[nbobj].title= $3;
539 				}
540     | init LOCALETITLE GSTR     {
541 				 (*tabobj)[nbobj].title= FGettextCopy($3);
542 				}
543     | init SWALLOWEXEC GSTR	{
544 				 (*tabobj)[nbobj].swallow=$3;
545 				}
546     | init ICON STR		{
547 				 (*tabobj)[nbobj].icon=$3;
548 				}
549     | init BACKCOLOR GSTR	{
550 				 (*tabobj)[nbobj].backcolor=$3;
551 				 (*tabobj)[nbobj].colorset = -1;
552 				}
553     | init FORECOLOR GSTR	{
554 				 (*tabobj)[nbobj].forecolor=$3;
555 				 (*tabobj)[nbobj].colorset = -1;
556 				}
557     | init SHADCOLOR GSTR	{
558 				 (*tabobj)[nbobj].shadcolor=$3;
559 				 (*tabobj)[nbobj].colorset = -1;
560 				}
561     | init LICOLOR GSTR		{
562 				 (*tabobj)[nbobj].hilicolor=$3;
563 				 (*tabobj)[nbobj].colorset = -1;
564 				}
565     | init COLORSET NUMBER	{
566 				 (*tabobj)[nbobj].colorset = $3;
567 				 AllocColorset($3);
568 				}
569     | init FONT			{
570 				 (*tabobj)[nbobj].font=$2;
571 				}
572     | init FLAGS flags
573     ;
574 flags:
575      | flags HIDDEN		{
576 				 (*tabobj)[nbobj].flags[0]=True;
577 				}
578      | flags NORELIEFSTRING	{
579 				 (*tabobj)[nbobj].flags[1]=True;
580 				}
581      | flags NOFOCUS		{
582 				 (*tabobj)[nbobj].flags[2]=True;
583 				}
584      | flags CENTER		{
585 				 (*tabobj)[nbobj].flags[3]=TEXT_POS_CENTER;
586 				}
587      | flags LEFT		{
588 				 (*tabobj)[nbobj].flags[3]=TEXT_POS_LEFT;
589 				}
590      | flags RIGHT		{
591 				 (*tabobj)[nbobj].flags[3]=TEXT_POS_RIGHT;
592 				}
593     ;
594 
595 
596 verify:				 {
597 				  if (!HasPosition)
598 				   { yyerror("No position for object");
599 				     exit(1);}
600 				  if (!HasType)
601 				   { yyerror("No type for object");
602 				     exit(1);}
603 				  HasPosition=0;
604 				  HasType=0;
605 				 }
606 
607 mainloop: END			{ InitObjTabCase(0); }
608 	| MAIN addtabcase CASE case END
609 	;
610 
611 addtabcase:			{ InitObjTabCase(1); }
612 
613 case:
614     | case clic POINT bloc
615     | case number POINT bloc
616     ;
617 
618 clic :  SINGLECLIC	{ InitCase(-1); }
619      |  DOUBLECLIC	{ InitCase(-2); }
620      ;
621 
622 number :  NUMBER		{ InitCase($1); }
623        ;
624 
625 bloc: BEG instr END
626     ;
627 
628 
629 /* instructions */
630 instr:
631     | instr EXEC exec
632     | instr WARP warp
633     | instr WRITETOFILE writetofile
634     | instr HIDE hide
635     | instr SHOW show
636     | instr CHVALUE chvalue
637     | instr CHVALUEMAX chvaluemax
638     | instr CHVALUEMIN chvaluemin
639     | instr CHWINDOWTITLE addlbuff gstrarg {AddCom(27,1);}
640     | instr CHWINDOWTITLEFARG numarg {AddCom(28,1);}
641     | instr POSITION position
642     | instr SIZE size
643     | instr TITLE title
644     | instr LOCALETITLE localetitle
645     | instr ICON icon
646     | instr CHFONT font
647     | instr CHFORECOLOR chforecolor
648     | instr CHBACKCOLOR chbackcolor
649     | instr CHCOLORSET chcolorset
650     | instr SET set
651     | instr SENDSIGN sendsign
652     | instr QUIT quit
653     | instr SENDTOSCRIPT sendtoscript
654     | instr IF ifthenelse
655     | instr FOR loop
656     | instr WHILE while
657     | instr KEY key
658     ;
659 
660 /* One single instruction */
661 oneinstr: EXEC exec
662     	| WARP warp
663 	| WRITETOFILE writetofile
664 	| HIDE hide
665 	| SHOW show
666 	| CHVALUE chvalue
667 	| CHVALUEMAX chvaluemax
668 	| CHVALUEMIN chvaluemin
669 	| CHWINDOWTITLE addlbuff gstrarg {AddCom(27,1);}
670 	| CHWINDOWTITLEFARG numarg {AddCom(28,1);}
671 	| POSITION position
672 	| SIZE size
673 	| TITLE title
674 	| LOCALETITLE localetitle
675 	| ICON icon
676 	| CHFONT font
677 	| CHFORECOLOR chforecolor
678 	| CHBACKCOLOR chbackcolor
679 	| CHCOLORSET chcolorset
680 	| SET set
681 	| SENDSIGN sendsign
682 	| QUIT quit
683 	| SENDTOSCRIPT sendtoscript
684 	| FOR loop
685 	| WHILE while
686     	| KEY key
687 	;
688 
689 exec: addlbuff args			{ AddCom(1,1); }
690     ;
691 hide: addlbuff numarg			{ AddCom(2,1);}
692     ;
693 show: addlbuff numarg			{ AddCom(3,1);}
694     ;
695 chvalue: addlbuff numarg addlbuff numarg	{ AddCom(4,2);}
696        ;
697 chvaluemax: addlbuff numarg addlbuff numarg	{ AddCom(21,2);}
698        ;
699 chvaluemin: addlbuff numarg addlbuff numarg	{ AddCom(22,2);}
700        ;
701 position: addlbuff numarg addlbuff numarg addlbuff numarg	{ AddCom(5,3);}
702         ;
703 size: addlbuff numarg addlbuff numarg addlbuff numarg		{ AddCom(6,3);}
704     ;
705 icon: addlbuff numarg addlbuff strarg	{ AddCom(7,2);}
706     ;
707 title: addlbuff numarg addlbuff gstrarg	{ AddCom(8,2);}
708      ;
709 font: addlbuff numarg addlbuff args { AddCom(9,2);}
710     ;
711 chforecolor: addlbuff numarg addlbuff gstrarg	{ AddCom(10,2);}
712            ;
713 chbackcolor: addlbuff numarg addlbuff gstrarg	{ AddCom(19,2);}
714            ;
715 chcolorset : addlbuff numarg addlbuff numarg	{ AddCom(24,2);}
716            ;
717 set: addlbuff vararg GET addlbuff args	{ AddCom(11,2);}
718    ;
719 sendsign: addlbuff numarg addlbuff numarg { AddCom(12,2);}
720 	;
721 quit: 					{ AddCom(13,0);}
722     ;
723 warp: addlbuff numarg			{ AddCom(17,1);}
724     ;
725 sendtoscript: addlbuff numarg addlbuff args 	{ AddCom(23,2);}
726 	    ;
727 writetofile: addlbuff strarg addlbuff args	{ AddCom(18,2);}
728 	   ;
729 key: addlbuff strarg addlbuff strarg addlbuff numarg addlbuff numarg addlbuff args { AddCom(25,5);}
730 	   ;
731 localetitle: addlbuff numarg addlbuff gstrarg	{ AddCom(26,2);}
732      ;
733 ifthenelse: headif creerbloc bloc1 else
734           ;
735 loop: headloop creerbloc bloc2
736     ;
737 while: headwhile creerbloc bloc2
738     ;
739 
740 /* Conditional loop: compare whatever argument type */
741 headif: addlbuff arg addlbuff compare addlbuff arg THEN 	{ AddComBloc(14,3,2); }
742       ;
743 else: 				/* else is optional */
744     | ELSE creerbloc bloc2
745     ;
746 creerbloc:			{ EmpilerBloc(); }
747          ;
748 bloc1: BEG instr END		{ DepilerBloc(2); }
749      | oneinstr			{ DepilerBloc(2); }
750      ;
751 
752 bloc2: BEG instr END		{ DepilerBloc(1); }
753      | oneinstr			{ DepilerBloc(1); }
754      ;
755 
756 /* Loop on a variable */
757 headloop: addlbuff vararg GET addlbuff arg TO addlbuff arg DO	{ AddComBloc(15,3,1); }
758         ;
759 
760 /* While conditional loop */
761 headwhile: addlbuff arg addlbuff compare addlbuff arg DO	{ AddComBloc(16,3,1); }
762         ;
763 
764 /* Command Argument */
765 /* Elementary Argument */
766 var	: VAR			{ AddVar($1); }
767 	;
768 str	: STR			{ AddConstStr($1); }
769 	;
770 gstr	: GSTR			{ AddConstStr($1); }
771 	;
772 num	: NUMBER		{ AddConstNum($1); }
773 	;
774 singleclic2: SINGLECLIC		{ AddConstNum(-1); }
775 	   ;
776 doubleclic2: DOUBLECLIC		{ AddConstNum(-2); }
777 	   ;
778 addlbuff:			{ AddLevelBufArg(); }
779 	;
780 function: GETVALUE numarg	{ AddFunct(1,1); }
781 	| GETTITLE numarg	{ AddFunct(2,1); }
782 	| GETOUTPUT gstrarg numarg numarg { AddFunct(3,1); }
783 	| NUMTOHEX numarg numarg { AddFunct(4,1); }
784 	| HEXTONUM gstrarg	{ AddFunct(5,1); }
785 	| ADD numarg numarg { AddFunct(6,1); }
786 	| MULT numarg numarg { AddFunct(7,1); }
787 	| DIV numarg numarg { AddFunct(8,1); }
788 	| STRCOPY gstrarg numarg numarg { AddFunct(9,1); }
789 	| LAUNCHSCRIPT gstrarg { AddFunct(10,1); }
790 	| GETSCRIPTFATHER { AddFunct(11,1); }
791 	| RECEIVFROMSCRIPT numarg { AddFunct(12,1); }
792 	| REMAINDEROFDIV numarg numarg { AddFunct(13,1); }
793 	| GETTIME { AddFunct(14,1); }
794 	| GETSCRIPTARG numarg { AddFunct(15,1); }
795 	| GETFORE numarg { AddFunct(16,1); }
796 	| GETBACK numarg { AddFunct(17,1); }
797 	| GETHILIGHT numarg { AddFunct(18,1); }
798 	| GETSHADOW numarg { AddFunct(19,1); }
799 	| GETMINVALUE numarg { AddFunct(20,1); }
800 	| GETMAXVALUE numarg { AddFunct(21,1); }
801 	| GETPID { AddFunct(22,1); }
802 	| SENDMSGANDGET gstrarg gstrarg numarg { AddFunct(23,1); }
803 	| PARSE gstrarg numarg { AddFunct(24,1); }
804 	| LASTSTRING { AddFunct(25,1); }
805 	| GETTEXT gstrarg { AddFunct(26,1); }
806 	;
807 
808 
809 /* Unique argument of several types */
810 args	:			{ }
811 	| singleclic2 args
812 	| doubleclic2 args
813 	| var args
814 	| gstr args
815 	| str args
816 	| num args
817 	| BEGF addlbuff function ENDF args
818 	;
819 
820 /* Unique argument of whatever type */
821 arg	: var
822 	| singleclic2
823 	| doubleclic2
824 	| gstr
825 	| str
826 	| num
827 	| BEGF addlbuff function ENDF
828 	;
829 
830 /* Unique argument of number type */
831 numarg	: singleclic2
832 	| doubleclic2
833 	| num
834 	| var
835 	| BEGF addlbuff function ENDF
836 	;
837 
838 /* Unique argument of str type */
839 strarg	: var
840 	| str
841 	| BEGF addlbuff function ENDF
842 	;
843 
844 /* Unique argument of gstr type */
845 gstrarg	: var
846 	| gstr
847 	| BEGF addlbuff function ENDF
848 	;
849 
850 /* Unique argument of variable type, no function */
851 vararg	: var
852 	;
853 
854 /* comparison element between 2 numbers */
855 compare	: INF			 { l=1-250000; AddBufArg(&l,1); }
856 	| INFEQ			 { l=2-250000; AddBufArg(&l,1); }
857 	| EQUAL			 { l=3-250000; AddBufArg(&l,1); }
858 	| SUPEQ			 { l=4-250000; AddBufArg(&l,1); }
859 	| SUP			 { l=5-250000; AddBufArg(&l,1); }
860 	| DIFF			 { l=6-250000; AddBufArg(&l,1); }
861 	;
862 
863 %%
864