aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/eventpro.c
diff options
context:
space:
mode:
Diffstat (limited to 'mps/code/eventpro.c')
-rw-r--r--mps/code/eventpro.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/mps/code/eventpro.c b/mps/code/eventpro.c
new file mode 100644
index 00000000000..9cb8700fe8d
--- /dev/null
+++ b/mps/code/eventpro.c
@@ -0,0 +1,433 @@
1/* impl.c.eventpro: Event processing routines
2 * Copyright (C) 1999 Harlequin Group plc. All rights reserved.
3 *
4 * $HopeName: MMsrc!eventpro.c(trunk.3) $
5 */
6
7#include "config.h"
8/* override variety setting for EVENT */
9#define EVENT
10
11#include "table.h"
12
13#include "eventcom.h"
14#include "eventpro.h"
15#include "misc.h"
16#include "mpmtypes.h"
17
18#include <assert.h> /* assert */
19#include <stdlib.h> /* size_t */
20#include <string.h> /* strcmp */
21
22
23struct EventProcStruct {
24 Bool partialLog; /* Is this a partial log? */
25 EventProcReader reader; /* reader fn */
26 void *readerP; /* closure pointer for reader fn */
27 Table internTable; /* dictionary of intern ids to symbols */
28 Table labelTable; /* dictionary of addrs to intern ids */
29 void *cachedEvent;
30};
31
32
33/* error -- error signalling
34 *
35 * Should integrate with client exceptions, but that'll do for now.
36 */
37
38#define error(fmt, arg) assert(((void)fmt, FALSE));
39
40
41/* PointerAdd -- add offset to pointer
42 *
43 * Copy of the def in mpm.h which we can't include
44 */
45
46#define PointerAdd(p, s) ((void *)((char *)(p) + (s)))
47
48
49/* sizeAlignUp -- align size_t values up */
50
51#define sizeAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1))
52
53
54/* EventSizeAlign -- Calculate actual size of event in the output
55 *
56 * Calculates the actual size of an event in the output, given the size
57 * of the structure. This has to agree with the writing (EVENT_END).
58 */
59
60#define EventSizeAlign(size) sizeAlignUp(size, sizeof(Word))
61
62
63
64/* Event types */
65
66
67/* eventTypes -- an array containing info about the event types */
68
69typedef struct {
70 EventType type;
71 char *name;
72 size_t code;
73 size_t length;
74 char *format;
75} eventRecord;
76
77static eventRecord eventTypes[] = {
78 {0, "(unused)", 0, 0, "0"},
79#define RELATION(name, code, always, kind, format) \
80 {Event##name, #name, code, \
81 EventSizeAlign(sizeof(Event##format##Struct)), #format},
82#include "eventdef.h"
83#undef RELATION
84};
85
86#define eventTypeCount (sizeof(eventTypes) / sizeof(eventRecord))
87
88
89/* eventType2Index -- find index in eventTypes for the given type */
90
91static size_t eventType2Index(EventType type)
92{
93 size_t i;
94
95 for(i = 0; i < eventTypeCount; ++i)
96 if (eventTypes[i].type == type)
97 return i;
98 error("Unknown event type %08lX", type);
99 return 0;
100}
101
102
103/* eventcode2Index -- find index in eventTypes for the given code */
104
105static size_t eventCode2Index(EventCode code, Bool errorp)
106{
107 size_t i;
108
109 for(i = 0; i < eventTypeCount; ++i)
110 if (eventTypes[i].code == code)
111 return i;
112 if (errorp)
113 error("Unknown event code %08lX", code);
114 return 0;
115}
116
117
118/* EventName2Code -- find event code for the given event name */
119
120EventCode EventName2Code(char *name)
121{
122 size_t i;
123
124 for(i = 0; i < eventTypeCount; ++i)
125 if (strcmp(eventTypes[i].name, name) == 0) {
126 assert(eventTypes[i].code <= EventCodeMAX);
127 return eventTypes[i].code;
128 }
129 error("Unknown event name %s", name);
130 return 0;
131}
132
133
134/* EventCode2Name -- find event name for the given event code */
135
136char *EventCode2Name(EventCode code)
137{
138 return eventTypes[eventCode2Index(code, TRUE)].name;
139}
140
141
142/* EventCode2Format -- find format for the given event code */
143
144char *EventCode2Format(EventCode code)
145{
146 return eventTypes[eventCode2Index(code, TRUE)].format;
147}
148
149
150/* EventGetCode -- get event code of the given event */
151
152EventCode EventGetCode(Event event)
153{
154 size_t i = eventType2Index(event->any.code);
155 assert(eventTypes[i].code <= EventCodeMAX);
156 return eventTypes[i].code;
157}
158
159
160Bool EventCodeIsValid(EventCode code)
161{
162 return (eventCode2Index(code, FALSE) != 0);
163}
164
165
166/* EventStrings */
167
168
169/* EventStringEmpty -- an empty event string */
170
171EventStringStruct EventStringEmpty = {0, ""};
172
173
174/* eventStringCopy -- copy an event string */
175
176static Res eventStringCopy(EventString *str_o, EventString str)
177{
178 EventString newStr;
179
180 newStr = (EventString)malloc(offsetof(EventStringStruct, str)
181 + str->len);
182 if (newStr == NULL) return ResMEMORY;
183 newStr->len = str->len;
184 memcpy(&(newStr->str), &(str->str), str->len);
185 *str_o = newStr;
186 return ResOK;
187}
188
189
190static void eventStringDestroy(EventString str)
191{
192 free(str);
193}
194
195
196/* Labels */
197
198
199/* Symbol -- representation of an interned string */
200
201typedef struct symbolStruct {
202 Word id;
203 EventString name;
204} symbolStruct;
205typedef struct symbolStruct *Symbol;
206
207
208/* Label -- representation of a labelled address */
209
210typedef struct labelStruct {
211 Word id;
212 Word time;
213 Addr addr;
214} labelStruct;
215typedef struct labelStruct *Label;
216
217
218/* AddrLabel -- return intern id for given addr (or 0 if none) */
219
220Word AddrLabel(EventProc proc, Addr addr)
221{
222 void *entry;
223
224 if (TableLookup(&entry, proc->labelTable, (Word)addr))
225 return ((Label)entry)->id;
226 else
227 return (Word)0;
228}
229
230
231/* LabelText -- return text for given intern id (or NULL if none) */
232
233EventString LabelText(EventProc proc, Word id)
234{
235 void *entry;
236
237 if (TableLookup(&entry, proc->internTable, id))
238 return ((Symbol)entry)->name;
239 else
240 return NULL;
241}
242
243
244/* Processing */
245
246
247/* EventRead -- read one event from the file and allocate descriptor */
248
249#define internStrOffset (offsetof(EventWSStruct, s1.str))
250
251Res EventRead(Event *eventReturn, EventProc proc)
252{
253 size_t index, length;
254 Res res;
255 EventType type;
256 Event event;
257 void *restOfEvent;
258
259 res = proc->reader(proc->readerP, &type, sizeof(EventType));
260 if (res != ResOK) return res;
261
262 index = eventType2Index(type);
263 length = eventTypes[index].length;
264 if (proc->cachedEvent != NULL) {
265 event = proc->cachedEvent;
266 proc->cachedEvent = NULL;
267 } else {
268 /* This is too long for most events, but never mind. */
269 event = (Event)malloc(sizeof(EventUnion));
270 if (event == NULL) return ResMEMORY;
271 }
272
273 event->any.code = type;
274 restOfEvent = PointerAdd(event, sizeof(EventType));
275 if (type == EventIntern) { /* the only string event */
276 /* read enough to get the length */
277 res = proc->reader(proc->readerP, restOfEvent,
278 internStrOffset - sizeof(EventType));
279 if (res != ResOK) return res;
280 /* read the rest */
281 res = proc->reader(proc->readerP, &(event->ws.s1.str),
282 /* Length must agree with EVENT_WS. */
283 EventSizeAlign(internStrOffset + event->ws.s1.len)
284 - internStrOffset);
285 if (res != ResOK) return res;
286 } else {
287 res = proc->reader(proc->readerP, restOfEvent,
288 length - sizeof(EventType));
289 if (res != ResOK) return res;
290 }
291 *eventReturn = event;
292 return ResOK;
293}
294
295
296/* EventRecord -- record event in databases
297 *
298 * Currently only labels are tracked, but perhaps there will be other
299 * stuff in the future.
300 */
301
302Res EventRecord(EventProc proc, Event event, Word etime)
303{
304 Res res;
305
306 switch(event->any.code) {
307 case EventIntern: { /* id, label */
308 Symbol sym = malloc(sizeof(symbolStruct));
309
310 if (sym == NULL) return ResMEMORY;
311 sym->id = event->ws.w0;
312 res = eventStringCopy(&(sym->name), &(event->ws.s1));
313 if (res != ResOK) {
314 free(sym);
315 return res;
316 }
317 res = TableDefine(proc->internTable, sym->id, sym);
318 } break;
319 case EventLabel: { /* addr, id */
320 Label label = malloc(sizeof(labelStruct));
321 void *entry;
322
323 if (label == NULL) return ResMEMORY;
324 label->id = event->aw.w1;
325 if (!proc->partialLog) {
326 assert(TableLookup(&entry, proc->internTable, label->id));
327 }
328 label->time = etime;
329 label->addr = event->aw.a0;
330 if (TableLookup(&entry, proc->labelTable, (Word)label->addr))
331 res = TableRedefine(proc->labelTable, (Word)label->addr, label);
332 else
333 res = TableDefine(proc->labelTable, (Word)label->addr, label);
334 } break;
335 default:
336 res = ResOK;
337 break;
338 }
339 return res;
340}
341
342
343/* EventDestroy -- destroy an event */
344
345void EventDestroy(EventProc proc, Event event)
346{
347 if (proc->cachedEvent == NULL)
348 proc->cachedEvent = event;
349 else
350 free(event);
351}
352
353
354/* initialization and finishing */
355
356
357/* Checking macros, copied from check.h */
358
359#define CHECKLVALUE(lv1, lv2) \
360 ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE)
361
362#define CHECKTYPE(t1, t2) \
363 (sizeof(t1) == sizeof(t2) && \
364 CHECKLVALUE(*((t1 *)0), *((t2 *)0)))
365
366#define CHECKFIELDAPPROX(s1, f1, s2, f2) \
367 (sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \
368 offsetof(s1, f1) == offsetof(s2, f2))
369
370#define CHECKFIELD(s1, f1, s2, f2) \
371 (CHECKFIELDAPPROX(s1, f1, s2, f2) && \
372 CHECKLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2))
373
374
375/* EventProcCreate -- initialize the module */
376
377Res EventProcCreate(EventProc *procReturn, Bool partial,
378 EventProcReader reader, void *readerP)
379{
380 Res res;
381 EventProc proc = malloc(sizeof(struct EventProcStruct));
382
383 if (proc == NULL) return ResMEMORY;
384
385 /* check event struct access */
386 assert(CHECKFIELD(EventUnion, any.code, EventWSStruct, code));
387 assert(CHECKFIELD(EventUnion, any.clock, EventWSStruct, clock));
388 /* check use of labelTable */
389 assert(sizeof(Word) >= sizeof(Addr));
390
391 proc->partialLog = partial;
392 proc->reader = reader; proc->readerP = readerP;
393 res = TableCreate(&proc->internTable, (size_t)1<<4);
394 if (res != ResOK) goto failIntern;
395 res = TableCreate(&proc->labelTable, (size_t)1<<7);
396 if (res != ResOK) goto failLabel;
397 proc->cachedEvent = NULL;
398 *procReturn = proc;
399 return ResOK;
400
401failLabel:
402 TableDestroy(proc->internTable);
403failIntern:
404 free(proc);
405 return res;
406}
407
408
409/* EventProcDestroy -- finish the module */
410
411static void deallocItem(Word key, void *value)
412{
413 UNUSED(key);
414 free(value);
415}
416
417static void deallocSym(Word key, void *value)
418{
419 UNUSED(key);
420 eventStringDestroy(((Symbol)value)->name);
421 free(value);
422}
423
424void EventProcDestroy(EventProc proc)
425{
426 TableMap(proc->labelTable, deallocItem);
427 TableMap(proc->internTable, deallocSym);
428 TableDestroy(proc->labelTable);
429 TableDestroy(proc->internTable);
430 if (proc->cachedEvent != NULL)
431 free(proc->cachedEvent);
432 free(proc);
433}