#define DEBUG_VAR_NOT_LOCAL
#define DEBUG_VAR parseDebug
#include "parseutils.h"
#include "xkbpath.h"
#include <X11/keysym.h>
#include <X11/extensions/XKBgeom.h>
#include <X11/Xalloca.h>
XkbFile *rtrnValue;
ParseCommon *
AppendStmt(ParseCommon *to,ParseCommon *append)
{
ParseCommon *start= to;
if (append==NULL)
return to;
while ((to!=NULL) && (to->next!=NULL)) {
to= to->next;
}
if (to) {
to->next= append;
return start;
}
return append;
}
ExprDef *
ExprCreate(unsigned op,unsigned type)
{
ExprDef *expr;
expr= uTypedAlloc(ExprDef);
if (expr) {
expr->common.stmtType= StmtExpr;
expr->common.next= NULL;
expr->op= op;
expr->type= type;
}
else {
FATAL("Couldn't allocate expression in parser\n");
}
return expr;
}
ExprDef *
ExprCreateUnary(unsigned op,unsigned type,ExprDef *child)
{
ExprDef *expr;
expr= uTypedAlloc(ExprDef);
if (expr) {
expr->common.stmtType= StmtExpr;
expr->common.next= NULL;
expr->op= op;
expr->type= type;
expr->value.child= child;
}
else {
FATAL("Couldn't allocate expression in parser\n");
}
return expr;
}
ExprDef *
ExprCreateBinary(unsigned op,ExprDef *left,ExprDef *right)
{
ExprDef *expr;
expr= uTypedAlloc(ExprDef);
if (expr) {
expr->common.stmtType= StmtExpr;
expr->common.next= NULL;
expr->op= op;
if ((op==OpAssign)||(left->type==TypeUnknown))
expr->type= right->type;
else if ((left->type==right->type)||(right->type==TypeUnknown))
expr->type= left->type;
else expr->type= TypeUnknown;
expr->value.binary.left= left;
expr->value.binary.right= right;
}
else {
FATAL("Couldn't allocate expression in parser\n");
}
return expr;
}
KeycodeDef *
KeycodeCreate(char *name,ExprDef *value)
{
KeycodeDef *def;
def= uTypedAlloc(KeycodeDef);
if (def) {
def->common.stmtType= StmtKeycodeDef;
def->common.next= NULL;
strncpy(def->name,name,XkbKeyNameLength);
def->name[XkbKeyNameLength]= '\0';
def->value= value;
}
else {
FATAL("Couldn't allocate key name definition in parser\n");
}
return def;
}
KeyAliasDef *
KeyAliasCreate(char *alias,char *real)
{
KeyAliasDef *def;
def= uTypedAlloc(KeyAliasDef);
if (def) {
def->common.stmtType= StmtKeyAliasDef;
def->common.next= NULL;
strncpy(def->alias,alias,XkbKeyNameLength);
def->alias[XkbKeyNameLength]= '\0';
strncpy(def->real,real,XkbKeyNameLength);
def->real[XkbKeyNameLength]= '\0';
}
else {
FATAL("Couldn't allocate key alias definition in parser\n");
}
return def;
}
VModDef *
VModCreate(Atom name,ExprDef *value)
{
VModDef *def;
def= uTypedAlloc(VModDef);
if (def) {
def->common.stmtType= StmtVModDef;
def->common.next= NULL;
def->name= name;
def->value= value;
}
else {
FATAL("Couldn't allocate variable definition in parser\n");
}
return def;
}
VarDef *
VarCreate(ExprDef *name,ExprDef *value)
{
VarDef *def;
def= uTypedAlloc(VarDef);
if (def) {
def->common.stmtType= StmtVarDef;
def->common.next= NULL;
def->name= name;
def->value= value;
}
else {
FATAL("Couldn't allocate variable definition in parser\n");
}
return def;
}
VarDef *
BoolVarCreate(Atom nameToken,unsigned set)
{
ExprDef *name,*value;
name= ExprCreate(ExprIdent,TypeUnknown);
name->value.str= nameToken;
value= ExprCreate(ExprValue,TypeBoolean);
value->value.uval= set;
return VarCreate(name,value);
}
InterpDef *
InterpCreate(KeySym sym,ExprDef *match)
{
InterpDef *def;
def= uTypedAlloc(InterpDef);
if (def) {
def->common.stmtType= StmtInterpDef;
def->common.next= NULL;
def->sym= sym;
def->match= match;
}
else {
FATAL("Couldn't allocate interp definition in parser\n");
}
return def;
}
KeyTypeDef *
KeyTypeCreate(Atom name,VarDef *body)
{
KeyTypeDef *def;
def= uTypedAlloc(KeyTypeDef);
if (def) {
def->common.stmtType= StmtKeyTypeDef;
def->common.next= NULL;
def->merge= MergeDefault;
def->name= name;
def->body= body;
}
else {
FATAL("Couldn't allocate key type definition in parser\n");
}
return def;
}
SymbolsDef *
SymbolsCreate(char *keyName,ExprDef *symbols)
{
SymbolsDef *def;
def= uTypedAlloc(SymbolsDef);
if (def) {
def->common.stmtType= StmtSymbolsDef;
def->common.next= NULL;
def->merge= MergeDefault;
bzero(def->keyName,5);
strncpy(def->keyName,keyName,4);
def->symbols= symbols;
}
else {
FATAL("Couldn't allocate symbols definition in parser\n");
}
return def;
}
GroupCompatDef *
GroupCompatCreate(int group,ExprDef *val)
{
GroupCompatDef *def;
def= uTypedAlloc(GroupCompatDef);
if (def) {
def->common.stmtType= StmtGroupCompatDef;
def->common.next= NULL;
def->merge= MergeDefault;
def->group= group;
def->def= val;
}
else {
FATAL("Couldn't allocate group compat definition in parser\n");
}
return def;
}
ModMapDef *
ModMapCreate(Atom modifier,ExprDef *keys)
{
ModMapDef *def;
def= uTypedAlloc(ModMapDef);
if (def) {
def->common.stmtType= StmtModMapDef;
def->common.next= NULL;
def->merge= MergeDefault;
def->modifier= modifier;
def->keys= keys;
}
else {
FATAL("Couldn't allocate mod mask definition in parser\n");
}
return def;
}
IndicatorMapDef *
IndicatorMapCreate(Atom name,VarDef *body)
{
IndicatorMapDef *def;
def= uTypedAlloc(IndicatorMapDef);
if (def) {
def->common.stmtType= StmtIndicatorMapDef;
def->common.next= NULL;
def->merge= MergeDefault;
def->name= name;
def->body= body;
}
else {
FATAL("Couldn't allocate indicator map definition in parser\n");
}
return def;
}
IndicatorNameDef *
IndicatorNameCreate(int ndx,ExprDef *name,Bool virtual)
{
IndicatorNameDef *def;
def= uTypedAlloc(IndicatorNameDef);
if (def) {
def->common.stmtType= StmtIndicatorNameDef;
def->common.next= NULL;
def->merge= MergeDefault;
def->ndx= ndx;
def->name= name;
def->virtual= virtual;
}
else {
FATAL("Couldn't allocate indicator index definition in parser\n");
}
return def;
}
ExprDef *
ActionCreate(Atom name,ExprDef *args)
{
ExprDef *act;
act= uTypedAlloc(ExprDef);
if (act) {
act->common.stmtType= StmtExpr;
act->common.next= NULL;
act->op= ExprActionDecl;
act->value.action.name= name;
act->value.action.args= args;
return act;
}
FATAL("Couldn't allocate ActionDef in parser\n");
return NULL;
}
ExprDef *
CreateKeysymList(KeySym sym)
{
ExprDef *def;
def= ExprCreate(ExprKeysymList,TypeSymbols);
if (def) {
def->value.list.nSyms= 1;
def->value.list.szSyms= 2;
def->value.list.syms= uTypedCalloc(2,KeySym);
if (def->value.list.syms!=NULL) {
def->value.list.syms[0]= sym;
return def;
}
}
FATAL("Couldn't allocate expression for keysym list in parser\n");
return NULL;
}
ShapeDef *
ShapeDeclCreate(Atom name,OutlineDef *outlines)
{
ShapeDef * shape;
OutlineDef * ol;
shape= uTypedAlloc(ShapeDef);
if (shape!=NULL) {
bzero(shape,sizeof(ShapeDef));
shape->common.stmtType= StmtShapeDef;
shape->common.next= NULL;
shape->merge= MergeDefault;
shape->name= name;
shape->nOutlines= 0;
shape->outlines= outlines;
for (ol=outlines;ol!=NULL;ol= (OutlineDef *)ol->common.next) {
if (ol->nPoints>0)
shape->nOutlines++;
}
}
return shape;
}
OutlineDef *
OutlineCreate(Atom field,ExprDef *points)
{
OutlineDef * outline;
ExprDef * pt;
outline= uTypedAlloc(OutlineDef);
if (outline!=NULL) {
bzero(outline,sizeof(OutlineDef));
outline->common.stmtType= StmtOutlineDef;
outline->common.next= NULL;
outline->field= field;
outline->nPoints= 0;
if (points->op==ExprCoord) {
for (pt=points;pt!=NULL;pt= (ExprDef *)pt->common.next) {
outline->nPoints++;
}
}
outline->points= points;
}
return outline;
}
KeyDef *
KeyDeclCreate(char *name,ExprDef *expr)
{
KeyDef * key;
key= uTypedAlloc(KeyDef);
if (key!=NULL) {
bzero(key,sizeof(KeyDef));
key->common.stmtType= StmtKeyDef;
key->common.next= NULL;
if (name) key->name= name;
else key->expr= expr;
}
return key;
}
KeyDef *
KeyDeclMerge(KeyDef *into,KeyDef *from)
{
into->expr= (ExprDef *)AppendStmt(&into->expr->common,&from->expr->common);
from->expr= NULL;
uFree(from);
return into;
}
RowDef *
RowDeclCreate(KeyDef * keys)
{
RowDef * row;
KeyDef * key;
row= uTypedAlloc(RowDef);
if (row!=NULL) {
bzero(row,sizeof(RowDef));
row->common.stmtType= StmtRowDef;
row->common.next= NULL;
row->nKeys= 0;
row->keys= keys;
for (key=keys;key!=NULL;key=(KeyDef *)key->common.next) {
if (key->common.stmtType==StmtKeyDef)
row->nKeys++;
}
}
return row;
}
SectionDef *
SectionDeclCreate(Atom name,RowDef *rows)
{
SectionDef * section;
RowDef * row;
section= uTypedAlloc(SectionDef);
if (section!=NULL) {
bzero(section,sizeof(SectionDef));
section->common.stmtType= StmtSectionDef;
section->common.next= NULL;
section->name= name;
section->nRows= 0;
section->rows= rows;
for (row=rows;row!=NULL;row=(RowDef *)row->common.next) {
if (row->common.stmtType==StmtRowDef)
section->nRows++;
}
}
return section;
}
OverlayKeyDef *
OverlayKeyCreate(char * under,char *over)
{
OverlayKeyDef * key;
key= uTypedAlloc(OverlayKeyDef);
if (key!=NULL) {
bzero(key,sizeof(OverlayKeyDef));
key->common.stmtType= StmtOverlayKeyDef;
strncpy(key->over,over,XkbKeyNameLength);
strncpy(key->under,under,XkbKeyNameLength);
if (over) uFree(over);
if (under) uFree(under);
}
return key;
}
OverlayDef *
OverlayDeclCreate(Atom name,OverlayKeyDef *keys)
{
OverlayDef * ol;
OverlayKeyDef * key;
ol= uTypedAlloc(OverlayDef);
if (ol!=NULL) {
bzero(ol,sizeof(OverlayDef));
ol->common.stmtType= StmtOverlayDef;
ol->name= name;
ol->keys= keys;
for (key=keys;key!=NULL;key=(OverlayKeyDef *)key->common.next) {
ol->nKeys++;
}
}
return ol;
}
DoodadDef *
DoodadCreate(unsigned type,Atom name,VarDef *body)
{
DoodadDef * doodad;
doodad= uTypedAlloc(DoodadDef);
if (doodad!=NULL) {
bzero(doodad,sizeof(DoodadDef));
doodad->common.stmtType= StmtDoodadDef;
doodad->common.next= NULL;
doodad->type= type;
doodad->name= name;
doodad->body= body;
}
return doodad;
}
ExprDef *
AppendKeysymList(ExprDef *list,KeySym sym)
{
if (list->value.list.nSyms>=list->value.list.szSyms) {
list->value.list.szSyms*=2;
list->value.list.syms= uTypedRecalloc(list->value.list.syms,
list->value.list.nSyms,
list->value.list.szSyms,
KeySym);
if (list->value.list.syms==NULL) {
FATAL("Couldn't resize list of symbols for append\n");
return NULL;
}
}
list->value.list.syms[list->value.list.nSyms++]= sym;
return list;
}
int
LookupKeysym(char *str,KeySym *sym_rtrn)
{
KeySym sym;
if ((!str)||(uStrCaseCmp(str,"any")==0)||(uStrCaseCmp(str,"nosymbol")==0)) {
*sym_rtrn= NoSymbol;
return 1;
}
else if ((uStrCaseCmp(str,"none")==0)||(uStrCaseCmp(str,"voidsymbol")==0)) {
*sym_rtrn= XK_VoidSymbol;
return 1;
}
sym= XStringToKeysym(str);
if (sym!=NoSymbol) {
*sym_rtrn= sym;
return 1;
}
return 0;
}
IncludeStmt *
IncludeCreate(char *str,unsigned merge)
{
IncludeStmt * incl,*first;
char * file,*map,*stmt,*tmp, *extra_data;
char nextop;
Bool haveSelf;
haveSelf= False;
incl= first= NULL;
file= map= NULL;
tmp= str;
stmt= uStringDup(str);
while ((tmp)&&(*tmp)) {
if (XkbParseIncludeMap(&tmp,&file,&map,&nextop,&extra_data)) {
if ((file==NULL)&&(map==NULL)) {
if (haveSelf)
goto BAIL;
haveSelf= True;
}
if (first==NULL)
first= incl= uTypedAlloc(IncludeStmt);
else {
incl->next= uTypedAlloc(IncludeStmt);
incl= incl->next;
}
if (incl) {
incl->common.stmtType= StmtInclude;
incl->common.next= NULL;
incl->merge= merge;
incl->stmt= NULL;
incl->file= file;
incl->map= map;
incl->modifier= extra_data;
incl->path= NULL;
incl->next= NULL;
}
else {
WSGO("Allocation failure in IncludeCreate\n");
ACTION("Using only part of the include\n");
break;
}
if (nextop=='|') merge= MergeAugment;
else merge= MergeOverride;
}
else {
goto BAIL;
}
}
if (first) first->stmt= stmt;
else if (stmt) uFree(stmt);
return first;
BAIL:
ERROR1("Illegal include statement \"%s\"\n",stmt);
ACTION("Ignored\n");
while (first) {
incl= first->next;
if (first->file) uFree(first->file);
if (first->map) uFree(first->map);
if (first->modifier) uFree(first->modifier);
if (first->path) uFree(first->path);
first->file= first->map= first->path= NULL;
uFree(first);
first= incl;
}
if (stmt)
uFree(stmt);
return NULL;
}
#ifdef DEBUG
void
PrintStmtAddrs(ParseCommon *stmt)
{
fprintf(stderr,"0x%x",stmt);
if (stmt) {
do {
fprintf(stderr,"->0x%x",stmt->next);
stmt= stmt->next;
} while (stmt);
}
fprintf(stderr,"\n");
}
#endif
static void
CheckDefaultMap(XkbFile *maps)
{
XkbFile * dflt,*tmp;
dflt= NULL;
for (tmp=maps,dflt=NULL;tmp!=NULL;tmp=(XkbFile *)tmp->common.next) {
if (tmp->flags&XkbLC_Default) {
if (dflt==NULL)
dflt= tmp;
else {
if (warningLevel>2) {
WARN1("Multiple default components in %s\n",
(scanFile?scanFile:"(unknown)"));
ACTION2("Using %s, ignoring %s\n",
(dflt->name?dflt->name:"(first)"),
(tmp->name?tmp->name:"(subsequent)"));
}
tmp->flags&= (~XkbLC_Default);
}
}
}
return;
}
int
XKBParseFile(FILE *file,XkbFile **pRtrn)
{
if (file) {
yyin= file;
rtrnValue= NULL;
if (yyparse()==0) {
*pRtrn= rtrnValue;
CheckDefaultMap(rtrnValue);
rtrnValue= NULL;
return 1;
}
*pRtrn= NULL;
return 0;
}
*pRtrn= NULL;
return 1;
}
XkbFile *
CreateXKBFile(int type,char *name,ParseCommon *defs,unsigned flags)
{
XkbFile * file;
static int fileID;
file= uTypedAlloc(XkbFile);
if (file) {
XkbEnsureSafeMapName(name);
bzero(file,sizeof(XkbFile));
file->type= type;
file->topName= uStringDup(name);
file->name= name;
file->defs= defs;
file->id= fileID++;
file->compiled= False;
file->flags= flags;
}
return file;
}
unsigned
StmtSetMerge(ParseCommon *stmt,unsigned merge)
{
if ((merge==MergeAltForm) && (stmt->stmtType!=StmtKeycodeDef)) {
yyerror("illegal use of 'alternate' merge mode");
merge= MergeDefault;
}
return merge;
}