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];
BOOL ActivateHooks(struct InterpreterHooks * hook);
BOOL 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
|