Bug Summary

File:TMparse.c
Location:line 677, column 9
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25 All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1998 The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71#ifdef HAVE_CONFIG_H1
72#include <config.h>
73#endif
74#include "IntrinsicI.h"
75#include "StringDefs.h"
76#include <ctype.h>
77#include <stdlib.h>
78#ifndef NOTASCII
79#define XK_LATIN1
80#endif
81#define XK_MISCELLANY
82#include <X11/keysymdef.h>
83
84#ifdef CACHE_TRANSLATIONS
85# ifdef REFCNT_TRANSLATIONS
86# define CACHED0x002 XtCacheAll0x002 | XtCacheRefCount0x100
87# else
88# define CACHED0x002 XtCacheAll0x002
89# endif
90#else
91# define CACHED0x002 XtCacheNone0x001
92#endif
93
94#ifndef MAX
95#define MAX(a,b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
96#endif
97
98#ifndef MIN
99#define MIN(a,b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
100#endif
101
102static String XtNtranslationParseError = "translationParseError";
103
104typedef int EventType;
105
106typedef String (*ParseProc)(
107 String /* str; */,
108 Opaque /* closure; */,
109 EventPtr /* event; */,
110 Boolean* /* error */);
111
112typedef TMShortCard Value;
113typedef void (*ModifierProc)(Value, LateBindingsPtr*, Boolean, Value*);
114
115typedef struct _ModifierRec {
116 const char *name;
117 XrmQuark signature;
118 ModifierProc modifierParseProc;
119 Value value;
120} ModifierRec, *ModifierKeys;
121
122typedef struct _EventKey {
123 const char *event;
124 XrmQuark signature;
125 EventType eventType;
126 ParseProc parseDetail;
127 Opaque closure;
128}EventKey, *EventKeys;
129
130typedef struct {
131 const char *name;
132 XrmQuark signature;
133 Value value;
134} NameValueRec, *NameValueTable;
135
136static void ParseModImmed(Value, LateBindingsPtr*, Boolean, Value*);
137static void ParseModSym(Value, LateBindingsPtr*, Boolean, Value*);
138static String PanicModeRecovery(String);
139static String CheckForPoundSign(String, _XtTranslateOp, _XtTranslateOp *);
140static KeySym StringToKeySym(String, Boolean *);
141static ModifierRec modifiers[] = {
142 {"Shift", 0, ParseModImmed,ShiftMask(1<<0)},
143 {"Lock", 0, ParseModImmed,LockMask(1<<1)},
144 {"Ctrl", 0, ParseModImmed,ControlMask(1<<2)},
145 {"Mod1", 0, ParseModImmed,Mod1Mask(1<<3)},
146 {"Mod2", 0, ParseModImmed,Mod2Mask(1<<4)},
147 {"Mod3", 0, ParseModImmed,Mod3Mask(1<<5)},
148 {"Mod4", 0, ParseModImmed,Mod4Mask(1<<6)},
149 {"Mod5", 0, ParseModImmed,Mod5Mask(1<<7)},
150 {"Meta", 0, ParseModSym, XK_Meta_L0xffe7},
151 {"m", 0, ParseModSym, XK_Meta_L0xffe7},
152 {"h", 0, ParseModSym, XK_Hyper_L0xffed},
153 {"su", 0, ParseModSym, XK_Super_L0xffeb},
154 {"a", 0, ParseModSym, XK_Alt_L0xffe9},
155 {"Hyper", 0, ParseModSym, XK_Hyper_L0xffed},
156 {"Super", 0, ParseModSym, XK_Super_L0xffeb},
157 {"Alt", 0, ParseModSym, XK_Alt_L0xffe9},
158 {"Button1", 0, ParseModImmed,Button1Mask(1<<8)},
159 {"Button2", 0, ParseModImmed,Button2Mask(1<<9)},
160 {"Button3", 0, ParseModImmed,Button3Mask(1<<10)},
161 {"Button4", 0, ParseModImmed,Button4Mask(1<<11)},
162 {"Button5", 0, ParseModImmed,Button5Mask(1<<12)},
163 {"c", 0, ParseModImmed,ControlMask(1<<2)},
164 {"s", 0, ParseModImmed,ShiftMask(1<<0)},
165 {"l", 0, ParseModImmed,LockMask(1<<1)},
166};
167
168static NameValueRec buttonNames[] = {
169 {"Button1", 0, Button11},
170 {"Button2", 0, Button22},
171 {"Button3", 0, Button33},
172 {"Button4", 0, Button44},
173 {"Button5", 0, Button55},
174 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
175};
176
177static NameValueRec motionDetails[] = {
178 {"Normal", 0, NotifyNormal0},
179 {"Hint", 0, NotifyHint1},
180 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
181};
182
183static NameValueRec notifyModes[] = {
184 {"Normal", 0, NotifyNormal0},
185 {"Grab", 0, NotifyGrab1},
186 {"Ungrab", 0, NotifyUngrab2},
187 {"WhileGrabbed", 0, NotifyWhileGrabbed3},
188 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
189};
190
191#if 0
192static NameValueRec notifyDetail[] = {
193 {"Ancestor", 0, NotifyAncestor0},
194 {"Virtual", 0, NotifyVirtual1},
195 {"Inferior", 0, NotifyInferior2},
196 {"Nonlinear", 0, NotifyNonlinear3},
197 {"NonlinearVirtual", 0, NotifyNonlinearVirtual4},
198 {"Pointer", 0, NotifyPointer5},
199 {"PointerRoot", 0, NotifyPointerRoot6},
200 {"DetailNone", 0, NotifyDetailNone7},
201 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
202};
203
204static NameValueRec visibilityNotify[] = {
205 {"Unobscured", 0, VisibilityUnobscured0},
206 {"PartiallyObscured", 0, VisibilityPartiallyObscured1},
207 {"FullyObscured", 0, VisibilityFullyObscured2},
208 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
209};
210
211static NameValueRec circulation[] = {
212 {"OnTop", 0, PlaceOnTop0},
213 {"OnBottom", 0, PlaceOnBottom1},
214 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
215};
216
217static NameValueRec propertyChanged[] = {
218 {"NewValue", 0, PropertyNewValue0},
219 {"Delete", 0, PropertyDelete1},
220 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
221};
222#endif /*0*/
223
224static NameValueRec mappingNotify[] = {
225 {"Modifier", 0, MappingModifier0},
226 {"Keyboard", 0, MappingKeyboard1},
227 {"Pointer", 0, MappingPointer2},
228 {NULL((void*)0), NULLQUARK((XrmQuark) 0), 0},
229};
230
231static String ParseKeySym(String, Opaque, EventPtr, Boolean*);
232static String ParseKeyAndModifiers(String, Opaque, EventPtr, Boolean*);
233static String ParseTable(String, Opaque, EventPtr, Boolean*);
234static String ParseImmed(String, Opaque, EventPtr, Boolean*);
235static String ParseAddModifier(String, Opaque, EventPtr, Boolean*);
236static String ParseNone(String, Opaque, EventPtr, Boolean*);
237static String ParseAtom(String, Opaque, EventPtr, Boolean*);
238
239static EventKey events[] = {
240
241/* Event Name, Quark, Event Type, Detail Parser, Closure */
242
243{"KeyPress", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeySym, NULL((void*)0)},
244{"Key", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeySym, NULL((void*)0)},
245{"KeyDown", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeySym, NULL((void*)0)},
246{"Ctrl", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeyAndModifiers,(Opaque)ControlMask(1<<2)},
247{"Shift", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeyAndModifiers,(Opaque)ShiftMask(1<<0)},
248{"Meta", NULLQUARK((XrmQuark) 0), KeyPress2, ParseKeyAndModifiers,(Opaque)NULL((void*)0)},
249{"KeyUp", NULLQUARK((XrmQuark) 0), KeyRelease3, ParseKeySym, NULL((void*)0)},
250{"KeyRelease", NULLQUARK((XrmQuark) 0), KeyRelease3, ParseKeySym, NULL((void*)0)},
251
252{"ButtonPress", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseTable,(Opaque)buttonNames},
253{"BtnDown", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseTable,(Opaque)buttonNames},
254{"Btn1Down", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseImmed,(Opaque)Button11},
255{"Btn2Down", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseImmed,(Opaque)Button22},
256{"Btn3Down", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseImmed,(Opaque)Button33},
257{"Btn4Down", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseImmed,(Opaque)Button44},
258{"Btn5Down", NULLQUARK((XrmQuark) 0), ButtonPress4, ParseImmed,(Opaque)Button55},
259
260/* Event Name, Quark, Event Type, Detail Parser, Closure */
261
262{"ButtonRelease", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseTable,(Opaque)buttonNames},
263{"BtnUp", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseTable,(Opaque)buttonNames},
264{"Btn1Up", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseImmed,(Opaque)Button11},
265{"Btn2Up", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseImmed,(Opaque)Button22},
266{"Btn3Up", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseImmed,(Opaque)Button33},
267{"Btn4Up", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseImmed,(Opaque)Button44},
268{"Btn5Up", NULLQUARK((XrmQuark) 0), ButtonRelease5, ParseImmed,(Opaque)Button55},
269
270{"MotionNotify", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseTable, (Opaque)motionDetails},
271{"PtrMoved", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseTable, (Opaque)motionDetails},
272{"Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseTable, (Opaque)motionDetails},
273{"MouseMoved", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseTable, (Opaque)motionDetails},
274{"BtnMotion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)AnyButtonMask(1L<<28)},
275{"Btn1Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)Button1Mask(1<<8)},
276{"Btn2Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)Button2Mask(1<<9)},
277{"Btn3Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)Button3Mask(1<<10)},
278{"Btn4Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)Button4Mask(1<<11)},
279{"Btn5Motion", NULLQUARK((XrmQuark) 0), MotionNotify6, ParseAddModifier, (Opaque)Button5Mask(1<<12)},
280
281{"EnterNotify", NULLQUARK((XrmQuark) 0), EnterNotify7, ParseTable,(Opaque)notifyModes},
282{"Enter", NULLQUARK((XrmQuark) 0), EnterNotify7, ParseTable,(Opaque)notifyModes},
283{"EnterWindow", NULLQUARK((XrmQuark) 0), EnterNotify7, ParseTable,(Opaque)notifyModes},
284
285{"LeaveNotify", NULLQUARK((XrmQuark) 0), LeaveNotify8, ParseTable,(Opaque)notifyModes},
286{"LeaveWindow", NULLQUARK((XrmQuark) 0), LeaveNotify8, ParseTable,(Opaque)notifyModes},
287{"Leave", NULLQUARK((XrmQuark) 0), LeaveNotify8, ParseTable,(Opaque)notifyModes},
288
289/* Event Name, Quark, Event Type, Detail Parser, Closure */
290
291{"FocusIn", NULLQUARK((XrmQuark) 0), FocusIn9, ParseTable,(Opaque)notifyModes},
292
293{"FocusOut", NULLQUARK((XrmQuark) 0), FocusOut10, ParseTable,(Opaque)notifyModes},
294
295{"KeymapNotify", NULLQUARK((XrmQuark) 0), KeymapNotify11, ParseNone, NULL((void*)0)},
296{"Keymap", NULLQUARK((XrmQuark) 0), KeymapNotify11, ParseNone, NULL((void*)0)},
297
298{"Expose", NULLQUARK((XrmQuark) 0), Expose12, ParseNone, NULL((void*)0)},
299
300{"GraphicsExpose", NULLQUARK((XrmQuark) 0), GraphicsExpose13, ParseNone, NULL((void*)0)},
301{"GrExp", NULLQUARK((XrmQuark) 0), GraphicsExpose13, ParseNone, NULL((void*)0)},
302
303{"NoExpose", NULLQUARK((XrmQuark) 0), NoExpose14, ParseNone, NULL((void*)0)},
304{"NoExp", NULLQUARK((XrmQuark) 0), NoExpose14, ParseNone, NULL((void*)0)},
305
306{"VisibilityNotify",NULLQUARK((XrmQuark) 0), VisibilityNotify15,ParseNone, NULL((void*)0)},
307{"Visible", NULLQUARK((XrmQuark) 0), VisibilityNotify15,ParseNone, NULL((void*)0)},
308
309{"CreateNotify", NULLQUARK((XrmQuark) 0), CreateNotify16, ParseNone, NULL((void*)0)},
310{"Create", NULLQUARK((XrmQuark) 0), CreateNotify16, ParseNone, NULL((void*)0)},
311
312/* Event Name, Quark, Event Type, Detail Parser, Closure */
313
314{"DestroyNotify", NULLQUARK((XrmQuark) 0), DestroyNotify17, ParseNone, NULL((void*)0)},
315{"Destroy", NULLQUARK((XrmQuark) 0), DestroyNotify17, ParseNone, NULL((void*)0)},
316
317{"UnmapNotify", NULLQUARK((XrmQuark) 0), UnmapNotify18, ParseNone, NULL((void*)0)},
318{"Unmap", NULLQUARK((XrmQuark) 0), UnmapNotify18, ParseNone, NULL((void*)0)},
319
320{"MapNotify", NULLQUARK((XrmQuark) 0), MapNotify19, ParseNone, NULL((void*)0)},
321{"Map", NULLQUARK((XrmQuark) 0), MapNotify19, ParseNone, NULL((void*)0)},
322
323{"MapRequest", NULLQUARK((XrmQuark) 0), MapRequest20, ParseNone, NULL((void*)0)},
324{"MapReq", NULLQUARK((XrmQuark) 0), MapRequest20, ParseNone, NULL((void*)0)},
325
326{"ReparentNotify", NULLQUARK((XrmQuark) 0), ReparentNotify21, ParseNone, NULL((void*)0)},
327{"Reparent", NULLQUARK((XrmQuark) 0), ReparentNotify21, ParseNone, NULL((void*)0)},
328
329{"ConfigureNotify", NULLQUARK((XrmQuark) 0), ConfigureNotify22, ParseNone, NULL((void*)0)},
330{"Configure", NULLQUARK((XrmQuark) 0), ConfigureNotify22, ParseNone, NULL((void*)0)},
331
332{"ConfigureRequest",NULLQUARK((XrmQuark) 0), ConfigureRequest23,ParseNone, NULL((void*)0)},
333{"ConfigureReq", NULLQUARK((XrmQuark) 0), ConfigureRequest23,ParseNone, NULL((void*)0)},
334
335/* Event Name, Quark, Event Type, Detail Parser, Closure */
336
337{"GravityNotify", NULLQUARK((XrmQuark) 0), GravityNotify24, ParseNone, NULL((void*)0)},
338{"Grav", NULLQUARK((XrmQuark) 0), GravityNotify24, ParseNone, NULL((void*)0)},
339
340{"ResizeRequest", NULLQUARK((XrmQuark) 0), ResizeRequest25, ParseNone, NULL((void*)0)},
341{"ResReq", NULLQUARK((XrmQuark) 0), ResizeRequest25, ParseNone, NULL((void*)0)},
342
343{"CirculateNotify", NULLQUARK((XrmQuark) 0), CirculateNotify26, ParseNone, NULL((void*)0)},
344{"Circ", NULLQUARK((XrmQuark) 0), CirculateNotify26, ParseNone, NULL((void*)0)},
345
346{"CirculateRequest",NULLQUARK((XrmQuark) 0), CirculateRequest27,ParseNone, NULL((void*)0)},
347{"CircReq", NULLQUARK((XrmQuark) 0), CirculateRequest27,ParseNone, NULL((void*)0)},
348
349{"PropertyNotify", NULLQUARK((XrmQuark) 0), PropertyNotify28, ParseAtom, NULL((void*)0)},
350{"Prop", NULLQUARK((XrmQuark) 0), PropertyNotify28, ParseAtom, NULL((void*)0)},
351
352{"SelectionClear", NULLQUARK((XrmQuark) 0), SelectionClear29, ParseAtom, NULL((void*)0)},
353{"SelClr", NULLQUARK((XrmQuark) 0), SelectionClear29, ParseAtom, NULL((void*)0)},
354
355{"SelectionRequest",NULLQUARK((XrmQuark) 0), SelectionRequest30,ParseAtom, NULL((void*)0)},
356{"SelReq", NULLQUARK((XrmQuark) 0), SelectionRequest30,ParseAtom, NULL((void*)0)},
357
358/* Event Name, Quark, Event Type, Detail Parser, Closure */
359
360{"SelectionNotify", NULLQUARK((XrmQuark) 0), SelectionNotify31, ParseAtom, NULL((void*)0)},
361{"Select", NULLQUARK((XrmQuark) 0), SelectionNotify31, ParseAtom, NULL((void*)0)},
362
363{"ColormapNotify", NULLQUARK((XrmQuark) 0), ColormapNotify32, ParseNone, NULL((void*)0)},
364{"Clrmap", NULLQUARK((XrmQuark) 0), ColormapNotify32, ParseNone, NULL((void*)0)},
365
366{"ClientMessage", NULLQUARK((XrmQuark) 0), ClientMessage33, ParseAtom, NULL((void*)0)},
367{"Message", NULLQUARK((XrmQuark) 0), ClientMessage33, ParseAtom, NULL((void*)0)},
368
369{"MappingNotify", NULLQUARK((XrmQuark) 0), MappingNotify34, ParseTable, (Opaque)mappingNotify},
370{"Mapping", NULLQUARK((XrmQuark) 0), MappingNotify34, ParseTable, (Opaque)mappingNotify},
371
372#ifdef DEBUG
373# ifdef notdef
374{"Timer", NULLQUARK((XrmQuark) 0), _XtTimerEventType,ParseNone, NULL((void*)0)},
375# endif /* notdef */
376{"EventTimer", NULLQUARK((XrmQuark) 0), _XtEventTimerEventType((TMLongCard)~0L),ParseNone,NULL((void*)0)},
377#endif /* DEBUG */
378
379/* Event Name, Quark, Event Type, Detail Parser, Closure */
380
381};
382
383#ifndef __UNIXOS2__
384#define IsNewline(str)((str) == '\n') ((str) == '\n')
385#else
386#define IsNewline(str)((str) == '\n') ((str) == '\n' || (str) == '\r')
387#endif
388
389#define ScanFor(str, ch)while ((*(str) != (ch)) && (*(str) != '\0') &&
!((*(str)) == '\n')) (str)++
\
390 while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))((*(str)) == '\n')) (str)++
391
392#define ScanNumeric(str)while ('0' <= *(str) && *(str) <= '9') (str)++ while ('0' <= *(str) && *(str) <= '9') (str)++
393
394#define ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
\
395 while (('A' <= *(str) && *(str) <= 'Z') || \
396 ('a' <= *(str) && *(str) <= 'z') || \
397 ('0' <= *(str) && *(str) <= '9')) (str)++
398
399#ifndef __UNIXOS2__
400#define ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++ \
401 while (*(str) == ' ' || *(str) == '\t') (str)++
402#else
403#define ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++ \
404 while (*(str) == ' ' || *(str) == '\t' || *(str) == '\r') (str)++
405#endif
406
407static Boolean initialized = FALSE0;
408static XrmQuark QMeta;
409static XrmQuark QCtrl;
410static XrmQuark QNone;
411static XrmQuark QAny;
412
413static void FreeEventSeq(
414 EventSeqPtr eventSeq)
415{
416 register EventSeqPtr evs = eventSeq;
417
418 while (evs != NULL((void*)0)) {
419 evs->state = (StatePtr) evs;
420 if (evs->next != NULL((void*)0)
421 && evs->next->state == (StatePtr) evs->next)
422 evs->next = NULL((void*)0);
423 evs = evs->next;
424 }
425
426 evs = eventSeq;
427 while (evs != NULL((void*)0)) {
428 register EventPtr event = evs;
429 evs = evs->next;
430 if (evs == event) evs = NULL((void*)0);
431 XtFree((char *)event);
432 }
433}
434
435static void CompileNameValueTable(
436 NameValueTable table)
437{
438 register int i;
439
440 for (i=0; table[i].name; i++)
441 table[i].signature = XrmPermStringToQuark(table[i].name);
442}
443
444static int OrderEvents(_Xconstconst void *a, _Xconstconst void *b)
445{
446 return ((((_Xconstconst EventKey *)a)->signature <
447 ((_Xconstconst EventKey *)b)->signature) ? -1 : 1);
448}
449
450static void Compile_XtEventTable(
451 EventKeys table,
452 Cardinal count)
453{
454 register int i;
455 register EventKeys entry = table;
456
457 for (i=count; --i >= 0; entry++)
458 entry->signature = XrmPermStringToQuark(entry->event);
459 qsort(table, count, sizeof(EventKey), OrderEvents);
460}
461
462static int OrderModifiers(_Xconstconst void *a, _Xconstconst void *b)
463{
464 return ((((_Xconstconst ModifierRec *)a)->signature <
465 ((_Xconstconst ModifierRec *)b)->signature) ? -1 : 1);
466}
467
468static void Compile_XtModifierTable(
469 ModifierKeys table,
470 Cardinal count)
471{
472 register int i;
473 register ModifierKeys entry = table;
474
475 for (i=count; --i >= 0; entry++)
476 entry->signature = XrmPermStringToQuark(entry->name);
477 qsort(table, count, sizeof(ModifierRec), OrderModifiers);
478}
479
480static String PanicModeRecovery(
481 String str)
482{
483 ScanFor(str,'\n')while ((*(str) != ('\n')) && (*(str) != '\0') &&
!((*(str)) == '\n')) (str)++
;
484 if (*str == '\n') str++;
485 return str;
486
487}
488
489
490static void Syntax(
491 String str0,String str1)
492{
493 Cardinal num_params = 2;
494 String params[2];
495
496 params[0] = str0;
497 params[1] = str1;
498 XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError,
499 "translation table syntax error: %s %s",params,&num_params);
500}
501
502
503
504static Cardinal LookupTMEventType(
505 String eventStr,
506 Boolean *error)
507{
508 register int i = 0, left, right;
509 register XrmQuark signature;
510 static int previous = 0;
511
512 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
513 if ((signature = StringToQuark(eventStr)XrmStringToQuark(eventStr)) == events[previous].signature) {
514 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
515 return (Cardinal) previous;
516 }
517
518 left = 0;
519 right = XtNumber(events)((Cardinal) (sizeof(events) / sizeof(events[0]))) - 1;
520 while (left <= right) {
521 i = (left + right) >> 1;
522 if (signature < events[i].signature)
523 right = i - 1;
524 else if (signature > events[i].signature)
525 left = i + 1;
526 else {
527 previous = i;
528 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
529 return (Cardinal) i;
530 }
531 }
532
533 Syntax("Unknown event type : ",eventStr);
534 *error = TRUE1;
535 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
536 return (Cardinal) i;
537}
538
539static void StoreLateBindings(
540 KeySym keysymL,
541 Boolean notL,
542 KeySym keysymR,
543 Boolean notR,
544 LateBindingsPtr* lateBindings)
545{
546 LateBindingsPtr temp;
547 Boolean pair = FALSE0;
548 unsigned long count,number;
549 if (lateBindings != NULL((void*)0)){
550 temp = *lateBindings;
551 if (temp != NULL((void*)0)) {
552 for (count = 0; temp[count].keysym; count++){/*EMPTY*/}
553 }
554 else count = 0;
555 if (! keysymR){
556 number = 1;pair = FALSE0;
557 } else{
558 number = 2;pair = TRUE1;
559 }
560
561 temp = (LateBindingsPtr)XtRealloc((char *)temp,
562 (unsigned)((count+number+1) * sizeof(LateBindings)) );
563 *lateBindings = temp;
564 temp[count].knot = notL;
565 temp[count].pair = pair;
566 if (count == 0)
567 temp[count].ref_count = 1;
568 temp[count++].keysym = keysymL;
569 if (keysymR){
570 temp[count].knot = notR;
571 temp[count].pair = FALSE0;
572 temp[count].ref_count = 0;
573 temp[count++].keysym = keysymR;
574 }
575 temp[count].knot = temp[count].pair = FALSE0;
576 temp[count].ref_count = 0;
577 temp[count].keysym = 0;
578 }
579}
580
581static void _XtParseKeysymMod(
582 String name,
583 LateBindingsPtr* lateBindings,
584 Boolean notFlag,
585 Value *valueP,
586 Boolean *error)
587{
588 KeySym keySym;
589 keySym = StringToKeySym(name, error);
590 *valueP = 0;
591 if (keySym != NoSymbol0L) {
592 StoreLateBindings(keySym,notFlag,(KeySym) NULL((void*)0),FALSE0,lateBindings);
593 }
594}
595
596static Boolean _XtLookupModifier(
597 XrmQuark signature,
598 LateBindingsPtr* lateBindings,
599 Boolean notFlag,
600 Value *valueP,
601 Boolint constMask)
602{
603 register int i, left, right;
604 static int previous = 0;
605
606 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
607 if (signature == modifiers[previous].signature) {
608 if (constMask) *valueP = modifiers[previous].value;
609 else /* if (modifiers[previous].modifierParseProc) always true */
610 (*modifiers[previous].modifierParseProc)
611 (modifiers[previous].value, lateBindings, notFlag, valueP);
612 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
613 return TRUE1;
614 }
615
616 left = 0;
617 right = XtNumber(modifiers)((Cardinal) (sizeof(modifiers) / sizeof(modifiers[0]))) - 1;
618 while (left <= right) {
619 i = (left + right) >> 1;
620 if (signature < modifiers[i].signature)
621 right = i - 1;
622 else if (signature > modifiers[i].signature)
623 left = i + 1;
624 else {
625 previous = i;
626 if (constMask) *valueP = modifiers[i].value;
627 else /* if (modifiers[i].modifierParseProc) always true */
628 (*modifiers[i].modifierParseProc)
629 (modifiers[i].value, lateBindings, notFlag, valueP);
630 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
631 return TRUE1;
632 }
633 }
634 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
635 return FALSE0;
636}
637
638
639static String ScanIdent(
640 register String str)
641{
642 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
643 while (
644 ('A' <= *str && *str <= 'Z')
645 || ('a' <= *str && *str <= 'z')
646 || ('0' <= *str && *str <= '9')
647 || (*str == '-')
648 || (*str == '_')
649 || (*str == '$')
650 ) str++;
651 return str;
652}
653
654static String FetchModifierToken(
655 String str,
656 XrmQuark *token_return)
657{
658 String start = str;
659
660 if (*str == '$') {
1
Taking false branch
661 *token_return = QMeta;
662 str++;
663 return str;
664 }
665 if (*str == '^') {
2
Taking false branch
666 *token_return = QCtrl;
667 str++;
668 return str;
669 }
670 str = ScanIdent(str);
671 if (start != str) {
3
Taking true branch
672 char modStrbuf[100];
673 char* modStr;
674
675 modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf)(((size_t)(str - start + 1)) <= sizeof(modStrbuf) ? (XtPointer
)(modStrbuf) : XtMalloc((unsigned)((size_t)(str - start + 1))
))
;
676 if (modStr == NULL((void*)0)) _XtAllocError (NULL((void*)0));
4
Assuming 'modStr' is equal to null
5
Taking true branch
677 (void) memmove(modStr, start, str-start);
6
Null pointer passed as an argument to a 'nonnull' parameter
678 modStr[str-start] = '\0';
679 *token_return = XrmStringToQuark(modStr);
680 XtStackFree (modStr, modStrbuf){ if ((modStr) != ((XtPointer)(modStrbuf))) XtFree(modStr); };
681 return str;
682 }
683 return str;
684}
685
686static String ParseModifiers(
687 register String str,
688 EventPtr event,
689 Boolean* error)
690{
691 register String start;
692 Boolean notFlag, exclusive, keysymAsMod;
693 Value maskBit;
694 XrmQuark Qmod;
695
696 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
697 start = str;
698 str = FetchModifierToken(str, &Qmod);
699 exclusive = FALSE0;
700 if (start != str) {
701 if (Qmod == QNone) {
702 event->event.modifierMask = ~0;
703 event->event.modifiers = 0;
704 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
705 return str;
706 } else if (Qmod == QAny) { /*backward compatability*/
707 event->event.modifierMask = 0;
708 event->event.modifiers = AnyModifier(1<<15);
709 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
710 return str;
711 }
712 str = start; /*if plain modifier, reset to beginning */
713 }
714 else while (*str == '!' || *str == ':') {
715 if (*str == '!') {
716 exclusive = TRUE1;
717 str++;
718 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
719 }
720 if (*str == ':') {
721 event->event.standard = TRUE1;
722 str++;
723 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
724 }
725 }
726
727 while (*str != '<') {
728 if (*str == '~') {
729 notFlag = TRUE1;
730 str++;
731 } else
732 notFlag = FALSE0;
733 if (*str == '@') {
734 keysymAsMod = TRUE1;
735 str++;
736 }
737 else keysymAsMod = FALSE0;
738 start = str;
739 str = FetchModifierToken(str, &Qmod);
740 if (start == str) {
741 Syntax("Modifier or '<' expected","");
742 *error = TRUE1;
743 return PanicModeRecovery(str);
744 }
745 if (keysymAsMod) {
746 _XtParseKeysymMod(XrmQuarkToString(Qmod),
747 &event->event.lateModifiers,
748 notFlag,&maskBit, error);
749 if (*error)
750 return PanicModeRecovery(str);
751
752 } else
753 if (!_XtLookupModifier(Qmod, &event->event.lateModifiers,
754 notFlag, &maskBit, FALSE0)) {
755 Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod));
756 *error = TRUE1;
757 return PanicModeRecovery(str);
758 }
759 event->event.modifierMask |= maskBit;
760 if (notFlag) event->event.modifiers &= ~maskBit;
761 else event->event.modifiers |= maskBit;
762 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
763 }
764 if (exclusive) event->event.modifierMask = ~0;
765 return str;
766}
767
768static String ParseXtEventType(
769 register String str,
770 EventPtr event,
771 Cardinal *tmEventP,
772 Boolean* error)
773{
774 String start = str;
775 char eventTypeStrbuf[100];
776 char* eventTypeStr;
777
778 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
779 eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf)(((size_t)(str - start + 1)) <= sizeof(eventTypeStrbuf) ? (
XtPointer)(eventTypeStrbuf) : XtMalloc((unsigned)((size_t)(str
- start + 1))))
;
780 if (eventTypeStr == NULL((void*)0)) _XtAllocError (NULL((void*)0));
781 (void) memmove(eventTypeStr, start, str-start);
782 eventTypeStr[str-start] = '\0';
783 *tmEventP = LookupTMEventType(eventTypeStr,error);
784 XtStackFree (eventTypeStr, eventTypeStrbuf){ if ((eventTypeStr) != ((XtPointer)(eventTypeStrbuf))) XtFree
(eventTypeStr); }
;
785 if (*error)
786 return PanicModeRecovery(str);
787 event->event.eventType = events[*tmEventP].eventType;
788 return str;
789}
790
791static unsigned long StrToHex(
792 String str)
793{
794 register char c;
795 register unsigned long val = 0;
796
797 while ((c = *str)) {
798 if ('0' <= c && c <= '9') val = val*16+c-'0';
799 else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10;
800 else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10;
801 else return 0;
802 str++;
803 }
804
805 return val;
806}
807
808static unsigned long StrToOct(
809 String str)
810{
811 register char c;
812 register unsigned long val = 0;
813
814 while ((c = *str)) {
815 if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0;
816 str++;
817 }
818
819 return val;
820}
821
822static unsigned long StrToNum(
823 String str)
824{
825 register char c;
826 register unsigned long val = 0;
827
828 if (*str == '0') {
829 str++;
830 if (*str == 'x' || *str == 'X') return StrToHex(++str);
831 else return StrToOct(str);
832 }
833
834 while ((c = *str)) {
835 if ('0' <= c && c <= '9') val = val*10+c-'0';
836 else return 0;
837 str++;
838 }
839
840 return val;
841}
842
843static KeySym StringToKeySym(
844 String str,
845 Boolean *error)
846{
847 KeySym k;
848
849 if (str == NULL((void*)0) || *str == '\0') return (KeySym) 0;
850
851#ifndef NOTASCII
852 /* special case single character ASCII, for speed */
853 if (*(str+1) == '\0') {
854 if (' ' <= *str && *str <= '~') return XK_space0x0020 + (*str - ' ');
855 }
856#endif
857
858 if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str);
859 k = XStringToKeysym(str);
860 if (k != NoSymbol0L) return k;
861
862#ifdef NOTASCII
863 /* fall-back case to preserve backwards compatibility; no-one
864 * should be relying upon this!
865 */
866 if (*(str+1) == '\0') return (KeySym) *str;
867#endif
868
869 Syntax("Unknown keysym name: ", str);
870 *error = TRUE1;
871 return NoSymbol0L;
872}
873/* ARGSUSED */
874static void ParseModImmed(
875 Value value,
876 LateBindingsPtr* lateBindings,
877 Boolean notFlag,
878 Value* valueP)
879{
880 *valueP = value;
881}
882
883 /* is only valid with keysyms that have an _L and _R in their name;
884 * and ignores keysym lookup errors (i.e. assumes only valid keysyms)
885 */
886static void ParseModSym(
887 Value value,
888 LateBindingsPtr* lateBindings,
889 Boolean notFlag,
890 Value* valueP)
891{
892 register KeySym keysymL = (KeySym)value;
893 register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */
894 StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings);
895 *valueP = 0;
896}
897
898#ifdef sparc
899/*
900 * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that
901 * causes the value of the most recently used variable to be returned instead
902 * of the value passed in.
903 */
904static String stupid_optimizer_kludge;
905#define BROKEN_OPTIMIZER_HACK(val)val stupid_optimizer_kludge = (val)
906#else
907#define BROKEN_OPTIMIZER_HACK(val)val val
908#endif
909
910/* ARGSUSED */
911static String ParseImmed(
912 register String str,
913 register Opaque closure,
914 register EventPtr event,
915 Boolean* error)
916{
917 event->event.eventCode = (unsigned long)closure;
918 event->event.eventCodeMask = ~0UL;
919
920 return BROKEN_OPTIMIZER_HACK(str)str;
921}
922
923/* ARGSUSED */
924static String ParseAddModifier(
925 register String str,
926 register Opaque closure,
927 register EventPtr event,
928 Boolean* error)
929{
930 register unsigned long modval = (unsigned long)closure;
931 event->event.modifiers |= modval;
932 if (modval != AnyButtonMask(1L<<28)) /* AnyButtonMask is don't-care mask */
933 event->event.modifierMask |= modval;
934
935 return BROKEN_OPTIMIZER_HACK(str)str;
936}
937
938
939static String ParseKeyAndModifiers(
940 String str,
941 Opaque closure,
942 EventPtr event,
943 Boolean* error)
944{
945 str = ParseKeySym(str, closure, event,error);
946 if ((unsigned long) closure == 0) {
947 Value metaMask; /* unused */
948 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE0,
949 &metaMask, FALSE0);
950 } else {
951 event->event.modifiers |= (unsigned long) closure;
952 event->event.modifierMask |= (unsigned long) closure;
953 }
954 return str;
955}
956
957/*ARGSUSED*/
958static String ParseKeySym(
959 register String str,
960 Opaque closure,
961 EventPtr event,
962 Boolean* error)
963{
964 char *start;
965 char keySymNamebuf[100];
966 char* keySymName;
967
968 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
969
970 if (*str == '\\') {
971 keySymName = keySymNamebuf;
972 str++;
973 keySymName[0] = *str;
974 if (*str != '\0' && !IsNewline(*str)((*str) == '\n')) str++;
975 keySymName[1] = '\0';
976 event->event.eventCode = StringToKeySym(keySymName, error);
977 event->event.eventCodeMask = ~0L;
978 } else if (*str == ',' || *str == ':' ||
979 /* allow leftparen to be single char symbol,
980 * for backwards compatibility
981 */
982 (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) {
983 keySymName = keySymNamebuf; /* just so we can stackfree it later */
984 /* no detail */
985 event->event.eventCode = 0L;
986 event->event.eventCodeMask = 0L;
987 } else {
988 start = str;
989 while (
990 *str != ','
991 && *str != ':'
992 && *str != ' '
993 && *str != '\t'
994 && !IsNewline(*str)((*str) == '\n')
995 && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9')
996 && *str != '\0') str++;
997 keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf)(((size_t)(str - start + 1)) <= sizeof(keySymNamebuf) ? (XtPointer
)(keySymNamebuf) : XtMalloc((unsigned)((size_t)(str - start +
1))))
;
998 (void) memmove(keySymName, start, str-start);
999 keySymName[str-start] = '\0';
1000 event->event.eventCode = StringToKeySym(keySymName, error);
1001 event->event.eventCodeMask = ~0L;
1002 }
1003 if (*error) {
1004 /* We never get here when keySymName hasn't been allocated */
1005 if (keySymName[0] == '<') {
1006 /* special case for common error */
1007 XtWarningMsg(XtNtranslationParseError, "missingComma",
1008 XtCXtToolkitError,
1009 "... possibly due to missing ',' in event sequence.",
1010 (String*)NULL((void*)0), (Cardinal*)NULL((void*)0));
1011 }
1012 XtStackFree (keySymName, keySymNamebuf){ if ((keySymName) != ((XtPointer)(keySymNamebuf))) XtFree(keySymName
); }
;
1013 return PanicModeRecovery(str);
1014 }
1015 if (event->event.standard)
1016 event->event.matchEvent = _XtMatchUsingStandardMods;
1017 else
1018 event->event.matchEvent = _XtMatchUsingDontCareMods;
1019
1020 XtStackFree (keySymName, keySymNamebuf){ if ((keySymName) != ((XtPointer)(keySymNamebuf))) XtFree(keySymName
); }
;
1021
1022 return str;
1023}
1024
1025static String ParseTable(
1026 register String str,
1027 Opaque closure,
1028 EventPtr event,
1029 Boolean* error)
1030{
1031 register String start = str;
1032 register XrmQuark signature;
1033 NameValueTable table = (NameValueTable) closure;
1034 char tableSymName[100];
1035
1036 event->event.eventCode = 0L;
1037 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
1038 if (str == start) {event->event.eventCodeMask = 0L; return str; }
1039 if (str-start >= 99) {
1040 Syntax("Invalid Detail Type (string is too long).", "");
1041 *error = TRUE1;
1042 return str;
1043 }
1044 (void) memmove(tableSymName, start, str-start);
1045 tableSymName[str-start] = '\0';
1046 signature = StringToQuark(tableSymName)XrmStringToQuark(tableSymName);
1047 for (; table->signature != NULLQUARK((XrmQuark) 0); table++)
1048 if (table->signature == signature) {
1049 event->event.eventCode = table->value;
1050 event->event.eventCodeMask = ~0L;
1051 return str;
1052 }
1053
1054 Syntax("Unknown Detail Type: ", tableSymName);
1055 *error = TRUE1;
1056 return PanicModeRecovery(str);
1057}
1058
1059/*ARGSUSED*/
1060static String ParseNone(
1061 String str,
1062 Opaque closure,
1063 EventPtr event,
1064 Boolean* error)
1065{
1066 event->event.eventCode = 0;
1067 event->event.eventCodeMask = 0;
1068
1069 return BROKEN_OPTIMIZER_HACK(str)str;
1070}
1071
1072/*ARGSUSED*/
1073static String ParseAtom(
1074 String str,
1075 Opaque closure,
1076 EventPtr event,
1077 Boolean* error)
1078{
1079 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1080
1081 if (*str == ',' || *str == ':') {
1082 /* no detail */
1083 event->event.eventCode = 0L;
1084 event->event.eventCodeMask = 0L;
1085 } else {
1086 char *start, atomName[1000];
1087 start = str;
1088 while (
1089 *str != ','
1090 && *str != ':'
1091 && *str != ' '
1092 && *str != '\t'
1093 && !IsNewline(*str)((*str) == '\n')
1094 && *str != '\0') str++;
1095 if (str-start >= 999) {
1096 Syntax( "Atom name must be less than 1000 characters long.", "" );
1097 *error = TRUE1;
1098 return str;
1099 }
1100 (void) memmove(atomName, start, str-start);
1101 atomName[str-start] = '\0';
1102 event->event.eventCode = XrmStringToQuark(atomName);
1103 event->event.matchEvent = _XtMatchAtom;
1104 }
1105 return str;
1106}
1107
1108static ModifierMask buttonModifierMasks[] = {
1109 0, Button1Mask(1<<8), Button2Mask(1<<9), Button3Mask(1<<10), Button4Mask(1<<11), Button5Mask(1<<12)
1110};
1111static String ParseRepeat(String, int *, Boolean *, Boolean *);
1112
1113static String ParseEvent(
1114 register String str,
1115 EventPtr event,
1116 int* reps,
1117 Boolean* plus,
1118 Boolean* error)
1119{
1120 Cardinal tmEvent;
1121
1122 str = ParseModifiers(str, event,error);
1123 if (*error) return str;
1124 if (*str != '<') {
1125 Syntax("Missing '<' while parsing event type.","");
1126 *error = TRUE1;
1127 return PanicModeRecovery(str);
1128 }
1129 else str++;
1130 str = ParseXtEventType(str, event, &tmEvent,error);
1131 if (*error) return str;
1132 if (*str != '>'){
1133 Syntax("Missing '>' while parsing event type","");
1134 *error = TRUE1;
1135 return PanicModeRecovery(str);
1136 }
1137 else str++;
1138 if (*str == '(') {
1139 str = ParseRepeat(str, reps, plus, error);
1140 if (*error) return str;
1141 }
1142 str = (*(events[tmEvent].parseDetail))(
1143 str, events[tmEvent].closure, event,error);
1144 if (*error) return str;
1145
1146/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t.
1147 * modifiers in grabs.
1148 */
1149 if ((event->event.eventType == ButtonRelease5)
1150 && (event->event.modifiers | event->event.modifierMask) /* any */
1151 && (event->event.modifiers != AnyModifier(1<<15)))
1152 {
1153 event->event.modifiers
1154 |= buttonModifierMasks[event->event.eventCode];
1155 /* the button that is going up will always be in the modifiers... */
1156 }
1157
1158 return str;
1159}
1160
1161static String ParseQuotedStringEvent(
1162 register String str,
1163 register EventPtr event,
1164 Boolean *error)
1165{
1166 Value metaMask;
1167 char s[2];
1168
1169 if (*str=='^') {
1170 str++;
1171 event->event.modifiers = ControlMask(1<<2);
1172 } else if (*str == '$') {
1173 str++;
1174 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE0,
1175 &metaMask, FALSE0);
1176 }
1177 if (*str == '\\')
1178 str++;
1179 s[0] = *str;
1180 s[1] = '\0';
1181 if (*str != '\0' && !IsNewline(*str)((*str) == '\n')) str++;
1182 event->event.eventType = KeyPress2;
1183 event->event.eventCode = StringToKeySym(s, error);
1184 if (*error) return PanicModeRecovery(str);
1185 event->event.eventCodeMask = ~0L;
1186 event->event.matchEvent = _XtMatchUsingStandardMods;
1187 event->event.standard = TRUE1;
1188
1189 return str;
1190}
1191
1192
1193static EventSeqRec timerEventRec = {
1194 {0, 0, NULL((void*)0), _XtEventTimerEventType((TMLongCard)~0L), 0L, 0L, NULL((void*)0), False0},
1195 /* (StatePtr) -1 */ NULL((void*)0),
1196 NULL((void*)0),
1197 NULL((void*)0)
1198};
1199
1200static void RepeatDown(
1201 EventPtr *eventP,
1202 int reps,
1203 ActionPtr **actionsP)
1204{
1205 EventRec upEventRec;
1206 register EventPtr event, downEvent;
1207 EventPtr upEvent = &upEventRec;
1208 register int i;
1209
1210 downEvent = event = *eventP;
1211 *upEvent = *downEvent;
1212 upEvent->event.eventType = ((event->event.eventType == ButtonPress4) ?
1213 ButtonRelease5 : KeyRelease3);
1214 if ((upEvent->event.eventType == ButtonRelease5)
1215 && (upEvent->event.modifiers != AnyModifier(1<<15))
1216 && (upEvent->event.modifiers | upEvent->event.modifierMask))
1217 upEvent->event.modifiers
1218 |= buttonModifierMasks[event->event.eventCode];
1219
1220 if (event->event.lateModifiers)
1221 event->event.lateModifiers->ref_count += (reps - 1) * 2;
1222
1223 for (i=1; i<reps; i++) {
1224
1225 /* up */
1226 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1227 event = event->next;
1228 *event = *upEvent;
1229
1230 /* timer */
1231 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1232 event = event->next;
1233 *event = timerEventRec;
1234
1235 /* down */
1236 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1237 event = event->next;
1238 *event = *downEvent;
1239
1240 }
1241
1242 event->next = NULL((void*)0);
1243 *eventP = event;
1244 *actionsP = &event->actions;
1245}
1246
1247static void RepeatDownPlus(
1248 EventPtr *eventP,
1249 int reps,
1250 ActionPtr **actionsP)
1251{
1252 EventRec upEventRec;
1253 register EventPtr event, downEvent, lastDownEvent = NULL((void*)0);
1254 EventPtr upEvent = &upEventRec;
1255 register int i;
1256
1257 downEvent = event = *eventP;
1258 *upEvent = *downEvent;
1259 upEvent->event.eventType = ((event->event.eventType == ButtonPress4) ?
1260 ButtonRelease5 : KeyRelease3);
1261 if ((upEvent->event.eventType == ButtonRelease5)
1262 && (upEvent->event.modifiers != AnyModifier(1<<15))
1263 && (upEvent->event.modifiers | upEvent->event.modifierMask))
1264 upEvent->event.modifiers
1265 |= buttonModifierMasks[event->event.eventCode];
1266
1267 if (event->event.lateModifiers)
1268 event->event.lateModifiers->ref_count += reps * 2 - 1;
1269
1270 for (i=0; i<reps; i++) {
1271
1272 if (i > 0) {
1273 /* down */
1274 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1275 event = event->next;
1276 *event = *downEvent;
1277 }
1278 lastDownEvent = event;
1279
1280 /* up */
1281 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1282 event = event->next;
1283 *event = *upEvent;
1284
1285 /* timer */
1286 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1287 event = event->next;
1288 *event = timerEventRec;
1289
1290 }
1291
1292 event->next = lastDownEvent;
1293 *eventP = event;
1294 *actionsP = &lastDownEvent->actions;
1295}
1296
1297static void RepeatUp(
1298 EventPtr *eventP,
1299 int reps,
1300 ActionPtr **actionsP)
1301{
1302 EventRec upEventRec;
1303 register EventPtr event, downEvent;
1304 EventPtr upEvent = &upEventRec;
1305 register int i;
1306
1307 /* the event currently sitting in *eventP is an "up" event */
1308 /* we want to make it a "down" event followed by an "up" event, */
1309 /* so that sequence matching on the "state" side works correctly. */
1310
1311 downEvent = event = *eventP;
1312 *upEvent = *downEvent;
1313 downEvent->event.eventType = ((event->event.eventType == ButtonRelease5) ?
1314 ButtonPress4 : KeyPress2);
1315 if ((downEvent->event.eventType == ButtonPress4)
1316 && (downEvent->event.modifiers != AnyModifier(1<<15))
1317 && (downEvent->event.modifiers | downEvent->event.modifierMask))
1318 downEvent->event.modifiers
1319 &= ~buttonModifierMasks[event->event.eventCode];
1320
1321 if (event->event.lateModifiers)
1322 event->event.lateModifiers->ref_count += reps * 2 - 1;
1323
1324 /* up */
1325 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1326 event = event->next;
1327 *event = *upEvent;
1328
1329 for (i=1; i<reps; i++) {
1330
1331 /* timer */
1332 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1333 event = event->next;
1334 *event = timerEventRec;
1335
1336 /* down */
1337 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1338 event = event->next;
1339 *event = *downEvent;
1340
1341 /* up */
1342 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1343 event = event->next;
1344 *event = *upEvent;
1345
1346 }
1347
1348 event->next = NULL((void*)0);
1349 *eventP = event;
1350 *actionsP = &event->actions;
1351}
1352
1353static void RepeatUpPlus(
1354 EventPtr *eventP,
1355 int reps,
1356 ActionPtr **actionsP)
1357{
1358 EventRec upEventRec;
1359 register EventPtr event, downEvent, lastUpEvent = NULL((void*)0);
1360 EventPtr upEvent = &upEventRec;
1361 register int i;
1362
1363 /* the event currently sitting in *eventP is an "up" event */
1364 /* we want to make it a "down" event followed by an "up" event, */
1365 /* so that sequence matching on the "state" side works correctly. */
1366
1367 downEvent = event = *eventP;
1368 *upEvent = *downEvent;
1369 downEvent->event.eventType = ((event->event.eventType == ButtonRelease5) ?
1370 ButtonPress4 : KeyPress2);
1371 if ((downEvent->event.eventType == ButtonPress4)
1372 && (downEvent->event.modifiers != AnyModifier(1<<15))
1373 && (downEvent->event.modifiers | downEvent->event.modifierMask))
1374 downEvent->event.modifiers
1375 &= ~buttonModifierMasks[event->event.eventCode];
1376
1377 if (event->event.lateModifiers)
1378 event->event.lateModifiers->ref_count += reps * 2;
1379
1380 for (i=0; i<reps; i++) {
1381
1382 /* up */
1383 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1384 lastUpEvent = event = event->next;
1385 *event = *upEvent;
1386
1387 /* timer */
1388 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1389 event = event->next;
1390 *event = timerEventRec;
1391
1392 /* down */
1393 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1394 event = event->next;
1395 *event = *downEvent;
1396
1397 }
1398
1399 event->next = lastUpEvent;
1400 *eventP = event;
1401 *actionsP = &lastUpEvent->actions;
1402}
1403
1404static void RepeatOther(
1405 EventPtr *eventP,
1406 int reps,
1407 ActionPtr **actionsP)
1408{
1409 register EventPtr event, tempEvent;
1410 register int i;
1411
1412 tempEvent = event = *eventP;
1413
1414 if (event->event.lateModifiers)
1415 event->event.lateModifiers->ref_count += reps - 1;
1416
1417 for (i=1; i<reps; i++) {
1418 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1419 event = event->next;
1420 *event = *tempEvent;
1421 }
1422
1423 *eventP = event;
1424 *actionsP = &event->actions;
1425}
1426
1427static void RepeatOtherPlus(
1428 EventPtr *eventP,
1429 int reps,
1430 ActionPtr **actionsP)
1431{
1432 register EventPtr event, tempEvent;
1433 register int i;
1434
1435 tempEvent = event = *eventP;
1436
1437 if (event->event.lateModifiers)
1438 event->event.lateModifiers->ref_count += reps - 1;
1439
1440 for (i=1; i<reps; i++) {
1441 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1442 event = event->next;
1443 *event = *tempEvent;
1444 }
1445
1446 event->next = event;
1447 *eventP = event;
1448 *actionsP = &event->actions;
1449}
1450
1451static void RepeatEvent(
1452 EventPtr *eventP,
1453 int reps,
1454 Boolean plus,
1455 ActionPtr **actionsP)
1456{
1457 switch ((*eventP)->event.eventType) {
1458
1459 case ButtonPress4:
1460 case KeyPress2:
1461 if (plus) RepeatDownPlus(eventP, reps, actionsP);
1462 else RepeatDown(eventP, reps, actionsP);
1463 break;
1464
1465 case ButtonRelease5:
1466 case KeyRelease3:
1467 if (plus) RepeatUpPlus(eventP, reps, actionsP);
1468 else RepeatUp(eventP, reps, actionsP);
1469 break;
1470
1471 default:
1472 if (plus) RepeatOtherPlus(eventP, reps, actionsP);
1473 else RepeatOther(eventP, reps, actionsP);
1474 }
1475}
1476
1477static String ParseRepeat(
1478 register String str,
1479 int *reps,
1480 Boolean *plus, Boolean *error)
1481{
1482
1483 /*** Parse the repetitions, for double click etc... ***/
1484 if (*str != '(' || !(isdigit(str[1])((*__ctype_b_loc ())[(int) ((str[1]))] & (unsigned short int
) _ISdigit)
|| str[1] == '+' || str[1] == ')'))
1485 return str;
1486 str++;
1487 if (isdigit(*str)((*__ctype_b_loc ())[(int) ((*str))] & (unsigned short int
) _ISdigit)
) {
1488 String start = str;
1489 char repStr[7];
1490 size_t len;
1491
1492 ScanNumeric(str)while ('0' <= *(str) && *(str) <= '9') (str)++;
1493 len = (str - start);
1494 if (len < sizeof repStr) {
1495 (void) memmove(repStr, start, len);
1496 repStr[len] = '\0';
1497 *reps = StrToNum(repStr);
1498 } else {
1499 Syntax("Repeat count too large.", "");
1500 *error = TRUE1;
1501 return str;
1502 }
1503 }
1504 if (*reps == 0) {
1505 Syntax("Missing repeat count.","");
1506 *error = True1;
1507 return str;
1508 }
1509
1510 if (*str == '+') {
1511 *plus = TRUE1;
1512 str++;
1513 }
1514 if (*str == ')')
1515 str++;
1516 else {
1517 Syntax("Missing ')'.","");
1518 *error = TRUE1;
1519 }
1520
1521 return str;
1522}
1523
1524/***********************************************************************
1525 * ParseEventSeq
1526 * Parses the left hand side of a translation table production
1527 * up to, and consuming the ":".
1528 * Takes a pointer to a char* (where to start parsing) and returns an
1529 * event seq (in a passed in variable), having updated the String
1530 **********************************************************************/
1531
1532static String ParseEventSeq(
1533 register String str,
1534 EventSeqPtr *eventSeqP,
1535 ActionPtr **actionsP,
1536 Boolean *error)
1537{
1538 EventSeqPtr *nextEvent = eventSeqP;
1539
1540 *eventSeqP = NULL((void*)0);
1541
1542 while ( *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1543 static Event nullEvent =
1544 {0, 0,NULL((void*)0), 0, 0L, 0L,_XtRegularMatch,FALSE0};
1545 EventPtr event;
1546
1547 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1548
1549 if (*str == '"') {
1550 str++;
1551 while (*str != '"' && *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1552 event = XtNew(EventRec)((EventRec *) XtMalloc((unsigned) sizeof(EventRec)));
1553 event->event = nullEvent;
1554 event->state = /* (StatePtr) -1 */ NULL((void*)0);
1555 event->next = NULL((void*)0);
1556 event->actions = NULL((void*)0);
1557 str = ParseQuotedStringEvent(str, event,error);
1558 if (*error) {
1559 XtWarningMsg(XtNtranslationParseError, "nonLatin1",
1560 XtCXtToolkitError,
1561 "... probably due to non-Latin1 character in quoted string",
1562 (String*)NULL((void*)0), (Cardinal*)NULL((void*)0));
1563 return PanicModeRecovery(str);
1564 }
1565 *nextEvent = event;
1566 *actionsP = &event->actions;
1567 nextEvent = &event->next;
1568 }
1569 if (*str != '"') {
1570 Syntax("Missing '\"'.","");
1571 *error = TRUE1;
1572 return PanicModeRecovery(str);
1573 }
1574 else str++;
1575 } else {
1576 int reps = 0;
1577 Boolean plus = FALSE0;
1578
1579 event = XtNew(EventRec)((EventRec *) XtMalloc((unsigned) sizeof(EventRec)));
1580 event->event = nullEvent;
1581 event->state = /* (StatePtr) -1 */ NULL((void*)0);
1582 event->next = NULL((void*)0);
1583 event->actions = NULL((void*)0);
1584
1585 str = ParseEvent(str, event, &reps, &plus, error);
1586 if (*error) return str;
1587 *nextEvent = event;
1588 *actionsP = &event->actions;
1589 if (reps > 1 || plus)
1590 RepeatEvent(&event, reps, plus, actionsP);
1591 nextEvent = &event->next;
1592 }
1593 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1594 if (*str == ':') break;
1595 else {
1596 if (*str != ',') {
1597 Syntax("',' or ':' expected while parsing event sequence.","");
1598 *error = TRUE1;
1599 return PanicModeRecovery(str);
1600 } else str++;
1601 }
1602 }
1603
1604 if (*str != ':') {
1605 Syntax("Missing ':'after event sequence.","");
1606 *error = TRUE1;
1607 return PanicModeRecovery(str);
1608 } else str++;
1609
1610 return str;
1611}
1612
1613
1614static String ParseActionProc(
1615 register String str,
1616 XrmQuark *actionProcNameP,
1617 Boolean *error)
1618{
1619 register String start = str;
1620 char procName[200];
1621
1622 str = ScanIdent(str);
1623 if (str-start >= 199) {
1624 Syntax("Action procedure name is longer than 199 chars","");
1625 *error = TRUE1;
1626 return str;
1627 }
1628 (void) memmove(procName, start, str-start);
1629 procName[str-start] = '\0';
1630 *actionProcNameP = XrmStringToQuark( procName );
1631 return str;
1632}
1633
1634
1635static String ParseString(
1636 register String str,
1637 String *strP)
1638{
1639 register String start;
1640
1641 if (*str == '"') {
1642 register unsigned prev_len, len;
1643 str++;
1644 start = str;
1645 *strP = NULL((void*)0);
1646 prev_len = 0;
1647
1648 while (*str != '"' && *str != '\0') {
1649 /* \" produces double quote embedded in a quoted parameter
1650 * \\" produces backslash as last character of a quoted parameter
1651 */
1652 if (*str == '\\' &&
1653 (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) {
1654 len = prev_len + (str-start+2);
1655 *strP = XtRealloc(*strP, len);
1656 (void) memmove(*strP + prev_len, start, str-start);
1657 prev_len = len-1;
1658 str++;
1659 (*strP)[prev_len-1] = *str;
1660 (*strP)[prev_len] = '\0';
1661 start = str+1;
1662 }
1663 str++;
1664 }
1665 len = prev_len + (str-start+1);
1666 *strP = XtRealloc(*strP, len);
1667 (void) memmove( *strP + prev_len, start, str-start);
1668 (*strP)[len-1] = '\0';
1669 if (*str == '"') str++; else
1670 XtWarningMsg(XtNtranslationParseError,"parseString",
1671 XtCXtToolkitError,"Missing '\"'.",
1672 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1673 } else {
1674 /* scan non-quoted string, stop on whitespace, ',' or ')' */
1675 start = str;
1676 while (*str != ' '
1677 && *str != '\t'
1678 && *str != ','
1679 && *str != ')'
1680 && !IsNewline(*str)((*str) == '\n')
1681 && *str != '\0') str++;
1682 *strP = __XtMalloc((unsigned)(str-start+1));
1683 (void) memmove(*strP, start, str-start);
1684 (*strP)[str-start] = '\0';
1685 }
1686 return str;
1687}
1688
1689
1690static String ParseParamSeq(
1691 register String str,
1692 String **paramSeqP,
1693 Cardinal *paramNumP)
1694{
1695 typedef struct _ParamRec *ParamPtr;
1696 typedef struct _ParamRec {
1697 ParamPtr next;
1698 String param;
1699 } ParamRec;
1700
1701 ParamPtr params = NULL((void*)0);
1702 register Cardinal num_params = 0;
1703 register Cardinal i;
1704
1705 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1706 while (*str != ')' && *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1707 String newStr;
1708 str = ParseString(str, &newStr);
1709 if (newStr != NULL((void*)0)) {
1710 ParamPtr temp = (ParamRec*)
1711 ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) )__builtin_alloca ((int)((unsigned)sizeof(ParamRec)));
1712 if (temp == NULL((void*)0)) _XtAllocError (NULL((void*)0));
1713
1714 num_params++;
1715 temp->next = params;
1716 params = temp;
1717 temp->param = newStr;
1718 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1719 if (*str == ',') {
1720 str++;
1721 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1722 }
1723 }
1724 }
1725
1726 if (num_params != 0) {
1727 String *paramP = (String *)
1728 __XtMalloc( (unsigned)(num_params+1) * sizeof(String) );
1729 *paramSeqP = paramP;
1730 *paramNumP = num_params;
1731 paramP += num_params; /* list is LIFO right now */
1732 *paramP-- = NULL((void*)0);
1733 for (i=0; i < num_params; i++) {
1734 ParamPtr next = params->next;
1735 *paramP-- = params->param;
1736 DEALLOCATE_LOCAL( (char *)params )do {} while(0);
1737 params = next;
1738 }
1739 } else {
1740 *paramSeqP = NULL((void*)0);
1741 *paramNumP = 0;
1742 }
1743
1744 return str;
1745}
1746
1747static String ParseAction(
1748 String str,
1749 ActionPtr actionP,
1750 XrmQuark* quarkP,
1751 Boolean* error)
1752{
1753 str = ParseActionProc(str, quarkP, error);
1754 if (*error) return str;
1755
1756 if (*str == '(') {
1757 str++;
1758 str = ParseParamSeq(str, &actionP->params, &actionP->num_params);
1759 } else {
1760 Syntax("Missing '(' while parsing action sequence","");
1761 *error = TRUE1;
1762 return str;
1763 }
1764 if (*str == ')') str++;
1765 else{
1766 Syntax("Missing ')' while parsing action sequence","");
1767 *error = TRUE1;
1768 return str;
1769 }
1770 return str;
1771}
1772
1773
1774static String ParseActionSeq(
1775 TMParseStateTree parseTree,
1776 String str,
1777 ActionPtr *actionsP,
1778 Boolean *error)
1779{
1780 ActionPtr *nextActionP = actionsP;
1781
1782 *actionsP = NULL((void*)0);
1783 while (*str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1784 register ActionPtr action;
1785 XrmQuark quark;
1786
1787 action = XtNew(ActionRec)((ActionRec *) XtMalloc((unsigned) sizeof(ActionRec)));
1788 action->params = NULL((void*)0);
1789 action->num_params = 0;
1790 action->next = NULL((void*)0);
1791
1792 str = ParseAction(str, action, &quark, error);
1793 if (*error) return PanicModeRecovery(str);
1794
1795 action->idx = _XtGetQuarkIndex(parseTree, quark);
1796 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1797 *nextActionP = action;
1798 nextActionP = &action->next;
1799 }
1800 if (IsNewline(*str)((*str) == '\n')) str++;
1801 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1802 return str;
1803}
1804
1805
1806static void ShowProduction(
1807 String currentProduction)
1808{
1809 Cardinal num_params = 1;
1810 String params[1];
1811 size_t len;
1812 char *eol, *production, productionbuf[500];
1813
1814#ifdef __UNIXOS2__
1815 eol = strchr(currentProduction, '\r');
1816 if (!eol) /* try '\n' as well below */
1817#endif
1818 eol = strchr(currentProduction, '\n');
1819 if (eol) len = eol - currentProduction;
1820 else len = strlen (currentProduction);
1821 production = XtStackAlloc (len + 1, productionbuf)((len + 1) <= sizeof(productionbuf) ? (XtPointer)(productionbuf
) : XtMalloc((unsigned)(len + 1)))
;
1822 if (production == NULL((void*)0)) _XtAllocError (NULL((void*)0));
1823 (void) memmove(production, currentProduction, len);
1824 production[len] = '\0';
1825
1826 params[0] = production;
1827 XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError,
1828 "... found while parsing '%s'", params, &num_params);
1829
1830 XtStackFree (production, productionbuf){ if ((production) != ((XtPointer)(productionbuf))) XtFree(production
); }
;
1831}
1832
1833/***********************************************************************
1834 * ParseTranslationTableProduction
1835 * Parses one line of event bindings.
1836 ***********************************************************************/
1837
1838static String ParseTranslationTableProduction(
1839 TMParseStateTree parseTree,
1840 register String str,
1841 Boolean* error)
1842{
1843 EventSeqPtr eventSeq = NULL((void*)0);
1844 ActionPtr *actionsP;
1845 String production = str;
1846
1847 actionsP = NULL((void*)0);
1848 str = ParseEventSeq(str, &eventSeq, &actionsP,error);
1849 if (*error == TRUE1) {
1850 ShowProduction(production);
1851 FreeEventSeq(eventSeq);
1852 return (str);
1853 }
1854 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1855 str = ParseActionSeq(parseTree, str, actionsP, error);
1856 if (*error == TRUE1) {
1857 ShowProduction(production);
1858 FreeEventSeq(eventSeq);
1859 return (str);
1860 }
1861
1862 _XtAddEventSeqToStateTree(eventSeq, parseTree);
1863 FreeEventSeq(eventSeq);
1864 return (str);
1865}
1866
1867static String CheckForPoundSign(
1868 String str,
1869 _XtTranslateOp defaultOp,
1870 _XtTranslateOp *actualOpRtn)
1871{
1872 String start;
1873 char operation[20];
1874 _XtTranslateOp opType;
1875
1876 opType = defaultOp;
1877 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1878 if (*str == '#') {
1879 int len;
1880 str++;
1881 start = str;
1882 str = ScanIdent(str);
1883 len = MIN(19, str-start)(((19) < (str-start)) ? (19) : (str-start));
1884 (void) memmove(operation, start, len);
1885 operation[len] = '\0';
1886 if (!strcmp(operation,"replace"))
1887 opType = XtTableReplace0;
1888 else if (!strcmp(operation,"augment"))
1889 opType = XtTableAugment1;
1890 else if (!strcmp(operation,"override"))
1891 opType = XtTableOverride2;
1892 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1893 if (IsNewline(*str)((*str) == '\n')) {
1894 str++;
1895 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1896 }
1897 }
1898 *actualOpRtn = opType;
1899 return str;
1900}
1901
1902static XtTranslations ParseTranslationTable(
1903 String source,
1904 Boolean isAccelerator,
1905 _XtTranslateOp defaultOp,
1906 Boolean* error)
1907{
1908 XtTranslations xlations;
1909 TMStateTree stateTrees[8];
1910 TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec;
1911 XrmQuark stackQuarks[200];
1912 TMBranchHeadRec stackBranchHeads[200];
1913 StatePtr stackComplexBranchHeads[200];
1914 _XtTranslateOp actualOp;
1915
1916 if (source == NULL((void*)0))
1917 return (XtTranslations)NULL((void*)0);
1918
1919 source = CheckForPoundSign(source, defaultOp, &actualOp);
1920 if (isAccelerator && actualOp == XtTableReplace0)
1921 actualOp = defaultOp;
1922
1923 parseTree->isSimple = TRUE1;
1924 parseTree->mappingNotifyInterest = FALSE0;
1925 parseTree->isAccelerator = isAccelerator;
1926 parseTree->isStackBranchHeads =
1927 parseTree->isStackQuarks =
1928 parseTree->isStackComplexBranchHeads = TRUE1;
1929
1930 parseTree->numQuarks =
1931 parseTree->numBranchHeads =
1932 parseTree->numComplexBranchHeads = 0;
1933
1934 parseTree->quarkTblSize =
1935 parseTree->branchHeadTblSize =
1936 parseTree->complexBranchHeadTblSize = 200;
1937
1938 parseTree->quarkTbl = stackQuarks;
1939 parseTree->branchHeadTbl = stackBranchHeads;
1940 parseTree->complexBranchHeadTbl = stackComplexBranchHeads;
1941
1942 while (source != NULL((void*)0) && *source != '\0') {
1943 source = ParseTranslationTableProduction(parseTree, source, error);
1944 if (*error == TRUE1) break;
1945 }
1946 stateTrees[0] = _XtParseTreeToStateTree(parseTree);
1947
1948 if (!parseTree->isStackQuarks)
1949 XtFree((char *)parseTree->quarkTbl);
1950 if (!parseTree->isStackBranchHeads)
1951 XtFree((char *)parseTree->branchHeadTbl);
1952 if (!parseTree->isStackComplexBranchHeads)
1953 XtFree((char *)parseTree->complexBranchHeadTbl);
1954
1955 xlations = _XtCreateXlations(stateTrees, 1, NULL((void*)0), NULL((void*)0));
1956 xlations->operation = actualOp;
1957
1958#ifdef notdef
1959 XtFree(stateTrees);
1960#endif /* notdef */
1961 return xlations;
1962}
1963
1964/*** public procedures ***/
1965
1966/*ARGSUSED*/
1967Boolean XtCvtStringToAcceleratorTable(
1968 Display* dpy,
1969 XrmValuePtr args,
1970 Cardinal *num_args,
1971 XrmValuePtr from,
1972 XrmValuePtr to,
1973 XtPointer *closure)
1974{
1975 String str;
1976 Boolean error = FALSE0;
1977
1978 if (*num_args != 0)
1979 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1980 "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
1981 "String to AcceleratorTable conversion needs no extra arguments",
1982 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1983 str = (String)(from->addr);
1984 if (str == NULL((void*)0)) {
1985 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1986 "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
1987 "String to AcceleratorTable conversion needs string",
1988 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1989 return FALSE0;
1990 }
1991 if (to->addr != NULL((void*)0)) {
1992 if (to->size < sizeof(XtAccelerators)) {
1993 to->size = sizeof(XtAccelerators);
1994 return FALSE0;
1995 }
1996 *(XtAccelerators*)to->addr =
1997 (XtAccelerators) ParseTranslationTable(str, TRUE1, XtTableAugment1, &error);
1998 }
1999 else {
2000 static XtAccelerators staticStateTable;
2001 staticStateTable =
2002 (XtAccelerators) ParseTranslationTable(str, TRUE1, XtTableAugment1, &error);
2003 to->addr = (XPointer) &staticStateTable;
2004 to->size = sizeof(XtAccelerators);
2005 }
2006 if (error == TRUE1)
2007 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2008 "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError,
2009 "String to AcceleratorTable conversion encountered errors",
2010 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2011 return (error != TRUE1);
2012}
2013
2014
2015/*ARGSUSED*/
2016Boolean
2017XtCvtStringToTranslationTable(
2018 Display *dpy,
2019 XrmValuePtr args,
2020 Cardinal *num_args,
2021 XrmValuePtr from,
2022 XrmValuePtr to,
2023 XtPointer *closure_ret)
2024{
2025 String str;
2026 Boolean error = FALSE0;
2027
2028 if (*num_args != 0)
2029 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2030 "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError,
2031 "String to TranslationTable conversion needs no extra arguments",
2032 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2033 str = (String)(from->addr);
2034 if (str == NULL((void*)0)) {
2035 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2036 "badParameters","cvtStringToTranslation",XtCXtToolkitError,
2037 "String to TranslationTable conversion needs string",
2038 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2039 return FALSE0;
2040 }
2041 if (to->addr != NULL((void*)0)) {
2042 if (to->size < sizeof(XtTranslations)) {
2043 to->size = sizeof(XtTranslations);
2044 return FALSE0;
2045 }
2046 *(XtTranslations*)to->addr =
2047 ParseTranslationTable(str, FALSE0, XtTableReplace0, &error);
2048 }
2049 else {
2050 static XtTranslations staticStateTable;
2051 staticStateTable =
2052 ParseTranslationTable(str, FALSE0, XtTableReplace0, &error);
2053 to->addr = (XPointer) &staticStateTable;
2054 to->size = sizeof(XtTranslations);
2055 }
2056 if (error == TRUE1)
2057 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2058 "parseError","cvtStringToTranslationTable",XtCXtToolkitError,
2059 "String to TranslationTable conversion encountered errors",
2060 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2061 return (error != TRUE1);
2062}
2063
2064
2065/*
2066 * Parses a user's or applications translation table
2067 */
2068XtAccelerators XtParseAcceleratorTable(
2069 _Xconstconst char* source)
2070{
2071 Boolean error = FALSE0;
2072 XtAccelerators ret =
2073 (XtAccelerators) ParseTranslationTable ((char *)source, TRUE1, XtTableAugment1, &error);
2074 if (error == TRUE1)
2075 XtWarningMsg ("parseError", "cvtStringToAcceleratorTable",
2076 XtCXtToolkitError,
2077 "String to AcceleratorTable conversion encountered errors",
2078 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2079 return ret;
2080}
2081
2082XtTranslations XtParseTranslationTable(
2083 _Xconstconst char* source)
2084{
2085 Boolean error = FALSE0;
2086 XtTranslations ret = ParseTranslationTable((char *)source, FALSE0, XtTableReplace0, &error);
2087 if (error == TRUE1)
2088 XtWarningMsg ("parseError",
2089 "cvtStringToTranslationTable", XtCXtToolkitError,
2090 "String to TranslationTable conversion encountered errors",
2091 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2092 return ret;
2093}
2094
2095void _XtTranslateInitialize(void)
2096{
2097 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2098 if (initialized) {
2099 XtWarningMsg("translationError","xtTranslateInitialize",
2100 XtCXtToolkitError,"Initializing Translation manager twice.",
2101 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2102 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2103 return;
2104 }
2105
2106 initialized = TRUE1;
2107 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2108 QMeta = XrmPermStringToQuark("Meta");
2109 QCtrl = XrmPermStringToQuark("Ctrl");
2110 QNone = XrmPermStringToQuark("None");
2111 QAny = XrmPermStringToQuark("Any");
2112
2113 Compile_XtEventTable( events, XtNumber(events)((Cardinal) (sizeof(events) / sizeof(events[0]))) );
2114 Compile_XtModifierTable( modifiers, XtNumber(modifiers)((Cardinal) (sizeof(modifiers) / sizeof(modifiers[0]))) );
2115 CompileNameValueTable( buttonNames );
2116 CompileNameValueTable( notifyModes );
2117 CompileNameValueTable( motionDetails );
2118#if 0
2119 CompileNameValueTable( notifyDetail );
2120 CompileNameValueTable( visibilityNotify );
2121 CompileNameValueTable( circulation );
2122 CompileNameValueTable( propertyChanged );
2123#endif
2124 CompileNameValueTable( mappingNotify );
2125}
2126
2127void _XtAddTMConverters(
2128 ConverterTable table)
2129{
2130 _XtTableAddConverter(table,
2131 _XtQString,
2132 XrmPermStringToQuark(XtRTranslationTable((char*)&XtStrings[1841])),
2133 XtCvtStringToTranslationTable, (XtConvertArgList) NULL((void*)0),
2134 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2135 _XtTableAddConverter(table, _XtQString,
2136 XrmPermStringToQuark(XtRAcceleratorTable((char*)&XtStrings[1527])),
2137 XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL((void*)0),
2138 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2139 _XtTableAddConverter(table,
2140 XrmPermStringToQuark( _XtRStateTablePair"_XtStateTablePair" ),
2141 XrmPermStringToQuark(XtRTranslationTable((char*)&XtStrings[1841])),
2142 _XtCvtMergeTranslations, (XtConvertArgList) NULL((void*)0),
2143 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2144}