Bug Summary

File:src/TMparse.c
Location:line 1810, column 12
Description:Null pointer argument in call to memory copy function

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{"EventTimer", NULLQUARK((XrmQuark) 0), _XtEventTimerEventType((TMLongCard)~0L),ParseNone,NULL((void*)0)},
376# endif /* notdef */
377#endif /* DEBUG */
378
379/* Event Name, Quark, Event Type, Detail Parser, Closure */
380
381};
382
383#define IsNewline(str)((str) == '\n') ((str) == '\n')
384
385#define ScanFor(str, ch)while ((*(str) != (ch)) && (*(str) != '\0') &&
!((*(str)) == '\n')) (str)++
\
386 while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))((*(str)) == '\n')) (str)++
387
388#define ScanNumeric(str)while ('0' <= *(str) && *(str) <= '9') (str)++ while ('0' <= *(str) && *(str) <= '9') (str)++
389
390#define ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
\
391 while (('A' <= *(str) && *(str) <= 'Z') || \
392 ('a' <= *(str) && *(str) <= 'z') || \
393 ('0' <= *(str) && *(str) <= '9')) (str)++
394
395#define ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++ \
396 while (*(str) == ' ' || *(str) == '\t') (str)++
397
398static Boolean initialized = FALSE0;
399static XrmQuark QMeta;
400static XrmQuark QCtrl;
401static XrmQuark QNone;
402static XrmQuark QAny;
403
404static void FreeEventSeq(
405 EventSeqPtr eventSeq)
406{
407 register EventSeqPtr evs = eventSeq;
408
409 while (evs != NULL((void*)0)) {
410 evs->state = (StatePtr) evs;
411 if (evs->next != NULL((void*)0)
412 && evs->next->state == (StatePtr) evs->next)
413 evs->next = NULL((void*)0);
414 evs = evs->next;
415 }
416
417 evs = eventSeq;
418 while (evs != NULL((void*)0)) {
419 register EventPtr event = evs;
420 evs = evs->next;
421 if (evs == event) evs = NULL((void*)0);
422 XtFree((char *)event);
423 }
424}
425
426static void CompileNameValueTable(
427 NameValueTable table)
428{
429 register int i;
430
431 for (i=0; table[i].name; i++)
432 table[i].signature = XrmPermStringToQuark(table[i].name);
433}
434
435static int OrderEvents(_Xconstconst void *a, _Xconstconst void *b)
436{
437 return ((((_Xconstconst EventKey *)a)->signature <
438 ((_Xconstconst EventKey *)b)->signature) ? -1 : 1);
439}
440
441static void Compile_XtEventTable(
442 EventKeys table,
443 Cardinal count)
444{
445 register int i;
446 register EventKeys entry = table;
447
448 for (i=count; --i >= 0; entry++)
449 entry->signature = XrmPermStringToQuark(entry->event);
450 qsort(table, count, sizeof(EventKey), OrderEvents);
451}
452
453static int OrderModifiers(_Xconstconst void *a, _Xconstconst void *b)
454{
455 return ((((_Xconstconst ModifierRec *)a)->signature <
456 ((_Xconstconst ModifierRec *)b)->signature) ? -1 : 1);
457}
458
459static void Compile_XtModifierTable(
460 ModifierKeys table,
461 Cardinal count)
462{
463 register int i;
464 register ModifierKeys entry = table;
465
466 for (i=count; --i >= 0; entry++)
467 entry->signature = XrmPermStringToQuark(entry->name);
468 qsort(table, count, sizeof(ModifierRec), OrderModifiers);
469}
470
471static String PanicModeRecovery(
472 String str)
473{
474 ScanFor(str,'\n')while ((*(str) != ('\n')) && (*(str) != '\0') &&
!((*(str)) == '\n')) (str)++
;
475 if (*str == '\n') str++;
476 return str;
477
478}
479
480
481static void Syntax(
482 String str0,String str1)
483{
484 Cardinal num_params = 2;
485 String params[2];
486
487 params[0] = str0;
488 params[1] = str1;
489 XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError,
490 "translation table syntax error: %s %s",params,&num_params);
491}
492
493
494
495static Cardinal LookupTMEventType(
496 String eventStr,
497 Boolean *error)
498{
499 register int i = 0, left, right;
500 register XrmQuark signature;
501 static int previous = 0;
502
503 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
504 if ((signature = StringToQuark(eventStr)XrmStringToQuark(eventStr)) == events[previous].signature) {
505 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
506 return (Cardinal) previous;
507 }
508
509 left = 0;
510 right = XtNumber(events)((Cardinal) (sizeof(events) / sizeof(events[0]))) - 1;
511 while (left <= right) {
512 i = (left + right) >> 1;
513 if (signature < events[i].signature)
514 right = i - 1;
515 else if (signature > events[i].signature)
516 left = i + 1;
517 else {
518 previous = i;
519 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
520 return (Cardinal) i;
521 }
522 }
523
524 Syntax("Unknown event type : ",eventStr);
525 *error = TRUE1;
526 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
527 return (Cardinal) i;
528}
529
530static void StoreLateBindings(
531 KeySym keysymL,
532 Boolean notL,
533 KeySym keysymR,
534 Boolean notR,
535 LateBindingsPtr* lateBindings)
536{
537 LateBindingsPtr temp;
538 Boolean pair = FALSE0;
539 unsigned long count,number;
540 if (lateBindings != NULL((void*)0)){
541 temp = *lateBindings;
542 if (temp != NULL((void*)0)) {
543 for (count = 0; temp[count].keysym; count++){/*EMPTY*/}
544 }
545 else count = 0;
546 if (! keysymR){
547 number = 1;pair = FALSE0;
548 } else{
549 number = 2;pair = TRUE1;
550 }
551
552 temp = (LateBindingsPtr)XtRealloc((char *)temp,
553 (unsigned)((count+number+1) * sizeof(LateBindings)) );
554 *lateBindings = temp;
555 temp[count].knot = notL;
556 temp[count].pair = pair;
557 if (count == 0)
558 temp[count].ref_count = 1;
559 temp[count++].keysym = keysymL;
560 if (keysymR){
561 temp[count].knot = notR;
562 temp[count].pair = FALSE0;
563 temp[count].ref_count = 0;
564 temp[count++].keysym = keysymR;
565 }
566 temp[count].knot = temp[count].pair = FALSE0;
567 temp[count].ref_count = 0;
568 temp[count].keysym = 0;
569 }
570}
571
572static void _XtParseKeysymMod(
573 String name,
574 LateBindingsPtr* lateBindings,
575 Boolean notFlag,
576 Value *valueP,
577 Boolean *error)
578{
579 KeySym keySym;
580 keySym = StringToKeySym(name, error);
581 *valueP = 0;
582 if (keySym != NoSymbol0L) {
583 StoreLateBindings(keySym,notFlag,(KeySym) NULL((void*)0),FALSE0,lateBindings);
584 }
585}
586
587static Boolean _XtLookupModifier(
588 XrmQuark signature,
589 LateBindingsPtr* lateBindings,
590 Boolean notFlag,
591 Value *valueP,
592 Boolint constMask)
593{
594 register int i, left, right;
595 static int previous = 0;
596
597 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
598 if (signature == modifiers[previous].signature) {
599 if (constMask) *valueP = modifiers[previous].value;
600 else /* if (modifiers[previous].modifierParseProc) always true */
601 (*modifiers[previous].modifierParseProc)
602 (modifiers[previous].value, lateBindings, notFlag, valueP);
603 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
604 return TRUE1;
605 }
606
607 left = 0;
608 right = XtNumber(modifiers)((Cardinal) (sizeof(modifiers) / sizeof(modifiers[0]))) - 1;
609 while (left <= right) {
610 i = (left + right) >> 1;
611 if (signature < modifiers[i].signature)
612 right = i - 1;
613 else if (signature > modifiers[i].signature)
614 left = i + 1;
615 else {
616 previous = i;
617 if (constMask) *valueP = modifiers[i].value;
618 else /* if (modifiers[i].modifierParseProc) always true */
619 (*modifiers[i].modifierParseProc)
620 (modifiers[i].value, lateBindings, notFlag, valueP);
621 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
622 return TRUE1;
623 }
624 }
625 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
626 return FALSE0;
627}
628
629
630static String ScanIdent(
631 register String str)
632{
633 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
634 while (
635 ('A' <= *str && *str <= 'Z')
636 || ('a' <= *str && *str <= 'z')
637 || ('0' <= *str && *str <= '9')
638 || (*str == '-')
639 || (*str == '_')
640 || (*str == '$')
641 ) str++;
642 return str;
643}
644
645static String FetchModifierToken(
646 String str,
647 XrmQuark *token_return)
648{
649 String start = str;
650
651 if (*str == '$') {
652 *token_return = QMeta;
653 str++;
654 return str;
655 }
656 if (*str == '^') {
657 *token_return = QCtrl;
658 str++;
659 return str;
660 }
661 str = ScanIdent(str);
662 if (start != str) {
663 char modStrbuf[100];
664 char* modStr;
665
666 modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf)(((size_t)(str - start + 1)) <= sizeof(modStrbuf) ? (XtPointer
)(modStrbuf) : XtMalloc((unsigned)((size_t)(str - start + 1))
))
;
667 if (modStr == NULL((void*)0)) _XtAllocError (NULL((void*)0));
668 (void) memmove(modStr, start, str-start)__builtin___memmove_chk (modStr, start, str-start, __builtin_object_size
(modStr, 0))
;
669 modStr[str-start] = '\0';
670 *token_return = XrmStringToQuark(modStr);
671 XtStackFree (modStr, modStrbuf){ if ((modStr) != ((XtPointer)(modStrbuf))) XtFree(modStr); };
672 return str;
673 }
674 return str;
675}
676
677static String ParseModifiers(
678 register String str,
679 EventPtr event,
680 Boolean* error)
681{
682 register String start;
683 Boolean notFlag, exclusive, keysymAsMod;
684 Value maskBit;
685 XrmQuark Qmod;
686
687 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
688 start = str;
689 str = FetchModifierToken(str, &Qmod);
690 exclusive = FALSE0;
691 if (start != str) {
692 if (Qmod == QNone) {
693 event->event.modifierMask = ~0;
694 event->event.modifiers = 0;
695 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
696 return str;
697 } else if (Qmod == QAny) { /*backward compatability*/
698 event->event.modifierMask = 0;
699 event->event.modifiers = AnyModifier(1<<15);
700 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
701 return str;
702 }
703 str = start; /*if plain modifier, reset to beginning */
704 }
705 else while (*str == '!' || *str == ':') {
706 if (*str == '!') {
707 exclusive = TRUE1;
708 str++;
709 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
710 }
711 if (*str == ':') {
712 event->event.standard = TRUE1;
713 str++;
714 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
715 }
716 }
717
718 while (*str != '<') {
719 if (*str == '~') {
720 notFlag = TRUE1;
721 str++;
722 } else
723 notFlag = FALSE0;
724 if (*str == '@') {
725 keysymAsMod = TRUE1;
726 str++;
727 }
728 else keysymAsMod = FALSE0;
729 start = str;
730 str = FetchModifierToken(str, &Qmod);
731 if (start == str) {
732 Syntax("Modifier or '<' expected","");
733 *error = TRUE1;
734 return PanicModeRecovery(str);
735 }
736 if (keysymAsMod) {
737 _XtParseKeysymMod(XrmQuarkToString(Qmod),
738 &event->event.lateModifiers,
739 notFlag,&maskBit, error);
740 if (*error)
741 return PanicModeRecovery(str);
742
743 } else
744 if (!_XtLookupModifier(Qmod, &event->event.lateModifiers,
745 notFlag, &maskBit, FALSE0)) {
746 Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod));
747 *error = TRUE1;
748 return PanicModeRecovery(str);
749 }
750 event->event.modifierMask |= maskBit;
751 if (notFlag) event->event.modifiers &= ~maskBit;
752 else event->event.modifiers |= maskBit;
753 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
754 }
755 if (exclusive) event->event.modifierMask = ~0;
756 return str;
757}
758
759static String ParseXtEventType(
760 register String str,
761 EventPtr event,
762 Cardinal *tmEventP,
763 Boolean* error)
764{
765 String start = str;
766 char eventTypeStrbuf[100];
767 char* eventTypeStr;
768
769 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
770 eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf)(((size_t)(str - start + 1)) <= sizeof(eventTypeStrbuf) ? (
XtPointer)(eventTypeStrbuf) : XtMalloc((unsigned)((size_t)(str
- start + 1))))
;
771 if (eventTypeStr == NULL((void*)0)) _XtAllocError (NULL((void*)0));
772 (void) memmove(eventTypeStr, start, str-start)__builtin___memmove_chk (eventTypeStr, start, str-start, __builtin_object_size
(eventTypeStr, 0))
;
773 eventTypeStr[str-start] = '\0';
774 *tmEventP = LookupTMEventType(eventTypeStr,error);
775 XtStackFree (eventTypeStr, eventTypeStrbuf){ if ((eventTypeStr) != ((XtPointer)(eventTypeStrbuf))) XtFree
(eventTypeStr); }
;
776 if (*error)
777 return PanicModeRecovery(str);
778 event->event.eventType = events[*tmEventP].eventType;
779 return str;
780}
781
782static unsigned long StrToHex(
783 String str)
784{
785 register char c;
786 register unsigned long val = 0;
787
788 while ((c = *str)) {
789 if ('0' <= c && c <= '9') val = val*16+c-'0';
790 else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10;
791 else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10;
792 else return 0;
793 str++;
794 }
795
796 return val;
797}
798
799static unsigned long StrToOct(
800 String str)
801{
802 register char c;
803 register unsigned long val = 0;
804
805 while ((c = *str)) {
806 if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0;
807 str++;
808 }
809
810 return val;
811}
812
813static unsigned long StrToNum(
814 String str)
815{
816 register char c;
817 register unsigned long val = 0;
818
819 if (*str == '0') {
820 str++;
821 if (*str == 'x' || *str == 'X') return StrToHex(++str);
822 else return StrToOct(str);
823 }
824
825 while ((c = *str)) {
826 if ('0' <= c && c <= '9') val = val*10+c-'0';
827 else return 0;
828 str++;
829 }
830
831 return val;
832}
833
834static KeySym StringToKeySym(
835 String str,
836 Boolean *error)
837{
838 KeySym k;
839
840 if (str == NULL((void*)0) || *str == '\0') return (KeySym) 0;
841
842#ifndef NOTASCII
843 /* special case single character ASCII, for speed */
844 if (*(str+1) == '\0') {
845 if (' ' <= *str && *str <= '~') return XK_space0x0020 + (*str - ' ');
846 }
847#endif
848
849 if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str);
850 k = XStringToKeysym(str);
851 if (k != NoSymbol0L) return k;
852
853#ifdef NOTASCII
854 /* fall-back case to preserve backwards compatibility; no-one
855 * should be relying upon this!
856 */
857 if (*(str+1) == '\0') return (KeySym) *str;
858#endif
859
860 Syntax("Unknown keysym name: ", str);
861 *error = TRUE1;
862 return NoSymbol0L;
863}
864/* ARGSUSED */
865static void ParseModImmed(
866 Value value,
867 LateBindingsPtr* lateBindings,
868 Boolean notFlag,
869 Value* valueP)
870{
871 *valueP = value;
872}
873
874 /* is only valid with keysyms that have an _L and _R in their name;
875 * and ignores keysym lookup errors (i.e. assumes only valid keysyms)
876 */
877static void ParseModSym(
878 Value value,
879 LateBindingsPtr* lateBindings,
880 Boolean notFlag,
881 Value* valueP)
882{
883 register KeySym keysymL = (KeySym)value;
884 register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */
885 StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings);
886 *valueP = 0;
887}
888
889#ifdef sparc
890/*
891 * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that
892 * causes the value of the most recently used variable to be returned instead
893 * of the value passed in.
894 */
895static String stupid_optimizer_kludge;
896#define BROKEN_OPTIMIZER_HACK(val)val stupid_optimizer_kludge = (val)
897#else
898#define BROKEN_OPTIMIZER_HACK(val)val val
899#endif
900
901/* ARGSUSED */
902static String ParseImmed(
903 register String str,
904 register Opaque closure,
905 register EventPtr event,
906 Boolean* error)
907{
908 event->event.eventCode = (unsigned long)closure;
909 event->event.eventCodeMask = ~0UL;
910
911 return BROKEN_OPTIMIZER_HACK(str)str;
912}
913
914/* ARGSUSED */
915static String ParseAddModifier(
916 register String str,
917 register Opaque closure,
918 register EventPtr event,
919 Boolean* error)
920{
921 register unsigned long modval = (unsigned long)closure;
922 event->event.modifiers |= modval;
923 if (modval != AnyButtonMask(1L<<28)) /* AnyButtonMask is don't-care mask */
924 event->event.modifierMask |= modval;
925
926 return BROKEN_OPTIMIZER_HACK(str)str;
927}
928
929
930static String ParseKeyAndModifiers(
931 String str,
932 Opaque closure,
933 EventPtr event,
934 Boolean* error)
935{
936 str = ParseKeySym(str, closure, event,error);
937 if ((unsigned long) closure == 0) {
938 Value metaMask; /* unused */
939 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE0,
940 &metaMask, FALSE0);
941 } else {
942 event->event.modifiers |= (unsigned long) closure;
943 event->event.modifierMask |= (unsigned long) closure;
944 }
945 return str;
946}
947
948/*ARGSUSED*/
949static String ParseKeySym(
950 register String str,
951 Opaque closure,
952 EventPtr event,
953 Boolean* error)
954{
955 char *start;
956 char keySymNamebuf[100];
957 char* keySymName;
958
959 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
960
961 if (*str == '\\') {
962 keySymName = keySymNamebuf;
963 str++;
964 keySymName[0] = *str;
965 if (*str != '\0' && !IsNewline(*str)((*str) == '\n')) str++;
966 keySymName[1] = '\0';
967 event->event.eventCode = StringToKeySym(keySymName, error);
968 event->event.eventCodeMask = ~0L;
969 } else if (*str == ',' || *str == ':' ||
970 /* allow leftparen to be single char symbol,
971 * for backwards compatibility
972 */
973 (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) {
974 keySymName = keySymNamebuf; /* just so we can stackfree it later */
975 /* no detail */
976 event->event.eventCode = 0L;
977 event->event.eventCodeMask = 0L;
978 } else {
979 start = str;
980 while (
981 *str != ','
982 && *str != ':'
983 && *str != ' '
984 && *str != '\t'
985 && !IsNewline(*str)((*str) == '\n')
986 && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9')
987 && *str != '\0') str++;
988 keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf)(((size_t)(str - start + 1)) <= sizeof(keySymNamebuf) ? (XtPointer
)(keySymNamebuf) : XtMalloc((unsigned)((size_t)(str - start +
1))))
;
989 (void) memmove(keySymName, start, str-start)__builtin___memmove_chk (keySymName, start, str-start, __builtin_object_size
(keySymName, 0))
;
990 keySymName[str-start] = '\0';
991 event->event.eventCode = StringToKeySym(keySymName, error);
992 event->event.eventCodeMask = ~0L;
993 }
994 if (*error) {
995 /* We never get here when keySymName hasn't been allocated */
996 if (keySymName[0] == '<') {
997 /* special case for common error */
998 XtWarningMsg(XtNtranslationParseError, "missingComma",
999 XtCXtToolkitError,
1000 "... possibly due to missing ',' in event sequence.",
1001 (String*)NULL((void*)0), (Cardinal*)NULL((void*)0));
1002 }
1003 XtStackFree (keySymName, keySymNamebuf){ if ((keySymName) != ((XtPointer)(keySymNamebuf))) XtFree(keySymName
); }
;
1004 return PanicModeRecovery(str);
1005 }
1006 if (event->event.standard)
1007 event->event.matchEvent = _XtMatchUsingStandardMods;
1008 else
1009 event->event.matchEvent = _XtMatchUsingDontCareMods;
1010
1011 XtStackFree (keySymName, keySymNamebuf){ if ((keySymName) != ((XtPointer)(keySymNamebuf))) XtFree(keySymName
); }
;
1012
1013 return str;
1014}
1015
1016static String ParseTable(
1017 register String str,
1018 Opaque closure,
1019 EventPtr event,
1020 Boolean* error)
1021{
1022 register String start = str;
1023 register XrmQuark signature;
1024 NameValueTable table = (NameValueTable) closure;
1025 char tableSymName[100];
1026
1027 event->event.eventCode = 0L;
1028 ScanAlphanumeric(str)while (('A' <= *(str) && *(str) <= 'Z') || ('a'
<= *(str) && *(str) <= 'z') || ('0' <= *(str
) && *(str) <= '9')) (str)++
;
1029 if (str == start) {event->event.eventCodeMask = 0L; return str; }
1030 if (str-start >= 99) {
1031 Syntax("Invalid Detail Type (string is too long).", "");
1032 *error = TRUE1;
1033 return str;
1034 }
1035 (void) memmove(tableSymName, start, str-start)__builtin___memmove_chk (tableSymName, start, str-start, __builtin_object_size
(tableSymName, 0))
;
1036 tableSymName[str-start] = '\0';
1037 signature = StringToQuark(tableSymName)XrmStringToQuark(tableSymName);
1038 for (; table->signature != NULLQUARK((XrmQuark) 0); table++)
1039 if (table->signature == signature) {
1040 event->event.eventCode = table->value;
1041 event->event.eventCodeMask = ~0L;
1042 return str;
1043 }
1044
1045 Syntax("Unknown Detail Type: ", tableSymName);
1046 *error = TRUE1;
1047 return PanicModeRecovery(str);
1048}
1049
1050/*ARGSUSED*/
1051static String ParseNone(
1052 String str,
1053 Opaque closure,
1054 EventPtr event,
1055 Boolean* error)
1056{
1057 event->event.eventCode = 0;
1058 event->event.eventCodeMask = 0;
1059
1060 return BROKEN_OPTIMIZER_HACK(str)str;
1061}
1062
1063/*ARGSUSED*/
1064static String ParseAtom(
1065 String str,
1066 Opaque closure,
1067 EventPtr event,
1068 Boolean* error)
1069{
1070 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1071
1072 if (*str == ',' || *str == ':') {
1073 /* no detail */
1074 event->event.eventCode = 0L;
1075 event->event.eventCodeMask = 0L;
1076 } else {
1077 char *start, atomName[1000];
1078 start = str;
1079 while (
1080 *str != ','
1081 && *str != ':'
1082 && *str != ' '
1083 && *str != '\t'
1084 && !IsNewline(*str)((*str) == '\n')
1085 && *str != '\0') str++;
1086 if (str-start >= 999) {
1087 Syntax( "Atom name must be less than 1000 characters long.", "" );
1088 *error = TRUE1;
1089 return str;
1090 }
1091 (void) memmove(atomName, start, str-start)__builtin___memmove_chk (atomName, start, str-start, __builtin_object_size
(atomName, 0))
;
1092 atomName[str-start] = '\0';
1093 event->event.eventCode = XrmStringToQuark(atomName);
1094 event->event.matchEvent = _XtMatchAtom;
1095 }
1096 return str;
1097}
1098
1099static ModifierMask buttonModifierMasks[] = {
1100 0, Button1Mask(1<<8), Button2Mask(1<<9), Button3Mask(1<<10), Button4Mask(1<<11), Button5Mask(1<<12)
1101};
1102static String ParseRepeat(String, int *, Boolean *, Boolean *);
1103
1104static String ParseEvent(
1105 register String str,
1106 EventPtr event,
1107 int* reps,
1108 Boolean* plus,
1109 Boolean* error)
1110{
1111 Cardinal tmEvent;
1112
1113 str = ParseModifiers(str, event,error);
1114 if (*error) return str;
1115 if (*str != '<') {
1116 Syntax("Missing '<' while parsing event type.","");
1117 *error = TRUE1;
1118 return PanicModeRecovery(str);
1119 }
1120 else str++;
1121 str = ParseXtEventType(str, event, &tmEvent,error);
1122 if (*error) return str;
1123 if (*str != '>'){
1124 Syntax("Missing '>' while parsing event type","");
1125 *error = TRUE1;
1126 return PanicModeRecovery(str);
1127 }
1128 else str++;
1129 if (*str == '(') {
1130 str = ParseRepeat(str, reps, plus, error);
1131 if (*error) return str;
1132 }
1133 str = (*(events[tmEvent].parseDetail))(
1134 str, events[tmEvent].closure, event,error);
1135 if (*error) return str;
1136
1137/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t.
1138 * modifiers in grabs.
1139 */
1140 if ((event->event.eventType == ButtonRelease5)
1141 && (event->event.modifiers | event->event.modifierMask) /* any */
1142 && (event->event.modifiers != AnyModifier(1<<15)))
1143 {
1144 event->event.modifiers
1145 |= buttonModifierMasks[event->event.eventCode];
1146 /* the button that is going up will always be in the modifiers... */
1147 }
1148
1149 return str;
1150}
1151
1152static String ParseQuotedStringEvent(
1153 register String str,
1154 register EventPtr event,
1155 Boolean *error)
1156{
1157 Value metaMask;
1158 char s[2];
1159
1160 if (*str=='^') {
1161 str++;
1162 event->event.modifiers = ControlMask(1<<2);
1163 } else if (*str == '$') {
1164 str++;
1165 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE0,
1166 &metaMask, FALSE0);
1167 }
1168 if (*str == '\\')
1169 str++;
1170 s[0] = *str;
1171 s[1] = '\0';
1172 if (*str != '\0' && !IsNewline(*str)((*str) == '\n')) str++;
1173 event->event.eventType = KeyPress2;
1174 event->event.eventCode = StringToKeySym(s, error);
1175 if (*error) return PanicModeRecovery(str);
1176 event->event.eventCodeMask = ~0L;
1177 event->event.matchEvent = _XtMatchUsingStandardMods;
1178 event->event.standard = TRUE1;
1179
1180 return str;
1181}
1182
1183
1184static EventSeqRec timerEventRec = {
1185 {0, 0, NULL((void*)0), _XtEventTimerEventType((TMLongCard)~0L), 0L, 0L, NULL((void*)0), False0},
1186 /* (StatePtr) -1 */ NULL((void*)0),
1187 NULL((void*)0),
1188 NULL((void*)0)
1189};
1190
1191static void RepeatDown(
1192 EventPtr *eventP,
1193 int reps,
1194 ActionPtr **actionsP)
1195{
1196 EventRec upEventRec;
1197 register EventPtr event, downEvent;
1198 EventPtr upEvent = &upEventRec;
1199 register int i;
1200
1201 downEvent = event = *eventP;
1202 *upEvent = *downEvent;
1203 upEvent->event.eventType = ((event->event.eventType == ButtonPress4) ?
1204 ButtonRelease5 : KeyRelease3);
1205 if ((upEvent->event.eventType == ButtonRelease5)
1206 && (upEvent->event.modifiers != AnyModifier(1<<15))
1207 && (upEvent->event.modifiers | upEvent->event.modifierMask))
1208 upEvent->event.modifiers
1209 |= buttonModifierMasks[event->event.eventCode];
1210
1211 if (event->event.lateModifiers)
1212 event->event.lateModifiers->ref_count += (reps - 1) * 2;
1213
1214 for (i=1; i<reps; i++) {
1215
1216 /* up */
1217 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1218 event = event->next;
1219 *event = *upEvent;
1220
1221 /* timer */
1222 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1223 event = event->next;
1224 *event = timerEventRec;
1225
1226 /* down */
1227 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1228 event = event->next;
1229 *event = *downEvent;
1230
1231 }
1232
1233 event->next = NULL((void*)0);
1234 *eventP = event;
1235 *actionsP = &event->actions;
1236}
1237
1238static void RepeatDownPlus(
1239 EventPtr *eventP,
1240 int reps,
1241 ActionPtr **actionsP)
1242{
1243 EventRec upEventRec;
1244 register EventPtr event, downEvent, lastDownEvent = NULL((void*)0);
1245 EventPtr upEvent = &upEventRec;
1246 register int i;
1247
1248 downEvent = event = *eventP;
1249 *upEvent = *downEvent;
1250 upEvent->event.eventType = ((event->event.eventType == ButtonPress4) ?
1251 ButtonRelease5 : KeyRelease3);
1252 if ((upEvent->event.eventType == ButtonRelease5)
1253 && (upEvent->event.modifiers != AnyModifier(1<<15))
1254 && (upEvent->event.modifiers | upEvent->event.modifierMask))
1255 upEvent->event.modifiers
1256 |= buttonModifierMasks[event->event.eventCode];
1257
1258 if (event->event.lateModifiers)
1259 event->event.lateModifiers->ref_count += reps * 2 - 1;
1260
1261 for (i=0; i<reps; i++) {
1262
1263 if (i > 0) {
1264 /* down */
1265 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1266 event = event->next;
1267 *event = *downEvent;
1268 }
1269 lastDownEvent = event;
1270
1271 /* up */
1272 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1273 event = event->next;
1274 *event = *upEvent;
1275
1276 /* timer */
1277 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1278 event = event->next;
1279 *event = timerEventRec;
1280
1281 }
1282
1283 event->next = lastDownEvent;
1284 *eventP = event;
1285 *actionsP = &lastDownEvent->actions;
1286}
1287
1288static void RepeatUp(
1289 EventPtr *eventP,
1290 int reps,
1291 ActionPtr **actionsP)
1292{
1293 EventRec upEventRec;
1294 register EventPtr event, downEvent;
1295 EventPtr upEvent = &upEventRec;
1296 register int i;
1297
1298 /* the event currently sitting in *eventP is an "up" event */
1299 /* we want to make it a "down" event followed by an "up" event, */
1300 /* so that sequence matching on the "state" side works correctly. */
1301
1302 downEvent = event = *eventP;
1303 *upEvent = *downEvent;
1304 downEvent->event.eventType = ((event->event.eventType == ButtonRelease5) ?
1305 ButtonPress4 : KeyPress2);
1306 if ((downEvent->event.eventType == ButtonPress4)
1307 && (downEvent->event.modifiers != AnyModifier(1<<15))
1308 && (downEvent->event.modifiers | downEvent->event.modifierMask))
1309 downEvent->event.modifiers
1310 &= ~buttonModifierMasks[event->event.eventCode];
1311
1312 if (event->event.lateModifiers)
1313 event->event.lateModifiers->ref_count += reps * 2 - 1;
1314
1315 /* up */
1316 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1317 event = event->next;
1318 *event = *upEvent;
1319
1320 for (i=1; i<reps; i++) {
1321
1322 /* timer */
1323 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1324 event = event->next;
1325 *event = timerEventRec;
1326
1327 /* down */
1328 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1329 event = event->next;
1330 *event = *downEvent;
1331
1332 /* up */
1333 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1334 event = event->next;
1335 *event = *upEvent;
1336
1337 }
1338
1339 event->next = NULL((void*)0);
1340 *eventP = event;
1341 *actionsP = &event->actions;
1342}
1343
1344static void RepeatUpPlus(
1345 EventPtr *eventP,
1346 int reps,
1347 ActionPtr **actionsP)
1348{
1349 EventRec upEventRec;
1350 register EventPtr event, downEvent, lastUpEvent = NULL((void*)0);
1351 EventPtr upEvent = &upEventRec;
1352 register int i;
1353
1354 /* the event currently sitting in *eventP is an "up" event */
1355 /* we want to make it a "down" event followed by an "up" event, */
1356 /* so that sequence matching on the "state" side works correctly. */
1357
1358 downEvent = event = *eventP;
1359 *upEvent = *downEvent;
1360 downEvent->event.eventType = ((event->event.eventType == ButtonRelease5) ?
1361 ButtonPress4 : KeyPress2);
1362 if ((downEvent->event.eventType == ButtonPress4)
1363 && (downEvent->event.modifiers != AnyModifier(1<<15))
1364 && (downEvent->event.modifiers | downEvent->event.modifierMask))
1365 downEvent->event.modifiers
1366 &= ~buttonModifierMasks[event->event.eventCode];
1367
1368 if (event->event.lateModifiers)
1369 event->event.lateModifiers->ref_count += reps * 2;
1370
1371 for (i=0; i<reps; i++) {
1372
1373 /* up */
1374 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1375 lastUpEvent = event = event->next;
1376 *event = *upEvent;
1377
1378 /* timer */
1379 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1380 event = event->next;
1381 *event = timerEventRec;
1382
1383 /* down */
1384 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1385 event = event->next;
1386 *event = *downEvent;
1387
1388 }
1389
1390 event->next = lastUpEvent;
1391 *eventP = event;
1392 *actionsP = &lastUpEvent->actions;
1393}
1394
1395static void RepeatOther(
1396 EventPtr *eventP,
1397 int reps,
1398 ActionPtr **actionsP)
1399{
1400 register EventPtr event, tempEvent;
1401 register int i;
1402
1403 tempEvent = event = *eventP;
1404
1405 if (event->event.lateModifiers)
1406 event->event.lateModifiers->ref_count += reps - 1;
1407
1408 for (i=1; i<reps; i++) {
1409 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1410 event = event->next;
1411 *event = *tempEvent;
1412 }
1413
1414 *eventP = event;
1415 *actionsP = &event->actions;
1416}
1417
1418static void RepeatOtherPlus(
1419 EventPtr *eventP,
1420 int reps,
1421 ActionPtr **actionsP)
1422{
1423 register EventPtr event, tempEvent;
1424 register int i;
1425
1426 tempEvent = event = *eventP;
1427
1428 if (event->event.lateModifiers)
1429 event->event.lateModifiers->ref_count += reps - 1;
1430
1431 for (i=1; i<reps; i++) {
1432 event->next = XtNew(EventSeqRec)((EventSeqRec *) XtMalloc((unsigned) sizeof(EventSeqRec)));
1433 event = event->next;
1434 *event = *tempEvent;
1435 }
1436
1437 event->next = event;
1438 *eventP = event;
1439 *actionsP = &event->actions;
1440}
1441
1442static void RepeatEvent(
1443 EventPtr *eventP,
1444 int reps,
1445 Boolean plus,
1446 ActionPtr **actionsP)
1447{
1448 switch ((*eventP)->event.eventType) {
1449
1450 case ButtonPress4:
1451 case KeyPress2:
1452 if (plus) RepeatDownPlus(eventP, reps, actionsP);
1453 else RepeatDown(eventP, reps, actionsP);
1454 break;
1455
1456 case ButtonRelease5:
1457 case KeyRelease3:
1458 if (plus) RepeatUpPlus(eventP, reps, actionsP);
1459 else RepeatUp(eventP, reps, actionsP);
1460 break;
1461
1462 default:
1463 if (plus) RepeatOtherPlus(eventP, reps, actionsP);
1464 else RepeatOther(eventP, reps, actionsP);
1465 }
1466}
1467
1468static String ParseRepeat(
1469 register String str,
1470 int *reps,
1471 Boolean *plus, Boolean *error)
1472{
1473
1474 /*** Parse the repetitions, for double click etc... ***/
1475 if (*str != '(' || !(isdigit((unsigned char)str[1]) || str[1] == '+' || str[1] == ')'))
1476 return str;
1477 str++;
1478 if (isdigit((unsigned char)*str)) {
1479 String start = str;
1480 char repStr[7];
1481 size_t len;
1482
1483 ScanNumeric(str)while ('0' <= *(str) && *(str) <= '9') (str)++;
1484 len = (str - start);
1485 if (len < sizeof repStr) {
1486 (void) memmove(repStr, start, len)__builtin___memmove_chk (repStr, start, len, __builtin_object_size
(repStr, 0))
;
1487 repStr[len] = '\0';
1488 *reps = StrToNum(repStr);
1489 } else {
1490 Syntax("Repeat count too large.", "");
1491 *error = TRUE1;
1492 return str;
1493 }
1494 }
1495 if (*reps == 0) {
1496 Syntax("Missing repeat count.","");
1497 *error = True1;
1498 return str;
1499 }
1500
1501 if (*str == '+') {
1502 *plus = TRUE1;
1503 str++;
1504 }
1505 if (*str == ')')
1506 str++;
1507 else {
1508 Syntax("Missing ')'.","");
1509 *error = TRUE1;
1510 }
1511
1512 return str;
1513}
1514
1515/***********************************************************************
1516 * ParseEventSeq
1517 * Parses the left hand side of a translation table production
1518 * up to, and consuming the ":".
1519 * Takes a pointer to a char* (where to start parsing) and returns an
1520 * event seq (in a passed in variable), having updated the String
1521 **********************************************************************/
1522
1523static String ParseEventSeq(
1524 register String str,
1525 EventSeqPtr *eventSeqP,
1526 ActionPtr **actionsP,
1527 Boolean *error)
1528{
1529 EventSeqPtr *nextEvent = eventSeqP;
1530
1531 *eventSeqP = NULL((void*)0);
1532
1533 while ( *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1534 static Event nullEvent =
1535 {0, 0,NULL((void*)0), 0, 0L, 0L,_XtRegularMatch,FALSE0};
1536 EventPtr event;
1537
1538 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1539
1540 if (*str == '"') {
1541 str++;
1542 while (*str != '"' && *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1543 event = XtNew(EventRec)((EventRec *) XtMalloc((unsigned) sizeof(EventRec)));
1544 event->event = nullEvent;
1545 event->state = /* (StatePtr) -1 */ NULL((void*)0);
1546 event->next = NULL((void*)0);
1547 event->actions = NULL((void*)0);
1548 str = ParseQuotedStringEvent(str, event,error);
1549 if (*error) {
1550 XtWarningMsg(XtNtranslationParseError, "nonLatin1",
1551 XtCXtToolkitError,
1552 "... probably due to non-Latin1 character in quoted string",
1553 (String*)NULL((void*)0), (Cardinal*)NULL((void*)0));
1554 return PanicModeRecovery(str);
1555 }
1556 *nextEvent = event;
1557 *actionsP = &event->actions;
1558 nextEvent = &event->next;
1559 }
1560 if (*str != '"') {
1561 Syntax("Missing '\"'.","");
1562 *error = TRUE1;
1563 return PanicModeRecovery(str);
1564 }
1565 else str++;
1566 } else {
1567 int reps = 0;
1568 Boolean plus = FALSE0;
1569
1570 event = XtNew(EventRec)((EventRec *) XtMalloc((unsigned) sizeof(EventRec)));
1571 event->event = nullEvent;
1572 event->state = /* (StatePtr) -1 */ NULL((void*)0);
1573 event->next = NULL((void*)0);
1574 event->actions = NULL((void*)0);
1575
1576 str = ParseEvent(str, event, &reps, &plus, error);
1577 if (*error) return str;
1578 *nextEvent = event;
1579 *actionsP = &event->actions;
1580 if (reps > 1 || plus)
1581 RepeatEvent(&event, reps, plus, actionsP);
1582 nextEvent = &event->next;
1583 }
1584 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1585 if (*str == ':') break;
1586 else {
1587 if (*str != ',') {
1588 Syntax("',' or ':' expected while parsing event sequence.","");
1589 *error = TRUE1;
1590 return PanicModeRecovery(str);
1591 } else str++;
1592 }
1593 }
1594
1595 if (*str != ':') {
1596 Syntax("Missing ':'after event sequence.","");
1597 *error = TRUE1;
1598 return PanicModeRecovery(str);
1599 } else str++;
1600
1601 return str;
1602}
1603
1604
1605static String ParseActionProc(
1606 register String str,
1607 XrmQuark *actionProcNameP,
1608 Boolean *error)
1609{
1610 register String start = str;
1611 char procName[200];
1612
1613 str = ScanIdent(str);
1614 if (str-start >= 199) {
1615 Syntax("Action procedure name is longer than 199 chars","");
1616 *error = TRUE1;
1617 return str;
1618 }
1619 (void) memmove(procName, start, str-start)__builtin___memmove_chk (procName, start, str-start, __builtin_object_size
(procName, 0))
;
1620 procName[str-start] = '\0';
1621 *actionProcNameP = XrmStringToQuark( procName );
1622 return str;
1623}
1624
1625
1626static String ParseString(
1627 register String str,
1628 String *strP)
1629{
1630 register String start;
1631
1632 if (*str == '"') {
1633 register unsigned prev_len, len;
1634 str++;
1635 start = str;
1636 *strP = NULL((void*)0);
1637 prev_len = 0;
1638
1639 while (*str != '"' && *str != '\0') {
1640 /* \" produces double quote embedded in a quoted parameter
1641 * \\" produces backslash as last character of a quoted parameter
1642 */
1643 if (*str == '\\' &&
1644 (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) {
1645 len = prev_len + (str-start+2);
1646 *strP = XtRealloc(*strP, len);
1647 (void) memmove(*strP + prev_len, start, str-start)__builtin___memmove_chk (*strP + prev_len, start, str-start, __builtin_object_size
(*strP + prev_len, 0))
;
1648 prev_len = len-1;
1649 str++;
1650 (*strP)[prev_len-1] = *str;
1651 (*strP)[prev_len] = '\0';
1652 start = str+1;
1653 }
1654 str++;
1655 }
1656 len = prev_len + (str-start+1);
1657 *strP = XtRealloc(*strP, len);
1658 (void) memmove( *strP + prev_len, start, str-start)__builtin___memmove_chk (*strP + prev_len, start, str-start, __builtin_object_size
(*strP + prev_len, 0))
;
1659 (*strP)[len-1] = '\0';
1660 if (*str == '"') str++; else
1661 XtWarningMsg(XtNtranslationParseError,"parseString",
1662 XtCXtToolkitError,"Missing '\"'.",
1663 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1664 } else {
1665 /* scan non-quoted string, stop on whitespace, ',' or ')' */
1666 start = str;
1667 while (*str != ' '
1668 && *str != '\t'
1669 && *str != ','
1670 && *str != ')'
1671 && !IsNewline(*str)((*str) == '\n')
1672 && *str != '\0') str++;
1673 *strP = __XtMalloc((unsigned)(str-start+1));
1674 (void) memmove(*strP, start, str-start)__builtin___memmove_chk (*strP, start, str-start, __builtin_object_size
(*strP, 0))
;
1675 (*strP)[str-start] = '\0';
1676 }
1677 return str;
1678}
1679
1680
1681static String ParseParamSeq(
1682 register String str,
1683 String **paramSeqP,
1684 Cardinal *paramNumP)
1685{
1686 typedef struct _ParamRec *ParamPtr;
1687 typedef struct _ParamRec {
1688 ParamPtr next;
1689 String param;
1690 } ParamRec;
1691
1692 ParamPtr params = NULL((void*)0);
1693 register Cardinal num_params = 0;
1694 register Cardinal i;
1695
1696 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1697 while (*str != ')' && *str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1698 String newStr;
1699 str = ParseString(str, &newStr);
1700 if (newStr != NULL((void*)0)) {
1701 ParamPtr temp = (ParamRec*)
1702 ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) )__builtin_alloca((int)((unsigned)sizeof(ParamRec)));
1703 if (temp == NULL((void*)0)) _XtAllocError (NULL((void*)0));
1704
1705 num_params++;
1706 temp->next = params;
1707 params = temp;
1708 temp->param = newStr;
1709 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1710 if (*str == ',') {
1711 str++;
1712 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1713 }
1714 }
1715 }
1716
1717 if (num_params != 0) {
1718 String *paramP = (String *)
1719 __XtMalloc( (unsigned)(num_params+1) * sizeof(String) );
1720 *paramSeqP = paramP;
1721 *paramNumP = num_params;
1722 paramP += num_params; /* list is LIFO right now */
1723 *paramP-- = NULL((void*)0);
1724 for (i=0; i < num_params; i++) {
1725 ParamPtr next = params->next;
1726 *paramP-- = params->param;
1727 DEALLOCATE_LOCAL( (char *)params )do {} while(0);
1728 params = next;
1729 }
1730 } else {
1731 *paramSeqP = NULL((void*)0);
1732 *paramNumP = 0;
1733 }
1734
1735 return str;
1736}
1737
1738static String ParseAction(
1739 String str,
1740 ActionPtr actionP,
1741 XrmQuark* quarkP,
1742 Boolean* error)
1743{
1744 str = ParseActionProc(str, quarkP, error);
1745 if (*error) return str;
1746
1747 if (*str == '(') {
1748 str++;
1749 str = ParseParamSeq(str, &actionP->params, &actionP->num_params);
1750 } else {
1751 Syntax("Missing '(' while parsing action sequence","");
1752 *error = TRUE1;
1753 return str;
1754 }
1755 if (*str == ')') str++;
1756 else{
1757 Syntax("Missing ')' while parsing action sequence","");
1758 *error = TRUE1;
1759 return str;
1760 }
1761 return str;
1762}
1763
1764
1765static String ParseActionSeq(
1766 TMParseStateTree parseTree,
1767 String str,
1768 ActionPtr *actionsP,
1769 Boolean *error)
1770{
1771 ActionPtr *nextActionP = actionsP;
1772
1773 *actionsP = NULL((void*)0);
1774 while (*str != '\0' && !IsNewline(*str)((*str) == '\n')) {
1775 register ActionPtr action;
1776 XrmQuark quark;
1777
1778 action = XtNew(ActionRec)((ActionRec *) XtMalloc((unsigned) sizeof(ActionRec)));
1779 action->params = NULL((void*)0);
1780 action->num_params = 0;
1781 action->next = NULL((void*)0);
1782
1783 str = ParseAction(str, action, &quark, error);
1784 if (*error) return PanicModeRecovery(str);
1785
1786 action->idx = _XtGetQuarkIndex(parseTree, quark);
1787 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1788 *nextActionP = action;
1789 nextActionP = &action->next;
1790 }
1791 if (IsNewline(*str)((*str) == '\n')) str++;
1792 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1793 return str;
1794}
1795
1796
1797static void ShowProduction(
1798 String currentProduction)
1799{
1800 Cardinal num_params = 1;
1801 String params[1];
1802 size_t len;
1803 char *eol, *production, productionbuf[500];
1804
1805 eol = strchr(currentProduction, '\n');
1806 if (eol) len = eol - currentProduction;
11
Assuming 'eol' is non-null
12
Taking true branch
1807 else len = strlen (currentProduction);
1808 production = XtStackAlloc (len + 1, productionbuf)((len + 1) <= sizeof(productionbuf) ? (XtPointer)(productionbuf
) : XtMalloc((unsigned)(len + 1)))
;
13
Value assigned to 'production'
1809 if (production == NULL((void*)0)) _XtAllocError (NULL((void*)0));
14
Assuming 'production' is equal to null
15
Taking true branch
1810 (void) memmove(production, currentProduction, len)__builtin___memmove_chk (production, currentProduction, len, __builtin_object_size
(production, 0))
;
16
Within the expansion of the macro 'memmove':
a
Null pointer argument in call to memory copy function
1811 production[len] = '\0';
1812
1813 params[0] = production;
1814 XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError,
1815 "... found while parsing '%s'", params, &num_params);
1816
1817 XtStackFree (production, productionbuf){ if ((production) != ((XtPointer)(productionbuf))) XtFree(production
); }
;
1818}
1819
1820/***********************************************************************
1821 * ParseTranslationTableProduction
1822 * Parses one line of event bindings.
1823 ***********************************************************************/
1824
1825static String ParseTranslationTableProduction(
1826 TMParseStateTree parseTree,
1827 register String str,
1828 Boolean* error)
1829{
1830 EventSeqPtr eventSeq = NULL((void*)0);
1831 ActionPtr *actionsP;
1832 String production = str;
1833
1834 actionsP = NULL((void*)0);
1835 str = ParseEventSeq(str, &eventSeq, &actionsP,error);
1836 if (*error == TRUE1) {
9
Taking true branch
1837 ShowProduction(production);
10
Calling 'ShowProduction'
1838 FreeEventSeq(eventSeq);
1839 return (str);
1840 }
1841 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1842 str = ParseActionSeq(parseTree, str, actionsP, error);
1843 if (*error == TRUE1) {
1844 ShowProduction(production);
1845 FreeEventSeq(eventSeq);
1846 return (str);
1847 }
1848
1849 _XtAddEventSeqToStateTree(eventSeq, parseTree);
1850 FreeEventSeq(eventSeq);
1851 return (str);
1852}
1853
1854static String CheckForPoundSign(
1855 String str,
1856 _XtTranslateOp defaultOp,
1857 _XtTranslateOp *actualOpRtn)
1858{
1859 String start;
1860 char operation[20];
1861 _XtTranslateOp opType;
1862
1863 opType = defaultOp;
1864 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1865 if (*str == '#') {
1866 int len;
1867 str++;
1868 start = str;
1869 str = ScanIdent(str);
1870 len = MIN(19, str-start)(((19) < (str-start)) ? (19) : (str-start));
1871 (void) memmove(operation, start, len)__builtin___memmove_chk (operation, start, len, __builtin_object_size
(operation, 0))
;
1872 operation[len] = '\0';
1873 if (!strcmp(operation,"replace"))
1874 opType = XtTableReplace0;
1875 else if (!strcmp(operation,"augment"))
1876 opType = XtTableAugment1;
1877 else if (!strcmp(operation,"override"))
1878 opType = XtTableOverride2;
1879 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1880 if (IsNewline(*str)((*str) == '\n')) {
1881 str++;
1882 ScanWhitespace(str)while (*(str) == ' ' || *(str) == '\t') (str)++;
1883 }
1884 }
1885 *actualOpRtn = opType;
1886 return str;
1887}
1888
1889static XtTranslations ParseTranslationTable(
1890 String source,
1891 Boolean isAccelerator,
1892 _XtTranslateOp defaultOp,
1893 Boolean* error)
1894{
1895 XtTranslations xlations;
1896 TMStateTree stateTrees[8];
1897 TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec;
1898 XrmQuark stackQuarks[200];
1899 TMBranchHeadRec stackBranchHeads[200];
1900 StatePtr stackComplexBranchHeads[200];
1901 _XtTranslateOp actualOp;
1902
1903 if (source == NULL((void*)0))
6
Taking false branch
1904 return (XtTranslations)NULL((void*)0);
1905
1906 source = CheckForPoundSign(source, defaultOp, &actualOp);
1907 if (isAccelerator && actualOp == XtTableReplace0)
1908 actualOp = defaultOp;
1909
1910 parseTree->isSimple = TRUE1;
1911 parseTree->mappingNotifyInterest = FALSE0;
1912 parseTree->isAccelerator = isAccelerator;
1913 parseTree->isStackBranchHeads =
1914 parseTree->isStackQuarks =
1915 parseTree->isStackComplexBranchHeads = TRUE1;
1916
1917 parseTree->numQuarks =
1918 parseTree->numBranchHeads =
1919 parseTree->numComplexBranchHeads = 0;
1920
1921 parseTree->quarkTblSize =
1922 parseTree->branchHeadTblSize =
1923 parseTree->complexBranchHeadTblSize = 200;
1924
1925 parseTree->quarkTbl = stackQuarks;
1926 parseTree->branchHeadTbl = stackBranchHeads;
1927 parseTree->complexBranchHeadTbl = stackComplexBranchHeads;
1928
1929 while (source != NULL((void*)0) && *source != '\0') {
7
Loop condition is true. Entering loop body
1930 source = ParseTranslationTableProduction(parseTree, source, error);
8
Calling 'ParseTranslationTableProduction'
1931 if (*error == TRUE1) break;
1932 }
1933 stateTrees[0] = _XtParseTreeToStateTree(parseTree);
1934
1935 if (!parseTree->isStackQuarks)
1936 XtFree((char *)parseTree->quarkTbl);
1937 if (!parseTree->isStackBranchHeads)
1938 XtFree((char *)parseTree->branchHeadTbl);
1939 if (!parseTree->isStackComplexBranchHeads)
1940 XtFree((char *)parseTree->complexBranchHeadTbl);
1941
1942 xlations = _XtCreateXlations(stateTrees, 1, NULL((void*)0), NULL((void*)0));
1943 xlations->operation = actualOp;
1944
1945#ifdef notdef
1946 XtFree(stateTrees);
1947#endif /* notdef */
1948 return xlations;
1949}
1950
1951/*** public procedures ***/
1952
1953/*ARGSUSED*/
1954Boolean XtCvtStringToAcceleratorTable(
1955 Display* dpy,
1956 XrmValuePtr args,
1957 Cardinal *num_args,
1958 XrmValuePtr from,
1959 XrmValuePtr to,
1960 XtPointer *closure)
1961{
1962 String str;
1963 Boolean error = FALSE0;
1964
1965 if (*num_args != 0)
1966 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1967 "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
1968 "String to AcceleratorTable conversion needs no extra arguments",
1969 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1970 str = (String)(from->addr);
1971 if (str == NULL((void*)0)) {
1972 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1973 "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
1974 "String to AcceleratorTable conversion needs string",
1975 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1976 return FALSE0;
1977 }
1978 if (to->addr != NULL((void*)0)) {
1979 if (to->size < sizeof(XtAccelerators)) {
1980 to->size = sizeof(XtAccelerators);
1981 return FALSE0;
1982 }
1983 *(XtAccelerators*)to->addr =
1984 (XtAccelerators) ParseTranslationTable(str, TRUE1, XtTableAugment1, &error);
1985 }
1986 else {
1987 static XtAccelerators staticStateTable;
1988 staticStateTable =
1989 (XtAccelerators) ParseTranslationTable(str, TRUE1, XtTableAugment1, &error);
1990 to->addr = (XPointer) &staticStateTable;
1991 to->size = sizeof(XtAccelerators);
1992 }
1993 if (error == TRUE1)
1994 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1995 "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError,
1996 "String to AcceleratorTable conversion encountered errors",
1997 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1998 return (error != TRUE1);
1999}
2000
2001
2002/*ARGSUSED*/
2003Boolean
2004XtCvtStringToTranslationTable(
2005 Display *dpy,
2006 XrmValuePtr args,
2007 Cardinal *num_args,
2008 XrmValuePtr from,
2009 XrmValuePtr to,
2010 XtPointer *closure_ret)
2011{
2012 String str;
2013 Boolean error = FALSE0;
2014
2015 if (*num_args != 0)
1
Taking false branch
2016 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2017 "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError,
2018 "String to TranslationTable conversion needs no extra arguments",
2019 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2020 str = (String)(from->addr);
2021 if (str == NULL((void*)0)) {
2
Assuming 'str' is not equal to null
3
Taking false branch
2022 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2023 "badParameters","cvtStringToTranslation",XtCXtToolkitError,
2024 "String to TranslationTable conversion needs string",
2025 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2026 return FALSE0;
2027 }
2028 if (to->addr != NULL((void*)0)) {
4
Taking false branch
2029 if (to->size < sizeof(XtTranslations)) {
2030 to->size = sizeof(XtTranslations);
2031 return FALSE0;
2032 }
2033 *(XtTranslations*)to->addr =
2034 ParseTranslationTable(str, FALSE0, XtTableReplace0, &error);
2035 }
2036 else {
2037 static XtTranslations staticStateTable;
2038 staticStateTable =
2039 ParseTranslationTable(str, FALSE0, XtTableReplace0, &error);
5
Calling 'ParseTranslationTable'
2040 to->addr = (XPointer) &staticStateTable;
2041 to->size = sizeof(XtTranslations);
2042 }
2043 if (error == TRUE1)
2044 XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2045 "parseError","cvtStringToTranslationTable",XtCXtToolkitError,
2046 "String to TranslationTable conversion encountered errors",
2047 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2048 return (error != TRUE1);
2049}
2050
2051
2052/*
2053 * Parses a user's or applications translation table
2054 */
2055XtAccelerators XtParseAcceleratorTable(
2056 _Xconstconst char* source)
2057{
2058 Boolean error = FALSE0;
2059 XtAccelerators ret =
2060 (XtAccelerators) ParseTranslationTable ((char *)source, TRUE1, XtTableAugment1, &error);
2061 if (error == TRUE1)
2062 XtWarningMsg ("parseError", "cvtStringToAcceleratorTable",
2063 XtCXtToolkitError,
2064 "String to AcceleratorTable conversion encountered errors",
2065 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2066 return ret;
2067}
2068
2069XtTranslations XtParseTranslationTable(
2070 _Xconstconst char* source)
2071{
2072 Boolean error = FALSE0;
2073 XtTranslations ret = ParseTranslationTable((char *)source, FALSE0, XtTableReplace0, &error);
2074 if (error == TRUE1)
2075 XtWarningMsg ("parseError",
2076 "cvtStringToTranslationTable", XtCXtToolkitError,
2077 "String to TranslationTable conversion encountered errors",
2078 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2079 return ret;
2080}
2081
2082void _XtTranslateInitialize(void)
2083{
2084 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2085 if (initialized) {
2086 XtWarningMsg("translationError","xtTranslateInitialize",
2087 XtCXtToolkitError,"Initializing Translation manager twice.",
2088 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2089 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2090 return;
2091 }
2092
2093 initialized = TRUE1;
2094 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2095 QMeta = XrmPermStringToQuark("Meta");
2096 QCtrl = XrmPermStringToQuark("Ctrl");
2097 QNone = XrmPermStringToQuark("None");
2098 QAny = XrmPermStringToQuark("Any");
2099
2100 Compile_XtEventTable( events, XtNumber(events)((Cardinal) (sizeof(events) / sizeof(events[0]))) );
2101 Compile_XtModifierTable( modifiers, XtNumber(modifiers)((Cardinal) (sizeof(modifiers) / sizeof(modifiers[0]))) );
2102 CompileNameValueTable( buttonNames );
2103 CompileNameValueTable( notifyModes );
2104 CompileNameValueTable( motionDetails );
2105#if 0
2106 CompileNameValueTable( notifyDetail );
2107 CompileNameValueTable( visibilityNotify );
2108 CompileNameValueTable( circulation );
2109 CompileNameValueTable( propertyChanged );
2110#endif
2111 CompileNameValueTable( mappingNotify );
2112}
2113
2114void _XtAddTMConverters(
2115 ConverterTable table)
2116{
2117 _XtTableAddConverter(table,
2118 _XtQString,
2119 XrmPermStringToQuark(XtRTranslationTable((char*)&XtStrings[1841])),
2120 XtCvtStringToTranslationTable, (XtConvertArgList) NULL((void*)0),
2121 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2122 _XtTableAddConverter(table, _XtQString,
2123 XrmPermStringToQuark(XtRAcceleratorTable((char*)&XtStrings[1527])),
2124 XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL((void*)0),
2125 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2126 _XtTableAddConverter(table,
2127 XrmPermStringToQuark( _XtRStateTablePair"_XtStateTablePair" ),
2128 XrmPermStringToQuark(XtRTranslationTable((char*)&XtStrings[1841])),
2129 _XtCvtMergeTranslations, (XtConvertArgList) NULL((void*)0),
2130 (Cardinal)0, True1, CACHED0x002, _XtFreeTranslations, True1);
2131}