parseutils.c revision f46a6179
1/* $Xorg: parseutils.c,v 1.3 2000/08/17 19:54:33 cpqbld Exp $ */
2/************************************************************
3 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4
5 Permission to use, copy, modify, and distribute this
6 software and its documentation for any purpose and without
7 fee is hereby granted, provided that the above copyright
8 notice appear in all copies and that both that copyright
9 notice and this permission notice appear in supporting
10 documentation, and that the name of Silicon Graphics not be
11 used in advertising or publicity pertaining to distribution
12 of the software without specific prior written permission.
13 Silicon Graphics makes no representation about the suitability
14 of this software for any purpose. It is provided "as is"
15 without any express or implied warranty.
16
17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26 ********************************************************/
27/* $XFree86$ */
28
29#define DEBUG_VAR_NOT_LOCAL
30#define	DEBUG_VAR parseDebug
31#include "parseutils.h"
32#include "xkbpath.h"
33#include <X11/keysym.h>
34#include <X11/extensions/XKBgeom.h>
35#include <X11/Xalloca.h>
36
37XkbFile	*rtrnValue;
38
39ParseCommon *
40AppendStmt(ParseCommon *to,ParseCommon *append)
41{
42ParseCommon	*start= to;
43
44    if (append==NULL)
45	return to;
46    while ((to!=NULL) && (to->next!=NULL)) {
47	to= to->next;
48    }
49    if (to) {
50	to->next= append;
51	return start;
52    }
53    return append;
54}
55
56ExprDef *
57ExprCreate(unsigned op,unsigned type)
58{
59ExprDef *expr;
60    expr= uTypedAlloc(ExprDef);
61    if (expr) {
62	expr->common.stmtType= StmtExpr;
63	expr->common.next= NULL;
64	expr->op= op;
65	expr->type= type;
66    }
67    else {
68	FATAL("Couldn't allocate expression in parser\n");
69	/* NOTREACHED */
70    }
71    return expr;
72}
73
74ExprDef *
75ExprCreateUnary(unsigned op,unsigned type,ExprDef *child)
76{
77ExprDef *expr;
78    expr= uTypedAlloc(ExprDef);
79    if (expr) {
80	expr->common.stmtType= StmtExpr;
81	expr->common.next= NULL;
82	expr->op= op;
83	expr->type= type;
84	expr->value.child= child;
85    }
86    else {
87	FATAL("Couldn't allocate expression in parser\n");
88	/* NOTREACHED */
89    }
90    return expr;
91}
92
93ExprDef *
94ExprCreateBinary(unsigned op,ExprDef *left,ExprDef *right)
95{
96ExprDef *expr;
97    expr= uTypedAlloc(ExprDef);
98    if (expr) {
99	expr->common.stmtType= StmtExpr;
100	expr->common.next= NULL;
101	expr->op= op;
102	if ((op==OpAssign)||(left->type==TypeUnknown))
103	     expr->type= right->type;
104	else if ((left->type==right->type)||(right->type==TypeUnknown))
105	     expr->type= left->type;
106	else expr->type= TypeUnknown;
107	expr->value.binary.left= left;
108	expr->value.binary.right= right;
109    }
110    else {
111	FATAL("Couldn't allocate expression in parser\n");
112	/* NOTREACHED */
113    }
114    return expr;
115}
116
117KeycodeDef *
118KeycodeCreate(char *name,ExprDef *value)
119{
120KeycodeDef *def;
121
122    def= uTypedAlloc(KeycodeDef);
123    if (def) {
124	def->common.stmtType= StmtKeycodeDef;
125	def->common.next= NULL;
126	strncpy(def->name,name,XkbKeyNameLength);
127	def->name[XkbKeyNameLength]= '\0';
128	def->value= value;
129    }
130    else {
131	FATAL("Couldn't allocate key name definition in parser\n");
132	/* NOTREACHED */
133    }
134    return def;
135}
136
137KeyAliasDef *
138KeyAliasCreate(char *alias,char *real)
139{
140KeyAliasDef *def;
141
142    def= uTypedAlloc(KeyAliasDef);
143    if (def) {
144	def->common.stmtType= StmtKeyAliasDef;
145	def->common.next= NULL;
146	strncpy(def->alias,alias,XkbKeyNameLength);
147	def->alias[XkbKeyNameLength]= '\0';
148	strncpy(def->real,real,XkbKeyNameLength);
149	def->real[XkbKeyNameLength]= '\0';
150    }
151    else {
152	FATAL("Couldn't allocate key alias definition in parser\n");
153	/* NOTREACHED */
154    }
155    return def;
156}
157
158VModDef *
159VModCreate(Atom name,ExprDef *value)
160{
161VModDef *def;
162    def= uTypedAlloc(VModDef);
163    if (def) {
164	def->common.stmtType= StmtVModDef;
165	def->common.next= NULL;
166	def->name= name;
167	def->value= value;
168    }
169    else {
170	FATAL("Couldn't allocate variable definition in parser\n");
171	/* NOTREACHED */
172    }
173    return def;
174}
175
176VarDef *
177VarCreate(ExprDef *name,ExprDef *value)
178{
179VarDef *def;
180    def= uTypedAlloc(VarDef);
181    if (def) {
182	def->common.stmtType= StmtVarDef;
183	def->common.next= NULL;
184	def->name= name;
185	def->value= value;
186    }
187    else {
188	FATAL("Couldn't allocate variable definition in parser\n");
189	/* NOTREACHED */
190    }
191    return def;
192}
193
194VarDef *
195BoolVarCreate(Atom nameToken,unsigned set)
196{
197ExprDef	*name,*value;
198
199    name= ExprCreate(ExprIdent,TypeUnknown);
200    name->value.str= nameToken;
201    value= ExprCreate(ExprValue,TypeBoolean);
202    value->value.uval= set;
203    return VarCreate(name,value);
204}
205
206InterpDef *
207InterpCreate(KeySym sym,ExprDef *match)
208{
209InterpDef *def;
210
211    def= uTypedAlloc(InterpDef);
212    if (def) {
213	def->common.stmtType= StmtInterpDef;
214	def->common.next= NULL;
215	def->sym= sym;
216	def->match= match;
217    }
218    else {
219	FATAL("Couldn't allocate interp definition in parser\n");
220	/* NOTREACHED */
221    }
222    return def;
223}
224
225KeyTypeDef *
226KeyTypeCreate(Atom name,VarDef *body)
227{
228KeyTypeDef *def;
229
230    def= uTypedAlloc(KeyTypeDef);
231    if (def) {
232	def->common.stmtType= StmtKeyTypeDef;
233	def->common.next= NULL;
234	def->merge= MergeDefault;
235	def->name= name;
236	def->body= body;
237    }
238    else {
239	FATAL("Couldn't allocate key type definition in parser\n");
240	/* NOTREACHED */
241    }
242    return def;
243}
244
245SymbolsDef *
246SymbolsCreate(char *keyName,ExprDef *symbols)
247{
248SymbolsDef *def;
249
250    def= uTypedAlloc(SymbolsDef);
251    if (def) {
252	def->common.stmtType= StmtSymbolsDef;
253	def->common.next= NULL;
254	def->merge= MergeDefault;
255	bzero(def->keyName,5);
256	strncpy(def->keyName,keyName,4);
257	def->symbols= symbols;
258    }
259    else {
260	FATAL("Couldn't allocate symbols definition in parser\n");
261	/* NOTREACHED */
262    }
263    return def;
264}
265
266GroupCompatDef *
267GroupCompatCreate(int group,ExprDef *val)
268{
269GroupCompatDef *def;
270
271    def= uTypedAlloc(GroupCompatDef);
272    if (def) {
273	def->common.stmtType= StmtGroupCompatDef;
274	def->common.next= NULL;
275	def->merge= MergeDefault;
276	def->group= group;
277	def->def= val;
278    }
279    else {
280	FATAL("Couldn't allocate group compat definition in parser\n");
281	/* NOTREACHED */
282    }
283    return def;
284}
285
286ModMapDef *
287ModMapCreate(Atom modifier,ExprDef *keys)
288{
289ModMapDef *def;
290
291    def= uTypedAlloc(ModMapDef);
292    if (def) {
293	def->common.stmtType= StmtModMapDef;
294	def->common.next= NULL;
295	def->merge= MergeDefault;
296	def->modifier= modifier;
297	def->keys= keys;
298    }
299    else {
300	FATAL("Couldn't allocate mod mask definition in parser\n");
301	/* NOTREACHED */
302    }
303    return def;
304}
305
306IndicatorMapDef *
307IndicatorMapCreate(Atom name,VarDef *body)
308{
309IndicatorMapDef *def;
310
311    def= uTypedAlloc(IndicatorMapDef);
312    if (def) {
313	def->common.stmtType= StmtIndicatorMapDef;
314	def->common.next= NULL;
315	def->merge= MergeDefault;
316	def->name= name;
317	def->body= body;
318    }
319    else {
320	FATAL("Couldn't allocate indicator map definition in parser\n");
321	/* NOTREACHED */
322    }
323    return def;
324}
325
326IndicatorNameDef *
327IndicatorNameCreate(int	ndx,ExprDef *name,Bool virtual)
328{
329IndicatorNameDef *def;
330
331    def= uTypedAlloc(IndicatorNameDef);
332    if (def) {
333	def->common.stmtType= StmtIndicatorNameDef;
334	def->common.next= NULL;
335	def->merge= MergeDefault;
336	def->ndx= ndx;
337	def->name= name;
338	def->virtual= virtual;
339    }
340    else {
341	FATAL("Couldn't allocate indicator index definition in parser\n");
342	/* NOTREACHED */
343    }
344    return def;
345}
346
347ExprDef *
348ActionCreate(Atom name,ExprDef *args)
349{
350ExprDef *act;
351
352    act= uTypedAlloc(ExprDef);
353    if (act) {
354	act->common.stmtType= StmtExpr;
355	act->common.next= NULL;
356	act->op= ExprActionDecl;
357	act->value.action.name= name;
358        act->value.action.args= args;
359	return act;
360    }
361    FATAL("Couldn't allocate ActionDef in parser\n");
362    return NULL;
363}
364
365ExprDef *
366CreateKeysymList(KeySym sym)
367{
368ExprDef	 *def;
369
370    def= ExprCreate(ExprKeysymList,TypeSymbols);
371    if (def) {
372	def->value.list.nSyms= 1;
373	def->value.list.szSyms= 2;
374	def->value.list.syms= uTypedCalloc(2,KeySym);
375	if (def->value.list.syms!=NULL) {
376	    def->value.list.syms[0]= sym;
377	    return def;
378	}
379    }
380    FATAL("Couldn't allocate expression for keysym list in parser\n");
381    return NULL;
382}
383
384ShapeDef *
385ShapeDeclCreate(Atom name,OutlineDef *outlines)
386{
387ShapeDef *	shape;
388OutlineDef *	ol;
389
390    shape= uTypedAlloc(ShapeDef);
391    if (shape!=NULL) {
392	bzero(shape,sizeof(ShapeDef));
393	shape->common.stmtType=	StmtShapeDef;
394	shape->common.next=	NULL;
395	shape->merge=		MergeDefault;
396	shape->name=		name;
397	shape->nOutlines=	0;
398	shape->outlines=	outlines;
399	for (ol=outlines;ol!=NULL;ol= (OutlineDef *)ol->common.next) {
400	    if (ol->nPoints>0)
401		shape->nOutlines++;
402	}
403    }
404    return shape;
405}
406
407OutlineDef *
408OutlineCreate(Atom field,ExprDef *points)
409{
410OutlineDef *	outline;
411ExprDef *	pt;
412
413    outline= uTypedAlloc(OutlineDef);
414    if (outline!=NULL) {
415	bzero(outline,sizeof(OutlineDef));
416	outline->common.stmtType= 	StmtOutlineDef;
417	outline->common.next=		NULL;
418	outline->field=		field;
419	outline->nPoints=	0;
420	if (points->op==ExprCoord) {
421	    for (pt=points;pt!=NULL;pt= (ExprDef *)pt->common.next) {
422		outline->nPoints++;
423	    }
424	}
425	outline->points= points;
426    }
427    return outline;
428}
429
430KeyDef *
431KeyDeclCreate(char *name,ExprDef *expr)
432{
433KeyDef *	key;
434
435    key= uTypedAlloc(KeyDef);
436    if (key!=NULL) {
437	bzero(key,sizeof(KeyDef));
438	key->common.stmtType= StmtKeyDef;
439	key->common.next= NULL;
440	if (name)	key->name= name;
441	else		key->expr= expr;
442    }
443    return key;
444}
445
446KeyDef *
447KeyDeclMerge(KeyDef *into,KeyDef *from)
448{
449    into->expr= (ExprDef *)AppendStmt(&into->expr->common,&from->expr->common);
450    from->expr= NULL;
451    uFree(from);
452    return into;
453}
454
455RowDef *
456RowDeclCreate(KeyDef *	keys)
457{
458RowDef *	row;
459KeyDef *	key;
460
461    row= uTypedAlloc(RowDef);
462    if (row!=NULL) {
463	bzero(row,sizeof(RowDef));
464	row->common.stmtType= StmtRowDef;
465	row->common.next= NULL;
466	row->nKeys= 0;
467	row->keys= keys;
468	for (key=keys;key!=NULL;key=(KeyDef *)key->common.next) {
469	    if (key->common.stmtType==StmtKeyDef)
470		row->nKeys++;
471	}
472    }
473    return row;
474}
475
476SectionDef *
477SectionDeclCreate(Atom name,RowDef *rows)
478{
479SectionDef *	section;
480RowDef *	row;
481
482    section= uTypedAlloc(SectionDef);
483    if (section!=NULL) {
484	bzero(section,sizeof(SectionDef));
485	section->common.stmtType= StmtSectionDef;
486	section->common.next= NULL;
487	section->name= name;
488	section->nRows= 0;
489	section->rows= rows;
490	for (row=rows;row!=NULL;row=(RowDef *)row->common.next) {
491	    if (row->common.stmtType==StmtRowDef)
492		section->nRows++;
493	}
494    }
495    return section;
496}
497
498OverlayKeyDef *
499OverlayKeyCreate(char *	under,char *over)
500{
501OverlayKeyDef *	key;
502
503    key= uTypedAlloc(OverlayKeyDef);
504    if (key!=NULL) {
505	bzero(key,sizeof(OverlayKeyDef));
506	key->common.stmtType= StmtOverlayKeyDef;
507	strncpy(key->over,over,XkbKeyNameLength);
508	strncpy(key->under,under,XkbKeyNameLength);
509	if (over)	uFree(over);
510	if (under)	uFree(under);
511    }
512    return key;
513}
514
515OverlayDef *
516OverlayDeclCreate(Atom name,OverlayKeyDef *keys)
517{
518OverlayDef *	ol;
519OverlayKeyDef *	key;
520
521    ol= uTypedAlloc(OverlayDef);
522    if (ol!=NULL) {
523	bzero(ol,sizeof(OverlayDef));
524	ol->common.stmtType= 	StmtOverlayDef;
525	ol->name=		name;
526	ol->keys=		keys;
527	for (key=keys;key!=NULL;key=(OverlayKeyDef *)key->common.next) {
528	    ol->nKeys++;
529	}
530    }
531    return ol;
532}
533
534DoodadDef *
535DoodadCreate(unsigned type,Atom name,VarDef *body)
536{
537DoodadDef *	doodad;
538
539    doodad= uTypedAlloc(DoodadDef);
540    if (doodad!=NULL) {
541	bzero(doodad,sizeof(DoodadDef));
542	doodad->common.stmtType= StmtDoodadDef;
543	doodad->common.next= NULL;
544	doodad->type= type;
545	doodad->name= name;
546	doodad->body= body;
547    }
548    return doodad;
549}
550
551ExprDef *
552AppendKeysymList(ExprDef *list,KeySym sym)
553{
554    if (list->value.list.nSyms>=list->value.list.szSyms) {
555	list->value.list.szSyms*=2;
556	list->value.list.syms= uTypedRecalloc(list->value.list.syms,
557						list->value.list.nSyms,
558						list->value.list.szSyms,
559						KeySym);
560	if (list->value.list.syms==NULL) {
561	    FATAL("Couldn't resize list of symbols for append\n");
562	    return NULL;
563	}
564    }
565    list->value.list.syms[list->value.list.nSyms++]= sym;
566    return list;
567}
568
569int
570LookupKeysym(char *str,KeySym *sym_rtrn)
571{
572KeySym sym;
573
574    if ((!str)||(uStrCaseCmp(str,"any")==0)||(uStrCaseCmp(str,"nosymbol")==0)) {
575	*sym_rtrn= NoSymbol;
576	return 1;
577    }
578    else if ((uStrCaseCmp(str,"none")==0)||(uStrCaseCmp(str,"voidsymbol")==0)) {
579	*sym_rtrn= XK_VoidSymbol;
580	return 1;
581    }
582    sym= XStringToKeysym(str);
583    if (sym!=NoSymbol) {
584	*sym_rtrn= sym;
585	return 1;
586    }
587    return 0;
588}
589
590IncludeStmt *
591IncludeCreate(char *str,unsigned merge)
592{
593IncludeStmt *	incl,*first;
594char *		file,*map,*stmt,*tmp, *extra_data;
595char 		nextop;
596Bool		haveSelf;
597
598    haveSelf= False;
599    incl= first= NULL;
600    file= map= NULL;
601    tmp= str;
602    stmt= uStringDup(str);
603    while ((tmp)&&(*tmp)) {
604	if (XkbParseIncludeMap(&tmp,&file,&map,&nextop,&extra_data)) {
605	    if ((file==NULL)&&(map==NULL)) {
606		if (haveSelf)
607		    goto BAIL;
608		haveSelf= True;
609	    }
610	    if (first==NULL)
611		first= incl= uTypedAlloc(IncludeStmt);
612	    else {
613		incl->next= uTypedAlloc(IncludeStmt);
614		incl= incl->next;
615	    }
616	    if (incl) {
617		incl->common.stmtType= StmtInclude;
618		incl->common.next= NULL;
619		incl->merge= merge;
620		incl->stmt= NULL;
621		incl->file= file;
622		incl->map= map;
623		incl->modifier= extra_data;
624		incl->path= NULL;
625		incl->next= NULL;
626	    }
627	    else {
628		WSGO("Allocation failure in IncludeCreate\n");
629		ACTION("Using only part of the include\n");
630		break;
631	    }
632	    if (nextop=='|')	merge= MergeAugment;
633	    else		merge= MergeOverride;
634	}
635	else {
636	    goto BAIL;
637	}
638    }
639    if (first)		first->stmt= stmt;
640    else if (stmt)	uFree(stmt);
641    return first;
642BAIL:
643    ERROR1("Illegal include statement \"%s\"\n",stmt);
644    ACTION("Ignored\n");
645    while (first) {
646	incl= first->next;
647	if (first->file) uFree(first->file);
648	if (first->map) uFree(first->map);
649	if (first->modifier) uFree(first->modifier);
650	if (first->path) uFree(first->path);
651	first->file= first->map= first->path= NULL;
652	uFree(first);
653	first= incl;
654    }
655    if (stmt)
656	uFree(stmt);
657    return NULL;
658}
659
660#ifdef DEBUG
661void
662PrintStmtAddrs(ParseCommon *stmt)
663{
664    fprintf(stderr,"0x%x",stmt);
665    if (stmt) {
666	do {
667	    fprintf(stderr,"->0x%x",stmt->next);
668	    stmt= stmt->next;
669	} while (stmt);
670    }
671    fprintf(stderr,"\n");
672}
673#endif
674
675static void
676CheckDefaultMap(XkbFile	*maps)
677{
678XkbFile * dflt,*tmp;
679
680    dflt= NULL;
681    for (tmp=maps,dflt=NULL;tmp!=NULL;tmp=(XkbFile *)tmp->common.next) {
682	if (tmp->flags&XkbLC_Default) {
683	    if (dflt==NULL)
684		dflt= tmp;
685	    else {
686		if (warningLevel>2) {
687		    WARN1("Multiple default components in %s\n",
688					(scanFile?scanFile:"(unknown)"));
689		    ACTION2("Using %s, ignoring %s\n",
690					(dflt->name?dflt->name:"(first)"),
691					(tmp->name?tmp->name:"(subsequent)"));
692		}
693		tmp->flags&= (~XkbLC_Default);
694	    }
695	}
696    }
697    return;
698}
699
700int
701XKBParseFile(FILE *file,XkbFile	**pRtrn)
702{
703    if (file) {
704	yyin= file;
705	rtrnValue= NULL;
706	if (yyparse()==0) {
707	    *pRtrn= rtrnValue;
708	    CheckDefaultMap(rtrnValue);
709	    rtrnValue= NULL;
710	    return 1;
711	}
712	*pRtrn= NULL;
713	return 0;
714    }
715    *pRtrn= NULL;
716    return 1;
717}
718
719XkbFile *
720CreateXKBFile(int type,char *name,ParseCommon *defs,unsigned flags)
721{
722XkbFile *	file;
723static int	fileID;
724
725    file= uTypedAlloc(XkbFile);
726    if (file) {
727	XkbEnsureSafeMapName(name);
728	bzero(file,sizeof(XkbFile));
729	file->type= type;
730	file->topName= uStringDup(name);
731	file->name= name;
732	file->defs= defs;
733	file->id= fileID++;
734	file->compiled= False;
735	file->flags= flags;
736    }
737    return file;
738}
739
740unsigned
741StmtSetMerge(ParseCommon *stmt,unsigned	merge)
742{
743    if ((merge==MergeAltForm) && (stmt->stmtType!=StmtKeycodeDef)) {
744	yyerror("illegal use of 'alternate' merge mode");
745	merge= MergeDefault;
746    }
747    return merge;
748}
749