forked from gap-system/gap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hookintrprtr.h
152 lines (126 loc) · 5.15 KB
/
hookintrprtr.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/****************************************************************************
**
** This file is part of GAP, a system for computational discrete algebra.
**
** Copyright of GAP belongs to its developers, whose names are too numerous
** to list here. Please refer to the COPYRIGHT file for details.
**
** SPDX-License-Identifier: GPL-2.0-or-later
**
** This file contains functions related to hooking the interpreter.
**
*/
#ifndef GAP_HOOKINTRPRTR_H
#define GAP_HOOKINTRPRTR_H
#include "common.h"
void InstallEvalBoolFunc(Int, EvalBoolFunc);
void InstallEvalExprFunc(Int, EvalExprFunc);
void InstallExecStatFunc(Int, ExecStatFunc);
/****************************************************************************
**
** Store the true values of each function we wrap for hooking. These always
** store the correct values and are never changed.
**
** These are provided for interpreter hooks to call the original methods.
*/
extern ExecStatFunc OriginalExecStatFuncsForHook[256];
extern EvalExprFunc OriginalEvalExprFuncsForHook[256];
extern EvalBoolFunc OriginalEvalBoolFuncsForHook[256];
/****************************************************************************
**
** A struct to represent the hooks allowed into the interpreter
**
**
** This struct represents a list of functions which will be called by the
** interpreter every time statements are executed. Note that the existence
** of any hooks slows GAP down measurably, so don't leave them in if you
** don't need them, and try to make it clear to users they are activated,
** and how to deactivate them.
**
** There are four functions:
**
** * 'visitStat' is called for every visited Stat (and Expr) from the
** GAP bytecode.
** * 'enterFunction' and 'leaveFunction' are called whenever a function
** is entered, or left. This is passed the function which is being
** entered (or left)
** * 'registerStat' is called whenever a statement is read from a text
** file. Note that you will only see files which are read while your
** hooks are running.
** * 'hookName' is a string is used in debugging messages to describe
** the currently active hooks.
**
** This is a sharp tool -- use with care! Look at 'profiling.c', and
** the 'debugger' package for guidance on usage, in particular look
** at FILENAMEID_STAT, FILENAME_STAT and LINE_STAT to find out which
** statement is running.
**
** Remember if you run GAP code during any of these functions, it will
** reinvoke your hooks!
*/
struct InterpreterHooks {
void (*visitStat)(Stat stat);
void (*visitInterpretedStat)(int fileid, int line);
void (*enterFunction)(Obj func);
void (*leaveFunction)(Obj func);
void (*registerStat)(int fileid, int line, int type);
void (*registerInterpretedStat)(int fileid, int line);
const char * hookName;
};
enum { MAX_HOOK_COUNT = 6 };
extern struct InterpreterHooks * activeHooks[MAX_HOOK_COUNT];
void ActivateHooks(struct InterpreterHooks * hook);
void DeactivateHooks(struct InterpreterHooks * hook);
/****************************************************************************
**
** We need the functions in the next three functions to be in the header,
** so they can be inlined away. The only functionality here which should
** be publicly used is 'VisitStatIfHooked',
** 'HookedLineIntoFunction' and 'HookedLineOutFunction'.
**
** 'RegisterStatWithHook' is used because some parts of the interpreter
** skip executing some statements by "cleverness", but we still want them
** to be visible to code coverage, so they appear 'executed'.
*/
/* Represents a loop we use frequently. We store 'hook' in a local
** variable to avoid race conditions.
*/
#define GAP_HOOK_LOOP(member, ...) \
do { \
struct InterpreterHooks * hook; \
for (int i = 0; i < MAX_HOOK_COUNT; ++i) { \
hook = activeHooks[i]; \
if (hook && hook->member) { \
(hook->member)(__VA_ARGS__); \
} \
} \
} while (0)
EXPORT_INLINE void VisitStatIfHooked(Stat stat)
{
GAP_HOOK_LOOP(visitStat, stat);
}
EXPORT_INLINE void HookedLineIntoFunction(Obj func)
{
GAP_HOOK_LOOP(enterFunction, func);
}
EXPORT_INLINE void HookedLineOutFunction(Obj func)
{
GAP_HOOK_LOOP(leaveFunction, func);
}
EXPORT_INLINE void RegisterStatWithHook(int fileid, int line, int type)
{
GAP_HOOK_LOOP(registerStat, fileid, line, type);
}
EXPORT_INLINE void InterpreterHook(int fileid, int line, Int skipped)
{
GAP_HOOK_LOOP(registerInterpretedStat, fileid, line);
if (!skipped) {
GAP_HOOK_LOOP(visitInterpretedStat, fileid, line);
}
}
/****************************************************************************
**
*F InitInfoHookIntrprtr() . . . . . . . . . . . . . table of init functions
*/
StructInitInfo * InitInfoHookIntrprtr(void);
#endif // GAP_HOOKINTRPRTR_H