1d4c6f1e6SMasatake YAMATO /*
2d4c6f1e6SMasatake YAMATO * Copyright (c) 2000-2003, Darren Hiebert
3d4c6f1e6SMasatake YAMATO *
4d4c6f1e6SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
6d4c6f1e6SMasatake YAMATO *
7d4c6f1e6SMasatake YAMATO * This module contains functions for applying regular expression matching.
8d4c6f1e6SMasatake YAMATO *
95dbd2e67SK.Takata * The code for utilizing the Gnu regex package with regards to processing the
10d4c6f1e6SMasatake YAMATO * regex option and checking for regex matches was adapted from routines in
11d4c6f1e6SMasatake YAMATO * Gnu etags.
12d4c6f1e6SMasatake YAMATO */
13d4c6f1e6SMasatake YAMATO
14d4c6f1e6SMasatake YAMATO /*
15d4c6f1e6SMasatake YAMATO * INCLUDE FILES
16d4c6f1e6SMasatake YAMATO */
17d4c6f1e6SMasatake YAMATO #include "general.h" /* must always come first */
18d4c6f1e6SMasatake YAMATO
19d4c6f1e6SMasatake YAMATO #include <string.h>
20d4c6f1e6SMasatake YAMATO
21d4c6f1e6SMasatake YAMATO #include <ctype.h>
22d4c6f1e6SMasatake YAMATO #include <stddef.h>
23d4c6f1e6SMasatake YAMATO #ifdef HAVE_SYS_TYPES_H
24d4c6f1e6SMasatake YAMATO # include <sys/types.h> /* declare off_t (not known to regex.h on FreeBSD) */
25d4c6f1e6SMasatake YAMATO #endif
26d4c6f1e6SMasatake YAMATO
27540cbe83SK.Takata #include <inttypes.h>
28540cbe83SK.Takata
29d4c6f1e6SMasatake YAMATO #include "debug.h"
30c2a93c9fSMasatake YAMATO #include "colprint_p.h"
31a57cbfc9SMasatake YAMATO #include "entry_p.h"
32c08c70d0SMasatake YAMATO #include "field_p.h"
33bf281e9cSMasatake YAMATO #include "flags_p.h"
34a4e7ab31SMasatake YAMATO #include "htable.h"
353525c8f1SMasatake YAMATO #include "kind.h"
36a7c0db8cSMasatake YAMATO #include "options.h"
37e8386a4eSMasatake YAMATO #include "optscript.h"
380d502ef0SMasatake YAMATO #include "parse_p.h"
39b19716b4SMasatake YAMATO #include "promise.h"
40d4c6f1e6SMasatake YAMATO #include "read.h"
41b5df137eSMasatake YAMATO #include "read_p.h"
42d4c6f1e6SMasatake YAMATO #include "routines.h"
4329e40fb6SMasatake YAMATO #include "routines_p.h"
44668e3666SMasatake YAMATO #include "script_p.h"
4585021c5bSMasatake YAMATO #include "trace.h"
46f53f3c39SMasatake YAMATO #include "trashbox.h"
47e2a3289bSMasatake YAMATO #include "xtag_p.h"
48d4c6f1e6SMasatake YAMATO
49ce990805SThomas Braun static bool regexAvailable = false;
50d4c6f1e6SMasatake YAMATO
51d4c6f1e6SMasatake YAMATO /*
52d4c6f1e6SMasatake YAMATO * MACROS
53d4c6f1e6SMasatake YAMATO */
54d4c6f1e6SMasatake YAMATO
55042e4190SMasatake YAMATO /* The max depth of taction=enter/leave stack */
56042e4190SMasatake YAMATO #define MTABLE_STACK_MAX_DEPTH 64
57042e4190SMasatake YAMATO
58afcf38b2SMasatake YAMATO /* How many times ctags allows a mtable parser
59afcf38b2SMasatake YAMATO stays at the same input position across table switching.
60afcf38b2SMasatake YAMATO
61afcf38b2SMasatake YAMATO The value is derived from MTABLE_STACK_MAX_DEPTH.
62afcf38b2SMasatake YAMATO No deep meaning is in that. It just for simplifying
63afcf38b2SMasatake YAMATO Tmain cases. */
64afcf38b2SMasatake YAMATO #define MTABLE_MOTIONLESS_MAX (MTABLE_STACK_MAX_DEPTH + 1)
65afcf38b2SMasatake YAMATO
66c30b89acSMasatake YAMATO #define DEFAULT_REGEX_BACKEND "e"
67042e4190SMasatake YAMATO
68d4c6f1e6SMasatake YAMATO /*
69d4c6f1e6SMasatake YAMATO * DATA DECLARATIONS
70d4c6f1e6SMasatake YAMATO */
71d4c6f1e6SMasatake YAMATO
72d4c6f1e6SMasatake YAMATO enum pType { PTRN_TAG, PTRN_CALLBACK };
73d4c6f1e6SMasatake YAMATO
742fa3c9e1SMasatake YAMATO enum scopeAction {
752fa3c9e1SMasatake YAMATO SCOPE_REF = 1UL << 0,
762fa3c9e1SMasatake YAMATO SCOPE_POP = 1UL << 1,
772fa3c9e1SMasatake YAMATO SCOPE_PUSH = 1UL << 2,
782fa3c9e1SMasatake YAMATO SCOPE_CLEAR = 1UL << 3,
79f998e51dSMasatake YAMATO SCOPE_REF_AFTER_POP = 1UL << 4,
80f998e51dSMasatake YAMATO SCOPE_PLACEHOLDER = 1UL << 5,
812fa3c9e1SMasatake YAMATO };
822fa3c9e1SMasatake YAMATO
830cbf3f0dSMasatake YAMATO enum tableAction {
840cbf3f0dSMasatake YAMATO TACTION_NOP,
850cbf3f0dSMasatake YAMATO TACTION_ENTER, /* {tenter=N} */
860cbf3f0dSMasatake YAMATO TACTION_LEAVE, /* {tleave} */
870cbf3f0dSMasatake YAMATO TACTION_JUMP, /* {tjump=N} */
880cbf3f0dSMasatake YAMATO TACTION_RESET, /* {treset=N} */
890cbf3f0dSMasatake YAMATO TACTION_QUIT, /* {tquit} */
900cbf3f0dSMasatake YAMATO };
910cbf3f0dSMasatake YAMATO
92f53f3c39SMasatake YAMATO struct fieldPattern {
93f53f3c39SMasatake YAMATO fieldType ftype;
94f53f3c39SMasatake YAMATO const char *template;
95f53f3c39SMasatake YAMATO };
96f53f3c39SMasatake YAMATO
976cdf5716SMasatake YAMATO struct boundarySpec {
986cdf5716SMasatake YAMATO int patternGroup;
996cdf5716SMasatake YAMATO bool fromStartOfGroup;
1006cdf5716SMasatake YAMATO bool placeholder;
1016cdf5716SMasatake YAMATO };
1026cdf5716SMasatake YAMATO
1036cdf5716SMasatake YAMATO struct guestLangSpec {
1046cdf5716SMasatake YAMATO enum guestLangSpecType {
1056cdf5716SMasatake YAMATO GUEST_LANG_UNKNOWN,
1066cdf5716SMasatake YAMATO GUEST_LANG_PLACEHOLDER, /* _ */
1076cdf5716SMasatake YAMATO GUEST_LANG_STATIC_LANGNAME, /* C, Python,... */
1086cdf5716SMasatake YAMATO GUEST_LANG_PTN_GROUP_FOR_LANGNAME, /* \1, \2, ..., \9 */
1096cdf5716SMasatake YAMATO GUEST_LANG_PTN_GROUP_FOR_FILEMAP, /* *1, *2, ... *9 */
1106cdf5716SMasatake YAMATO } type;
1116cdf5716SMasatake YAMATO union {
1126cdf5716SMasatake YAMATO langType lang;
1136cdf5716SMasatake YAMATO int patternGroup;
1146cdf5716SMasatake YAMATO } spec;
1156cdf5716SMasatake YAMATO };
1166cdf5716SMasatake YAMATO
1176cdf5716SMasatake YAMATO struct guestSpec {
1186cdf5716SMasatake YAMATO struct guestLangSpec lang;
1196cdf5716SMasatake YAMATO #define BOUNDARY_START 0
1206cdf5716SMasatake YAMATO #define BOUNDARY_END 1
1216cdf5716SMasatake YAMATO struct boundarySpec boundary[2];
1226cdf5716SMasatake YAMATO };
1236cdf5716SMasatake YAMATO
124c9bfc26fSMasatake YAMATO struct mGroupSpec {
125b2c16b34SMasatake YAMATO #define NO_MULTILINE -1
126c9bfc26fSMasatake YAMATO int forLineNumberDetermination;
127c9bfc26fSMasatake YAMATO int forNextScanning;
128c9bfc26fSMasatake YAMATO /* true => start, false => end */
129c9bfc26fSMasatake YAMATO bool nextFromStart;
130c9bfc26fSMasatake YAMATO };
131c9bfc26fSMasatake YAMATO
1320cbf3f0dSMasatake YAMATO struct mTableActionSpec {
1330cbf3f0dSMasatake YAMATO enum tableAction action;
1340cbf3f0dSMasatake YAMATO struct regexTable *table;
13540177cd9SMasatake YAMATO
13640177cd9SMasatake YAMATO /* used when action == TACTION_ENTER */
13740177cd9SMasatake YAMATO struct regexTable *continuation_table;
1380cbf3f0dSMasatake YAMATO };
1390cbf3f0dSMasatake YAMATO
140d4c6f1e6SMasatake YAMATO typedef struct {
141c30b89acSMasatake YAMATO regexCompiledCode pattern;
142d4c6f1e6SMasatake YAMATO enum pType type;
143ce990805SThomas Braun bool exclusive;
144ce990805SThomas Braun bool accept_empty_name;
145d4c6f1e6SMasatake YAMATO union {
146d4c6f1e6SMasatake YAMATO struct {
147fbcb3274SMasatake YAMATO int kindIndex;
14884f3a057SMasatake YAMATO roleBitsType roleBits;
149d4c6f1e6SMasatake YAMATO char *name_pattern;
150d4c6f1e6SMasatake YAMATO } tag;
151d4c6f1e6SMasatake YAMATO struct {
152d4c6f1e6SMasatake YAMATO regexCallback function;
1536ff4dab6SMasatake YAMATO void *userData;
154d4c6f1e6SMasatake YAMATO } callback;
155d4c6f1e6SMasatake YAMATO } u;
1562fa3c9e1SMasatake YAMATO unsigned int scopeActions;
157ce990805SThomas Braun bool *disabled;
1581b9c3aecSMasatake YAMATO
1591b9c3aecSMasatake YAMATO enum regexParserType regptype;
160c9bfc26fSMasatake YAMATO struct mGroupSpec mgroup;
1616cdf5716SMasatake YAMATO struct guestSpec guest;
1620cbf3f0dSMasatake YAMATO struct mTableActionSpec taction;
1630cbf3f0dSMasatake YAMATO
16410db13faSMasatake YAMATO int xtagType;
165f53f3c39SMasatake YAMATO ptrArray *fieldPatterns;
1669ec7efeaSMasatake YAMATO
1675372d785SMasatake YAMATO char *pattern_string;
1681e923193SMasatake YAMATO
1690d56cc8eSMasatake YAMATO char *anonymous_tag_prefix;
1700d56cc8eSMasatake YAMATO
1719a1e266aSHadriel Kaplan struct {
1729a1e266aSHadriel Kaplan errorSelection selection;
1739a1e266aSHadriel Kaplan char *message_string;
1749a1e266aSHadriel Kaplan } message;
1759a1e266aSHadriel Kaplan
176e8386a4eSMasatake YAMATO char *optscript_src;
177e8386a4eSMasatake YAMATO EsObject *optscript;
178e8386a4eSMasatake YAMATO
1799ec7efeaSMasatake YAMATO int refcount;
180d4c6f1e6SMasatake YAMATO } regexPattern;
181d4c6f1e6SMasatake YAMATO
182d4c6f1e6SMasatake YAMATO
183134629a0SHadriel Kaplan typedef struct {
184134629a0SHadriel Kaplan /* the pattern can be shared among entries using a refcount */
185134629a0SHadriel Kaplan regexPattern *pattern;
186134629a0SHadriel Kaplan
187134629a0SHadriel Kaplan /* but the statistics are per-table-entry */
188134629a0SHadriel Kaplan struct {
189134629a0SHadriel Kaplan unsigned int match;
190134629a0SHadriel Kaplan unsigned int unmatch;
191134629a0SHadriel Kaplan } statistics;
192134629a0SHadriel Kaplan } regexTableEntry;
193134629a0SHadriel Kaplan
194134629a0SHadriel Kaplan
1950cbf3f0dSMasatake YAMATO #define TABLE_INDEX_UNUSED -1
196e0e33135SMasatake YAMATO struct regexTable {
197e0e33135SMasatake YAMATO char *name;
198134629a0SHadriel Kaplan ptrArray *entries;
199e0e33135SMasatake YAMATO };
200e0e33135SMasatake YAMATO
2016cdf5716SMasatake YAMATO struct boundaryInRequest {
2026cdf5716SMasatake YAMATO bool offset_set;
2036cdf5716SMasatake YAMATO off_t offset;
2046cdf5716SMasatake YAMATO };
2056cdf5716SMasatake YAMATO
2066cdf5716SMasatake YAMATO struct guestRequest {
2076cdf5716SMasatake YAMATO bool lang_set;
2086cdf5716SMasatake YAMATO langType lang;
2096cdf5716SMasatake YAMATO
2106cdf5716SMasatake YAMATO struct boundaryInRequest boundary[2];
2116cdf5716SMasatake YAMATO };
2126cdf5716SMasatake YAMATO
2132bbd136eSMasatake YAMATO typedef struct {
2142bbd136eSMasatake YAMATO const char *line;
215ed3202bdSMasatake YAMATO const char *start;
2162bbd136eSMasatake YAMATO const regexPattern* const patbuf;
2172bbd136eSMasatake YAMATO const regmatch_t* const pmatch;
2182bbd136eSMasatake YAMATO int nmatch;
2192b8d4c66SMasatake YAMATO struct mTableActionSpec taction;
220653692b7SMasatake YAMATO bool advanceto;
221653692b7SMasatake YAMATO unsigned int advanceto_delta;
2222bbd136eSMasatake YAMATO } scriptWindow;
2232bbd136eSMasatake YAMATO
22453dda59eSMasatake YAMATO struct lregexControlBlock {
2253afb5475SMasatake YAMATO int currentScope;
226134629a0SHadriel Kaplan ptrArray *entries [2];
227e0e33135SMasatake YAMATO
228e0e33135SMasatake YAMATO ptrArray *tables;
22941e0b4f8SMasatake YAMATO ptrArray *tstack;
230e0e33135SMasatake YAMATO
2316cdf5716SMasatake YAMATO struct guestRequest *guest_req;
2326cdf5716SMasatake YAMATO
233e8386a4eSMasatake YAMATO EsObject *local_dict;
234e8386a4eSMasatake YAMATO
235b6124a60SMasatake YAMATO ptrArray *hook[SCRIPT_HOOK_MAX];
236b6124a60SMasatake YAMATO ptrArray *hook_code[SCRIPT_HOOK_MAX];
2375c872341SMasatake YAMATO
238bce55cc7SMasatake YAMATO langType owner;
2392bbd136eSMasatake YAMATO
2402bbd136eSMasatake YAMATO scriptWindow *window;
241bce55cc7SMasatake YAMATO };
242bce55cc7SMasatake YAMATO
243d4c6f1e6SMasatake YAMATO /*
244d4c6f1e6SMasatake YAMATO * DATA DEFINITIONS
245d4c6f1e6SMasatake YAMATO */
246e8386a4eSMasatake YAMATO static OptVM *optvm;
247e8386a4eSMasatake YAMATO static EsObject *lregex_dict = es_nil;
248d4c6f1e6SMasatake YAMATO
249d4c6f1e6SMasatake YAMATO /*
250d4c6f1e6SMasatake YAMATO * FUNCTION DEFINITIONS
251d4c6f1e6SMasatake YAMATO */
25246837a67SHadriel Kaplan static int getTableIndexForName (const struct lregexControlBlock *const lcb, const char *name);
253134629a0SHadriel Kaplan static void deletePattern (regexPattern *p);
254b19716b4SMasatake YAMATO static int makePromiseForAreaSpecifiedWithOffsets (const char *parser,
255b19716b4SMasatake YAMATO off_t startOffset,
256b19716b4SMasatake YAMATO off_t endOffset);
257b19716b4SMasatake YAMATO
2586cdf5716SMasatake YAMATO static struct guestRequest *guestRequestNew (void);
2596cdf5716SMasatake YAMATO static void guestRequestDelete (struct guestRequest *);
2606cdf5716SMasatake YAMATO static bool guestRequestIsFilled(struct guestRequest *);
2616cdf5716SMasatake YAMATO static void guestRequestClear (struct guestRequest *);
2626cdf5716SMasatake YAMATO static void guestRequestSubmit (struct guestRequest *);
263d4c6f1e6SMasatake YAMATO
264668e3666SMasatake YAMATO static EsObject *scriptRead (OptVM *vm, const char *src);
2652bbd136eSMasatake YAMATO static void scriptSetup (OptVM *vm, struct lregexControlBlock *lcb, int corkIndex, scriptWindow *window);
266668e3666SMasatake YAMATO static EsObject* scriptEval (OptVM *vm, EsObject *optscript);
267b6124a60SMasatake YAMATO static void scriptEvalHook (OptVM *vm, struct lregexControlBlock *lcb, enum scriptHook hook);
268668e3666SMasatake YAMATO static void scriptTeardown (OptVM *vm, struct lregexControlBlock *lcb);
269fba3677cSMasatake YAMATO
27077bd99b5SMasatake YAMATO static char* make_match_string (scriptWindow *window, int group);
271cf6b3bb9SMasatake YAMATO static matchLoc *make_mloc (scriptWindow *window, int group, bool start);
27277bd99b5SMasatake YAMATO
deleteTable(void * ptrn)273e0e33135SMasatake YAMATO static void deleteTable (void *ptrn)
274e0e33135SMasatake YAMATO {
275e0e33135SMasatake YAMATO struct regexTable *t = ptrn;
276e0e33135SMasatake YAMATO
277134629a0SHadriel Kaplan ptrArrayDelete (t->entries);
27806a48990SMasatake YAMATO eFree (t->name);
279e0e33135SMasatake YAMATO eFree (t);
280e0e33135SMasatake YAMATO }
281e0e33135SMasatake YAMATO
deleteTableEntry(void * ptrn)282134629a0SHadriel Kaplan static void deleteTableEntry (void *ptrn)
283c9bfc26fSMasatake YAMATO {
284134629a0SHadriel Kaplan regexTableEntry *e = ptrn;
285134629a0SHadriel Kaplan Assert (e && e->pattern);
286134629a0SHadriel Kaplan deletePattern (e->pattern);
287134629a0SHadriel Kaplan eFree (e);
288134629a0SHadriel Kaplan }
289c9bfc26fSMasatake YAMATO
deletePattern(regexPattern * p)290134629a0SHadriel Kaplan static void deletePattern (regexPattern *p)
291134629a0SHadriel Kaplan {
2929ec7efeaSMasatake YAMATO p->refcount--;
2939ec7efeaSMasatake YAMATO
2949ec7efeaSMasatake YAMATO if (p->refcount > 0)
2959ec7efeaSMasatake YAMATO return;
2969ec7efeaSMasatake YAMATO
297c30b89acSMasatake YAMATO p->pattern.backend->delete_code (p->pattern.code);
298d4c6f1e6SMasatake YAMATO
299d4c6f1e6SMasatake YAMATO if (p->type == PTRN_TAG)
300d4c6f1e6SMasatake YAMATO {
301d4c6f1e6SMasatake YAMATO eFree (p->u.tag.name_pattern);
302d4c6f1e6SMasatake YAMATO p->u.tag.name_pattern = NULL;
303d4c6f1e6SMasatake YAMATO }
304f53f3c39SMasatake YAMATO
305f53f3c39SMasatake YAMATO if (p->fieldPatterns)
306f53f3c39SMasatake YAMATO {
307f53f3c39SMasatake YAMATO ptrArrayDelete (p->fieldPatterns);
308f53f3c39SMasatake YAMATO p->fieldPatterns = NULL;
309f53f3c39SMasatake YAMATO }
310b2c16b34SMasatake YAMATO
3115372d785SMasatake YAMATO eFree (p->pattern_string);
3129a1e266aSHadriel Kaplan
3139a1e266aSHadriel Kaplan if (p->message.message_string)
3149a1e266aSHadriel Kaplan eFree (p->message.message_string);
3159a1e266aSHadriel Kaplan
3160d56cc8eSMasatake YAMATO if (p->anonymous_tag_prefix)
3170d56cc8eSMasatake YAMATO eFree (p->anonymous_tag_prefix);
3180d56cc8eSMasatake YAMATO
319e8386a4eSMasatake YAMATO if (p->optscript)
320e8386a4eSMasatake YAMATO es_object_unref (p->optscript);
321e8386a4eSMasatake YAMATO if (p->optscript_src)
322e8386a4eSMasatake YAMATO eFree (p->optscript_src);
323e8386a4eSMasatake YAMATO
324134629a0SHadriel Kaplan eFree (p);
325d4c6f1e6SMasatake YAMATO }
326b2c16b34SMasatake YAMATO
clearPatternSet(struct lregexControlBlock * lcb)327b2c16b34SMasatake YAMATO static void clearPatternSet (struct lregexControlBlock *lcb)
328b2c16b34SMasatake YAMATO {
329134629a0SHadriel Kaplan ptrArrayClear (lcb->entries [REG_PARSER_SINGLE_LINE]);
330134629a0SHadriel Kaplan ptrArrayClear (lcb->entries [REG_PARSER_MULTI_LINE]);
331e0e33135SMasatake YAMATO ptrArrayClear (lcb->tables);
332d4c6f1e6SMasatake YAMATO }
333d4c6f1e6SMasatake YAMATO
allocLregexControlBlock(parserDefinition * parser)334bce55cc7SMasatake YAMATO extern struct lregexControlBlock* allocLregexControlBlock (parserDefinition *parser)
335bce55cc7SMasatake YAMATO {
336bce55cc7SMasatake YAMATO struct lregexControlBlock *lcb = xCalloc (1, struct lregexControlBlock);
337b2c16b34SMasatake YAMATO
338134629a0SHadriel Kaplan lcb->entries[REG_PARSER_SINGLE_LINE] = ptrArrayNew(deleteTableEntry);
339134629a0SHadriel Kaplan lcb->entries[REG_PARSER_MULTI_LINE] = ptrArrayNew(deleteTableEntry);
340e0e33135SMasatake YAMATO lcb->tables = ptrArrayNew(deleteTable);
34141e0b4f8SMasatake YAMATO lcb->tstack = ptrArrayNew(NULL);
3426cdf5716SMasatake YAMATO lcb->guest_req = guestRequestNew ();
343e8386a4eSMasatake YAMATO lcb->local_dict = es_nil;
3441409a195SMasatake YAMATO
345b6124a60SMasatake YAMATO for (int i = 0; i< SCRIPT_HOOK_MAX; i++)
3461409a195SMasatake YAMATO {
3471409a195SMasatake YAMATO lcb->hook[i] = ptrArrayNew (eFree);
3481409a195SMasatake YAMATO lcb->hook_code[i] = ptrArrayNew ((ptrArrayDeleteFunc)es_object_unref);
3491409a195SMasatake YAMATO }
350bce55cc7SMasatake YAMATO lcb->owner = parser->id;
351b2c16b34SMasatake YAMATO
352bce55cc7SMasatake YAMATO return lcb;
353bce55cc7SMasatake YAMATO }
354bce55cc7SMasatake YAMATO
freeLregexControlBlock(struct lregexControlBlock * lcb)355bce55cc7SMasatake YAMATO extern void freeLregexControlBlock (struct lregexControlBlock* lcb)
356bce55cc7SMasatake YAMATO {
357056b32e1SMasatake YAMATO clearPatternSet (lcb);
358b2c16b34SMasatake YAMATO
359134629a0SHadriel Kaplan ptrArrayDelete (lcb->entries [REG_PARSER_SINGLE_LINE]);
360134629a0SHadriel Kaplan lcb->entries [REG_PARSER_SINGLE_LINE] = NULL;
361134629a0SHadriel Kaplan ptrArrayDelete (lcb->entries [REG_PARSER_MULTI_LINE]);
362134629a0SHadriel Kaplan lcb->entries [REG_PARSER_MULTI_LINE] = NULL;
363b2c16b34SMasatake YAMATO
364e0e33135SMasatake YAMATO ptrArrayDelete (lcb->tables);
365e0e33135SMasatake YAMATO lcb->tables = NULL;
366e0e33135SMasatake YAMATO
36741e0b4f8SMasatake YAMATO ptrArrayDelete (lcb->tstack);
36841e0b4f8SMasatake YAMATO lcb->tstack = NULL;
36941e0b4f8SMasatake YAMATO
3706cdf5716SMasatake YAMATO guestRequestDelete (lcb->guest_req);
3716cdf5716SMasatake YAMATO lcb->guest_req = NULL;
3726cdf5716SMasatake YAMATO
373e8386a4eSMasatake YAMATO es_object_unref (lcb->local_dict);
374e8386a4eSMasatake YAMATO lcb->local_dict = es_nil;
375e8386a4eSMasatake YAMATO
376b6124a60SMasatake YAMATO for (int i = 0; i < SCRIPT_HOOK_MAX; i++)
3771409a195SMasatake YAMATO {
3781409a195SMasatake YAMATO ptrArrayDelete (lcb->hook[i]);
3791409a195SMasatake YAMATO lcb->hook[i] = NULL;
3805c872341SMasatake YAMATO
3811409a195SMasatake YAMATO ptrArrayDelete (lcb->hook_code[i]);
3821409a195SMasatake YAMATO lcb->hook_code[i] = NULL;
3831409a195SMasatake YAMATO }
384cda2e6c3SMasatake YAMATO
385bce55cc7SMasatake YAMATO eFree (lcb);
386bce55cc7SMasatake YAMATO }
387bce55cc7SMasatake YAMATO
388d4c6f1e6SMasatake YAMATO /*
3895dbd2e67SK.Takata * Regex pseudo-parser
390d4c6f1e6SMasatake YAMATO */
391d4c6f1e6SMasatake YAMATO
initRegexTag(tagEntryInfo * e,const char * name,int kindIndex,int roleIndex,int scopeIndex,int placeholder,unsigned long line,MIOPos * pos,int xtag_type)392e024ff82SHadriel Kaplan static void initRegexTag (tagEntryInfo *e,
393a114f06bSMasatake YAMATO const char * name, int kindIndex, int roleIndex, int scopeIndex, int placeholder,
39410db13faSMasatake YAMATO unsigned long line, MIOPos *pos, int xtag_type)
395d4c6f1e6SMasatake YAMATO {
396a114f06bSMasatake YAMATO Assert (name != NULL && ((name[0] != '\0') || placeholder));
397a114f06bSMasatake YAMATO initRefTagEntry (e, name, kindIndex, roleIndex);
398f53f3c39SMasatake YAMATO e->extensionFields.scopeIndex = scopeIndex;
399f53f3c39SMasatake YAMATO e->placeholder = !!placeholder;
40013939209SMasatake YAMATO if (line)
40113939209SMasatake YAMATO {
402f53f3c39SMasatake YAMATO e->lineNumber = line;
403f53f3c39SMasatake YAMATO e->filePosition = *pos;
40413939209SMasatake YAMATO }
40513939209SMasatake YAMATO
40610db13faSMasatake YAMATO if (xtag_type != XTAG_UNKNOWN)
407f53f3c39SMasatake YAMATO markTagExtraBit (e, xtag_type);
408d4c6f1e6SMasatake YAMATO }
409d4c6f1e6SMasatake YAMATO
410d4c6f1e6SMasatake YAMATO /*
411d4c6f1e6SMasatake YAMATO * Regex pattern definition
412d4c6f1e6SMasatake YAMATO */
413d4c6f1e6SMasatake YAMATO
414d4c6f1e6SMasatake YAMATO /* Take a string like "/blah/" and turn it into "blah", making sure
415d4c6f1e6SMasatake YAMATO * that the first and last characters are the same, and handling
416d4c6f1e6SMasatake YAMATO * quoted separator characters. Actually, stops on the occurrence of
417d4c6f1e6SMasatake YAMATO * an unquoted separator. Also turns "\t" into a Tab character.
418641e337aSMasatake YAMATO * Turns "\n" into a Newline character if MULTILINE is true.
419d4c6f1e6SMasatake YAMATO * Returns pointer to terminating separator. Works in place. Null
420d4c6f1e6SMasatake YAMATO * terminates name string.
421d4c6f1e6SMasatake YAMATO */
scanSeparators(char * name,bool multiline)42263611edeSMasatake YAMATO static char* scanSeparators (char* name, bool multiline)
423d4c6f1e6SMasatake YAMATO {
424d4c6f1e6SMasatake YAMATO char sep = name [0];
425d4c6f1e6SMasatake YAMATO char *copyto = name;
426ce990805SThomas Braun bool quoted = false;
427d4c6f1e6SMasatake YAMATO
428d4c6f1e6SMasatake YAMATO for (++name ; *name != '\0' ; ++name)
429d4c6f1e6SMasatake YAMATO {
430d4c6f1e6SMasatake YAMATO if (quoted)
431d4c6f1e6SMasatake YAMATO {
432d4c6f1e6SMasatake YAMATO if (*name == sep)
433d4c6f1e6SMasatake YAMATO *copyto++ = sep;
434d4c6f1e6SMasatake YAMATO else if (*name == 't')
435d4c6f1e6SMasatake YAMATO *copyto++ = '\t';
43663611edeSMasatake YAMATO else if (multiline && *name == 'n')
437641e337aSMasatake YAMATO *copyto++ = '\n';
438d4c6f1e6SMasatake YAMATO else
439d4c6f1e6SMasatake YAMATO {
440d4c6f1e6SMasatake YAMATO /* Something else is quoted, so preserve the quote. */
441d4c6f1e6SMasatake YAMATO *copyto++ = '\\';
442d4c6f1e6SMasatake YAMATO *copyto++ = *name;
443d4c6f1e6SMasatake YAMATO }
444ce990805SThomas Braun quoted = false;
445d4c6f1e6SMasatake YAMATO }
446d4c6f1e6SMasatake YAMATO else if (*name == '\\')
447ce990805SThomas Braun quoted = true;
448d4c6f1e6SMasatake YAMATO else if (*name == sep)
449d4c6f1e6SMasatake YAMATO {
450d4c6f1e6SMasatake YAMATO break;
451d4c6f1e6SMasatake YAMATO }
452d4c6f1e6SMasatake YAMATO else
453d4c6f1e6SMasatake YAMATO *copyto++ = *name;
454d4c6f1e6SMasatake YAMATO }
455d4c6f1e6SMasatake YAMATO *copyto = '\0';
456d4c6f1e6SMasatake YAMATO return name;
457d4c6f1e6SMasatake YAMATO }
458d4c6f1e6SMasatake YAMATO
459d4c6f1e6SMasatake YAMATO /* Parse `regexp', in form "/regex/name/[k,Kind/]flags" (where the separator
460d4c6f1e6SMasatake YAMATO * character is whatever the first character of `regexp' is), by breaking it
461d4c6f1e6SMasatake YAMATO * up into null terminated strings, removing the separators, and expanding
462d4c6f1e6SMasatake YAMATO * '\t' into tabs. When complete, `regexp' points to the line matching
463d4c6f1e6SMasatake YAMATO * pattern, a pointer to the name matching pattern is written to `name', a
464d4c6f1e6SMasatake YAMATO * pointer to the kinds is written to `kinds' (possibly NULL), and a pointer
465d4c6f1e6SMasatake YAMATO * to the trailing flags is written to `flags'. If the pattern is not in the
466d4c6f1e6SMasatake YAMATO * correct format, a false value is returned.
467d4c6f1e6SMasatake YAMATO */
parseTagRegex(enum regexParserType regptype,char * const regexp,char ** const name,char ** const kinds,char ** const flags)468ce990805SThomas Braun static bool parseTagRegex (
4691b9c3aecSMasatake YAMATO enum regexParserType regptype,
470d4c6f1e6SMasatake YAMATO char* const regexp, char** const name,
471d4c6f1e6SMasatake YAMATO char** const kinds, char** const flags)
472d4c6f1e6SMasatake YAMATO {
473ce990805SThomas Braun bool result = false;
474d4c6f1e6SMasatake YAMATO const int separator = (unsigned char) regexp [0];
475d4c6f1e6SMasatake YAMATO
47663611edeSMasatake YAMATO *name = scanSeparators (regexp, (regptype == REG_PARSER_MULTI_LINE
47763611edeSMasatake YAMATO || regptype == REG_PARSER_MULTI_TABLE));
478d4c6f1e6SMasatake YAMATO if (*regexp == '\0')
479d4c6f1e6SMasatake YAMATO error (WARNING, "empty regexp");
480d4c6f1e6SMasatake YAMATO else if (**name != separator)
481d4c6f1e6SMasatake YAMATO error (WARNING, "%s: incomplete regexp", regexp);
482d4c6f1e6SMasatake YAMATO else
483d4c6f1e6SMasatake YAMATO {
484641e337aSMasatake YAMATO char* const third = scanSeparators (*name, false);
48512ddaaa3SMasatake YAMATO if (**name != '\0' && (*name) [strlen (*name) - 1] == '\\')
486d4c6f1e6SMasatake YAMATO error (WARNING, "error in name pattern: \"%s\"", *name);
487d4c6f1e6SMasatake YAMATO if (*third != separator)
488d4c6f1e6SMasatake YAMATO error (WARNING, "%s: regexp missing final separator", regexp);
489d4c6f1e6SMasatake YAMATO else
490d4c6f1e6SMasatake YAMATO {
491b8e4238dSMasatake YAMATO /*
492b8e4238dSMasatake YAMATO * first----------V third------------V
493162e9f15SMasatake YAMATO * --regex-<LANG>=/regexp/replacement/[kind-spec/][flags][{{\n...\n}}]
494b8e4238dSMasatake YAMATO * second----------------^ fourth---------------^
495b8e4238dSMasatake YAMATO */
496b8e4238dSMasatake YAMATO
497162e9f15SMasatake YAMATO /*
498162e9f15SMasatake YAMATO * The following code assumes "{{\n" is never used in flags.
499162e9f15SMasatake YAMATO * If the input comes from the command line or an optlib file,
500162e9f15SMasatake YAMATO * this assumption is always correct; a new line character is never
501162e9f15SMasatake YAMATO * put at the middle (or end) of the input.
502162e9f15SMasatake YAMATO *
503162e9f15SMasatake YAMATO * TODO: How about the input comes from the source code translated
504162e9f15SMasatake YAMATO * by optlib2c?
505162e9f15SMasatake YAMATO */
506162e9f15SMasatake YAMATO char *script = strstr (third, "{{\n");
507162e9f15SMasatake YAMATO if (script)
508162e9f15SMasatake YAMATO {
509162e9f15SMasatake YAMATO /* The script part should not be unescaed by scanSeparators().
510162e9f15SMasatake YAMATO * By spitting the string, we can hide the script part from
511162e9f15SMasatake YAMATO * scanSeparators(). */
512162e9f15SMasatake YAMATO script [0] = '\0';
513162e9f15SMasatake YAMATO }
514162e9f15SMasatake YAMATO
515641e337aSMasatake YAMATO char* const fourth = scanSeparators (third, false);
516d4c6f1e6SMasatake YAMATO if (*fourth == separator)
517d4c6f1e6SMasatake YAMATO {
518d4c6f1e6SMasatake YAMATO *kinds = third;
519641e337aSMasatake YAMATO scanSeparators (fourth, false);
520d4c6f1e6SMasatake YAMATO *flags = fourth;
521d4c6f1e6SMasatake YAMATO }
522d4c6f1e6SMasatake YAMATO else
523d4c6f1e6SMasatake YAMATO {
524d4c6f1e6SMasatake YAMATO *flags = third;
525d4c6f1e6SMasatake YAMATO *kinds = NULL;
526d4c6f1e6SMasatake YAMATO }
527162e9f15SMasatake YAMATO
528162e9f15SMasatake YAMATO if (script)
529162e9f15SMasatake YAMATO {
530162e9f15SMasatake YAMATO Assert (*flags);
531162e9f15SMasatake YAMATO
532162e9f15SMasatake YAMATO char *end = *flags + strlen (*flags);
533162e9f15SMasatake YAMATO script [0] = '{';
534162e9f15SMasatake YAMATO if (end != script)
535162e9f15SMasatake YAMATO {
536162e9f15SMasatake YAMATO size_t len = strlen (script);
537162e9f15SMasatake YAMATO memmove (end, script, len);
538162e9f15SMasatake YAMATO end [len] = '\0';
539162e9f15SMasatake YAMATO }
540162e9f15SMasatake YAMATO }
541162e9f15SMasatake YAMATO
542ce990805SThomas Braun result = true;
543d4c6f1e6SMasatake YAMATO }
544d4c6f1e6SMasatake YAMATO }
545d4c6f1e6SMasatake YAMATO return result;
546d4c6f1e6SMasatake YAMATO }
547d4c6f1e6SMasatake YAMATO
548d4c6f1e6SMasatake YAMATO
pre_ptrn_flag_exclusive_short(char c CTAGS_ATTR_UNUSED,void * data)5498ccb7ee9SJiří Techet static void pre_ptrn_flag_exclusive_short (char c CTAGS_ATTR_UNUSED, void* data)
550d4c6f1e6SMasatake YAMATO {
551ce990805SThomas Braun bool *exclusive = data;
552ce990805SThomas Braun *exclusive = true;
553d4c6f1e6SMasatake YAMATO }
554d4c6f1e6SMasatake YAMATO
pre_ptrn_flag_exclusive_long(const char * const s CTAGS_ATTR_UNUSED,const char * const unused CTAGS_ATTR_UNUSED,void * data)5558ccb7ee9SJiří Techet static void pre_ptrn_flag_exclusive_long (const char* const s CTAGS_ATTR_UNUSED, const char* const unused CTAGS_ATTR_UNUSED, void* data)
556d4c6f1e6SMasatake YAMATO {
5575fdabf71SMasatake YAMATO pre_ptrn_flag_exclusive_short ('x', data);
558d4c6f1e6SMasatake YAMATO }
559d4c6f1e6SMasatake YAMATO
5605fdabf71SMasatake YAMATO static flagDefinition prePtrnFlagDef[] = {
5613fac0fc6SMasatake YAMATO { 'x', "exclusive", pre_ptrn_flag_exclusive_short, pre_ptrn_flag_exclusive_long ,
5623fac0fc6SMasatake YAMATO NULL, "skip testing the other patterns if a line is matched to this pattern"},
5635fdabf71SMasatake YAMATO };
5645fdabf71SMasatake YAMATO
scope_ptrn_flag_eval(const char * const f CTAGS_ATTR_UNUSED,const char * const v,void * data)5658ccb7ee9SJiří Techet static void scope_ptrn_flag_eval (const char* const f CTAGS_ATTR_UNUSED,
5662fa3c9e1SMasatake YAMATO const char* const v, void* data)
5672fa3c9e1SMasatake YAMATO {
568c2bd0a7eSMasatake YAMATO unsigned int *bfields = data;
5692fa3c9e1SMasatake YAMATO
5702fa3c9e1SMasatake YAMATO if (strcmp (v, "ref") == 0)
5712fa3c9e1SMasatake YAMATO *bfields |= SCOPE_REF;
5722fa3c9e1SMasatake YAMATO else if (strcmp (v, "push") == 0)
5732fa3c9e1SMasatake YAMATO *bfields |= (SCOPE_PUSH | SCOPE_REF);
5742fa3c9e1SMasatake YAMATO else if (strcmp (v, "pop") == 0)
5752fa3c9e1SMasatake YAMATO *bfields |= SCOPE_POP;
5762fa3c9e1SMasatake YAMATO else if (strcmp (v, "clear") == 0)
5772fa3c9e1SMasatake YAMATO *bfields |= SCOPE_CLEAR;
5782fa3c9e1SMasatake YAMATO else if (strcmp (v, "set") == 0)
5792fa3c9e1SMasatake YAMATO *bfields |= (SCOPE_CLEAR | SCOPE_PUSH);
580f998e51dSMasatake YAMATO else if (strcmp (v, "replace") == 0)
581f998e51dSMasatake YAMATO *bfields |= (SCOPE_POP|SCOPE_REF_AFTER_POP|SCOPE_PUSH);
5822fa3c9e1SMasatake YAMATO else
5832fa3c9e1SMasatake YAMATO error (FATAL, "Unexpected value for scope flag in regex definition: scope=%s", v);
5842fa3c9e1SMasatake YAMATO }
5852fa3c9e1SMasatake YAMATO
placeholder_ptrn_flag_eval(const char * const f CTAGS_ATTR_UNUSED,const char * const v CTAGS_ATTR_UNUSED,void * data)5868ccb7ee9SJiří Techet static void placeholder_ptrn_flag_eval (const char* const f CTAGS_ATTR_UNUSED,
5878ccb7ee9SJiří Techet const char* const v CTAGS_ATTR_UNUSED, void* data)
588b593f516SMasatake YAMATO {
589c2bd0a7eSMasatake YAMATO unsigned int *bfields = data;
590b593f516SMasatake YAMATO *bfields |= SCOPE_PLACEHOLDER;
591b593f516SMasatake YAMATO }
592b593f516SMasatake YAMATO
5932fa3c9e1SMasatake YAMATO static flagDefinition scopePtrnFlagDef[] = {
5942fa3c9e1SMasatake YAMATO { '\0', "scope", NULL, scope_ptrn_flag_eval,
595f998e51dSMasatake YAMATO "ACTION", "use scope stack: ACTION = ref|push|pop|clear|set|replace"},
596b593f516SMasatake YAMATO { '\0', "placeholder", NULL, placeholder_ptrn_flag_eval,
597b593f516SMasatake YAMATO NULL, "don't put this tag to tags file."},
5982fa3c9e1SMasatake YAMATO };
5992fa3c9e1SMasatake YAMATO
kindNew(char letter,const char * name,const char * description)600fbcb3274SMasatake YAMATO static kindDefinition *kindNew (char letter, const char *name, const char *description)
601a4e7ab31SMasatake YAMATO {
602fbcb3274SMasatake YAMATO kindDefinition *kdef = xCalloc (1, kindDefinition);
603fbcb3274SMasatake YAMATO kdef->letter = letter;
604691d5f94SMasatake YAMATO kdef->name = eStrdup (name);
605fbcb3274SMasatake YAMATO kdef->description = eStrdup(description? description: kdef->name);
606fbcb3274SMasatake YAMATO kdef->enabled = true;
607fbcb3274SMasatake YAMATO return kdef;
608a4e7ab31SMasatake YAMATO }
609a4e7ab31SMasatake YAMATO
kindFree(kindDefinition * kind)610fbcb3274SMasatake YAMATO static void kindFree (kindDefinition *kind)
611a4e7ab31SMasatake YAMATO {
612a4e7ab31SMasatake YAMATO kind->letter = '\0';
6135705d883SMasatake YAMATO eFree ((void *)kind->name);
614a4e7ab31SMasatake YAMATO kind->name = NULL;
6155705d883SMasatake YAMATO eFree ((void *)kind->description);
616a4e7ab31SMasatake YAMATO kind->description = NULL;
617a4e7ab31SMasatake YAMATO eFree (kind);
618a4e7ab31SMasatake YAMATO }
619a4e7ab31SMasatake YAMATO
initMgroup(struct mGroupSpec * mgroup)620b2c16b34SMasatake YAMATO static void initMgroup(struct mGroupSpec *mgroup)
621b2c16b34SMasatake YAMATO {
622b2c16b34SMasatake YAMATO mgroup->forLineNumberDetermination = NO_MULTILINE;
623b2c16b34SMasatake YAMATO mgroup->forNextScanning = NO_MULTILINE;
624b2c16b34SMasatake YAMATO mgroup->nextFromStart = false;
625b2c16b34SMasatake YAMATO }
626b2c16b34SMasatake YAMATO
initGuestSpec(struct guestSpec * guest)6276cdf5716SMasatake YAMATO static void initGuestSpec (struct guestSpec *guest)
6286cdf5716SMasatake YAMATO {
6296cdf5716SMasatake YAMATO guest->lang.type = GUEST_LANG_UNKNOWN;
6306cdf5716SMasatake YAMATO }
6316cdf5716SMasatake YAMATO
initTaction(struct mTableActionSpec * taction)6320cbf3f0dSMasatake YAMATO static void initTaction(struct mTableActionSpec *taction)
6330cbf3f0dSMasatake YAMATO {
6340cbf3f0dSMasatake YAMATO taction->action = TACTION_NOP;
6350cbf3f0dSMasatake YAMATO taction->table = NULL;
6360cbf3f0dSMasatake YAMATO }
6370cbf3f0dSMasatake YAMATO
refPattern(regexPattern * ptrn)638bf809d1aSMasatake YAMATO static regexPattern * refPattern (regexPattern * ptrn)
639bf809d1aSMasatake YAMATO {
640bf809d1aSMasatake YAMATO ptrn->refcount++;
641bf809d1aSMasatake YAMATO return ptrn;
642bf809d1aSMasatake YAMATO }
643bf809d1aSMasatake YAMATO
newPattern(regexCompiledCode * const pattern,enum regexParserType regptype)644c30b89acSMasatake YAMATO static regexPattern * newPattern (regexCompiledCode* const pattern,
645b2c16b34SMasatake YAMATO enum regexParserType regptype)
646b2c16b34SMasatake YAMATO {
647b2c16b34SMasatake YAMATO regexPattern *ptrn = xCalloc(1, regexPattern);
648b2c16b34SMasatake YAMATO
649c30b89acSMasatake YAMATO ptrn->pattern.backend = pattern->backend;
650c30b89acSMasatake YAMATO ptrn->pattern.code = pattern->code;
651c30b89acSMasatake YAMATO
652b2c16b34SMasatake YAMATO ptrn->exclusive = false;
653b2c16b34SMasatake YAMATO ptrn->accept_empty_name = false;
654b2c16b34SMasatake YAMATO ptrn->regptype = regptype;
655f74a98d6SHadriel Kaplan ptrn->xtagType = XTAG_UNKNOWN;
656b2c16b34SMasatake YAMATO
657b2c16b34SMasatake YAMATO if (regptype == REG_PARSER_MULTI_LINE)
658b2c16b34SMasatake YAMATO initMgroup(&ptrn->mgroup);
6590cbf3f0dSMasatake YAMATO if (regptype == REG_PARSER_MULTI_TABLE)
6600cbf3f0dSMasatake YAMATO initTaction(&ptrn->taction);
6616cdf5716SMasatake YAMATO initGuestSpec (&ptrn->guest);
662b2c16b34SMasatake YAMATO
66384f3a057SMasatake YAMATO ptrn->u.tag.roleBits = 0;
6649ec7efeaSMasatake YAMATO ptrn->refcount = 1;
665e8386a4eSMasatake YAMATO
666e8386a4eSMasatake YAMATO ptrn->optscript = NULL;
667e8386a4eSMasatake YAMATO ptrn->optscript_src = NULL;
668e8386a4eSMasatake YAMATO
669b2c16b34SMasatake YAMATO return ptrn;
670b2c16b34SMasatake YAMATO }
671b2c16b34SMasatake YAMATO
newRefPatternEntry(regexTableEntry * other)672134629a0SHadriel Kaplan static regexTableEntry * newRefPatternEntry (regexTableEntry * other)
673134629a0SHadriel Kaplan {
674134629a0SHadriel Kaplan regexTableEntry *entry = xCalloc (1, regexTableEntry);
675134629a0SHadriel Kaplan
676134629a0SHadriel Kaplan Assert (other && other->pattern);
677134629a0SHadriel Kaplan
678134629a0SHadriel Kaplan entry->pattern = refPattern(other->pattern);
679134629a0SHadriel Kaplan return entry;
680134629a0SHadriel Kaplan }
681134629a0SHadriel Kaplan
newEntry(regexCompiledCode * const pattern,enum regexParserType regptype)682c30b89acSMasatake YAMATO static regexTableEntry * newEntry (regexCompiledCode* const pattern,
683134629a0SHadriel Kaplan enum regexParserType regptype)
684134629a0SHadriel Kaplan {
685134629a0SHadriel Kaplan regexTableEntry *entry = xCalloc (1, regexTableEntry);
686134629a0SHadriel Kaplan entry->pattern = newPattern (pattern, regptype);
687134629a0SHadriel Kaplan return entry;
688134629a0SHadriel Kaplan }
689134629a0SHadriel Kaplan
addCompiledTagCommon(struct lregexControlBlock * lcb,int table_index,regexCompiledCode * const pattern,enum regexParserType regptype)69053dda59eSMasatake YAMATO static regexPattern* addCompiledTagCommon (struct lregexControlBlock *lcb,
6910cbf3f0dSMasatake YAMATO int table_index,
692c30b89acSMasatake YAMATO regexCompiledCode* const pattern,
6931b9c3aecSMasatake YAMATO enum regexParserType regptype)
694d4c6f1e6SMasatake YAMATO {
695134629a0SHadriel Kaplan regexTableEntry *entry = newEntry (pattern, regptype);
696a4e7ab31SMasatake YAMATO
6970cbf3f0dSMasatake YAMATO if (regptype == REG_PARSER_MULTI_TABLE)
6980cbf3f0dSMasatake YAMATO {
6990cbf3f0dSMasatake YAMATO struct regexTable *table = ptrArrayItem (lcb->tables, table_index);
7000cbf3f0dSMasatake YAMATO Assert(table);
7010cbf3f0dSMasatake YAMATO
702134629a0SHadriel Kaplan ptrArrayAdd (table->entries, entry);
7030cbf3f0dSMasatake YAMATO }
7040cbf3f0dSMasatake YAMATO else
705134629a0SHadriel Kaplan ptrArrayAdd (lcb->entries[regptype], entry);
706d4c6f1e6SMasatake YAMATO
70753dda59eSMasatake YAMATO useRegexMethod(lcb->owner);
708c9bfc26fSMasatake YAMATO
709134629a0SHadriel Kaplan return entry->pattern;
710d4c6f1e6SMasatake YAMATO }
711d4c6f1e6SMasatake YAMATO
pre_ptrn_flag_mgroup_long(const char * const s,const char * const v,void * data)712e77d0926SMasatake YAMATO static void pre_ptrn_flag_mgroup_long (const char* const s, const char* const v, void* data)
71313939209SMasatake YAMATO {
714c9bfc26fSMasatake YAMATO struct mGroupSpec *mgroup = data;
715ed569600SMasatake YAMATO if (!v)
716ed569600SMasatake YAMATO {
717ed569600SMasatake YAMATO error (WARNING, "no value is given for: %s", s);
718ed569600SMasatake YAMATO return;
719ed569600SMasatake YAMATO }
720c9bfc26fSMasatake YAMATO if (!strToInt (v, 10, &mgroup->forLineNumberDetermination))
72113939209SMasatake YAMATO {
722c9bfc26fSMasatake YAMATO error (WARNING, "wrong %s specification: %s", s, v);
723c9bfc26fSMasatake YAMATO mgroup->forLineNumberDetermination = NO_MULTILINE;
72413939209SMasatake YAMATO }
725c9bfc26fSMasatake YAMATO else if (mgroup->forLineNumberDetermination < 0
726c9bfc26fSMasatake YAMATO || mgroup->forLineNumberDetermination >= BACK_REFERENCE_COUNT)
72713939209SMasatake YAMATO {
728c9bfc26fSMasatake YAMATO error (WARNING, "out of range(0 ~ %d) %s specification: %s",
729c9bfc26fSMasatake YAMATO (BACK_REFERENCE_COUNT - 1),
730c9bfc26fSMasatake YAMATO s, v);
731c9bfc26fSMasatake YAMATO mgroup->forLineNumberDetermination = NO_MULTILINE;
73213939209SMasatake YAMATO }
733c9bfc26fSMasatake YAMATO }
734c9bfc26fSMasatake YAMATO
pre_ptrn_flag_advanceTo_long(const char * const s,const char * const v,void * data)735c9bfc26fSMasatake YAMATO static void pre_ptrn_flag_advanceTo_long (const char* const s, const char* const v, void* data)
736c9bfc26fSMasatake YAMATO {
737c9bfc26fSMasatake YAMATO struct mGroupSpec *mgroup = data;
738c9bfc26fSMasatake YAMATO char *vdup;
739c9bfc26fSMasatake YAMATO char *tmp;
740c9bfc26fSMasatake YAMATO
741c9bfc26fSMasatake YAMATO
742c9bfc26fSMasatake YAMATO if (!v)
743c9bfc26fSMasatake YAMATO {
744c9bfc26fSMasatake YAMATO error (WARNING, "no value is given for: %s", s);
745c9bfc26fSMasatake YAMATO return;
746c9bfc26fSMasatake YAMATO }
747c9bfc26fSMasatake YAMATO
748c9bfc26fSMasatake YAMATO vdup = eStrdup (v);
749c9bfc26fSMasatake YAMATO
750c9bfc26fSMasatake YAMATO mgroup->nextFromStart = false;
751c9bfc26fSMasatake YAMATO if ((tmp = strstr(vdup, "start")))
752c9bfc26fSMasatake YAMATO {
753c9bfc26fSMasatake YAMATO mgroup->nextFromStart = true;
754c9bfc26fSMasatake YAMATO *tmp = '\0';
755c9bfc26fSMasatake YAMATO }
756c9bfc26fSMasatake YAMATO else if ((tmp = strstr(vdup, "end")))
757c9bfc26fSMasatake YAMATO *tmp = '\0';
758c9bfc26fSMasatake YAMATO
759c9bfc26fSMasatake YAMATO if (!strToInt (vdup, 10, &(mgroup->forNextScanning)))
760c9bfc26fSMasatake YAMATO {
761c9bfc26fSMasatake YAMATO error (WARNING, "wrong %s specification: %s", s, vdup);
762c9bfc26fSMasatake YAMATO mgroup->nextFromStart = false;
763c9bfc26fSMasatake YAMATO }
764c9bfc26fSMasatake YAMATO else if (mgroup->forNextScanning < 0 || mgroup->forNextScanning >= BACK_REFERENCE_COUNT)
765c9bfc26fSMasatake YAMATO {
766c9bfc26fSMasatake YAMATO error (WARNING, "out of range(0 ~ %d) %s specification: %s",
767c9bfc26fSMasatake YAMATO (BACK_REFERENCE_COUNT - 1), s, vdup);
768c9bfc26fSMasatake YAMATO mgroup->nextFromStart = false;
769c9bfc26fSMasatake YAMATO }
770c9bfc26fSMasatake YAMATO
771c9bfc26fSMasatake YAMATO eFree (vdup);
77213939209SMasatake YAMATO }
77313939209SMasatake YAMATO
7746cdf5716SMasatake YAMATO struct guestPtrnFlagData {
7756cdf5716SMasatake YAMATO enum regexParserType type;
7766cdf5716SMasatake YAMATO struct guestSpec *guest;
7776cdf5716SMasatake YAMATO };
7786cdf5716SMasatake YAMATO
pre_ptrn_flag_guest_long(const char * const s,const char * const v,void * data)7796cdf5716SMasatake YAMATO static void pre_ptrn_flag_guest_long (const char* const s, const char* const v, void* data)
7806cdf5716SMasatake YAMATO {
7816cdf5716SMasatake YAMATO struct guestPtrnFlagData *flagData = data;
7826cdf5716SMasatake YAMATO enum regexParserType type = flagData->type;
7836cdf5716SMasatake YAMATO struct guestSpec *guest = flagData->guest;
7846cdf5716SMasatake YAMATO struct boundarySpec *current;
7856cdf5716SMasatake YAMATO
7866cdf5716SMasatake YAMATO if (!v)
7876cdf5716SMasatake YAMATO {
7886cdf5716SMasatake YAMATO error (WARNING, "no value is given for: %s", s);
7896cdf5716SMasatake YAMATO return;
7906cdf5716SMasatake YAMATO }
7916cdf5716SMasatake YAMATO
7926cdf5716SMasatake YAMATO char *tmp = strchr (v, ',');
7936cdf5716SMasatake YAMATO if (tmp == NULL)
7946cdf5716SMasatake YAMATO {
7956cdf5716SMasatake YAMATO error (WARNING, "no terminator found for parser name: %s", s);
7966cdf5716SMasatake YAMATO return;
7976cdf5716SMasatake YAMATO }
7986cdf5716SMasatake YAMATO
7996cdf5716SMasatake YAMATO if ((tmp - v) == 0)
8006cdf5716SMasatake YAMATO {
8016cdf5716SMasatake YAMATO if (type == REG_PARSER_MULTI_LINE)
8026cdf5716SMasatake YAMATO {
8036cdf5716SMasatake YAMATO error (WARNING,
8046cdf5716SMasatake YAMATO "using placeholder for guest name field is not allowed in multiline regex spec: %s", v);
8056cdf5716SMasatake YAMATO goto err;
8066cdf5716SMasatake YAMATO }
8076cdf5716SMasatake YAMATO
8086cdf5716SMasatake YAMATO guest->lang.type = GUEST_LANG_PLACEHOLDER;
8096cdf5716SMasatake YAMATO }
8106cdf5716SMasatake YAMATO else if (*v == '\\' || *v == '*')
8116cdf5716SMasatake YAMATO {
8126cdf5716SMasatake YAMATO const char *n_tmp = v + 1;
8136cdf5716SMasatake YAMATO const char *n = n_tmp;
8146cdf5716SMasatake YAMATO for (; isdigit (*n_tmp); n_tmp++);
8156cdf5716SMasatake YAMATO char c = *n_tmp;
8166cdf5716SMasatake YAMATO *(char *)n_tmp = '\0';
8176cdf5716SMasatake YAMATO if (!strToInt (n, 10, &(guest->lang.spec.patternGroup)))
8186cdf5716SMasatake YAMATO {
8196cdf5716SMasatake YAMATO error (WARNING, "wrong guest name specification: %s", v);
8206cdf5716SMasatake YAMATO goto err;
8216cdf5716SMasatake YAMATO }
8226cdf5716SMasatake YAMATO else if (guest->lang.spec.patternGroup >= BACK_REFERENCE_COUNT)
8236cdf5716SMasatake YAMATO {
8246cdf5716SMasatake YAMATO error (WARNING, "wrong guest name specification (back reference count is too large): %d",
8256cdf5716SMasatake YAMATO guest->lang.spec.patternGroup);
8266cdf5716SMasatake YAMATO goto err;
8276cdf5716SMasatake YAMATO }
8286cdf5716SMasatake YAMATO
8296cdf5716SMasatake YAMATO *(char *)n_tmp = c;
8306cdf5716SMasatake YAMATO if (*n_tmp != ',')
8316cdf5716SMasatake YAMATO {
8326cdf5716SMasatake YAMATO error (WARNING, "wrong guest specification (garbage at the end of end guest spec): %s", v);
8336cdf5716SMasatake YAMATO goto err;
8346cdf5716SMasatake YAMATO }
8356cdf5716SMasatake YAMATO
8366cdf5716SMasatake YAMATO guest->lang.type = (*v == '\\')
8376cdf5716SMasatake YAMATO ? GUEST_LANG_PTN_GROUP_FOR_LANGNAME
8386cdf5716SMasatake YAMATO : GUEST_LANG_PTN_GROUP_FOR_FILEMAP;
8396cdf5716SMasatake YAMATO }
8406cdf5716SMasatake YAMATO else
8416cdf5716SMasatake YAMATO {
842*6024deefSMasatake YAMATO guest->lang.spec.lang = getNamedLanguageOrAlias (v, (tmp - v));
8436cdf5716SMasatake YAMATO if (guest->lang.spec.lang == LANG_IGNORE)
8446cdf5716SMasatake YAMATO {
8456cdf5716SMasatake YAMATO error (WARNING, "no parser found for the guest spec: %s", v);
8466cdf5716SMasatake YAMATO goto err;
8476cdf5716SMasatake YAMATO }
8486cdf5716SMasatake YAMATO guest->lang.type = GUEST_LANG_STATIC_LANGNAME;
8496cdf5716SMasatake YAMATO }
8506cdf5716SMasatake YAMATO
8516cdf5716SMasatake YAMATO tmp++;
8526cdf5716SMasatake YAMATO if (*tmp == '\0')
8536cdf5716SMasatake YAMATO {
8546cdf5716SMasatake YAMATO error (WARNING, "no area spec found in the guest spec: %s", v);
8556cdf5716SMasatake YAMATO goto err;
8566cdf5716SMasatake YAMATO }
8576cdf5716SMasatake YAMATO
8586cdf5716SMasatake YAMATO for (int i = 0; i < 2; i++)
8596cdf5716SMasatake YAMATO {
8606cdf5716SMasatake YAMATO current = guest->boundary + i;
8616cdf5716SMasatake YAMATO const char *current_field_str = (i == BOUNDARY_START? "start": "end");
8626cdf5716SMasatake YAMATO
8636cdf5716SMasatake YAMATO if (tmp [0] == ((i == BOUNDARY_START)? ',': '\0'))
8646cdf5716SMasatake YAMATO {
8656cdf5716SMasatake YAMATO if (type == REG_PARSER_MULTI_LINE)
8666cdf5716SMasatake YAMATO error (WARNING,
8676cdf5716SMasatake YAMATO "using placeholder for %s field is not allowed in multiline regex spec: %s",
8686cdf5716SMasatake YAMATO current_field_str, v);
8696cdf5716SMasatake YAMATO
8706cdf5716SMasatake YAMATO current->placeholder = true;
8716cdf5716SMasatake YAMATO }
8726cdf5716SMasatake YAMATO else
8736cdf5716SMasatake YAMATO {
8746cdf5716SMasatake YAMATO char *n = tmp;
8756cdf5716SMasatake YAMATO
8766cdf5716SMasatake YAMATO for (; isdigit (*tmp); tmp++);
8776cdf5716SMasatake YAMATO char c = *tmp;
8786cdf5716SMasatake YAMATO *tmp = '\0';
8796cdf5716SMasatake YAMATO if (!strToInt (n, 10, &(current->patternGroup)))
8806cdf5716SMasatake YAMATO {
8816cdf5716SMasatake YAMATO error (WARNING, "wrong guest area specification (patternGroup of %s, number expected): %s:%s",
8826cdf5716SMasatake YAMATO current_field_str, v, n);
8836cdf5716SMasatake YAMATO goto err;
8846cdf5716SMasatake YAMATO }
8856cdf5716SMasatake YAMATO *tmp = c;
8866cdf5716SMasatake YAMATO if (*tmp == '\0')
8876cdf5716SMasatake YAMATO {
8886cdf5716SMasatake YAMATO error (WARNING, "wrong guest area specification (patternGroup of %s, nether start nor end given): %s",
8896cdf5716SMasatake YAMATO current_field_str, v);
8906cdf5716SMasatake YAMATO goto err;
8916cdf5716SMasatake YAMATO }
8926cdf5716SMasatake YAMATO else if (strncmp (tmp, "start", 5) == 0)
8936cdf5716SMasatake YAMATO {
8946cdf5716SMasatake YAMATO current->fromStartOfGroup = true;
8956cdf5716SMasatake YAMATO tmp += 5;
8966cdf5716SMasatake YAMATO }
8976cdf5716SMasatake YAMATO else if (strncmp (tmp, "end", 3) == 0)
8986cdf5716SMasatake YAMATO {
8996cdf5716SMasatake YAMATO current->fromStartOfGroup = false;
9006cdf5716SMasatake YAMATO tmp += 3;
9016cdf5716SMasatake YAMATO }
9026cdf5716SMasatake YAMATO else
9036cdf5716SMasatake YAMATO {
9046cdf5716SMasatake YAMATO error (WARNING, "wrong guest area specification (%s): %s",
9056cdf5716SMasatake YAMATO current_field_str, v);
9066cdf5716SMasatake YAMATO goto err;
9076cdf5716SMasatake YAMATO }
9086cdf5716SMasatake YAMATO }
9096cdf5716SMasatake YAMATO
9106cdf5716SMasatake YAMATO if (i == 0)
9116cdf5716SMasatake YAMATO {
9126cdf5716SMasatake YAMATO if (*tmp != ',')
9136cdf5716SMasatake YAMATO {
9146cdf5716SMasatake YAMATO error (WARNING,
9156cdf5716SMasatake YAMATO "wrong guest area specification (separator between start and end boundaries): %s", v);
9166cdf5716SMasatake YAMATO goto err;
9176cdf5716SMasatake YAMATO }
9186cdf5716SMasatake YAMATO tmp++;
9196cdf5716SMasatake YAMATO }
9206cdf5716SMasatake YAMATO else if (i == 1 && (*tmp != '\0'))
9216cdf5716SMasatake YAMATO {
9226cdf5716SMasatake YAMATO error (WARNING, "wrong guest area specification (garbage at the end of end boundary spec): %s", v);
9236cdf5716SMasatake YAMATO goto err;
9246cdf5716SMasatake YAMATO }
9256cdf5716SMasatake YAMATO }
9266cdf5716SMasatake YAMATO return;
9276cdf5716SMasatake YAMATO err:
9286cdf5716SMasatake YAMATO guest->lang.type = GUEST_LANG_UNKNOWN;
9296cdf5716SMasatake YAMATO }
9306cdf5716SMasatake YAMATO
93113939209SMasatake YAMATO static flagDefinition multilinePtrnFlagDef[] = {
932e77d0926SMasatake YAMATO { '\0', "mgroup", NULL, pre_ptrn_flag_mgroup_long,
933641e337aSMasatake YAMATO "N", "a group in pattern determining the line number of tag"},
934c9bfc26fSMasatake YAMATO { '\0', "_advanceTo", NULL, pre_ptrn_flag_advanceTo_long,
935c9bfc26fSMasatake YAMATO "N[start|end]", "a group in pattern from where the next scan starts [0end]"},
93613939209SMasatake YAMATO };
93713939209SMasatake YAMATO
9386cdf5716SMasatake YAMATO static flagDefinition guestPtrnFlagDef[] = {
9396cdf5716SMasatake YAMATO #define EXPERIMENTAL "_"
9406cdf5716SMasatake YAMATO { '\0', EXPERIMENTAL "guest", NULL, pre_ptrn_flag_guest_long,
9416cdf5716SMasatake YAMATO "PARSERSPEC,N0[start|end],N1[start|end]", "run guest parser on the area"},
9426cdf5716SMasatake YAMATO };
9436cdf5716SMasatake YAMATO
hasMessage(const regexPattern * const ptrn)9449a1e266aSHadriel Kaplan static bool hasMessage(const regexPattern *const ptrn)
9459a1e266aSHadriel Kaplan {
9469a1e266aSHadriel Kaplan return (ptrn->message.selection > 0 && ptrn->message.message_string);
9479a1e266aSHadriel Kaplan }
9489a1e266aSHadriel Kaplan
949f74a98d6SHadriel Kaplan struct commonFlagData {
95046837a67SHadriel Kaplan const langType owner;
95146837a67SHadriel Kaplan const struct lregexControlBlock *const lcb;
952f74a98d6SHadriel Kaplan regexPattern *ptrn;
95310db13faSMasatake YAMATO };
95410db13faSMasatake YAMATO
common_flag_msg_long(const char * const s,const char * const v,void * data)9559a1e266aSHadriel Kaplan static void common_flag_msg_long (const char* const s, const char* const v, void* data)
9569a1e266aSHadriel Kaplan {
9579a1e266aSHadriel Kaplan struct commonFlagData *cdata = data;
9589a1e266aSHadriel Kaplan regexPattern *ptrn = cdata->ptrn;
9599a1e266aSHadriel Kaplan
9609a1e266aSHadriel Kaplan Assert (ptrn);
9619a1e266aSHadriel Kaplan
9629a1e266aSHadriel Kaplan if (hasMessage(ptrn))
9639a1e266aSHadriel Kaplan {
9649a1e266aSHadriel Kaplan error (WARNING, "only one message flag may be given per regex (already set to '%s')",
9659a1e266aSHadriel Kaplan ptrn->message.message_string);
9669a1e266aSHadriel Kaplan return;
9679a1e266aSHadriel Kaplan }
9689a1e266aSHadriel Kaplan
9699a1e266aSHadriel Kaplan if (strcmp (s, "fatal") == 0)
9709a1e266aSHadriel Kaplan {
9719a1e266aSHadriel Kaplan ptrn->message.selection = FATAL;
9729a1e266aSHadriel Kaplan }
9739a1e266aSHadriel Kaplan else if (strcmp (s, "warning") == 0)
9749a1e266aSHadriel Kaplan {
9759a1e266aSHadriel Kaplan ptrn->message.selection = WARNING;
9769a1e266aSHadriel Kaplan }
9779a1e266aSHadriel Kaplan
9789a1e266aSHadriel Kaplan Assert (ptrn->message.selection != 0);
9799a1e266aSHadriel Kaplan
9809a1e266aSHadriel Kaplan if (!v || !*v)
9819a1e266aSHadriel Kaplan {
9829a1e266aSHadriel Kaplan error (WARNING, "no message value is given for {%s}", s);
9839a1e266aSHadriel Kaplan return;
9849a1e266aSHadriel Kaplan }
9859a1e266aSHadriel Kaplan
9869a1e266aSHadriel Kaplan const char* begin = v;
9879a1e266aSHadriel Kaplan const char* end = v + strlen (v);
9889a1e266aSHadriel Kaplan --end;
9899a1e266aSHadriel Kaplan
9909a1e266aSHadriel Kaplan if (*begin != '"' || *end != '"' || begin == end)
9919a1e266aSHadriel Kaplan {
9929a1e266aSHadriel Kaplan error (WARNING, "argument for {%s} must be in double-quotes", s);
9939a1e266aSHadriel Kaplan return;
9949a1e266aSHadriel Kaplan }
9959a1e266aSHadriel Kaplan
9969a1e266aSHadriel Kaplan ++begin;
9979a1e266aSHadriel Kaplan
9989a1e266aSHadriel Kaplan if (begin < end)
9999a1e266aSHadriel Kaplan ptrn->message.message_string = eStrndup (begin, end - begin);
10009a1e266aSHadriel Kaplan }
10019a1e266aSHadriel Kaplan
common_flag_extra_long(const char * const s,const char * const v,void * data)100217d77272SHadriel Kaplan static void common_flag_extra_long (const char* const s, const char* const v, void* data)
100310db13faSMasatake YAMATO {
1004f74a98d6SHadriel Kaplan struct commonFlagData * cdata = data;
1005f74a98d6SHadriel Kaplan
1006f74a98d6SHadriel Kaplan Assert (cdata->ptrn);
100710db13faSMasatake YAMATO
100810db13faSMasatake YAMATO if (!v)
100910db13faSMasatake YAMATO {
101010db13faSMasatake YAMATO error (WARNING, "no value is given for: %s", s);
101110db13faSMasatake YAMATO return;
101210db13faSMasatake YAMATO }
101310db13faSMasatake YAMATO
1014f74a98d6SHadriel Kaplan cdata->ptrn->xtagType = getXtagTypeForNameAndLanguage (v, cdata->owner);
1015f74a98d6SHadriel Kaplan if (cdata->ptrn->xtagType == XTAG_UNKNOWN)
1016f74a98d6SHadriel Kaplan error (WARNING, "no such extra \"%s\" in %s", v, getLanguageName(cdata->owner));
101710db13faSMasatake YAMATO }
101810db13faSMasatake YAMATO
1019f53f3c39SMasatake YAMATO
fieldPatternNew(fieldType ftype,const char * template)1020f53f3c39SMasatake YAMATO static struct fieldPattern * fieldPatternNew (fieldType ftype, const char *template)
1021f53f3c39SMasatake YAMATO {
1022f53f3c39SMasatake YAMATO struct fieldPattern *fp;
1023f53f3c39SMasatake YAMATO
1024f53f3c39SMasatake YAMATO fp = xMalloc(1, struct fieldPattern);
1025f53f3c39SMasatake YAMATO fp->ftype = ftype;
1026f53f3c39SMasatake YAMATO fp->template = eStrdup(template);
1027f53f3c39SMasatake YAMATO
1028f53f3c39SMasatake YAMATO return fp;
1029f53f3c39SMasatake YAMATO }
1030f53f3c39SMasatake YAMATO
fieldPatternDelete(struct fieldPattern * fp)1031f53f3c39SMasatake YAMATO static void fieldPatternDelete (struct fieldPattern *fp)
1032f53f3c39SMasatake YAMATO {
1033f53f3c39SMasatake YAMATO eFree ((void *)fp->template);
1034f53f3c39SMasatake YAMATO eFree (fp);
1035f53f3c39SMasatake YAMATO }
1036f53f3c39SMasatake YAMATO
common_flag_field_long(const char * const s,const char * const v,void * data)103717d77272SHadriel Kaplan static void common_flag_field_long (const char* const s, const char* const v, void* data)
1038f53f3c39SMasatake YAMATO {
10399c2744edSHadriel Kaplan struct commonFlagData * cdata = data;
10409c2744edSHadriel Kaplan regexPattern *ptrn = cdata->ptrn;
10419c2744edSHadriel Kaplan
10429c2744edSHadriel Kaplan Assert (ptrn);
1043f53f3c39SMasatake YAMATO
1044f53f3c39SMasatake YAMATO struct fieldPattern *fp;
1045f53f3c39SMasatake YAMATO fieldType ftype;
1046f53f3c39SMasatake YAMATO char *fname;
1047f53f3c39SMasatake YAMATO const char* template;
1048f53f3c39SMasatake YAMATO char *tmp;
1049f53f3c39SMasatake YAMATO
1050f53f3c39SMasatake YAMATO if (!v)
1051f53f3c39SMasatake YAMATO {
1052f53f3c39SMasatake YAMATO error (WARNING, "no value is given for: %s", s);
1053f53f3c39SMasatake YAMATO return;
1054f53f3c39SMasatake YAMATO }
1055f53f3c39SMasatake YAMATO
1056f53f3c39SMasatake YAMATO tmp = strchr (v, ':');
1057f53f3c39SMasatake YAMATO if (tmp == NULL || tmp == v)
1058f53f3c39SMasatake YAMATO {
1059f53f3c39SMasatake YAMATO error (WARNING, "no field name is given for: %s", s);
1060f53f3c39SMasatake YAMATO return;
1061f53f3c39SMasatake YAMATO }
1062f53f3c39SMasatake YAMATO
1063f53f3c39SMasatake YAMATO fname = eStrndup (v, tmp - v);
10649c2744edSHadriel Kaplan ftype = getFieldTypeForNameAndLanguage (fname, cdata->owner);
1065f53f3c39SMasatake YAMATO if (ftype == FIELD_UNKNOWN)
1066f53f3c39SMasatake YAMATO {
10679c2744edSHadriel Kaplan error (WARNING, "no such field \"%s\" in %s", fname, getLanguageName(cdata->owner));
1068f53f3c39SMasatake YAMATO eFree (fname);
1069f53f3c39SMasatake YAMATO return;
1070f53f3c39SMasatake YAMATO }
1071f53f3c39SMasatake YAMATO
10729c2744edSHadriel Kaplan if (ptrn->fieldPatterns)
1073f53f3c39SMasatake YAMATO {
10749c2744edSHadriel Kaplan for (unsigned int i = 0; i < ptrArrayCount(ptrn->fieldPatterns); i++)
1075f53f3c39SMasatake YAMATO {
10769c2744edSHadriel Kaplan fp = ptrArrayItem(ptrn->fieldPatterns, i);
1077f53f3c39SMasatake YAMATO if (fp->ftype == ftype)
1078f53f3c39SMasatake YAMATO {
10799c2744edSHadriel Kaplan error (WARNING, "duplicated field specification \"%s\" in %s", fname, getLanguageName(cdata->owner));
1080f53f3c39SMasatake YAMATO eFree (fname);
1081f53f3c39SMasatake YAMATO return;
1082f53f3c39SMasatake YAMATO }
1083f53f3c39SMasatake YAMATO }
1084f53f3c39SMasatake YAMATO }
1085f53f3c39SMasatake YAMATO eFree (fname);
1086f53f3c39SMasatake YAMATO
1087f53f3c39SMasatake YAMATO template = tmp + 1;
1088f53f3c39SMasatake YAMATO fp = fieldPatternNew (ftype, template);
1089f53f3c39SMasatake YAMATO
10909c2744edSHadriel Kaplan if (ptrn->fieldPatterns == NULL)
10919c2744edSHadriel Kaplan ptrn->fieldPatterns = ptrArrayNew((ptrArrayDeleteFunc)fieldPatternDelete);
10929c2744edSHadriel Kaplan ptrArrayAdd(ptrn->fieldPatterns, fp);
1093f53f3c39SMasatake YAMATO }
1094f53f3c39SMasatake YAMATO
common_flag_role_long(const char * const s,const char * const v,void * data)109517d77272SHadriel Kaplan static void common_flag_role_long (const char* const s, const char* const v, void* data)
109617d77272SHadriel Kaplan {
109717d77272SHadriel Kaplan struct commonFlagData * cdata = data;
109817d77272SHadriel Kaplan regexPattern *ptrn = cdata->ptrn;
109917d77272SHadriel Kaplan roleDefinition * role;
110017d77272SHadriel Kaplan
110117d77272SHadriel Kaplan Assert (ptrn);
110217d77272SHadriel Kaplan
110317d77272SHadriel Kaplan if (!v)
110417d77272SHadriel Kaplan {
110517d77272SHadriel Kaplan error (WARNING, "no value is given for: %s", s);
110617d77272SHadriel Kaplan return;
110717d77272SHadriel Kaplan }
110817d77272SHadriel Kaplan
110917d77272SHadriel Kaplan role = getLanguageRoleForName(cdata->owner,
111017d77272SHadriel Kaplan ptrn->u.tag.kindIndex, v);
111117d77272SHadriel Kaplan if (!role)
111217d77272SHadriel Kaplan {
111317d77272SHadriel Kaplan error (WARNING, "no such role: %s", v);
111417d77272SHadriel Kaplan return;
111517d77272SHadriel Kaplan }
111617d77272SHadriel Kaplan
111717d77272SHadriel Kaplan ptrn->u.tag.roleBits |= makeRoleBit(role->id);
111817d77272SHadriel Kaplan }
11199c2744edSHadriel Kaplan
common_flag_anonymous_long(const char * const s,const char * const v,void * data)1120c2c0d2b7SMasatake YAMATO static void common_flag_anonymous_long (const char* const s, const char* const v, void* data)
11210d56cc8eSMasatake YAMATO {
11220d56cc8eSMasatake YAMATO struct commonFlagData * cdata = data;
11230d56cc8eSMasatake YAMATO regexPattern *ptrn = cdata->ptrn;
11240d56cc8eSMasatake YAMATO
11250d56cc8eSMasatake YAMATO Assert (ptrn);
11260d56cc8eSMasatake YAMATO
11270d56cc8eSMasatake YAMATO if (ptrn->anonymous_tag_prefix)
11280d56cc8eSMasatake YAMATO {
11290d56cc8eSMasatake YAMATO error (WARNING, "an anonymous tag prefix for this pattern (%s) is already given: %s",
11300d56cc8eSMasatake YAMATO ptrn->pattern_string? ptrn->pattern_string: "",
11310d56cc8eSMasatake YAMATO ptrn->anonymous_tag_prefix);
11320d56cc8eSMasatake YAMATO return;
11330d56cc8eSMasatake YAMATO }
11340d56cc8eSMasatake YAMATO
11350d56cc8eSMasatake YAMATO if (!v)
11360d56cc8eSMasatake YAMATO {
11370d56cc8eSMasatake YAMATO error (WARNING, "no PREFIX for anonymous regex flag is given (pattern == %s)",
11380d56cc8eSMasatake YAMATO ptrn->pattern_string? ptrn->pattern_string: "");
11390d56cc8eSMasatake YAMATO return;
11400d56cc8eSMasatake YAMATO }
11410d56cc8eSMasatake YAMATO
1142c2c0d2b7SMasatake YAMATO if (ptrn->u.tag.kindIndex == KIND_GHOST_INDEX)
1143c2c0d2b7SMasatake YAMATO {
1144c2c0d2b7SMasatake YAMATO error (WARNING, "use \"%s\" regex flag only with an explicitly defined kind", s);
1145c2c0d2b7SMasatake YAMATO return;
1146c2c0d2b7SMasatake YAMATO }
1147c2c0d2b7SMasatake YAMATO
11480d56cc8eSMasatake YAMATO ptrn->anonymous_tag_prefix = eStrdup (v);
11490d56cc8eSMasatake YAMATO }
11500d56cc8eSMasatake YAMATO
11519c2744edSHadriel Kaplan static flagDefinition commonSpecFlagDef[] = {
11529c2744edSHadriel Kaplan { '\0', "fatal", NULL, common_flag_msg_long ,
11539c2744edSHadriel Kaplan "\"MESSAGE\"", "print the given MESSAGE and exit"},
11549c2744edSHadriel Kaplan { '\0', "warning", NULL, common_flag_msg_long ,
11559c2744edSHadriel Kaplan "\"MESSAGE\"", "print the given MESSAGE at WARNING level"},
1156f53f3c39SMasatake YAMATO #define EXPERIMENTAL "_"
11579c2744edSHadriel Kaplan { '\0', EXPERIMENTAL "extra", NULL, common_flag_extra_long ,
11589c2744edSHadriel Kaplan "EXTRA", "record the tag only when the extra is enabled"},
11599c2744edSHadriel Kaplan { '\0', EXPERIMENTAL "field", NULL, common_flag_field_long ,
116084f3a057SMasatake YAMATO "FIELD:VALUE", "record the matched string(VALUE) to parser own FIELD of the tag"},
116117d77272SHadriel Kaplan { '\0', EXPERIMENTAL "role", NULL, common_flag_role_long,
116217d77272SHadriel Kaplan "ROLE", "set the given ROLE to the roles field"},
11630d56cc8eSMasatake YAMATO { '\0', EXPERIMENTAL "anonymous", NULL, common_flag_anonymous_long,
11640d56cc8eSMasatake YAMATO "PREFIX", "make an anonymous tag with PREFIX"},
1165f53f3c39SMasatake YAMATO };
1166f53f3c39SMasatake YAMATO
116713939209SMasatake YAMATO
pre_ptrn_flag_mtable_long(const char * const s,const char * const v,void * data)11680cbf3f0dSMasatake YAMATO static void pre_ptrn_flag_mtable_long (const char* const s, const char* const v, void* data)
11690cbf3f0dSMasatake YAMATO {
117046837a67SHadriel Kaplan struct commonFlagData * cdata = data;
117146837a67SHadriel Kaplan regexPattern *ptrn = cdata->ptrn;
117246837a67SHadriel Kaplan struct mTableActionSpec *taction;
11730cbf3f0dSMasatake YAMATO bool taking_table = true;
11740cbf3f0dSMasatake YAMATO
117546837a67SHadriel Kaplan Assert (ptrn);
117646837a67SHadriel Kaplan Assert (cdata->lcb);
117746837a67SHadriel Kaplan
117846837a67SHadriel Kaplan taction = &ptrn->taction;
117946837a67SHadriel Kaplan
11800cbf3f0dSMasatake YAMATO if (strcmp (s, "tenter") == 0)
11810cbf3f0dSMasatake YAMATO taction->action = TACTION_ENTER;
11820cbf3f0dSMasatake YAMATO else if (strcmp (s, "tleave") == 0)
11830cbf3f0dSMasatake YAMATO {
11840cbf3f0dSMasatake YAMATO taction->action = TACTION_LEAVE;
11850cbf3f0dSMasatake YAMATO taking_table = false;
11860cbf3f0dSMasatake YAMATO }
11870cbf3f0dSMasatake YAMATO else if (strcmp (s, "tjump") == 0)
11880cbf3f0dSMasatake YAMATO taction->action = TACTION_JUMP;
11890cbf3f0dSMasatake YAMATO else if (strcmp (s, "treset") == 0)
11900cbf3f0dSMasatake YAMATO taction->action = TACTION_RESET;
11910cbf3f0dSMasatake YAMATO else if (strcmp (s, "tquit") == 0)
11920cbf3f0dSMasatake YAMATO {
11930cbf3f0dSMasatake YAMATO taction->action = TACTION_QUIT;
11940cbf3f0dSMasatake YAMATO taking_table = false;
11950cbf3f0dSMasatake YAMATO }
11960cbf3f0dSMasatake YAMATO
11970cbf3f0dSMasatake YAMATO if (taking_table)
11980cbf3f0dSMasatake YAMATO {
119940177cd9SMasatake YAMATO int t;
120040177cd9SMasatake YAMATO char *continuation = NULL;
120140177cd9SMasatake YAMATO
120240177cd9SMasatake YAMATO
12030cbf3f0dSMasatake YAMATO if (!v || (!*v))
12040cbf3f0dSMasatake YAMATO error (FATAL, "no table is given for table action: %s", s);
12050cbf3f0dSMasatake YAMATO
120640177cd9SMasatake YAMATO if (taction->action == TACTION_ENTER
120740177cd9SMasatake YAMATO && (continuation = strchr (v, ',')))
120840177cd9SMasatake YAMATO {
120940177cd9SMasatake YAMATO char *tableEnterTo;
121040177cd9SMasatake YAMATO
121140177cd9SMasatake YAMATO tableEnterTo = eStrndup (v, continuation - v);
121246837a67SHadriel Kaplan t = getTableIndexForName (cdata->lcb, tableEnterTo);
121340177cd9SMasatake YAMATO if (t < 0)
121440177cd9SMasatake YAMATO error (FATAL, "table is not defined: %s", tableEnterTo);
121546837a67SHadriel Kaplan taction->table = ptrArrayItem (cdata->lcb->tables, t);
121640177cd9SMasatake YAMATO eFree (tableEnterTo);
121740177cd9SMasatake YAMATO
121840177cd9SMasatake YAMATO if (!*(continuation + 1))
121940177cd9SMasatake YAMATO error (FATAL, "no continuation table is given for: %s", v);
122040177cd9SMasatake YAMATO
122146837a67SHadriel Kaplan int t_cont = getTableIndexForName (cdata->lcb, continuation + 1);
122240177cd9SMasatake YAMATO if (t_cont < 0)
122340177cd9SMasatake YAMATO error (FATAL, "table for continuation is not defined: %s", continuation + 1);
122446837a67SHadriel Kaplan taction->continuation_table = ptrArrayItem (cdata->lcb->tables, t_cont);
122540177cd9SMasatake YAMATO }
122640177cd9SMasatake YAMATO else
122740177cd9SMasatake YAMATO {
122846837a67SHadriel Kaplan t = getTableIndexForName (cdata->lcb, v);
12290cbf3f0dSMasatake YAMATO if (t < 0)
12300cbf3f0dSMasatake YAMATO error (FATAL, "table is not defined: %s", v);
123146837a67SHadriel Kaplan taction->table = ptrArrayItem (cdata->lcb->tables, t);
123240177cd9SMasatake YAMATO taction->continuation_table = NULL;
123340177cd9SMasatake YAMATO }
12340cbf3f0dSMasatake YAMATO }
12350cbf3f0dSMasatake YAMATO }
12360cbf3f0dSMasatake YAMATO
12370cbf3f0dSMasatake YAMATO static flagDefinition multitablePtrnFlagDef[] = {
12380cbf3f0dSMasatake YAMATO { '\0', "tenter", NULL, pre_ptrn_flag_mtable_long ,
123940177cd9SMasatake YAMATO "TABLE[,CONT]", "enter to given regext table (with specifying continuation)"},
12400cbf3f0dSMasatake YAMATO { '\0', "tleave", NULL, pre_ptrn_flag_mtable_long ,
12410cbf3f0dSMasatake YAMATO NULL, "leave from the current regext table"},
12420cbf3f0dSMasatake YAMATO { '\0', "tjump", NULL, pre_ptrn_flag_mtable_long ,
12430cbf3f0dSMasatake YAMATO "TABLE", "jump to another regext table(don't push the current table to state stack)"},
12440cbf3f0dSMasatake YAMATO { '\0', "treset", NULL, pre_ptrn_flag_mtable_long ,
12450cbf3f0dSMasatake YAMATO "TABLE", "clear the state stack and jump to given regex table"},
12460cbf3f0dSMasatake YAMATO { '\0', "tquit", NULL, pre_ptrn_flag_mtable_long ,
12470cbf3f0dSMasatake YAMATO NULL, "stop the parsing with this parser"},
12480cbf3f0dSMasatake YAMATO };
12490cbf3f0dSMasatake YAMATO
12500cbf3f0dSMasatake YAMATO
setKind(regexPattern * ptrn,const langType owner,const char kindLetter,const char * kindName,const char * const description,bool kind_explicitly_defined)12517dda83ebSHadriel Kaplan static void setKind(regexPattern * ptrn, const langType owner,
12527dda83ebSHadriel Kaplan const char kindLetter, const char* kindName,
12533950d588SMasatake YAMATO const char *const description,
12543950d588SMasatake YAMATO bool kind_explicitly_defined)
12557dda83ebSHadriel Kaplan {
12567dda83ebSHadriel Kaplan Assert (ptrn);
12577dda83ebSHadriel Kaplan Assert (ptrn->u.tag.name_pattern);
1258691d5f94SMasatake YAMATO Assert (kindName);
12593950d588SMasatake YAMATO kindDefinition *kdef = getLanguageKindForLetter (owner, kindLetter);
12607dda83ebSHadriel Kaplan
12617dda83ebSHadriel Kaplan if (kdef)
12627dda83ebSHadriel Kaplan {
1263691d5f94SMasatake YAMATO if (strcmp (kdef->name, kindName) && (strcmp(kindName, KIND_REGEX_DEFAULT_NAME)))
12647dda83ebSHadriel Kaplan /* When using a same kind letter for multiple regex patterns, the name of kind
12657dda83ebSHadriel Kaplan should be the same. */
12667dda83ebSHadriel Kaplan error (WARNING, "Don't reuse the kind letter `%c' in a language %s (old: \"%s\", new: \"%s\")",
12677dda83ebSHadriel Kaplan kdef->letter, getLanguageName (owner),
12687dda83ebSHadriel Kaplan kdef->name, kindName);
12693950d588SMasatake YAMATO ptrn->u.tag.kindIndex = kdef->id;
12707dda83ebSHadriel Kaplan }
12713950d588SMasatake YAMATO else if (*ptrn->u.tag.name_pattern == '\0' &&
12723950d588SMasatake YAMATO kindLetter == KIND_REGEX_DEFAULT_LETTER &&
12733950d588SMasatake YAMATO (strcmp(kindName, KIND_REGEX_DEFAULT_NAME) == 0) &&
12743950d588SMasatake YAMATO (!kind_explicitly_defined))
12753950d588SMasatake YAMATO ptrn->u.tag.kindIndex = KIND_GHOST_INDEX;
12767dda83ebSHadriel Kaplan else
12777dda83ebSHadriel Kaplan {
12787dda83ebSHadriel Kaplan kdef = kindNew (kindLetter, kindName, description);
12797dda83ebSHadriel Kaplan defineLanguageKind (owner, kdef, kindFree);
12807dda83ebSHadriel Kaplan ptrn->u.tag.kindIndex = kdef->id;
12817dda83ebSHadriel Kaplan }
12827dda83ebSHadriel Kaplan }
12837dda83ebSHadriel Kaplan
patternEvalFlags(struct lregexControlBlock * lcb,regexPattern * ptrn,enum regexParserType regptype,const char * flags)1284afe7a692SMasatake YAMATO static void patternEvalFlags (struct lregexControlBlock *lcb,
1285afe7a692SMasatake YAMATO regexPattern * ptrn,
1286afe7a692SMasatake YAMATO enum regexParserType regptype,
1287afe7a692SMasatake YAMATO const char* flags)
1288d4c6f1e6SMasatake YAMATO {
1289f74a98d6SHadriel Kaplan struct commonFlagData commonFlagData = {
129010db13faSMasatake YAMATO .owner = lcb->owner,
12910cbf3f0dSMasatake YAMATO .lcb = lcb,
129246837a67SHadriel Kaplan .ptrn = ptrn
12930cbf3f0dSMasatake YAMATO };
12940cbf3f0dSMasatake YAMATO
129546837a67SHadriel Kaplan if (regptype == REG_PARSER_SINGLE_LINE)
129646837a67SHadriel Kaplan flagsEval (flags, prePtrnFlagDef, ARRAY_SIZE(prePtrnFlagDef), &ptrn->exclusive);
129746837a67SHadriel Kaplan
1298e8386a4eSMasatake YAMATO const char * optscript = flagsEval (flags, commonSpecFlagDef, ARRAY_SIZE(commonSpecFlagDef), &commonFlagData);
1299e8386a4eSMasatake YAMATO if (optscript)
1300e8386a4eSMasatake YAMATO {
1301668e3666SMasatake YAMATO ptrn->optscript = scriptRead (optvm, optscript);
1302e8386a4eSMasatake YAMATO ptrn->optscript_src = eStrdup (optscript);
1303e8386a4eSMasatake YAMATO }
1304f74a98d6SHadriel Kaplan
130546837a67SHadriel Kaplan if (regptype == REG_PARSER_SINGLE_LINE || regptype == REG_PARSER_MULTI_TABLE)
1306f998e51dSMasatake YAMATO {
130746837a67SHadriel Kaplan flagsEval (flags, scopePtrnFlagDef, ARRAY_SIZE(scopePtrnFlagDef), &ptrn->scopeActions);
1308f998e51dSMasatake YAMATO if ((ptrn->scopeActions & (SCOPE_REF|SCOPE_REF_AFTER_POP)) == (SCOPE_REF|SCOPE_REF_AFTER_POP))
1309f998e51dSMasatake YAMATO error (WARNING, "%s: don't combine \"replace\" with the other scope action.",
1310f998e51dSMasatake YAMATO getLanguageName (lcb->owner));
1311f998e51dSMasatake YAMATO }
131246837a67SHadriel Kaplan
13130cbf3f0dSMasatake YAMATO if (regptype == REG_PARSER_MULTI_LINE || regptype == REG_PARSER_MULTI_TABLE)
1314f5ccb78dSMasatake YAMATO {
1315f5ccb78dSMasatake YAMATO ptrn->mgroup.forNextScanning = 0;
1316f5ccb78dSMasatake YAMATO /* ptrn->mgroup.nextFromStart is initialized in initMgroup() already. */
1317c9bfc26fSMasatake YAMATO flagsEval (flags, multilinePtrnFlagDef, ARRAY_SIZE(multilinePtrnFlagDef), &ptrn->mgroup);
1318f5ccb78dSMasatake YAMATO }
1319c9bfc26fSMasatake YAMATO
13206cdf5716SMasatake YAMATO struct guestPtrnFlagData guestPtrnFlagData = {
13216cdf5716SMasatake YAMATO .type = regptype,
13226cdf5716SMasatake YAMATO .guest = &ptrn->guest,
13236cdf5716SMasatake YAMATO };
13246cdf5716SMasatake YAMATO flagsEval (flags, guestPtrnFlagDef, ARRAY_SIZE(guestPtrnFlagDef), &guestPtrnFlagData);
13256cdf5716SMasatake YAMATO
13260cbf3f0dSMasatake YAMATO if (regptype == REG_PARSER_MULTI_TABLE)
132746837a67SHadriel Kaplan flagsEval (flags, multitablePtrnFlagDef, ARRAY_SIZE(multitablePtrnFlagDef), &commonFlagData);
1328afe7a692SMasatake YAMATO }
1329afe7a692SMasatake YAMATO
addCompiledTagPattern(struct lregexControlBlock * lcb,int table_index,enum regexParserType regptype,regexCompiledCode * const pattern,const char * const name,char kindLetter,const char * kindName,char * const description,const char * flags,bool kind_explicitly_defined,bool * disabled)1330afe7a692SMasatake YAMATO static regexPattern *addCompiledTagPattern (struct lregexControlBlock *lcb,
1331afe7a692SMasatake YAMATO int table_index,
1332c30b89acSMasatake YAMATO enum regexParserType regptype, regexCompiledCode* const pattern,
1333afe7a692SMasatake YAMATO const char* const name, char kindLetter, const char* kindName,
1334afe7a692SMasatake YAMATO char *const description, const char* flags,
13353950d588SMasatake YAMATO bool kind_explicitly_defined,
1336afe7a692SMasatake YAMATO bool *disabled)
1337afe7a692SMasatake YAMATO {
1338afe7a692SMasatake YAMATO regexPattern * ptrn = addCompiledTagCommon(lcb, table_index, pattern, regptype);
1339afe7a692SMasatake YAMATO
1340afe7a692SMasatake YAMATO ptrn->type = PTRN_TAG;
1341afe7a692SMasatake YAMATO ptrn->u.tag.name_pattern = eStrdup (name);
1342afe7a692SMasatake YAMATO ptrn->disabled = disabled;
1343afe7a692SMasatake YAMATO
13443950d588SMasatake YAMATO setKind(ptrn, lcb->owner, kindLetter, kindName, description, kind_explicitly_defined);
1345afe7a692SMasatake YAMATO patternEvalFlags (lcb, ptrn, regptype, flags);
13460cbf3f0dSMasatake YAMATO
134712ddaaa3SMasatake YAMATO return ptrn;
1348d4c6f1e6SMasatake YAMATO }
1349d4c6f1e6SMasatake YAMATO
addCompiledCallbackPattern(struct lregexControlBlock * lcb,regexCompiledCode * const pattern,const regexCallback callback,const char * flags,bool * disabled,void * userData)1350c30b89acSMasatake YAMATO static regexPattern *addCompiledCallbackPattern (struct lregexControlBlock *lcb, regexCompiledCode* const pattern,
13516ff4dab6SMasatake YAMATO const regexCallback callback, const char* flags,
1352ce990805SThomas Braun bool *disabled,
13536ff4dab6SMasatake YAMATO void *userData)
1354d4c6f1e6SMasatake YAMATO {
1355d4c6f1e6SMasatake YAMATO regexPattern * ptrn;
1356ce990805SThomas Braun bool exclusive = false;
13573db72c21SMasatake YAMATO flagsEval (flags, prePtrnFlagDef, ARRAY_SIZE(prePtrnFlagDef), &exclusive);
13580cbf3f0dSMasatake YAMATO ptrn = addCompiledTagCommon(lcb, TABLE_INDEX_UNUSED, pattern, REG_PARSER_SINGLE_LINE);
1359d4c6f1e6SMasatake YAMATO ptrn->type = PTRN_CALLBACK;
1360d4c6f1e6SMasatake YAMATO ptrn->u.callback.function = callback;
13616ff4dab6SMasatake YAMATO ptrn->u.callback.userData = userData;
13625fdabf71SMasatake YAMATO ptrn->exclusive = exclusive;
13632a738f47SMasatake YAMATO ptrn->disabled = disabled;
13645372d785SMasatake YAMATO return ptrn;
1365d4c6f1e6SMasatake YAMATO }
1366d4c6f1e6SMasatake YAMATO
136765426ae0SMasatake YAMATO #ifndef HAVE_PCRE2
no_pcre2_regex_flag_short(char c,void * data)136865426ae0SMasatake YAMATO static void no_pcre2_regex_flag_short (char c, void* data)
136965426ae0SMasatake YAMATO {
137065426ae0SMasatake YAMATO error (WARNING, "'p' flag is specied but pcre2 regex engine is not linked.");
137165426ae0SMasatake YAMATO }
no_pcre2_regex_flag_long(const char * const s,const char * const unused CTAGS_ATTR_UNUSED,void * data)137265426ae0SMasatake YAMATO static void no_pcre2_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
137365426ae0SMasatake YAMATO {
137465426ae0SMasatake YAMATO error (WARNING, "{pcre2} flag is specied but pcre2 regex engine is not linked.");
137565426ae0SMasatake YAMATO }
137665426ae0SMasatake YAMATO #endif
137765426ae0SMasatake YAMATO
1378c30b89acSMasatake YAMATO static flagDefinition backendFlagDefs[] = {
1379c30b89acSMasatake YAMATO { 'b', "basic", basic_regex_flag_short, basic_regex_flag_long,
1380c30b89acSMasatake YAMATO NULL, "interpreted as a Posix basic regular expression."},
1381c30b89acSMasatake YAMATO { 'e', "extend", extend_regex_flag_short, extend_regex_flag_long,
1382c30b89acSMasatake YAMATO NULL, "interpreted as a Posix extended regular expression (default)"},
13836a8d5b70SMasatake YAMATO #ifdef HAVE_PCRE2
13846a8d5b70SMasatake YAMATO { 'p', "pcre2", pcre2_regex_flag_short, pcre2_regex_flag_long,
13856a8d5b70SMasatake YAMATO NULL, "use pcre2 regex engine"},
138665426ae0SMasatake YAMATO #else
138765426ae0SMasatake YAMATO { 'p', "pcre2", no_pcre2_regex_flag_short, no_pcre2_regex_flag_long,
138865426ae0SMasatake YAMATO NULL, "pcre2 is NOT linked!"},
13896a8d5b70SMasatake YAMATO #endif
1390c30b89acSMasatake YAMATO };
1391d4c6f1e6SMasatake YAMATO
regex_flag_icase_short(char c CTAGS_ATTR_UNUSED,void * data)13928ccb7ee9SJiří Techet static void regex_flag_icase_short (char c CTAGS_ATTR_UNUSED, void* data)
1393d4c6f1e6SMasatake YAMATO {
1394c30b89acSMasatake YAMATO struct flagDefsDescriptor *desc = data;
1395c30b89acSMasatake YAMATO desc->backend->set_icase_flag (&desc->flags);
1396d4c6f1e6SMasatake YAMATO }
1397d4c6f1e6SMasatake YAMATO
regex_flag_icase_long(const char * s CTAGS_ATTR_UNUSED,const char * const unused CTAGS_ATTR_UNUSED,void * data)13988ccb7ee9SJiří Techet static void regex_flag_icase_long (const char* s CTAGS_ATTR_UNUSED, const char* const unused CTAGS_ATTR_UNUSED, void* data)
1399d4c6f1e6SMasatake YAMATO {
1400d4c6f1e6SMasatake YAMATO regex_flag_icase_short ('i', data);
1401d4c6f1e6SMasatake YAMATO }
1402d4c6f1e6SMasatake YAMATO
1403c30b89acSMasatake YAMATO static flagDefinition backendCommonRegexFlagDefs[] = {
14043fac0fc6SMasatake YAMATO { 'i', "icase", regex_flag_icase_short, regex_flag_icase_long,
14053fac0fc6SMasatake YAMATO NULL, "applied in a case-insensitive manner"},
14063fac0fc6SMasatake YAMATO };
14073fac0fc6SMasatake YAMATO
1408c30b89acSMasatake YAMATO
choose_backend(const char * flags,enum regexParserType regptype,bool error_if_no_backend)14096a8d5b70SMasatake YAMATO static struct flagDefsDescriptor choose_backend (const char *flags, enum regexParserType regptype, bool error_if_no_backend)
1410c30b89acSMasatake YAMATO {
1411c30b89acSMasatake YAMATO struct flagDefsDescriptor desc = {
1412c30b89acSMasatake YAMATO .backend = NULL,
1413c30b89acSMasatake YAMATO .flags = 0,
1414c30b89acSMasatake YAMATO .regptype = regptype,
1415c30b89acSMasatake YAMATO };
1416c30b89acSMasatake YAMATO
1417c30b89acSMasatake YAMATO if (flags)
1418c30b89acSMasatake YAMATO flagsEval (flags,
1419c30b89acSMasatake YAMATO backendFlagDefs,
1420c30b89acSMasatake YAMATO ARRAY_SIZE(backendFlagDefs),
1421c30b89acSMasatake YAMATO &desc);
1422c30b89acSMasatake YAMATO
1423c30b89acSMasatake YAMATO /* Choose the default backend. */
1424c30b89acSMasatake YAMATO if (desc.backend == NULL)
14256a8d5b70SMasatake YAMATO {
14266a8d5b70SMasatake YAMATO if (flags && error_if_no_backend)
14276a8d5b70SMasatake YAMATO error (FATAL, "No sunch backend for the name: \"%s\"", flags);
14286a8d5b70SMasatake YAMATO
1429c30b89acSMasatake YAMATO flagsEval (DEFAULT_REGEX_BACKEND,
1430c30b89acSMasatake YAMATO backendFlagDefs,
1431c30b89acSMasatake YAMATO ARRAY_SIZE(backendFlagDefs),
1432c30b89acSMasatake YAMATO &desc);
14336a8d5b70SMasatake YAMATO }
1434c30b89acSMasatake YAMATO return desc;
1435c30b89acSMasatake YAMATO }
1436c30b89acSMasatake YAMATO
compileRegex(enum regexParserType regptype,const char * const regexp,const char * const flags)1437c30b89acSMasatake YAMATO static regexCompiledCode compileRegex (enum regexParserType regptype,
143841e0b4f8SMasatake YAMATO const char* const regexp, const char* const flags)
1439d4c6f1e6SMasatake YAMATO {
14406a8d5b70SMasatake YAMATO struct flagDefsDescriptor desc = choose_backend (flags, regptype, false);
144141e0b4f8SMasatake YAMATO
1442c30b89acSMasatake YAMATO /* Evaluate backend specific flags */
1443c30b89acSMasatake YAMATO flagsEval (flags,
1444c30b89acSMasatake YAMATO desc.backend->fdefs,
1445c30b89acSMasatake YAMATO desc.backend->fdef_count,
1446c30b89acSMasatake YAMATO &desc.flags);
1447d4c6f1e6SMasatake YAMATO
1448d4c6f1e6SMasatake YAMATO flagsEval (flags,
1449c30b89acSMasatake YAMATO backendCommonRegexFlagDefs,
1450c30b89acSMasatake YAMATO ARRAY_SIZE (backendCommonRegexFlagDefs),
1451c30b89acSMasatake YAMATO &desc);
1452d4c6f1e6SMasatake YAMATO
1453c30b89acSMasatake YAMATO return desc.backend->compile (desc.backend, regexp, desc.flags);
1454d4c6f1e6SMasatake YAMATO }
1455d4c6f1e6SMasatake YAMATO
1456d4c6f1e6SMasatake YAMATO
14577882f6d8SMasatake YAMATO /* If a letter and/or a name are defined in kindSpec, return true. */
parseKinds(const char * const kindSpec,char * const kindLetter,char ** const kindName,char ** description)14587882f6d8SMasatake YAMATO static bool parseKinds (
14594b447dd0SMasatake YAMATO const char* const kindSpec, char* const kindLetter, char** const kindName,
1460d4c6f1e6SMasatake YAMATO char **description)
1461d4c6f1e6SMasatake YAMATO {
1462d4c6f1e6SMasatake YAMATO *description = NULL;
1463b948e230SMasatake YAMATO
14644b447dd0SMasatake YAMATO if (kindSpec == NULL || kindSpec [0] == '\0')
1465d4c6f1e6SMasatake YAMATO {
146649a1e332SMasatake YAMATO *kindLetter = KIND_REGEX_DEFAULT_LETTER;
14677e1bd430SMasatake YAMATO *kindName = eStrdup (KIND_REGEX_DEFAULT_NAME);
14687882f6d8SMasatake YAMATO return false;
1469d4c6f1e6SMasatake YAMATO }
1470087b3e2bSMasatake YAMATO else
1471d4c6f1e6SMasatake YAMATO {
14727882f6d8SMasatake YAMATO bool explicitly_defined = false;
14734b447dd0SMasatake YAMATO const char* k = kindSpec;
1474b948e230SMasatake YAMATO
1475d4c6f1e6SMasatake YAMATO if (k [0] != ',' && (k [1] == ',' || k [1] == '\0'))
14767882f6d8SMasatake YAMATO {
147749a1e332SMasatake YAMATO *kindLetter = *k++;
14787882f6d8SMasatake YAMATO explicitly_defined = true;
14797882f6d8SMasatake YAMATO }
1480d4c6f1e6SMasatake YAMATO else
148149a1e332SMasatake YAMATO *kindLetter = KIND_REGEX_DEFAULT_LETTER;
1482b948e230SMasatake YAMATO
1483d4c6f1e6SMasatake YAMATO if (*k == ',')
1484d4c6f1e6SMasatake YAMATO ++k;
1485b948e230SMasatake YAMATO
1486d4c6f1e6SMasatake YAMATO if (k [0] == '\0')
14877e1bd430SMasatake YAMATO *kindName = eStrdup (KIND_REGEX_DEFAULT_NAME);
1488d4c6f1e6SMasatake YAMATO else
1489d4c6f1e6SMasatake YAMATO {
1490d4c6f1e6SMasatake YAMATO const char *const comma = strchr (k, ',');
1491b948e230SMasatake YAMATO
1492d4c6f1e6SMasatake YAMATO if (comma == NULL)
14937882f6d8SMasatake YAMATO {
14947882f6d8SMasatake YAMATO if (strlen (k) == 0)
14957882f6d8SMasatake YAMATO *kindName = eStrdup (KIND_REGEX_DEFAULT_NAME);
14967882f6d8SMasatake YAMATO else
14977882f6d8SMasatake YAMATO {
1498d4c6f1e6SMasatake YAMATO *kindName = eStrdup (k);
14997882f6d8SMasatake YAMATO explicitly_defined = true;
15007882f6d8SMasatake YAMATO }
15017882f6d8SMasatake YAMATO }
15027882f6d8SMasatake YAMATO else
15037882f6d8SMasatake YAMATO {
15047882f6d8SMasatake YAMATO if (comma - k == 0)
15057882f6d8SMasatake YAMATO *kindName = eStrdup (KIND_REGEX_DEFAULT_NAME);
1506d4c6f1e6SMasatake YAMATO else
1507d4c6f1e6SMasatake YAMATO {
1508153ec6e9SMasatake YAMATO *kindName = eStrndup (k, comma - k );
15097882f6d8SMasatake YAMATO explicitly_defined = true;
15107882f6d8SMasatake YAMATO }
1511d4c6f1e6SMasatake YAMATO k = comma + 1;
1512d4c6f1e6SMasatake YAMATO if (k [0] != '\0')
1513d4c6f1e6SMasatake YAMATO *description = eStrdup (k);
1514d4c6f1e6SMasatake YAMATO }
1515d4c6f1e6SMasatake YAMATO }
15167882f6d8SMasatake YAMATO return explicitly_defined;
1517d4c6f1e6SMasatake YAMATO }
1518d4c6f1e6SMasatake YAMATO }
1519d4c6f1e6SMasatake YAMATO
1520d4c6f1e6SMasatake YAMATO /*
1521d4c6f1e6SMasatake YAMATO * Regex pattern matching
1522d4c6f1e6SMasatake YAMATO */
1523d4c6f1e6SMasatake YAMATO
1524d4c6f1e6SMasatake YAMATO
substitute(const char * const in,const char * out,const int nmatch,const regmatch_t * const pmatch)1525d4c6f1e6SMasatake YAMATO static vString* substitute (
1526d4c6f1e6SMasatake YAMATO const char* const in, const char* out,
15270248c4bfSMasatake YAMATO const int nmatch, const regmatch_t* const pmatch)
1528d4c6f1e6SMasatake YAMATO {
1529d4c6f1e6SMasatake YAMATO vString* result = vStringNew ();
1530d4c6f1e6SMasatake YAMATO const char* p;
1531d4c6f1e6SMasatake YAMATO for (p = out ; *p != '\0' ; p++)
1532d4c6f1e6SMasatake YAMATO {
1533d4c6f1e6SMasatake YAMATO if (*p == '\\' && isdigit ((int) *++p))
1534d4c6f1e6SMasatake YAMATO {
1535d4c6f1e6SMasatake YAMATO const int dig = *p - '0';
1536d4c6f1e6SMasatake YAMATO if (0 < dig && dig < nmatch && pmatch [dig].rm_so != -1)
1537d4c6f1e6SMasatake YAMATO {
1538d4c6f1e6SMasatake YAMATO const int diglen = pmatch [dig].rm_eo - pmatch [dig].rm_so;
1539d4c6f1e6SMasatake YAMATO vStringNCatS (result, in + pmatch [dig].rm_so, diglen);
1540d4c6f1e6SMasatake YAMATO }
1541d4c6f1e6SMasatake YAMATO }
15420248c4bfSMasatake YAMATO else if (*p != '\n' && *p != '\r')
1543d4c6f1e6SMasatake YAMATO vStringPut (result, *p);
1544d4c6f1e6SMasatake YAMATO }
1545d4c6f1e6SMasatake YAMATO return result;
1546d4c6f1e6SMasatake YAMATO }
1547d4c6f1e6SMasatake YAMATO
getInputLineNumberInRegPType(enum regexParserType regptype,off_t offset)15480abfb303SMasatake YAMATO static unsigned long getInputLineNumberInRegPType (enum regexParserType regptype,
15490abfb303SMasatake YAMATO off_t offset)
15500abfb303SMasatake YAMATO {
155141e0b4f8SMasatake YAMATO return (regptype == REG_PARSER_MULTI_LINE || regptype == REG_PARSER_MULTI_TABLE)
15520abfb303SMasatake YAMATO ? getInputLineNumberForFileOffset (offset)
15530abfb303SMasatake YAMATO : getInputLineNumber ();
15540abfb303SMasatake YAMATO }
15550abfb303SMasatake YAMATO
fillEndLineFieldOfUpperScopes(struct lregexControlBlock * lcb,unsigned long endline)1556ec25b18fSMasatake YAMATO static void fillEndLineFieldOfUpperScopes (struct lregexControlBlock *lcb, unsigned long endline)
1557ec25b18fSMasatake YAMATO {
1558ec25b18fSMasatake YAMATO tagEntryInfo *entry;
15593afb5475SMasatake YAMATO int n = lcb->currentScope;
1560ec25b18fSMasatake YAMATO
1561ec25b18fSMasatake YAMATO while ((entry = getEntryInCorkQueue (n))
1562ec25b18fSMasatake YAMATO && (entry->extensionFields.endLine == 0))
1563ec25b18fSMasatake YAMATO {
1564ec25b18fSMasatake YAMATO entry->extensionFields.endLine = endline;
1565ec25b18fSMasatake YAMATO n = entry->extensionFields.scopeIndex;
1566ec25b18fSMasatake YAMATO }
1567ec25b18fSMasatake YAMATO }
1568ec25b18fSMasatake YAMATO
hasNameSlot(const regexPattern * const patbuf)1569e8386a4eSMasatake YAMATO static bool hasNameSlot (const regexPattern* const patbuf)
1570e8386a4eSMasatake YAMATO {
1571e8386a4eSMasatake YAMATO return (patbuf->u.tag.name_pattern[0] != '\0'
1572e8386a4eSMasatake YAMATO || patbuf->anonymous_tag_prefix);
1573e8386a4eSMasatake YAMATO }
1574e8386a4eSMasatake YAMATO
scopeActionRef(int currentScope)1575f998e51dSMasatake YAMATO static int scopeActionRef (int currentScope)
1576f998e51dSMasatake YAMATO {
1577f998e51dSMasatake YAMATO int scope = currentScope;
1578f998e51dSMasatake YAMATO tagEntryInfo *entry;
1579f998e51dSMasatake YAMATO while ((entry = getEntryInCorkQueue (scope)) && entry->placeholder)
1580f998e51dSMasatake YAMATO /* Look at parent */
1581f998e51dSMasatake YAMATO scope = entry->extensionFields.scopeIndex;
1582f998e51dSMasatake YAMATO return scope;
1583f998e51dSMasatake YAMATO }
1584f998e51dSMasatake YAMATO
matchTagPattern(struct lregexControlBlock * lcb,const char * line,const regexPattern * const patbuf,const regmatch_t * const pmatch,off_t offset,scriptWindow * window)1585fbcb3274SMasatake YAMATO static void matchTagPattern (struct lregexControlBlock *lcb,
1586fbcb3274SMasatake YAMATO const char* line,
1587d4c6f1e6SMasatake YAMATO const regexPattern* const patbuf,
158813939209SMasatake YAMATO const regmatch_t* const pmatch,
15892bbd136eSMasatake YAMATO off_t offset, scriptWindow *window)
1590d4c6f1e6SMasatake YAMATO {
15910d56cc8eSMasatake YAMATO vString *const name =
15920d56cc8eSMasatake YAMATO (patbuf->u.tag.name_pattern[0] != '\0') ? substitute (line,
15930d56cc8eSMasatake YAMATO patbuf->u.tag.name_pattern,
15940d56cc8eSMasatake YAMATO BACK_REFERENCE_COUNT, pmatch):
15950d56cc8eSMasatake YAMATO (patbuf->anonymous_tag_prefix) ? anonGenerateNew (patbuf->anonymous_tag_prefix,
15960d56cc8eSMasatake YAMATO patbuf->u.tag.kindIndex):
15970d56cc8eSMasatake YAMATO vStringNewInit ("");
1598ce990805SThomas Braun bool placeholder = !!((patbuf->scopeActions & SCOPE_PLACEHOLDER) == SCOPE_PLACEHOLDER);
15993afb5475SMasatake YAMATO int scope = CORK_NIL;
16002fa3c9e1SMasatake YAMATO int n;
16012fa3c9e1SMasatake YAMATO
1602b593f516SMasatake YAMATO vStringStripLeading (name);
1603b593f516SMasatake YAMATO vStringStripTrailing (name);
1604b593f516SMasatake YAMATO
16052fa3c9e1SMasatake YAMATO if (patbuf->scopeActions & SCOPE_REF)
1606f998e51dSMasatake YAMATO scope = scopeActionRef (lcb->currentScope);
16072fa3c9e1SMasatake YAMATO if (patbuf->scopeActions & SCOPE_CLEAR)
16082db4cedcSMasatake YAMATO {
16091e91f04aSMasatake YAMATO unsigned long endline = getInputLineNumberInRegPType(patbuf->regptype, offset);
1610dcac9704SMasatake YAMATO
1611dcac9704SMasatake YAMATO /*
1612dcac9704SMasatake YAMATO * SCOPE_CLEAR|SCOPE_PUSH implies that "set" was specified as the scope action.
1613dcac9704SMasatake YAMATO * If the specified action is "set", getInputLineNumberInRegPType()
1614dcac9704SMasatake YAMATO * returns the start line of the NEW scope. The cleared scopes are ended BEFORE
1615dcac9704SMasatake YAMATO * the new scope. There is a gap. We must adjust the "end:" field here.
1616dcac9704SMasatake YAMATO */
1617dcac9704SMasatake YAMATO if (patbuf->scopeActions & SCOPE_PUSH && endline > 0)
1618dcac9704SMasatake YAMATO endline--;
1619dcac9704SMasatake YAMATO
1620ec25b18fSMasatake YAMATO fillEndLineFieldOfUpperScopes (lcb, endline);
16212db4cedcSMasatake YAMATO lcb->currentScope = CORK_NIL;
16222db4cedcSMasatake YAMATO }
16232fa3c9e1SMasatake YAMATO if (patbuf->scopeActions & SCOPE_POP)
16242fa3c9e1SMasatake YAMATO {
16252db4cedcSMasatake YAMATO tagEntryInfo *entry = getEntryInCorkQueue (lcb->currentScope);
16261e91f04aSMasatake YAMATO
16271e91f04aSMasatake YAMATO if (entry && (entry->extensionFields.endLine == 0))
1628f998e51dSMasatake YAMATO {
16291e91f04aSMasatake YAMATO entry->extensionFields.endLine = getInputLineNumberInRegPType(patbuf->regptype, offset);
16301e91f04aSMasatake YAMATO
1631f998e51dSMasatake YAMATO /*
1632f998e51dSMasatake YAMATO * SCOPE_POP|SCOPE_REF_AFTER_POP implies that "replace" was specified as the
1633f998e51dSMasatake YAMATO * scope action. If the specified action is "replace", getInputLineNumberInRegPType()
1634f998e51dSMasatake YAMATO * returns the start line of the NEW scope. The popped scope is ended BEFORE
1635f998e51dSMasatake YAMATO * the new scope. There is a gap. We must adjust the "end:" field here.
1636f998e51dSMasatake YAMATO */
1637f998e51dSMasatake YAMATO if ((patbuf->scopeActions & SCOPE_REF_AFTER_POP) &&
1638f998e51dSMasatake YAMATO entry->extensionFields.endLine > 1)
1639f998e51dSMasatake YAMATO entry->extensionFields.endLine--;
1640f998e51dSMasatake YAMATO }
1641f998e51dSMasatake YAMATO
16422db4cedcSMasatake YAMATO lcb->currentScope = entry? entry->extensionFields.scopeIndex: CORK_NIL;
16432fa3c9e1SMasatake YAMATO }
1644f998e51dSMasatake YAMATO if (patbuf->scopeActions & SCOPE_REF_AFTER_POP)
1645f998e51dSMasatake YAMATO scope = scopeActionRef (lcb->currentScope);
1646b593f516SMasatake YAMATO
1647ce990805SThomas Braun if (vStringLength (name) == 0 && (placeholder == false))
1648b593f516SMasatake YAMATO {
1649ce990805SThomas Braun if (patbuf->accept_empty_name == false)
165013939209SMasatake YAMATO error (WARNING, "%s:%lu: null expansion of name pattern \"%s\"",
165113939209SMasatake YAMATO getInputFileName (),
16520abfb303SMasatake YAMATO getInputLineNumberInRegPType(patbuf->regptype, offset),
1653d4c6f1e6SMasatake YAMATO patbuf->u.tag.name_pattern);
1654f6027918SMasatake YAMATO n = CORK_NIL;
16552fa3c9e1SMasatake YAMATO }
1656b593f516SMasatake YAMATO else
165713939209SMasatake YAMATO {
1658e024ff82SHadriel Kaplan static TrashBox* field_trashbox;
165913939209SMasatake YAMATO unsigned long ln = 0;
166013939209SMasatake YAMATO MIOPos pos;
1661f53f3c39SMasatake YAMATO tagEntryInfo e;
166216a2541cSMasatake YAMATO int kind;
166384f3a057SMasatake YAMATO roleBitsType roleBits;
166413939209SMasatake YAMATO
166541e0b4f8SMasatake YAMATO if ((patbuf->regptype == REG_PARSER_MULTI_LINE)
166641e0b4f8SMasatake YAMATO || (patbuf->regptype == REG_PARSER_MULTI_TABLE))
166713939209SMasatake YAMATO {
166813939209SMasatake YAMATO ln = getInputLineNumberForFileOffset (offset);
166913939209SMasatake YAMATO pos = getInputFilePositionForLine (ln);
167013939209SMasatake YAMATO }
167113939209SMasatake YAMATO
1672f53f3c39SMasatake YAMATO n = CORK_NIL;
167316a2541cSMasatake YAMATO kind = patbuf->u.tag.kindIndex;
167484f3a057SMasatake YAMATO roleBits = patbuf->u.tag.roleBits;
1675f53f3c39SMasatake YAMATO
1676a114f06bSMasatake YAMATO initRegexTag (&e, vStringValue (name), kind, ROLE_DEFINITION_INDEX, scope, placeholder,
1677e024ff82SHadriel Kaplan ln, ln == 0? NULL: &pos, patbuf->xtagType);
1678e024ff82SHadriel Kaplan
1679f53f3c39SMasatake YAMATO if (field_trashbox == NULL)
1680f53f3c39SMasatake YAMATO {
1681f53f3c39SMasatake YAMATO field_trashbox = trashBoxNew();
1682f53f3c39SMasatake YAMATO DEFAULT_TRASH_BOX (field_trashbox, trashBoxDelete);
1683f53f3c39SMasatake YAMATO }
1684f53f3c39SMasatake YAMATO
1685f53f3c39SMasatake YAMATO if (patbuf->fieldPatterns)
1686f53f3c39SMasatake YAMATO {
168746ab94ccSMasatake YAMATO for (unsigned int i = 0; i < ptrArrayCount(patbuf->fieldPatterns); i++)
1688f53f3c39SMasatake YAMATO {
1689f53f3c39SMasatake YAMATO struct fieldPattern *fp = ptrArrayItem(patbuf->fieldPatterns, i);
1690f53f3c39SMasatake YAMATO if (isFieldEnabled (fp->ftype))
1691f53f3c39SMasatake YAMATO {
1692f53f3c39SMasatake YAMATO vString * const value = substitute (line, fp->template,
16930248c4bfSMasatake YAMATO BACK_REFERENCE_COUNT, pmatch);
1694aa4def17SMasatake YAMATO attachParserField (&e, false, fp->ftype, vStringValue (value));
1695f53f3c39SMasatake YAMATO trashBoxPut (field_trashbox, value,
1696f53f3c39SMasatake YAMATO (TrashBoxDestroyItemProc)vStringDelete);
1697f53f3c39SMasatake YAMATO }
1698f53f3c39SMasatake YAMATO }
1699f53f3c39SMasatake YAMATO }
170084f3a057SMasatake YAMATO
170184f3a057SMasatake YAMATO if (roleBits)
170284f3a057SMasatake YAMATO {
17034c64e833SMasatake YAMATO unsigned int roleIndex;
170484f3a057SMasatake YAMATO
170584f3a057SMasatake YAMATO for (roleIndex = 0;
170684f3a057SMasatake YAMATO roleIndex < countLanguageRoles(e.langType, kind);
170784f3a057SMasatake YAMATO roleIndex++)
170884f3a057SMasatake YAMATO {
170984f3a057SMasatake YAMATO if (roleBits & makeRoleBit(roleIndex))
171084f3a057SMasatake YAMATO assignRole (&e, roleIndex);
171184f3a057SMasatake YAMATO }
171284f3a057SMasatake YAMATO }
17130d56cc8eSMasatake YAMATO
17140d56cc8eSMasatake YAMATO if (patbuf->anonymous_tag_prefix)
17150d56cc8eSMasatake YAMATO markTagExtraBit (&e, XTAG_ANONYMOUS);
17160d56cc8eSMasatake YAMATO
1717f53f3c39SMasatake YAMATO n = makeTagEntry (&e);
1718f53f3c39SMasatake YAMATO
1719f53f3c39SMasatake YAMATO trashBoxMakeEmpty(field_trashbox);
1720f53f3c39SMasatake YAMATO }
1721b593f516SMasatake YAMATO
1722b593f516SMasatake YAMATO if (patbuf->scopeActions & SCOPE_PUSH)
17232db4cedcSMasatake YAMATO lcb->currentScope = n;
17242fa3c9e1SMasatake YAMATO
17252bbd136eSMasatake YAMATO if (n != CORK_NIL && window)
1726e8386a4eSMasatake YAMATO {
17272bbd136eSMasatake YAMATO scriptSetup (optvm, lcb, n, window);
1728668e3666SMasatake YAMATO EsObject *e = scriptEval (optvm, patbuf->optscript);
1729e8386a4eSMasatake YAMATO if (es_error_p (e))
1730e8386a4eSMasatake YAMATO error (WARNING, "error when evaluating: %s", patbuf->optscript_src);
1731e8386a4eSMasatake YAMATO es_object_unref (e);
1732668e3666SMasatake YAMATO scriptTeardown (optvm, lcb);
1733e8386a4eSMasatake YAMATO }
1734e8386a4eSMasatake YAMATO
1735d4c6f1e6SMasatake YAMATO vStringDelete (name);
1736d4c6f1e6SMasatake YAMATO }
1737d4c6f1e6SMasatake YAMATO
matchCallbackPattern(const vString * const line,const regexPattern * const patbuf,const regmatch_t * const pmatch)173818480890SMasatake YAMATO static bool matchCallbackPattern (
1739d4c6f1e6SMasatake YAMATO const vString* const line, const regexPattern* const patbuf,
1740d4c6f1e6SMasatake YAMATO const regmatch_t* const pmatch)
1741d4c6f1e6SMasatake YAMATO {
1742d4c6f1e6SMasatake YAMATO regexMatch matches [BACK_REFERENCE_COUNT];
1743d4c6f1e6SMasatake YAMATO unsigned int count = 0;
1744d4c6f1e6SMasatake YAMATO int i;
1745d4c6f1e6SMasatake YAMATO for (i = 0 ; i < BACK_REFERENCE_COUNT ; ++i)
1746d4c6f1e6SMasatake YAMATO {
1747d4c6f1e6SMasatake YAMATO matches [i].start = pmatch [i].rm_so;
1748d4c6f1e6SMasatake YAMATO matches [i].length = pmatch [i].rm_eo - pmatch [i].rm_so;
1749d4c6f1e6SMasatake YAMATO /* a valid match may have both offsets == -1,
1750d4c6f1e6SMasatake YAMATO * e.g. (foo)*(bar) matching "bar" - see CTags bug 271.
1751d4c6f1e6SMasatake YAMATO * As POSIX regex doesn't seem to have a way to count matches,
1752d4c6f1e6SMasatake YAMATO * we return the count up to the last non-empty match. */
1753d4c6f1e6SMasatake YAMATO if (pmatch [i].rm_so != -1)
1754d4c6f1e6SMasatake YAMATO count = i + 1;
1755d4c6f1e6SMasatake YAMATO }
175618480890SMasatake YAMATO return patbuf->u.callback.function (vStringValue (line), matches, count,
17576ff4dab6SMasatake YAMATO patbuf->u.callback.userData);
1758d4c6f1e6SMasatake YAMATO }
1759d4c6f1e6SMasatake YAMATO
17609a1e266aSHadriel Kaplan
printMessage(const langType language,const regexPattern * const ptrn,const off_t offset,const char * const line,const regmatch_t * const pmatch)17619a1e266aSHadriel Kaplan static void printMessage(const langType language,
17629a1e266aSHadriel Kaplan const regexPattern *const ptrn,
17639a1e266aSHadriel Kaplan const off_t offset,
17649a1e266aSHadriel Kaplan const char *const line,
17659a1e266aSHadriel Kaplan const regmatch_t* const pmatch)
17669a1e266aSHadriel Kaplan {
17679a1e266aSHadriel Kaplan vString *msg;
17689a1e266aSHadriel Kaplan
17699a1e266aSHadriel Kaplan Assert (ptrn);
17709a1e266aSHadriel Kaplan Assert (ptrn->message.selection > 0);
17719a1e266aSHadriel Kaplan Assert (ptrn->message.message_string);
17729a1e266aSHadriel Kaplan
17739a1e266aSHadriel Kaplan msg = substitute (line, ptrn->message.message_string, BACK_REFERENCE_COUNT, pmatch);
17749a1e266aSHadriel Kaplan
17759a1e266aSHadriel Kaplan error (ptrn->message.selection, "%sMessage from regex<%s>: %s (%s:%lu)",
17769a1e266aSHadriel Kaplan (ptrn->message.selection == FATAL ? "Fatal: " : ""),
17779a1e266aSHadriel Kaplan getLanguageName (language),
17789a1e266aSHadriel Kaplan vStringValue (msg),
17799a1e266aSHadriel Kaplan getInputFileName (),
17809a1e266aSHadriel Kaplan getInputLineNumberInRegPType (ptrn->regptype, offset));
17819a1e266aSHadriel Kaplan
17829a1e266aSHadriel Kaplan vStringDelete (msg);
17839a1e266aSHadriel Kaplan }
17849a1e266aSHadriel Kaplan
isGuestRequestConsistent(struct guestRequest * guest_req)17856cdf5716SMasatake YAMATO static bool isGuestRequestConsistent (struct guestRequest *guest_req)
17866cdf5716SMasatake YAMATO {
17876cdf5716SMasatake YAMATO return (guest_req->lang != LANG_IGNORE)
17886cdf5716SMasatake YAMATO && (guest_req->boundary[BOUNDARY_START].offset < guest_req->boundary[BOUNDARY_END].offset);
17896cdf5716SMasatake YAMATO }
17906cdf5716SMasatake YAMATO
fillGuestRequest(const char * start,const char * current,regmatch_t pmatch[BACK_REFERENCE_COUNT],struct guestSpec * guest_spec,struct guestRequest * guest_req)17916cdf5716SMasatake YAMATO static bool fillGuestRequest (const char *start,
17926cdf5716SMasatake YAMATO const char *current,
17936cdf5716SMasatake YAMATO regmatch_t pmatch [BACK_REFERENCE_COUNT],
17946cdf5716SMasatake YAMATO struct guestSpec *guest_spec,
17956cdf5716SMasatake YAMATO struct guestRequest *guest_req)
17966cdf5716SMasatake YAMATO {
17976cdf5716SMasatake YAMATO if (guest_spec->lang.type == GUEST_LANG_UNKNOWN)
17986cdf5716SMasatake YAMATO return false;
17996cdf5716SMasatake YAMATO else if (guest_spec->lang.type == GUEST_LANG_PLACEHOLDER)
18006cdf5716SMasatake YAMATO ;
18016cdf5716SMasatake YAMATO else if (guest_spec->lang.type == GUEST_LANG_STATIC_LANGNAME)
18026cdf5716SMasatake YAMATO {
18036cdf5716SMasatake YAMATO guest_req->lang = guest_spec->lang.spec.lang;
18046cdf5716SMasatake YAMATO guest_req->lang_set = true;
18056cdf5716SMasatake YAMATO }
18066cdf5716SMasatake YAMATO else if (guest_spec->lang.type == GUEST_LANG_PTN_GROUP_FOR_LANGNAME)
18076cdf5716SMasatake YAMATO {
18086cdf5716SMasatake YAMATO const char * name = current + pmatch [guest_spec->lang.spec.patternGroup].rm_so;
18096cdf5716SMasatake YAMATO int size = pmatch [guest_spec->lang.spec.patternGroup].rm_eo
18106cdf5716SMasatake YAMATO - pmatch [guest_spec->lang.spec.patternGroup].rm_so;
18116cdf5716SMasatake YAMATO if (size > 0)
181202108d6fScyy {
1813*6024deefSMasatake YAMATO guest_req->lang = getNamedLanguageOrAlias (name, size);
18146cdf5716SMasatake YAMATO guest_req->lang_set = true;
18156cdf5716SMasatake YAMATO }
181602108d6fScyy }
18176cdf5716SMasatake YAMATO else if (guest_spec->lang.type == GUEST_LANG_PTN_GROUP_FOR_FILEMAP)
18186cdf5716SMasatake YAMATO {
18196cdf5716SMasatake YAMATO const char * name = current + pmatch [guest_spec->lang.spec.patternGroup].rm_so;
18206cdf5716SMasatake YAMATO int size = pmatch [guest_spec->lang.spec.patternGroup].rm_eo
18216cdf5716SMasatake YAMATO - pmatch [guest_spec->lang.spec.patternGroup].rm_so;
18226cdf5716SMasatake YAMATO char *fname = (size > 0)? eStrndup (name, size): NULL;
18236cdf5716SMasatake YAMATO
18246cdf5716SMasatake YAMATO if (fname)
18256cdf5716SMasatake YAMATO {
18266cdf5716SMasatake YAMATO guest_req->lang = getLanguageForFilename (fname, LANG_AUTO);
182702108d6fScyy guest_req->lang_set = true;
18286cdf5716SMasatake YAMATO eFree (fname);
18296cdf5716SMasatake YAMATO }
18306cdf5716SMasatake YAMATO }
18316cdf5716SMasatake YAMATO
18326cdf5716SMasatake YAMATO for (int i = 0; i < 2; i++)
18336cdf5716SMasatake YAMATO {
18346cdf5716SMasatake YAMATO struct boundarySpec *boundary_spec = guest_spec->boundary + i;
18356cdf5716SMasatake YAMATO struct boundaryInRequest *boundary = guest_req->boundary + i;
18366cdf5716SMasatake YAMATO if (!boundary_spec->placeholder)
18376cdf5716SMasatake YAMATO {
18386cdf5716SMasatake YAMATO boundary->offset = current - start + (boundary_spec->fromStartOfGroup
18396cdf5716SMasatake YAMATO ? pmatch [boundary_spec->patternGroup].rm_so
18406cdf5716SMasatake YAMATO : pmatch [boundary_spec->patternGroup].rm_eo);
18416cdf5716SMasatake YAMATO boundary->offset_set = true;
18426cdf5716SMasatake YAMATO }
18436cdf5716SMasatake YAMATO }
18446cdf5716SMasatake YAMATO return guestRequestIsFilled (guest_req);
18456cdf5716SMasatake YAMATO }
18469a1e266aSHadriel Kaplan
matchRegexPattern(struct lregexControlBlock * lcb,const vString * const line,regexTableEntry * entry)1847fbcb3274SMasatake YAMATO static bool matchRegexPattern (struct lregexControlBlock *lcb,
1848fbcb3274SMasatake YAMATO const vString* const line,
1849134629a0SHadriel Kaplan regexTableEntry *entry)
1850d4c6f1e6SMasatake YAMATO {
1851ce990805SThomas Braun bool result = false;
1852d4c6f1e6SMasatake YAMATO regmatch_t pmatch [BACK_REFERENCE_COUNT];
18532a738f47SMasatake YAMATO int match;
1854134629a0SHadriel Kaplan regexPattern* patbuf = entry->pattern;
18556cdf5716SMasatake YAMATO struct guestSpec *guest = &patbuf->guest;
18562a738f47SMasatake YAMATO
18572a738f47SMasatake YAMATO if (patbuf->disabled && *(patbuf->disabled))
1858ce990805SThomas Braun return false;
18592a738f47SMasatake YAMATO
1860c30b89acSMasatake YAMATO match = patbuf->pattern.backend->match (patbuf->pattern.backend,
1861c30b89acSMasatake YAMATO patbuf->pattern.code, vStringValue (line),
1862c30b89acSMasatake YAMATO vStringLength (line),
1863c30b89acSMasatake YAMATO pmatch);
1864c30b89acSMasatake YAMATO
1865d4c6f1e6SMasatake YAMATO if (match == 0)
1866d4c6f1e6SMasatake YAMATO {
1867ce990805SThomas Braun result = true;
1868134629a0SHadriel Kaplan entry->statistics.match++;
18692bbd136eSMasatake YAMATO scriptWindow window = {
18702bbd136eSMasatake YAMATO .line = vStringValue (line),
1871ed3202bdSMasatake YAMATO .start = 0,
18722bbd136eSMasatake YAMATO .patbuf = patbuf,
18732bbd136eSMasatake YAMATO .pmatch = pmatch,
18742bbd136eSMasatake YAMATO .nmatch = BACK_REFERENCE_COUNT,
1875653692b7SMasatake YAMATO .advanceto = false,
18762bbd136eSMasatake YAMATO };
18772bbd136eSMasatake YAMATO
1878e8386a4eSMasatake YAMATO if (patbuf->optscript && (! hasNameSlot (patbuf)))
1879e8386a4eSMasatake YAMATO {
18802bbd136eSMasatake YAMATO scriptSetup (optvm, lcb, CORK_NIL, &window);
1881668e3666SMasatake YAMATO EsObject *e = scriptEval (optvm, patbuf->optscript);
1882e8386a4eSMasatake YAMATO if (es_error_p (e))
1883e8386a4eSMasatake YAMATO error (WARNING, "error when evaluating: %s", patbuf->optscript_src);
1884e8386a4eSMasatake YAMATO es_object_unref (e);
1885668e3666SMasatake YAMATO scriptTeardown (optvm, lcb);
1886e8386a4eSMasatake YAMATO }
18871e923193SMasatake YAMATO
18889a1e266aSHadriel Kaplan if (hasMessage(patbuf))
18899a1e266aSHadriel Kaplan printMessage(lcb->owner, patbuf, 0, vStringValue (line), pmatch);
18909a1e266aSHadriel Kaplan
1891d4c6f1e6SMasatake YAMATO if (patbuf->type == PTRN_TAG)
18926cdf5716SMasatake YAMATO {
18932bbd136eSMasatake YAMATO matchTagPattern (lcb, vStringValue (line), patbuf, pmatch, 0,
18942bbd136eSMasatake YAMATO (patbuf->optscript && hasNameSlot (patbuf))? &window: NULL);
18956cdf5716SMasatake YAMATO
18966cdf5716SMasatake YAMATO if (guest->lang.type != GUEST_LANG_UNKNOWN)
18976cdf5716SMasatake YAMATO {
18986cdf5716SMasatake YAMATO unsigned long ln = getInputLineNumber ();
18996cdf5716SMasatake YAMATO long current = getInputFileOffsetForLine (ln);
19006cdf5716SMasatake YAMATO if (fillGuestRequest (vStringValue (line) - current,
19016cdf5716SMasatake YAMATO vStringValue (line), pmatch, guest, lcb->guest_req))
19026cdf5716SMasatake YAMATO {
19036cdf5716SMasatake YAMATO Assert (lcb->guest_req->lang != LANG_AUTO);
19046cdf5716SMasatake YAMATO if (isGuestRequestConsistent(lcb->guest_req))
19056cdf5716SMasatake YAMATO guestRequestSubmit (lcb->guest_req);
19066cdf5716SMasatake YAMATO guestRequestClear (lcb->guest_req);
19076cdf5716SMasatake YAMATO }
19086cdf5716SMasatake YAMATO }
19096cdf5716SMasatake YAMATO }
1910d4c6f1e6SMasatake YAMATO else if (patbuf->type == PTRN_CALLBACK)
191118480890SMasatake YAMATO result = matchCallbackPattern (line, patbuf, pmatch);
1912d4c6f1e6SMasatake YAMATO else
1913d4c6f1e6SMasatake YAMATO {
1914d4c6f1e6SMasatake YAMATO Assert ("invalid pattern type" == NULL);
1915ce990805SThomas Braun result = false;
1916d4c6f1e6SMasatake YAMATO }
1917d4c6f1e6SMasatake YAMATO }
19181e923193SMasatake YAMATO else
1919134629a0SHadriel Kaplan entry->statistics.unmatch++;
1920d4c6f1e6SMasatake YAMATO return result;
1921d4c6f1e6SMasatake YAMATO }
1922d4c6f1e6SMasatake YAMATO
matchMultilineRegexPattern(struct lregexControlBlock * lcb,const vString * const allLines,regexTableEntry * entry)1923fbcb3274SMasatake YAMATO static bool matchMultilineRegexPattern (struct lregexControlBlock *lcb,
1924fbcb3274SMasatake YAMATO const vString* const allLines,
1925134629a0SHadriel Kaplan regexTableEntry *entry)
192613939209SMasatake YAMATO {
192713939209SMasatake YAMATO const char *start;
192813939209SMasatake YAMATO const char *current;
19299a1e266aSHadriel Kaplan off_t offset = 0;
1930134629a0SHadriel Kaplan regexPattern* patbuf = entry->pattern;
19316cdf5716SMasatake YAMATO struct mGroupSpec *mgroup = &patbuf->mgroup;
19326cdf5716SMasatake YAMATO struct guestSpec *guest = &patbuf->guest;
193313939209SMasatake YAMATO
193413939209SMasatake YAMATO bool result = false;
193513939209SMasatake YAMATO regmatch_t pmatch [BACK_REFERENCE_COUNT];
193613939209SMasatake YAMATO int match = 0;
1937a33dec34SMasatake YAMATO unsigned int delta = 1;
193813939209SMasatake YAMATO
1939134629a0SHadriel Kaplan Assert (patbuf);
1940134629a0SHadriel Kaplan
194113939209SMasatake YAMATO if (patbuf->disabled && *(patbuf->disabled))
194213939209SMasatake YAMATO return false;
194313939209SMasatake YAMATO
1944a33dec34SMasatake YAMATO current = start = vStringValue (allLines);
1945a33dec34SMasatake YAMATO do
194613939209SMasatake YAMATO {
1947c30b89acSMasatake YAMATO match = patbuf->pattern.backend->match (patbuf->pattern.backend,
1948c30b89acSMasatake YAMATO patbuf->pattern.code, current,
1949c30b89acSMasatake YAMATO vStringLength (allLines) - (current - start),
1950c30b89acSMasatake YAMATO pmatch);
1951c30b89acSMasatake YAMATO
1952a33dec34SMasatake YAMATO if (match != 0)
195313939209SMasatake YAMATO {
1954134629a0SHadriel Kaplan entry->statistics.unmatch++;
1955a33dec34SMasatake YAMATO break;
1956a33dec34SMasatake YAMATO }
1957a33dec34SMasatake YAMATO
19589a1e266aSHadriel Kaplan if (hasMessage(patbuf))
19599a1e266aSHadriel Kaplan printMessage(lcb->owner, patbuf, (current + pmatch[0].rm_so) - start, current, pmatch);
19609a1e266aSHadriel Kaplan
19616cdf5716SMasatake YAMATO offset = (current + pmatch [mgroup->forLineNumberDetermination].rm_so)
19629a1e266aSHadriel Kaplan - start;
19639a1e266aSHadriel Kaplan
1964134629a0SHadriel Kaplan entry->statistics.match++;
19652bbd136eSMasatake YAMATO scriptWindow window = {
19662bbd136eSMasatake YAMATO .line = current,
1967ed3202bdSMasatake YAMATO .start = start,
19682bbd136eSMasatake YAMATO .patbuf = patbuf,
19692bbd136eSMasatake YAMATO .pmatch = pmatch,
19702bbd136eSMasatake YAMATO .nmatch = BACK_REFERENCE_COUNT,
1971653692b7SMasatake YAMATO .advanceto = false,
19722bbd136eSMasatake YAMATO };
19732bbd136eSMasatake YAMATO
1974e8386a4eSMasatake YAMATO if (patbuf->optscript && (! hasNameSlot (patbuf)))
1975e8386a4eSMasatake YAMATO {
19762bbd136eSMasatake YAMATO scriptSetup (optvm, lcb, CORK_NIL, &window);
1977668e3666SMasatake YAMATO EsObject *e = scriptEval (optvm, patbuf->optscript);
1978e8386a4eSMasatake YAMATO if (es_error_p (e))
1979e8386a4eSMasatake YAMATO error (WARNING, "error when evaluating: %s", patbuf->optscript_src);
1980e8386a4eSMasatake YAMATO es_object_unref (e);
1981668e3666SMasatake YAMATO scriptTeardown (optvm, lcb);
1982e8386a4eSMasatake YAMATO }
1983e8386a4eSMasatake YAMATO
198413939209SMasatake YAMATO if (patbuf->type == PTRN_TAG)
198513939209SMasatake YAMATO {
19862bbd136eSMasatake YAMATO matchTagPattern (lcb, current, patbuf, pmatch, offset,
19872bbd136eSMasatake YAMATO (patbuf->optscript && hasNameSlot (patbuf))? &window: NULL);
198813939209SMasatake YAMATO result = true;
198913939209SMasatake YAMATO }
199013939209SMasatake YAMATO else if (patbuf->type == PTRN_CALLBACK)
199113939209SMasatake YAMATO ; /* Not implemented yet */
199213939209SMasatake YAMATO else
199313939209SMasatake YAMATO {
199413939209SMasatake YAMATO Assert ("invalid pattern type" == NULL);
199513939209SMasatake YAMATO result = false;
199613939209SMasatake YAMATO break;
199713939209SMasatake YAMATO }
1998a33dec34SMasatake YAMATO
19996cdf5716SMasatake YAMATO if (fillGuestRequest (start, current, pmatch, guest, lcb->guest_req))
20006cdf5716SMasatake YAMATO {
20016cdf5716SMasatake YAMATO Assert (lcb->guest_req->lang != LANG_AUTO);
20026cdf5716SMasatake YAMATO if (isGuestRequestConsistent(lcb->guest_req))
20036cdf5716SMasatake YAMATO guestRequestSubmit (lcb->guest_req);
20046cdf5716SMasatake YAMATO guestRequestClear (lcb->guest_req);
20056cdf5716SMasatake YAMATO }
20066cdf5716SMasatake YAMATO
20076cdf5716SMasatake YAMATO delta = (mgroup->nextFromStart
20086cdf5716SMasatake YAMATO ? pmatch [mgroup->forNextScanning].rm_so
20096cdf5716SMasatake YAMATO : pmatch [mgroup->forNextScanning].rm_eo);
2010a33dec34SMasatake YAMATO if (delta == 0)
2011a33dec34SMasatake YAMATO {
2012746bdfabSColomban Wendling unsigned int pos = current - start;
2013a33dec34SMasatake YAMATO error (WARNING,
2014a33dec34SMasatake YAMATO "a multi line regex pattern doesn't advance the input cursor: %s",
2015a33dec34SMasatake YAMATO patbuf->pattern_string);
2016a33dec34SMasatake YAMATO error (WARNING, "Language: %s, input file: %s, pos: %u",
2017746bdfabSColomban Wendling getLanguageName (lcb->owner), getInputFileName(), pos);
2018a33dec34SMasatake YAMATO break;
201913939209SMasatake YAMATO }
2020a33dec34SMasatake YAMATO current += delta;
2021a33dec34SMasatake YAMATO
2022a33dec34SMasatake YAMATO } while (current < start + vStringLength (allLines));
2023a33dec34SMasatake YAMATO
202413939209SMasatake YAMATO return result;
202513939209SMasatake YAMATO }
2026d4c6f1e6SMasatake YAMATO
2027d4c6f1e6SMasatake YAMATO /* PUBLIC INTERFACE */
2028d4c6f1e6SMasatake YAMATO
2029d4c6f1e6SMasatake YAMATO /* Match against all patterns for specified language. Returns true if at least
2030d4c6f1e6SMasatake YAMATO * on pattern matched.
2031d4c6f1e6SMasatake YAMATO */
matchRegex(struct lregexControlBlock * lcb,const vString * const line)203253dda59eSMasatake YAMATO extern bool matchRegex (struct lregexControlBlock *lcb, const vString* const line)
2033d4c6f1e6SMasatake YAMATO {
2034ce990805SThomas Braun bool result = false;
2035d4c6f1e6SMasatake YAMATO unsigned int i;
2036134629a0SHadriel Kaplan for (i = 0 ; i < ptrArrayCount(lcb->entries[REG_PARSER_SINGLE_LINE]) ; ++i)
2037d4c6f1e6SMasatake YAMATO {
2038134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem(lcb->entries[REG_PARSER_SINGLE_LINE], i);
2039134629a0SHadriel Kaplan regexPattern *ptrn = entry->pattern;
2040134629a0SHadriel Kaplan
2041134629a0SHadriel Kaplan Assert (ptrn);
204210db13faSMasatake YAMATO
204310db13faSMasatake YAMATO if ((ptrn->xtagType != XTAG_UNKNOWN)
204410db13faSMasatake YAMATO && (!isXtagEnabled (ptrn->xtagType)))
204510db13faSMasatake YAMATO continue;
204610db13faSMasatake YAMATO
2047134629a0SHadriel Kaplan if (matchRegexPattern (lcb, line, entry))
2048d4c6f1e6SMasatake YAMATO {
2049ce990805SThomas Braun result = true;
2050d4c6f1e6SMasatake YAMATO if (ptrn->exclusive)
2051d4c6f1e6SMasatake YAMATO break;
2052d4c6f1e6SMasatake YAMATO }
2053d4c6f1e6SMasatake YAMATO }
2054d4c6f1e6SMasatake YAMATO return result;
2055d4c6f1e6SMasatake YAMATO }
2056d4c6f1e6SMasatake YAMATO
notifyRegexInputStart(struct lregexControlBlock * lcb)20572db4cedcSMasatake YAMATO extern void notifyRegexInputStart (struct lregexControlBlock *lcb)
20582db4cedcSMasatake YAMATO {
20592db4cedcSMasatake YAMATO lcb->currentScope = CORK_NIL;
206041e0b4f8SMasatake YAMATO
206141e0b4f8SMasatake YAMATO ptrArrayClear (lcb->tstack);
20626cdf5716SMasatake YAMATO guestRequestClear (lcb->guest_req);
2063e8386a4eSMasatake YAMATO
2064e8386a4eSMasatake YAMATO opt_vm_dstack_push (optvm, lregex_dict);
2065e8386a4eSMasatake YAMATO
2066e8386a4eSMasatake YAMATO if (es_null (lcb->local_dict))
2067e8386a4eSMasatake YAMATO lcb->local_dict = opt_dict_new (23);
2068e8386a4eSMasatake YAMATO opt_vm_dstack_push (optvm, lcb->local_dict);
20692bbd136eSMasatake YAMATO opt_vm_set_app_data (optvm, lcb);
2070b6124a60SMasatake YAMATO scriptEvalHook (optvm, lcb, SCRIPT_HOOK_PRELUDE);
20712db4cedcSMasatake YAMATO }
20722db4cedcSMasatake YAMATO
notifyRegexInputEnd(struct lregexControlBlock * lcb)20732db4cedcSMasatake YAMATO extern void notifyRegexInputEnd (struct lregexControlBlock *lcb)
20742db4cedcSMasatake YAMATO {
2075b6124a60SMasatake YAMATO scriptEvalHook (optvm, lcb, SCRIPT_HOOK_SEQUEL);
20762bbd136eSMasatake YAMATO opt_vm_set_app_data (optvm, NULL);
2077e8386a4eSMasatake YAMATO opt_vm_clear (optvm);
2078e8386a4eSMasatake YAMATO opt_dict_clear (lcb->local_dict);
2079ec25b18fSMasatake YAMATO unsigned long endline = getInputLineNumber ();
2080ec25b18fSMasatake YAMATO fillEndLineFieldOfUpperScopes (lcb, endline);
20812db4cedcSMasatake YAMATO }
20822db4cedcSMasatake YAMATO
findRegexTagsMainloop(int (* driver)(void))20832d7d0792SMasatake YAMATO extern void findRegexTagsMainloop (int (* driver)(void))
2084d4c6f1e6SMasatake YAMATO {
2085d4c6f1e6SMasatake YAMATO /* merely read all lines of the file */
20862d7d0792SMasatake YAMATO while (driver () != EOF)
2087d4c6f1e6SMasatake YAMATO ;
2088d4c6f1e6SMasatake YAMATO }
2089d4c6f1e6SMasatake YAMATO
fileReadLineDriver(void)20902d7d0792SMasatake YAMATO static int fileReadLineDriver(void)
20912d7d0792SMasatake YAMATO {
20921b312fe7SMasatake YAMATO return (readLineFromInputFile () == NULL)? EOF: 1;
20932d7d0792SMasatake YAMATO }
20942d7d0792SMasatake YAMATO
findRegexTags(void)20952d7d0792SMasatake YAMATO extern void findRegexTags (void)
20962d7d0792SMasatake YAMATO {
20972d7d0792SMasatake YAMATO findRegexTagsMainloop (fileReadLineDriver);
20982d7d0792SMasatake YAMATO }
20992d7d0792SMasatake YAMATO
doesExpectCorkInRegex0(ptrArray * entries)2100c25346c2SMasatake YAMATO static bool doesExpectCorkInRegex0(ptrArray *entries)
21012fa3c9e1SMasatake YAMATO {
2102134629a0SHadriel Kaplan for (unsigned int i = 0; i < ptrArrayCount(entries); i++)
2103b2c16b34SMasatake YAMATO {
2104134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem(entries, i);
2105134629a0SHadriel Kaplan Assert (entry && entry->pattern);
2106e8386a4eSMasatake YAMATO if (entry->pattern->scopeActions
2107e8386a4eSMasatake YAMATO || entry->pattern->optscript
2108e8386a4eSMasatake YAMATO )
210941e0b4f8SMasatake YAMATO return true;
211041e0b4f8SMasatake YAMATO }
211141e0b4f8SMasatake YAMATO return false;
2112b2c16b34SMasatake YAMATO }
2113a656c9bfSMasatake YAMATO
doesExpectCorkInRegex(struct lregexControlBlock * lcb)2114c25346c2SMasatake YAMATO extern bool doesExpectCorkInRegex (struct lregexControlBlock *lcb)
211541e0b4f8SMasatake YAMATO {
2116134629a0SHadriel Kaplan ptrArray *entries;
211741e0b4f8SMasatake YAMATO
2118134629a0SHadriel Kaplan entries = lcb->entries[REG_PARSER_SINGLE_LINE];
2119c25346c2SMasatake YAMATO if (doesExpectCorkInRegex0 (entries))
212041e0b4f8SMasatake YAMATO return true;
212141e0b4f8SMasatake YAMATO
2122235d5682SMasatake YAMATO entries = lcb->entries[REG_PARSER_MULTI_LINE];
2123235d5682SMasatake YAMATO if (doesExpectCorkInRegex0 (entries))
2124235d5682SMasatake YAMATO return true;
2125235d5682SMasatake YAMATO
212641e0b4f8SMasatake YAMATO for (unsigned int i = 0; i < ptrArrayCount(lcb->tables); i++)
212741e0b4f8SMasatake YAMATO {
212841e0b4f8SMasatake YAMATO struct regexTable *table = ptrArrayItem(lcb->tables, i);
2129c25346c2SMasatake YAMATO if (doesExpectCorkInRegex0 (table->entries))
213041e0b4f8SMasatake YAMATO return true;
213141e0b4f8SMasatake YAMATO }
213241e0b4f8SMasatake YAMATO
213341e0b4f8SMasatake YAMATO return false;
21342fa3c9e1SMasatake YAMATO }
21352fa3c9e1SMasatake YAMATO
escapeRegexPattern(const char * pattern)21365372d785SMasatake YAMATO static char *escapeRegexPattern (const char* pattern)
21375372d785SMasatake YAMATO {
21385372d785SMasatake YAMATO vString *p = vStringNew ();
21395372d785SMasatake YAMATO
21405372d785SMasatake YAMATO while (*pattern != '\0')
21415372d785SMasatake YAMATO {
21425372d785SMasatake YAMATO char c = *pattern;
21435372d785SMasatake YAMATO if (c == '\n')
21445372d785SMasatake YAMATO vStringCatS(p, "\\n");
21455372d785SMasatake YAMATO else if (c == '\t')
21465372d785SMasatake YAMATO vStringCatS(p, "\\t");
21475372d785SMasatake YAMATO else if (c == '\\')
21485372d785SMasatake YAMATO vStringCatS(p, "\\\\");
21495372d785SMasatake YAMATO else
21505372d785SMasatake YAMATO vStringPut(p, c);
21515372d785SMasatake YAMATO
21525372d785SMasatake YAMATO pattern++;
21535372d785SMasatake YAMATO }
21545372d785SMasatake YAMATO
21555372d785SMasatake YAMATO return vStringDeleteUnwrap (p);
21565372d785SMasatake YAMATO }
21575372d785SMasatake YAMATO
addTagRegexInternal(struct lregexControlBlock * lcb,int table_index,enum regexParserType regptype,const char * const regex,const char * const name,const char * const kinds,const char * const flags,bool * disabled)2158056b32e1SMasatake YAMATO static regexPattern *addTagRegexInternal (struct lregexControlBlock *lcb,
21590cbf3f0dSMasatake YAMATO int table_index,
21601b9c3aecSMasatake YAMATO enum regexParserType regptype,
2161ed0c063bSMasatake YAMATO const char* const regex,
2162ed0c063bSMasatake YAMATO const char* const name,
2163ed0c063bSMasatake YAMATO const char* const kinds,
21642a738f47SMasatake YAMATO const char* const flags,
2165ce990805SThomas Braun bool *disabled)
2166d4c6f1e6SMasatake YAMATO {
2167d4c6f1e6SMasatake YAMATO Assert (regex != NULL);
2168d4c6f1e6SMasatake YAMATO Assert (name != NULL);
2169d00f728aSMasatake YAMATO
2170d00f728aSMasatake YAMATO if (!regexAvailable)
2171d00f728aSMasatake YAMATO return NULL;
2172d00f728aSMasatake YAMATO
2173c30b89acSMasatake YAMATO regexCompiledCode cp = compileRegex (regptype, regex, flags);
2174c30b89acSMasatake YAMATO if (cp.code == NULL)
2175c30b89acSMasatake YAMATO {
2176c30b89acSMasatake YAMATO error (WARNING, "pattern: %s", regex);
2177c30b89acSMasatake YAMATO if (table_index != TABLE_INDEX_UNUSED)
2178c30b89acSMasatake YAMATO {
2179c30b89acSMasatake YAMATO struct regexTable *table = ptrArrayItem (lcb->tables, table_index);
2180c30b89acSMasatake YAMATO error (WARNING, "table: %s[%u]", table->name, ptrArrayCount (table->entries));
2181c30b89acSMasatake YAMATO error (WARNING, "language: %s", getLanguageName (lcb->owner));
2182c30b89acSMasatake YAMATO }
2183c30b89acSMasatake YAMATO else
2184c30b89acSMasatake YAMATO error (WARNING, "language: %s[%u]", getLanguageName (lcb->owner),
2185c30b89acSMasatake YAMATO ptrArrayCount (lcb->entries[regptype]));
2186f4e9820bSMasatake YAMATO return NULL;
2187c30b89acSMasatake YAMATO }
218841e0b4f8SMasatake YAMATO
21890f8ba855SMasatake YAMATO char kindLetter;
2190d4c6f1e6SMasatake YAMATO char* kindName;
2191d4c6f1e6SMasatake YAMATO char* description;
21920f8ba855SMasatake YAMATO kindDefinition* fileKind;
21931fc8725aSMasatake YAMATO
21943950d588SMasatake YAMATO bool explictly_defined = parseKinds (kinds, &kindLetter, &kindName, &description);
21950f8ba855SMasatake YAMATO fileKind = getLanguageKind (lcb->owner, KIND_FILE_INDEX);
21960f8ba855SMasatake YAMATO if (kindLetter == fileKind->letter)
21971fc8725aSMasatake YAMATO error (FATAL,
21981fc8725aSMasatake YAMATO "Kind letter \'%c\' used in regex definition \"%s\" of %s language is reserved in ctags main",
21990f8ba855SMasatake YAMATO kindLetter,
22000f8ba855SMasatake YAMATO regex,
22010f8ba855SMasatake YAMATO getLanguageName (lcb->owner));
2202b0747823SMasatake YAMATO else if (!isalpha ((unsigned char)kindLetter))
2203b0747823SMasatake YAMATO error (FATAL,
2204b0747823SMasatake YAMATO "Kind letter must be an alphabetical character: \"%c\"",
2205b0747823SMasatake YAMATO kindLetter);
2206b0747823SMasatake YAMATO
2207b0747823SMasatake YAMATO if (strcmp (kindName, fileKind->name) == 0)
22080f8ba855SMasatake YAMATO error (FATAL,
22090f8ba855SMasatake YAMATO "Kind name \"%s\" used in regex definition \"%s\" of %s language is reserved in ctags main",
22100f8ba855SMasatake YAMATO kindName,
22111fc8725aSMasatake YAMATO regex,
2212056b32e1SMasatake YAMATO getLanguageName (lcb->owner));
2213b0747823SMasatake YAMATO
2214b0747823SMasatake YAMATO const char *option_bsae = (regptype == REG_PARSER_SINGLE_LINE? "regex" :
2215b0747823SMasatake YAMATO regptype == REG_PARSER_MULTI_LINE ? "mline-regex" :
2216b0747823SMasatake YAMATO regptype == REG_PARSER_MULTI_TABLE? "_mtable-regex":
2217b0747823SMasatake YAMATO NULL);
2218b0747823SMasatake YAMATO Assert (option_bsae);
2219b0747823SMasatake YAMATO
2220b0747823SMasatake YAMATO for (const char * p = kindName; *p; p++)
2221b0747823SMasatake YAMATO {
2222b0747823SMasatake YAMATO if (p == kindName)
2223b0747823SMasatake YAMATO {
2224b0747823SMasatake YAMATO if (!isalpha(*p))
2225e0b5213bSMasatake YAMATO error (FATAL,
2226b0747823SMasatake YAMATO "A kind name doesn't start with an alphabetical character: "
2227b0747823SMasatake YAMATO "'%s' in \"--%s-%s\" option",
2228b0747823SMasatake YAMATO kindName,
2229b0747823SMasatake YAMATO option_bsae,
2230b0747823SMasatake YAMATO getLanguageName (lcb->owner));
2231b0747823SMasatake YAMATO }
2232b0747823SMasatake YAMATO else
2233b0747823SMasatake YAMATO {
2234b0747823SMasatake YAMATO /*
2235b0747823SMasatake YAMATO * People may object to this error.
2236b0747823SMasatake YAMATO * Searching github repositories, I found not a few .ctags files
2237b0747823SMasatake YAMATO * in which Exuberant-ctags users define kind names with whitespaces.
2238b0747823SMasatake YAMATO * "FATAL" error breaks the compatibility.
2239b0747823SMasatake YAMATO */
2240b0747823SMasatake YAMATO if (!isalnum(*p))
2241b0747823SMasatake YAMATO error (/* regptype == REG_PARSER_SINGLE_LINE? WARNING: */ FATAL,
2242b0747823SMasatake YAMATO "Non-alphanumeric char is used in kind name: "
2243b0747823SMasatake YAMATO "'%s' in \"--%s-%s\" option",
2244b0747823SMasatake YAMATO kindName,
2245b0747823SMasatake YAMATO option_bsae,
2246b0747823SMasatake YAMATO getLanguageName (lcb->owner));
2247b0747823SMasatake YAMATO
2248b0747823SMasatake YAMATO }
2249b0747823SMasatake YAMATO }
22501fc8725aSMasatake YAMATO
2251f4e9820bSMasatake YAMATO regexPattern *rptr = addCompiledTagPattern (lcb, table_index,
2252c30b89acSMasatake YAMATO regptype, &cp, name,
22530f8ba855SMasatake YAMATO kindLetter, kindName, description, flags,
22543950d588SMasatake YAMATO explictly_defined,
22552a738f47SMasatake YAMATO disabled);
22565372d785SMasatake YAMATO rptr->pattern_string = escapeRegexPattern(regex);
2257691d5f94SMasatake YAMATO
2258a4e7ab31SMasatake YAMATO eFree (kindName);
2259a4e7ab31SMasatake YAMATO if (description)
2260a4e7ab31SMasatake YAMATO eFree (description);
2261a87d30edSMasatake YAMATO
2262a87d30edSMasatake YAMATO if (*name == '\0')
2263a87d30edSMasatake YAMATO {
22640cbf3f0dSMasatake YAMATO if (rptr->exclusive || rptr->scopeActions & SCOPE_PLACEHOLDER
22650d56cc8eSMasatake YAMATO || rptr->anonymous_tag_prefix
22666cdf5716SMasatake YAMATO || regptype == REG_PARSER_MULTI_TABLE
22676cdf5716SMasatake YAMATO || rptr->guest.lang.type != GUEST_LANG_UNKNOWN
2268e8386a4eSMasatake YAMATO || rptr->optscript
22696cdf5716SMasatake YAMATO )
2270ce990805SThomas Braun rptr->accept_empty_name = true;
2271a87d30edSMasatake YAMATO else
2272a87d30edSMasatake YAMATO error (WARNING, "%s: regexp missing name pattern", regex);
2273a87d30edSMasatake YAMATO }
2274a87d30edSMasatake YAMATO
227512ddaaa3SMasatake YAMATO return rptr;
227612ddaaa3SMasatake YAMATO }
227712ddaaa3SMasatake YAMATO
addTagRegex(struct lregexControlBlock * lcb,const char * const regex,const char * const name,const char * const kinds,const char * const flags,bool * disabled)2278056b32e1SMasatake YAMATO extern void addTagRegex (struct lregexControlBlock *lcb,
227911af5b2cSMasatake YAMATO const char* const regex,
228011af5b2cSMasatake YAMATO const char* const name,
228111af5b2cSMasatake YAMATO const char* const kinds,
228211af5b2cSMasatake YAMATO const char* const flags,
2283ce990805SThomas Braun bool *disabled)
228412ddaaa3SMasatake YAMATO {
22850cbf3f0dSMasatake YAMATO addTagRegexInternal (lcb, TABLE_INDEX_UNUSED,
22860cbf3f0dSMasatake YAMATO REG_PARSER_SINGLE_LINE, regex, name, kinds, flags, disabled);
2287641e337aSMasatake YAMATO }
2288641e337aSMasatake YAMATO
addTagMultiLineRegex(struct lregexControlBlock * lcb,const char * const regex,const char * const name,const char * const kinds,const char * const flags,bool * disabled)2289641e337aSMasatake YAMATO extern void addTagMultiLineRegex (struct lregexControlBlock *lcb, const char* const regex,
2290641e337aSMasatake YAMATO const char* const name, const char* const kinds, const char* const flags,
2291641e337aSMasatake YAMATO bool *disabled)
2292641e337aSMasatake YAMATO {
22930cbf3f0dSMasatake YAMATO addTagRegexInternal (lcb, TABLE_INDEX_UNUSED,
22940cbf3f0dSMasatake YAMATO REG_PARSER_MULTI_LINE, regex, name, kinds, flags, disabled);
2295d4c6f1e6SMasatake YAMATO }
2296d4c6f1e6SMasatake YAMATO
addTagMultiTableRegex(struct lregexControlBlock * lcb,const char * const table_name,const char * const regex,const char * const name,const char * const kinds,const char * const flags,bool * disabled)229789c588f7SMasatake YAMATO extern void addTagMultiTableRegex(struct lregexControlBlock *lcb,
229889c588f7SMasatake YAMATO const char* const table_name,
229989c588f7SMasatake YAMATO const char* const regex,
230089c588f7SMasatake YAMATO const char* const name, const char* const kinds, const char* const flags,
230189c588f7SMasatake YAMATO bool *disabled)
230289c588f7SMasatake YAMATO {
230389c588f7SMasatake YAMATO int table_index = getTableIndexForName (lcb, table_name);
230489c588f7SMasatake YAMATO
230589c588f7SMasatake YAMATO if (table_index < 0)
230689c588f7SMasatake YAMATO error (FATAL, "unknown table name: %s", table_name);
230789c588f7SMasatake YAMATO
230889c588f7SMasatake YAMATO addTagRegexInternal (lcb, table_index, REG_PARSER_MULTI_TABLE, regex, name, kinds, flags,
230989c588f7SMasatake YAMATO disabled);
231089c588f7SMasatake YAMATO }
231189c588f7SMasatake YAMATO
addCallbackRegex(struct lregexControlBlock * lcb,const char * const regex,const char * const flags,const regexCallback callback,bool * disabled,void * userData)231253dda59eSMasatake YAMATO extern void addCallbackRegex (struct lregexControlBlock *lcb,
231353dda59eSMasatake YAMATO const char* const regex,
231453dda59eSMasatake YAMATO const char* const flags,
231553dda59eSMasatake YAMATO const regexCallback callback,
2316ce990805SThomas Braun bool *disabled,
23176ff4dab6SMasatake YAMATO void * userData)
2318d4c6f1e6SMasatake YAMATO {
2319d4c6f1e6SMasatake YAMATO Assert (regex != NULL);
2320d00f728aSMasatake YAMATO
2321d00f728aSMasatake YAMATO if (!regexAvailable)
2322d00f728aSMasatake YAMATO return;
2323d00f728aSMasatake YAMATO
2324d00f728aSMasatake YAMATO
2325c30b89acSMasatake YAMATO regexCompiledCode cp = compileRegex (REG_PARSER_SINGLE_LINE, regex, flags);
2326c30b89acSMasatake YAMATO if (cp.code == NULL)
23275372d785SMasatake YAMATO {
2328c30b89acSMasatake YAMATO error (WARNING, "pattern: %s", regex);
2329c30b89acSMasatake YAMATO error (WARNING, "language: %s", getLanguageName (lcb->owner));
2330c30b89acSMasatake YAMATO return;
2331c30b89acSMasatake YAMATO }
2332c30b89acSMasatake YAMATO
2333c30b89acSMasatake YAMATO regexPattern *rptr = addCompiledCallbackPattern (lcb, &cp, callback, flags,
23342a738f47SMasatake YAMATO disabled, userData);
23355372d785SMasatake YAMATO rptr->pattern_string = escapeRegexPattern(regex);
23365372d785SMasatake YAMATO }
2337d4c6f1e6SMasatake YAMATO
addTagRegexOption(struct lregexControlBlock * lcb,enum regexParserType regptype,const char * const pattern)2338056b32e1SMasatake YAMATO static void addTagRegexOption (struct lregexControlBlock *lcb,
23391b9c3aecSMasatake YAMATO enum regexParserType regptype,
2340056b32e1SMasatake YAMATO const char* const pattern)
2341d4c6f1e6SMasatake YAMATO {
2342d00f728aSMasatake YAMATO if (!regexAvailable)
2343d00f728aSMasatake YAMATO return;
2344d00f728aSMasatake YAMATO
23450cbf3f0dSMasatake YAMATO int table_index = TABLE_INDEX_UNUSED;
23460cbf3f0dSMasatake YAMATO char * regex_pat = NULL;
2347d4c6f1e6SMasatake YAMATO char *name, *kinds, *flags;
23480cbf3f0dSMasatake YAMATO
23490cbf3f0dSMasatake YAMATO
23500cbf3f0dSMasatake YAMATO if (regptype == REG_PARSER_MULTI_TABLE)
23510cbf3f0dSMasatake YAMATO {
23520cbf3f0dSMasatake YAMATO const char *c;
23530cbf3f0dSMasatake YAMATO for (c = pattern; *c; c++)
23540cbf3f0dSMasatake YAMATO {
23550cbf3f0dSMasatake YAMATO if (! (isalnum(*c) || *c == '_'))
23560cbf3f0dSMasatake YAMATO {
235741e0b4f8SMasatake YAMATO if (*c && (*(c + 1) != '^'))
235841e0b4f8SMasatake YAMATO {
235941e0b4f8SMasatake YAMATO vString *tmp = vStringNew ();
236041e0b4f8SMasatake YAMATO
236141e0b4f8SMasatake YAMATO /* Put '^' as prefix for the pattern */
236241e0b4f8SMasatake YAMATO vStringPut(tmp, *c);
236341e0b4f8SMasatake YAMATO vStringPut(tmp, '^');
236441e0b4f8SMasatake YAMATO vStringCatS(tmp, c + 1);
236541e0b4f8SMasatake YAMATO regex_pat = vStringDeleteUnwrap(tmp);
236641e0b4f8SMasatake YAMATO }
236741e0b4f8SMasatake YAMATO else
23680cbf3f0dSMasatake YAMATO regex_pat = eStrdup (c);
23690cbf3f0dSMasatake YAMATO break;
23700cbf3f0dSMasatake YAMATO }
23710cbf3f0dSMasatake YAMATO }
237241e0b4f8SMasatake YAMATO
23730cbf3f0dSMasatake YAMATO if (regex_pat == NULL || *regex_pat == '\0')
23740cbf3f0dSMasatake YAMATO error (FATAL, "wrong mtable pattern specification: %s", pattern);
23750cbf3f0dSMasatake YAMATO
23760cbf3f0dSMasatake YAMATO char *table_name = eStrndup(pattern, c - pattern);
23770cbf3f0dSMasatake YAMATO table_index = getTableIndexForName (lcb, table_name);
23780cbf3f0dSMasatake YAMATO if (table_index < 0)
23790cbf3f0dSMasatake YAMATO error (FATAL, "unknown table name: %s (in %s)", table_name, pattern);
23800cbf3f0dSMasatake YAMATO eFree(table_name);
23810cbf3f0dSMasatake YAMATO }
23820cbf3f0dSMasatake YAMATO else
23830cbf3f0dSMasatake YAMATO regex_pat = eStrdup (pattern);
23840cbf3f0dSMasatake YAMATO
23851b9c3aecSMasatake YAMATO if (parseTagRegex (regptype, regex_pat, &name, &kinds, &flags))
23860cbf3f0dSMasatake YAMATO addTagRegexInternal (lcb, table_index, regptype, regex_pat, name, kinds, flags,
23872a738f47SMasatake YAMATO NULL);
23880cbf3f0dSMasatake YAMATO
2389d4c6f1e6SMasatake YAMATO eFree (regex_pat);
2390d4c6f1e6SMasatake YAMATO }
2391d4c6f1e6SMasatake YAMATO
processTagRegexOption(struct lregexControlBlock * lcb,enum regexParserType regptype,const char * const parameter)2392056b32e1SMasatake YAMATO extern void processTagRegexOption (struct lregexControlBlock *lcb,
23931b9c3aecSMasatake YAMATO enum regexParserType regptype,
2394056b32e1SMasatake YAMATO const char* const parameter)
2395056b32e1SMasatake YAMATO {
2396056b32e1SMasatake YAMATO if (parameter == NULL || parameter [0] == '\0')
2397056b32e1SMasatake YAMATO clearPatternSet (lcb);
2398056b32e1SMasatake YAMATO else if (parameter [0] != '@')
23991b9c3aecSMasatake YAMATO addTagRegexOption (lcb, regptype, parameter);
2400056b32e1SMasatake YAMATO else if (! doesFileExist (parameter + 1))
2401056b32e1SMasatake YAMATO error (WARNING, "cannot open regex file");
2402056b32e1SMasatake YAMATO else
2403056b32e1SMasatake YAMATO {
2404056b32e1SMasatake YAMATO const char* regexfile = parameter + 1;
24052b808106SMasatake YAMATO
24062b808106SMasatake YAMATO verbose ("open a regex file: %s\n", regexfile);
2407056b32e1SMasatake YAMATO MIO* const mio = mio_new_file (regexfile, "r");
2408056b32e1SMasatake YAMATO if (mio == NULL)
2409056b32e1SMasatake YAMATO error (WARNING | PERROR, "%s", regexfile);
2410056b32e1SMasatake YAMATO else
2411056b32e1SMasatake YAMATO {
2412056b32e1SMasatake YAMATO vString* const regex = vStringNew ();
2413056b32e1SMasatake YAMATO while (readLineRaw (regex, mio))
24146b2b1915SMasatake YAMATO {
24156b2b1915SMasatake YAMATO if (vStringLength (regex) > 1 && vStringValue (regex)[0] != '\n')
24161b9c3aecSMasatake YAMATO addTagRegexOption (lcb, regptype, vStringValue (regex));
24176b2b1915SMasatake YAMATO }
2418b978efd6SMasatake YAMATO mio_unref (mio);
2419056b32e1SMasatake YAMATO vStringDelete (regex);
2420056b32e1SMasatake YAMATO }
2421056b32e1SMasatake YAMATO }
2422056b32e1SMasatake YAMATO }
2423056b32e1SMasatake YAMATO
2424d4c6f1e6SMasatake YAMATO /*
2425d4c6f1e6SMasatake YAMATO * Regex option parsing
2426d4c6f1e6SMasatake YAMATO */
2427d4c6f1e6SMasatake YAMATO
printRegexFlags(bool withListHeader,bool machinable,const char * flags,FILE * fp)2428c30b89acSMasatake YAMATO extern void printRegexFlags (bool withListHeader, bool machinable, const char *flags, FILE *fp)
24293fac0fc6SMasatake YAMATO {
2430c30b89acSMasatake YAMATO struct colprintTable * table = flagsColprintTableNew ();
2431d4a3a6e8SMasatake YAMATO
2432c30b89acSMasatake YAMATO if (flags && *flags != '\0')
2433c30b89acSMasatake YAMATO {
24346a8d5b70SMasatake YAMATO /* Print backend specific flags.
24356a8d5b70SMasatake YAMATO * This code is just stub because there is no backend having a specific flag.
24366a8d5b70SMasatake YAMATO * The help message for this option is not updated. */
24376a8d5b70SMasatake YAMATO struct flagDefsDescriptor desc = choose_backend (flags, REG_PARSER_SINGLE_LINE, true);
2438c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, desc.backend->fdefs, desc.backend->fdef_count);
2439c30b89acSMasatake YAMATO }
2440c30b89acSMasatake YAMATO else
2441c30b89acSMasatake YAMATO {
2442c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendFlagDefs, ARRAY_SIZE(backendFlagDefs));
2443c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendCommonRegexFlagDefs, ARRAY_SIZE(backendCommonRegexFlagDefs));
2444d4a3a6e8SMasatake YAMATO flagsColprintAddDefinitions (table, prePtrnFlagDef, ARRAY_SIZE (prePtrnFlagDef));
24456cdf5716SMasatake YAMATO flagsColprintAddDefinitions (table, guestPtrnFlagDef, ARRAY_SIZE (guestPtrnFlagDef));
2446d4a3a6e8SMasatake YAMATO flagsColprintAddDefinitions (table, scopePtrnFlagDef, ARRAY_SIZE (scopePtrnFlagDef));
2447f74a98d6SHadriel Kaplan flagsColprintAddDefinitions (table, commonSpecFlagDef, ARRAY_SIZE (commonSpecFlagDef));
2448c30b89acSMasatake YAMATO }
24499653ebd3SMasatake YAMATO
24509653ebd3SMasatake YAMATO flagsColprintTablePrint (table, withListHeader, machinable, fp);
24519653ebd3SMasatake YAMATO colprintTableDelete(table);
24529653ebd3SMasatake YAMATO }
24539653ebd3SMasatake YAMATO
printMultilineRegexFlags(bool withListHeader,bool machinable,const char * flags,FILE * fp)2454c30b89acSMasatake YAMATO extern void printMultilineRegexFlags (bool withListHeader, bool machinable, const char *flags, FILE *fp)
24559653ebd3SMasatake YAMATO {
2456c30b89acSMasatake YAMATO struct colprintTable * table = flagsColprintTableNew ();
24579653ebd3SMasatake YAMATO
2458c30b89acSMasatake YAMATO if (flags && *flags != '\0')
2459c30b89acSMasatake YAMATO {
24606a8d5b70SMasatake YAMATO /* Print backend specific flags.
24616a8d5b70SMasatake YAMATO * This code is just stub because there is no backend having a specific flag.
24626a8d5b70SMasatake YAMATO * The help message for this option is not updated. */
24636a8d5b70SMasatake YAMATO struct flagDefsDescriptor desc = choose_backend (flags, REG_PARSER_MULTI_LINE, true);
2464c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, desc.backend->fdefs, desc.backend->fdef_count);
2465c30b89acSMasatake YAMATO }
2466c30b89acSMasatake YAMATO else
2467c30b89acSMasatake YAMATO {
2468c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendFlagDefs, ARRAY_SIZE(backendFlagDefs));
2469c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendCommonRegexFlagDefs, ARRAY_SIZE(backendCommonRegexFlagDefs));
2470d4a3a6e8SMasatake YAMATO flagsColprintAddDefinitions (table, multilinePtrnFlagDef, ARRAY_SIZE (multilinePtrnFlagDef));
24716cdf5716SMasatake YAMATO flagsColprintAddDefinitions (table, guestPtrnFlagDef, ARRAY_SIZE (guestPtrnFlagDef));
2472f74a98d6SHadriel Kaplan flagsColprintAddDefinitions (table, commonSpecFlagDef, ARRAY_SIZE (commonSpecFlagDef));
2473c30b89acSMasatake YAMATO }
2474d4a3a6e8SMasatake YAMATO
2475d4a3a6e8SMasatake YAMATO flagsColprintTablePrint (table, withListHeader, machinable, fp);
2476d4a3a6e8SMasatake YAMATO colprintTableDelete(table);
24773fac0fc6SMasatake YAMATO }
24783fac0fc6SMasatake YAMATO
printMultitableRegexFlags(bool withListHeader,bool machinable,const char * flags,FILE * fp)2479c30b89acSMasatake YAMATO extern void printMultitableRegexFlags (bool withListHeader, bool machinable, const char *flags, FILE *fp)
2480e5f37e21SMasatake YAMATO {
2481c30b89acSMasatake YAMATO struct colprintTable * table = flagsColprintTableNew ();
2482e5f37e21SMasatake YAMATO
2483c30b89acSMasatake YAMATO if (flags && *flags != '\0')
2484c30b89acSMasatake YAMATO {
24856a8d5b70SMasatake YAMATO /* Print backend specific flags.
24866a8d5b70SMasatake YAMATO * This code is just stub because there is no backend having a specific flag.
24876a8d5b70SMasatake YAMATO * The help message for this option is not updated. */
24886a8d5b70SMasatake YAMATO struct flagDefsDescriptor desc = choose_backend (flags, REG_PARSER_MULTI_TABLE, true);
2489c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, desc.backend->fdefs, desc.backend->fdef_count);
2490c30b89acSMasatake YAMATO }
2491c30b89acSMasatake YAMATO else
2492c30b89acSMasatake YAMATO {
2493c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendFlagDefs, ARRAY_SIZE(backendFlagDefs));
2494c30b89acSMasatake YAMATO flagsColprintAddDefinitions (table, backendCommonRegexFlagDefs, ARRAY_SIZE(backendCommonRegexFlagDefs));
2495e5f37e21SMasatake YAMATO flagsColprintAddDefinitions (table, multilinePtrnFlagDef, ARRAY_SIZE (multilinePtrnFlagDef));
2496e5f37e21SMasatake YAMATO flagsColprintAddDefinitions (table, multitablePtrnFlagDef, ARRAY_SIZE (multitablePtrnFlagDef));
24976cdf5716SMasatake YAMATO flagsColprintAddDefinitions (table, guestPtrnFlagDef, ARRAY_SIZE (guestPtrnFlagDef));
2498e5f37e21SMasatake YAMATO flagsColprintAddDefinitions (table, scopePtrnFlagDef, ARRAY_SIZE (scopePtrnFlagDef));
2499f74a98d6SHadriel Kaplan flagsColprintAddDefinitions (table, commonSpecFlagDef, ARRAY_SIZE (commonSpecFlagDef));
2500c30b89acSMasatake YAMATO }
2501e5f37e21SMasatake YAMATO
2502e5f37e21SMasatake YAMATO flagsColprintTablePrint (table, withListHeader, machinable, fp);
2503e5f37e21SMasatake YAMATO colprintTableDelete(table);
2504e5f37e21SMasatake YAMATO }
2505e5f37e21SMasatake YAMATO
freeRegexResources(void)2506d4c6f1e6SMasatake YAMATO extern void freeRegexResources (void)
2507d4c6f1e6SMasatake YAMATO {
2508e8386a4eSMasatake YAMATO es_object_unref (lregex_dict);
2509e8386a4eSMasatake YAMATO opt_vm_delete (optvm);
2510d4c6f1e6SMasatake YAMATO }
2511d4c6f1e6SMasatake YAMATO
regexNeedsMultilineBuffer(struct lregexControlBlock * lcb)251216a203f6SMasatake YAMATO extern bool regexNeedsMultilineBuffer (struct lregexControlBlock *lcb)
251313939209SMasatake YAMATO {
2514134629a0SHadriel Kaplan if (ptrArrayCount(lcb->entries [REG_PARSER_MULTI_LINE]) > 0)
251541e0b4f8SMasatake YAMATO return true;
251641e0b4f8SMasatake YAMATO else if (ptrArrayCount(lcb->tables) > 0)
251741e0b4f8SMasatake YAMATO return true;
251841e0b4f8SMasatake YAMATO else
251941e0b4f8SMasatake YAMATO return false;
252013939209SMasatake YAMATO }
252113939209SMasatake YAMATO
matchMultilineRegex(struct lregexControlBlock * lcb,const vString * const allLines)252253dda59eSMasatake YAMATO extern bool matchMultilineRegex (struct lregexControlBlock *lcb, const vString* const allLines)
252313939209SMasatake YAMATO {
252413939209SMasatake YAMATO bool result = false;
252513939209SMasatake YAMATO
252653dda59eSMasatake YAMATO unsigned int i;
252753dda59eSMasatake YAMATO
2528134629a0SHadriel Kaplan for (i = 0; i < ptrArrayCount(lcb->entries [REG_PARSER_MULTI_LINE]); ++i)
252953dda59eSMasatake YAMATO {
2530134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem(lcb->entries [REG_PARSER_MULTI_LINE], i);
2531134629a0SHadriel Kaplan Assert (entry && entry->pattern);
253210db13faSMasatake YAMATO
2533134629a0SHadriel Kaplan if ((entry->pattern->xtagType != XTAG_UNKNOWN)
2534134629a0SHadriel Kaplan && (!isXtagEnabled (entry->pattern->xtagType)))
253510db13faSMasatake YAMATO continue;
253610db13faSMasatake YAMATO
2537134629a0SHadriel Kaplan result = matchMultilineRegexPattern (lcb, allLines, entry) || result;
253813939209SMasatake YAMATO }
2539ce71b90aSMasatake YAMATO return result;
254013939209SMasatake YAMATO }
254113939209SMasatake YAMATO
getTableIndexForName(const struct lregexControlBlock * const lcb,const char * name)254246837a67SHadriel Kaplan static int getTableIndexForName (const struct lregexControlBlock *const lcb, const char *name)
2543e0e33135SMasatake YAMATO {
2544e0e33135SMasatake YAMATO unsigned int i;
2545e0e33135SMasatake YAMATO
2546e0e33135SMasatake YAMATO for (i = 0; i < ptrArrayCount(lcb->tables); i++)
2547e0e33135SMasatake YAMATO {
2548e0e33135SMasatake YAMATO struct regexTable *table = ptrArrayItem(lcb->tables, i);
2549e0e33135SMasatake YAMATO if (strcmp (table->name, name) == 0)
2550e0e33135SMasatake YAMATO return (int)i;
2551e0e33135SMasatake YAMATO }
2552e0e33135SMasatake YAMATO
25530cbf3f0dSMasatake YAMATO return TABLE_INDEX_UNUSED;
2554e0e33135SMasatake YAMATO }
2555e0e33135SMasatake YAMATO
addRegexTable(struct lregexControlBlock * lcb,const char * name)2556e0e33135SMasatake YAMATO extern void addRegexTable (struct lregexControlBlock *lcb, const char *name)
2557e0e33135SMasatake YAMATO {
2558e0e33135SMasatake YAMATO const char *c;
2559e0e33135SMasatake YAMATO for (c = name; *c; c++)
2560e0e33135SMasatake YAMATO if (! (isalnum(*c) || *c == '_'))
2561e0e33135SMasatake YAMATO error (FATAL, "`%c' in \"%s\" is not acceptable as part of table name", *c, name);
2562e0e33135SMasatake YAMATO
2563e0e33135SMasatake YAMATO if (getTableIndexForName(lcb, name) >= 0)
2564e0e33135SMasatake YAMATO {
2565e0e33135SMasatake YAMATO error (WARNING, "regex table \"%s\" is already defined", name);
2566e0e33135SMasatake YAMATO return;
2567e0e33135SMasatake YAMATO }
2568e0e33135SMasatake YAMATO
2569e0e33135SMasatake YAMATO struct regexTable *table = xCalloc(1, struct regexTable);
2570e0e33135SMasatake YAMATO table->name = eStrdup (name);
2571134629a0SHadriel Kaplan table->entries = ptrArrayNew(deleteTableEntry);
2572e0e33135SMasatake YAMATO
2573e0e33135SMasatake YAMATO ptrArrayAdd (lcb->tables, table);
2574e0e33135SMasatake YAMATO }
257513939209SMasatake YAMATO
dumpSstack(FILE * fp,int scope)25763afb5475SMasatake YAMATO static void dumpSstack(FILE* fp, int scope)
2577adafc5f9SMasatake YAMATO {
25783671ad72SMasatake YAMATO tagEntryInfo *entry;
2579adafc5f9SMasatake YAMATO fprintf (fp, "scope : ");
25803671ad72SMasatake YAMATO while ((entry = getEntryInCorkQueue (scope)))
2581adafc5f9SMasatake YAMATO {
2582adafc5f9SMasatake YAMATO fprintf(fp, "%s", entry->name);
2583adafc5f9SMasatake YAMATO
2584adafc5f9SMasatake YAMATO scope = entry->extensionFields.scopeIndex;
2585adafc5f9SMasatake YAMATO if (scope != CORK_NIL)
2586adafc5f9SMasatake YAMATO fprintf(fp, "%c", '/');
2587adafc5f9SMasatake YAMATO }
2588adafc5f9SMasatake YAMATO fprintf (fp, "\n");
2589adafc5f9SMasatake YAMATO }
2590adafc5f9SMasatake YAMATO
dumpTstack(FILE * fp,ptrArray * tstack)2591adafc5f9SMasatake YAMATO static void dumpTstack(FILE* fp, ptrArray *tstack)
2592adafc5f9SMasatake YAMATO {
2593adafc5f9SMasatake YAMATO for (unsigned int i = ptrArrayCount(tstack); i > 0; i--)
2594adafc5f9SMasatake YAMATO {
2595adafc5f9SMasatake YAMATO char tmp[2];
2596adafc5f9SMasatake YAMATO struct regexTable *t = ptrArrayItem(tstack, i - 1);
2597adafc5f9SMasatake YAMATO if (i == 1)
2598adafc5f9SMasatake YAMATO tmp[0] = '\0';
2599adafc5f9SMasatake YAMATO else
2600adafc5f9SMasatake YAMATO {
2601adafc5f9SMasatake YAMATO tmp[0] = '/';
2602adafc5f9SMasatake YAMATO tmp[1] = '\0';
2603adafc5f9SMasatake YAMATO }
2604adafc5f9SMasatake YAMATO fprintf(fp, "%s%s", t->name, tmp);
2605adafc5f9SMasatake YAMATO }
2606adafc5f9SMasatake YAMATO fprintf(fp, "\n");
2607adafc5f9SMasatake YAMATO }
2608adafc5f9SMasatake YAMATO
printInputLine(FILE * vfp,const char * c,const off_t offset)2609e8dbee90SHadriel Kaplan static void printInputLine(FILE* vfp, const char *c, const off_t offset)
2610e8dbee90SHadriel Kaplan {
2611e8dbee90SHadriel Kaplan vString *v = vStringNew ();
2612e8dbee90SHadriel Kaplan
2613e8dbee90SHadriel Kaplan for (; *c && (*c != '\n'); c++)
2614e8dbee90SHadriel Kaplan vStringPut(v, *c);
2615e8dbee90SHadriel Kaplan
2616e8dbee90SHadriel Kaplan if (vStringLength (v) == 0 && *c == '\n')
2617e8dbee90SHadriel Kaplan vStringCatS (v, "\\n");
2618e8dbee90SHadriel Kaplan
2619e8dbee90SHadriel Kaplan fprintf (vfp, "\ninput : \"%s\" L%lu\n",
2620e8dbee90SHadriel Kaplan vStringValue (v),
2621e8dbee90SHadriel Kaplan getInputLineNumberForFileOffset(offset));
2622e8dbee90SHadriel Kaplan vStringDelete(v);
2623e8dbee90SHadriel Kaplan }
2624e8dbee90SHadriel Kaplan
printMultitableMessage(const langType language,const char * const tableName,const unsigned int index,const regexPattern * const ptrn,const off_t offset,const char * const current,const regmatch_t * const pmatch)26259a1e266aSHadriel Kaplan static void printMultitableMessage(const langType language,
26269a1e266aSHadriel Kaplan const char *const tableName,
26279a1e266aSHadriel Kaplan const unsigned int index,
26289a1e266aSHadriel Kaplan const regexPattern *const ptrn,
26299a1e266aSHadriel Kaplan const off_t offset,
26309a1e266aSHadriel Kaplan const char *const current,
26319a1e266aSHadriel Kaplan const regmatch_t* const pmatch)
26329a1e266aSHadriel Kaplan {
26339a1e266aSHadriel Kaplan vString *msg;
26349a1e266aSHadriel Kaplan
26359a1e266aSHadriel Kaplan Assert (ptrn);
26369a1e266aSHadriel Kaplan Assert (ptrn->message.selection > 0);
26379a1e266aSHadriel Kaplan Assert (ptrn->message.message_string);
26389a1e266aSHadriel Kaplan
26399a1e266aSHadriel Kaplan msg = substitute (current, ptrn->message.message_string, BACK_REFERENCE_COUNT, pmatch);
26409a1e266aSHadriel Kaplan
26419a1e266aSHadriel Kaplan error (ptrn->message.selection, "%sMessage from mtable<%s/%s[%2u]>: %s (%s:%lu)",
26429a1e266aSHadriel Kaplan (ptrn->message.selection == FATAL ? "Fatal: " : ""),
26439a1e266aSHadriel Kaplan getLanguageName (language),
26449a1e266aSHadriel Kaplan tableName,
26459a1e266aSHadriel Kaplan index,
26469a1e266aSHadriel Kaplan vStringValue (msg),
26479a1e266aSHadriel Kaplan getInputFileName (),
26489a1e266aSHadriel Kaplan getInputLineNumberForFileOffset (offset));
26499a1e266aSHadriel Kaplan
26509a1e266aSHadriel Kaplan vStringDelete (msg);
26519a1e266aSHadriel Kaplan }
26529a1e266aSHadriel Kaplan
matchMultitableRegexTable(struct lregexControlBlock * lcb,struct regexTable * table,const vString * const start,unsigned int * offset)265341e0b4f8SMasatake YAMATO static struct regexTable * matchMultitableRegexTable (struct lregexControlBlock *lcb,
265441e0b4f8SMasatake YAMATO struct regexTable *table, const vString *const start, unsigned int *offset)
265541e0b4f8SMasatake YAMATO {
265641e0b4f8SMasatake YAMATO struct regexTable *next = NULL;
265741e0b4f8SMasatake YAMATO const char *current;
265841e0b4f8SMasatake YAMATO regmatch_t pmatch [BACK_REFERENCE_COUNT];
265941e0b4f8SMasatake YAMATO const char *cstart = vStringValue(start);
26601f3437b7SMasatake YAMATO unsigned int delta;
266141e0b4f8SMasatake YAMATO
266241e0b4f8SMasatake YAMATO
266341e0b4f8SMasatake YAMATO restart:
266441e0b4f8SMasatake YAMATO current = cstart + *offset;
266541e0b4f8SMasatake YAMATO
26661f3437b7SMasatake YAMATO /* Accept the case *offset == vStringLength(start)
26671f3437b7SMasatake YAMATO because we want an empty regex // still matches empty input. */
26681f3437b7SMasatake YAMATO if (*offset > vStringLength(start))
26691f3437b7SMasatake YAMATO {
26701f3437b7SMasatake YAMATO *offset = vStringLength(start);
267141e0b4f8SMasatake YAMATO goto out;
26721f3437b7SMasatake YAMATO }
267341e0b4f8SMasatake YAMATO
2674e8dbee90SHadriel Kaplan BEGIN_VERBOSE(vfp);
2675e8dbee90SHadriel Kaplan {
2676e8dbee90SHadriel Kaplan printInputLine(vfp, current, *offset);
2677e8dbee90SHadriel Kaplan }
2678e8dbee90SHadriel Kaplan END_VERBOSE();
2679e8dbee90SHadriel Kaplan
2680134629a0SHadriel Kaplan for (unsigned int i = 0; i < ptrArrayCount(table->entries); i++)
268141e0b4f8SMasatake YAMATO {
2682134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem(table->entries, i);
26836fa01766SBernd if ((entry->pattern->xtagType != XTAG_UNKNOWN)
26846fa01766SBernd && (!isXtagEnabled (entry->pattern->xtagType)))
26856fa01766SBernd continue;
26866fa01766SBernd
2687134629a0SHadriel Kaplan regexPattern *ptrn = entry->pattern;
26886cdf5716SMasatake YAMATO struct guestSpec *guest = &ptrn->guest;
2689134629a0SHadriel Kaplan
2690134629a0SHadriel Kaplan Assert (ptrn);
2691adafc5f9SMasatake YAMATO
2692adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2693adafc5f9SMasatake YAMATO {
2694adafc5f9SMasatake YAMATO char s[3];
2695adafc5f9SMasatake YAMATO if (*current == '\n')
2696adafc5f9SMasatake YAMATO {
2697adafc5f9SMasatake YAMATO s [0] = '\\';
2698adafc5f9SMasatake YAMATO s [1] = 'n';
2699adafc5f9SMasatake YAMATO s [2] = '\0';
2700adafc5f9SMasatake YAMATO }
2701adafc5f9SMasatake YAMATO else if (*current == '\t')
2702adafc5f9SMasatake YAMATO {
2703adafc5f9SMasatake YAMATO s [0] = '\\';
2704adafc5f9SMasatake YAMATO s [1] = 't';
2705adafc5f9SMasatake YAMATO s [2] = '\0';
2706adafc5f9SMasatake YAMATO }
2707adafc5f9SMasatake YAMATO else if (*current == '\\')
2708adafc5f9SMasatake YAMATO {
2709adafc5f9SMasatake YAMATO s [0] = '\\';
2710adafc5f9SMasatake YAMATO s [1] = '\\';
2711adafc5f9SMasatake YAMATO s [2] = '\0';
2712adafc5f9SMasatake YAMATO }
2713adafc5f9SMasatake YAMATO else
2714adafc5f9SMasatake YAMATO {
2715adafc5f9SMasatake YAMATO s[0] = *current;
2716adafc5f9SMasatake YAMATO s[1] = '\0';
2717adafc5f9SMasatake YAMATO }
2718adafc5f9SMasatake YAMATO
2719adafc5f9SMasatake YAMATO if (s[1] == '\0')
2720adafc5f9SMasatake YAMATO fprintf (vfp, "match : '%s' %15s[%2u] /", s, table->name, i);
2721adafc5f9SMasatake YAMATO else if (s[0] == '\0')
2722adafc5f9SMasatake YAMATO fprintf (vfp, "match : '' %15s[%2u] /", table->name, i);
2723adafc5f9SMasatake YAMATO else
2724adafc5f9SMasatake YAMATO fprintf (vfp, "match :'%s' %15s[%2u] / ", s, table->name, i);
2725adafc5f9SMasatake YAMATO fprintf (vfp, "%s/\n", ptrn->pattern_string);
2726adafc5f9SMasatake YAMATO }
2727adafc5f9SMasatake YAMATO END_VERBOSE();
2728adafc5f9SMasatake YAMATO
272941e0b4f8SMasatake YAMATO int match = 0;
273041e0b4f8SMasatake YAMATO
273141e0b4f8SMasatake YAMATO if (ptrn->disabled && *(ptrn->disabled))
273241e0b4f8SMasatake YAMATO continue;
273341e0b4f8SMasatake YAMATO
2734c30b89acSMasatake YAMATO match = ptrn->pattern.backend->match (ptrn->pattern.backend,
2735c30b89acSMasatake YAMATO ptrn->pattern.code, current,
2736c30b89acSMasatake YAMATO vStringLength(start) - (current - cstart),
2737c30b89acSMasatake YAMATO pmatch);
273841e0b4f8SMasatake YAMATO if (match == 0)
273941e0b4f8SMasatake YAMATO {
2740134629a0SHadriel Kaplan entry->statistics.match++;
27412bbd136eSMasatake YAMATO off_t offset_for_tag = (current
27422bbd136eSMasatake YAMATO + pmatch [ptrn->mgroup.forLineNumberDetermination].rm_so)
27432bbd136eSMasatake YAMATO - cstart;
27442bbd136eSMasatake YAMATO scriptWindow window = {
27452bbd136eSMasatake YAMATO .line = current,
2746ed3202bdSMasatake YAMATO .start = cstart,
27472bbd136eSMasatake YAMATO .patbuf = ptrn,
27482bbd136eSMasatake YAMATO .pmatch = pmatch,
27492bbd136eSMasatake YAMATO .nmatch = BACK_REFERENCE_COUNT,
2750653692b7SMasatake YAMATO .advanceto = false,
27512bbd136eSMasatake YAMATO };
27522b8d4c66SMasatake YAMATO initTaction (&window.taction);
27532b8d4c66SMasatake YAMATO
2754e8386a4eSMasatake YAMATO if (ptrn->optscript && (! hasNameSlot (ptrn)))
2755e8386a4eSMasatake YAMATO {
27562bbd136eSMasatake YAMATO scriptSetup (optvm, lcb, CORK_NIL, &window);
2757668e3666SMasatake YAMATO EsObject *e = scriptEval (optvm, ptrn->optscript);
2758e8386a4eSMasatake YAMATO if (es_error_p (e))
2759e8386a4eSMasatake YAMATO error (WARNING, "error when evaluating: %s", ptrn->optscript_src);
2760e8386a4eSMasatake YAMATO es_object_unref (e);
2761668e3666SMasatake YAMATO scriptTeardown (optvm, lcb);
2762e8386a4eSMasatake YAMATO }
27639a1e266aSHadriel Kaplan
276441e0b4f8SMasatake YAMATO if (ptrn->type == PTRN_TAG)
276541e0b4f8SMasatake YAMATO {
27662bbd136eSMasatake YAMATO matchTagPattern (lcb, current, ptrn, pmatch, offset_for_tag,
27672bbd136eSMasatake YAMATO (ptrn->optscript && hasNameSlot (ptrn))? &window: NULL);
27682b8d4c66SMasatake YAMATO
27692b8d4c66SMasatake YAMATO struct mTableActionSpec *taction = (window.taction.action == TACTION_NOP)
27702b8d4c66SMasatake YAMATO ? &(ptrn->taction)
27712b8d4c66SMasatake YAMATO : &window.taction;
27722b8d4c66SMasatake YAMATO
2773adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2774adafc5f9SMasatake YAMATO {
2775e8dbee90SHadriel Kaplan fprintf(vfp, "result: matched %d bytes\n", (int)(pmatch[0].rm_eo));
2776adafc5f9SMasatake YAMATO dumpSstack (vfp, lcb->currentScope);
2777adafc5f9SMasatake YAMATO }
2778adafc5f9SMasatake YAMATO END_VERBOSE();
2779adafc5f9SMasatake YAMATO
27809a1e266aSHadriel Kaplan if (hasMessage(ptrn))
27819a1e266aSHadriel Kaplan printMultitableMessage (lcb->owner, table->name, i, ptrn,
27829a1e266aSHadriel Kaplan *offset, current, pmatch);
27839a1e266aSHadriel Kaplan
27846cdf5716SMasatake YAMATO if (fillGuestRequest (cstart, current, pmatch, guest, lcb->guest_req))
27856cdf5716SMasatake YAMATO {
27866cdf5716SMasatake YAMATO Assert (lcb->guest_req->lang != LANG_AUTO);
27876cdf5716SMasatake YAMATO if (isGuestRequestConsistent(lcb->guest_req))
27886cdf5716SMasatake YAMATO guestRequestSubmit (lcb->guest_req);
27896cdf5716SMasatake YAMATO guestRequestClear (lcb->guest_req);
27906cdf5716SMasatake YAMATO }
27916cdf5716SMasatake YAMATO
2792653692b7SMasatake YAMATO if (window.advanceto)
2793653692b7SMasatake YAMATO delta = window.advanceto_delta;
2794653692b7SMasatake YAMATO else
27951f3437b7SMasatake YAMATO delta = (ptrn->mgroup.nextFromStart
279641e0b4f8SMasatake YAMATO ? pmatch [ptrn->mgroup.forNextScanning].rm_so
279741e0b4f8SMasatake YAMATO : pmatch [ptrn->mgroup.forNextScanning].rm_eo);
27981f3437b7SMasatake YAMATO *offset += delta;
279941e0b4f8SMasatake YAMATO
280041e0b4f8SMasatake YAMATO switch (taction->action)
280141e0b4f8SMasatake YAMATO {
280241e0b4f8SMasatake YAMATO case TACTION_NOP:
2803adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2804adafc5f9SMasatake YAMATO {
2805adafc5f9SMasatake YAMATO fprintf(vfp, "action: NOP in {%s}, stack: /", table->name);
2806adafc5f9SMasatake YAMATO dumpTstack(vfp, lcb->tstack);
2807adafc5f9SMasatake YAMATO }
2808adafc5f9SMasatake YAMATO END_VERBOSE();
280941e0b4f8SMasatake YAMATO break;
281041e0b4f8SMasatake YAMATO case TACTION_ENTER:
2811bf809d1aSMasatake YAMATO /* TODO: Limit the depth of tstack. */
281240177cd9SMasatake YAMATO ptrArrayAdd (lcb->tstack,
281340177cd9SMasatake YAMATO taction->continuation_table
281440177cd9SMasatake YAMATO ? taction->continuation_table
281540177cd9SMasatake YAMATO : table);
281641e0b4f8SMasatake YAMATO next = taction->table;
2817adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2818adafc5f9SMasatake YAMATO {
2819adafc5f9SMasatake YAMATO if (taction->continuation_table)
2820adafc5f9SMasatake YAMATO fprintf(vfp, "action: [enter] to {%s}, cont: {%s}, stack: /",
2821adafc5f9SMasatake YAMATO next->name,
2822adafc5f9SMasatake YAMATO taction->continuation_table->name);
2823adafc5f9SMasatake YAMATO else
2824adafc5f9SMasatake YAMATO fprintf(vfp, "action: [enter] to {%s}, stack: /", next->name);
2825adafc5f9SMasatake YAMATO dumpTstack(vfp, lcb->tstack);
2826adafc5f9SMasatake YAMATO }
2827adafc5f9SMasatake YAMATO END_VERBOSE();
282841e0b4f8SMasatake YAMATO break;
282941e0b4f8SMasatake YAMATO case TACTION_LEAVE:
2830adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2831adafc5f9SMasatake YAMATO {
2832adafc5f9SMasatake YAMATO fprintf(vfp, "action: [leave] from {%s}, stack: /", table->name);
2833adafc5f9SMasatake YAMATO dumpTstack(vfp, lcb->tstack);
2834adafc5f9SMasatake YAMATO }
2835adafc5f9SMasatake YAMATO END_VERBOSE();
283641e0b4f8SMasatake YAMATO if (ptrArrayCount (lcb->tstack) == 0)
283741e0b4f8SMasatake YAMATO {
283841e0b4f8SMasatake YAMATO error (WARNING, "leave is specified as regex table action but the table stack is empty");
283941e0b4f8SMasatake YAMATO return NULL;
284041e0b4f8SMasatake YAMATO }
284141e0b4f8SMasatake YAMATO next = ptrArrayLast(lcb->tstack);
284241e0b4f8SMasatake YAMATO ptrArrayRemoveLast (lcb->tstack);
284341e0b4f8SMasatake YAMATO break;
284441e0b4f8SMasatake YAMATO case TACTION_JUMP:
284541e0b4f8SMasatake YAMATO next = taction->table;
2846adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2847adafc5f9SMasatake YAMATO {
2848adafc5f9SMasatake YAMATO fprintf(vfp, "action: [jump] from {%s} to {%s}, stack: /", table->name, next->name);
2849adafc5f9SMasatake YAMATO dumpTstack(vfp, lcb->tstack);
2850adafc5f9SMasatake YAMATO }
2851adafc5f9SMasatake YAMATO END_VERBOSE();
2852adafc5f9SMasatake YAMATO
285341e0b4f8SMasatake YAMATO break;
285441e0b4f8SMasatake YAMATO case TACTION_RESET:
285541e0b4f8SMasatake YAMATO next = taction->table;
2856adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2857adafc5f9SMasatake YAMATO {
2858adafc5f9SMasatake YAMATO fprintf(vfp, "action: [reset] to {%s}, stack: /", next->name);
2859adafc5f9SMasatake YAMATO }
2860adafc5f9SMasatake YAMATO END_VERBOSE();
2861adafc5f9SMasatake YAMATO
2862adafc5f9SMasatake YAMATO ptrArrayClear (lcb->tstack);
286341e0b4f8SMasatake YAMATO break;
286441e0b4f8SMasatake YAMATO case TACTION_QUIT:
2865adafc5f9SMasatake YAMATO BEGIN_VERBOSE(vfp);
2866adafc5f9SMasatake YAMATO {
2867adafc5f9SMasatake YAMATO fprintf(vfp, "action: [quit], stack: /");
2868adafc5f9SMasatake YAMATO dumpTstack(vfp, lcb->tstack);
2869adafc5f9SMasatake YAMATO }
2870adafc5f9SMasatake YAMATO END_VERBOSE();
287141e0b4f8SMasatake YAMATO return NULL;
287241e0b4f8SMasatake YAMATO }
287341e0b4f8SMasatake YAMATO
287441e0b4f8SMasatake YAMATO if (next)
287541e0b4f8SMasatake YAMATO break;
28761f3437b7SMasatake YAMATO
28771f3437b7SMasatake YAMATO if (delta == 0)
28781f3437b7SMasatake YAMATO {
28791f3437b7SMasatake YAMATO error (WARNING, "Forcefully advance the input pos because");
28801f3437b7SMasatake YAMATO error (WARNING, "following conditions for entering infinite loop are satisfied:");
28811f3437b7SMasatake YAMATO error (WARNING, "+ matching the pattern succeeds,");
28821f3437b7SMasatake YAMATO error (WARNING, "+ the next table is not given, and");
28831f3437b7SMasatake YAMATO error (WARNING, "+ the input file pos doesn't advance.");
28841f3437b7SMasatake YAMATO error (WARNING, "Language: %s, input file: %s, pos: %u",
28851f3437b7SMasatake YAMATO getLanguageName (lcb->owner), getInputFileName(), *offset);
28861f3437b7SMasatake YAMATO ++*offset;
28871f3437b7SMasatake YAMATO }
288841e0b4f8SMasatake YAMATO }
288941e0b4f8SMasatake YAMATO else if (ptrn->type == PTRN_CALLBACK)
289041e0b4f8SMasatake YAMATO ; /* Not implemented yet */
289141e0b4f8SMasatake YAMATO else
289241e0b4f8SMasatake YAMATO {
289341e0b4f8SMasatake YAMATO Assert ("invalid pattern type" == NULL);
289441e0b4f8SMasatake YAMATO break;
289541e0b4f8SMasatake YAMATO }
289641e0b4f8SMasatake YAMATO goto restart;
289741e0b4f8SMasatake YAMATO }
28981e923193SMasatake YAMATO else
2899134629a0SHadriel Kaplan entry->statistics.unmatch++;
290041e0b4f8SMasatake YAMATO }
290141e0b4f8SMasatake YAMATO out:
290241e0b4f8SMasatake YAMATO if (next == NULL && ptrArrayCount (lcb->tstack) > 0)
290341e0b4f8SMasatake YAMATO {
2904adafc5f9SMasatake YAMATO static int apop_count = 0;
290541e0b4f8SMasatake YAMATO next = ptrArrayLast(lcb->tstack);
2906e8dbee90SHadriel Kaplan verbose("result: no match - autopop<%d> from {%s} to {%s} @ %lu\n", apop_count++, table->name, next->name,
2907adafc5f9SMasatake YAMATO getInputLineNumberForFileOffset(*offset));
290841e0b4f8SMasatake YAMATO ptrArrayRemoveLast (lcb->tstack);
290941e0b4f8SMasatake YAMATO }
291041e0b4f8SMasatake YAMATO return next;
291141e0b4f8SMasatake YAMATO }
291241e0b4f8SMasatake YAMATO
extendRegexTable(struct lregexControlBlock * lcb,const char * src,const char * dist)2913bf809d1aSMasatake YAMATO extern void extendRegexTable (struct lregexControlBlock *lcb, const char *src, const char *dist)
2914bf809d1aSMasatake YAMATO {
2915bf809d1aSMasatake YAMATO
2916bf809d1aSMasatake YAMATO int i;
2917bf809d1aSMasatake YAMATO struct regexTable * src_table;
2918bf809d1aSMasatake YAMATO struct regexTable * dist_table;
2919bf809d1aSMasatake YAMATO
2920bf809d1aSMasatake YAMATO verbose ("extend regex table \"%s\" with \"%s\"\n", dist, src);
2921bf809d1aSMasatake YAMATO
2922bf809d1aSMasatake YAMATO i = getTableIndexForName (lcb, src);
2923bf809d1aSMasatake YAMATO if (i < 0)
2924bf809d1aSMasatake YAMATO error (FATAL, "no such regex table in %s: %s", getLanguageName(lcb->owner), src);
2925bf809d1aSMasatake YAMATO src_table = ptrArrayItem(lcb->tables, i);
2926bf809d1aSMasatake YAMATO
2927bf809d1aSMasatake YAMATO i = getTableIndexForName (lcb, dist);
2928bf809d1aSMasatake YAMATO if (i < 0)
2929bf809d1aSMasatake YAMATO error (FATAL, "no such regex table in %s: %s", getLanguageName(lcb->owner), dist);
2930bf809d1aSMasatake YAMATO dist_table = ptrArrayItem(lcb->tables, i);
2931bf809d1aSMasatake YAMATO
29324c64e833SMasatake YAMATO for (i = 0; i < (int)ptrArrayCount(src_table->entries); i++)
2933bf809d1aSMasatake YAMATO {
2934134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem (src_table->entries, i);
2935134629a0SHadriel Kaplan ptrArrayAdd(dist_table->entries, newRefPatternEntry(entry));
2936bf809d1aSMasatake YAMATO }
2937bf809d1aSMasatake YAMATO }
2938bf809d1aSMasatake YAMATO
printMultitableStatistics(struct lregexControlBlock * lcb)2939d4318624SMasatake YAMATO extern void printMultitableStatistics (struct lregexControlBlock *lcb)
29401e923193SMasatake YAMATO {
29411e923193SMasatake YAMATO if (ptrArrayCount(lcb->tables) == 0)
29421e923193SMasatake YAMATO return;
29431e923193SMasatake YAMATO
2944d4318624SMasatake YAMATO fprintf(stderr, "\nMTABLE REGEX STATISTICS of %s\n", getLanguageName (lcb->owner));
2945d4318624SMasatake YAMATO fputs("==============================================\n", stderr);
29461e923193SMasatake YAMATO for (unsigned int i = 0; i < ptrArrayCount(lcb->tables); i++)
29471e923193SMasatake YAMATO {
2948ba5ad3fbSAlan Barr struct regexTable *table = ptrArrayItem (lcb->tables, i);
2949d4318624SMasatake YAMATO fprintf(stderr, "%s\n", table->name);
2950d4318624SMasatake YAMATO fputs("-----------------------\n", stderr);
2951134629a0SHadriel Kaplan for (unsigned int j = 0; j < ptrArrayCount(table->entries); j++)
29521e923193SMasatake YAMATO {
2953134629a0SHadriel Kaplan regexTableEntry *entry = ptrArrayItem (table->entries, j);
2954134629a0SHadriel Kaplan Assert (entry && entry->pattern);
2955d4318624SMasatake YAMATO fprintf(stderr, "%10u/%-10u%-40s ref: %d\n",
2956134629a0SHadriel Kaplan entry->statistics.match,
2957134629a0SHadriel Kaplan entry->statistics.unmatch + entry->statistics.match,
2958134629a0SHadriel Kaplan entry->pattern->pattern_string,
2959134629a0SHadriel Kaplan entry->pattern->refcount);
29601e923193SMasatake YAMATO }
2961d4318624SMasatake YAMATO fputc('\n', stderr);
29621e923193SMasatake YAMATO }
29631e923193SMasatake YAMATO }
29641e923193SMasatake YAMATO
matchMultitableRegex(struct lregexControlBlock * lcb,const vString * const allLines)296541e0b4f8SMasatake YAMATO extern bool matchMultitableRegex (struct lregexControlBlock *lcb, const vString* const allLines)
296641e0b4f8SMasatake YAMATO {
296741e0b4f8SMasatake YAMATO if (ptrArrayCount (lcb->tables) == 0)
296841e0b4f8SMasatake YAMATO return false;
296941e0b4f8SMasatake YAMATO
297041e0b4f8SMasatake YAMATO struct regexTable *table = ptrArrayItem (lcb->tables, 0);
297141e0b4f8SMasatake YAMATO unsigned int offset = 0;
297241e0b4f8SMasatake YAMATO
2973afcf38b2SMasatake YAMATO int motionless_counter = 0;
2974afcf38b2SMasatake YAMATO unsigned int last_offset;
2975afcf38b2SMasatake YAMATO
2976afcf38b2SMasatake YAMATO
297741e0b4f8SMasatake YAMATO while (table)
297841e0b4f8SMasatake YAMATO {
2979afcf38b2SMasatake YAMATO last_offset = offset;
298041e0b4f8SMasatake YAMATO table = matchMultitableRegexTable(lcb, table, allLines, &offset);
2981afcf38b2SMasatake YAMATO
2982afcf38b2SMasatake YAMATO if (last_offset == offset)
2983afcf38b2SMasatake YAMATO motionless_counter++;
2984afcf38b2SMasatake YAMATO else
2985afcf38b2SMasatake YAMATO motionless_counter = 0;
2986afcf38b2SMasatake YAMATO
2987afcf38b2SMasatake YAMATO if (motionless_counter > MTABLE_MOTIONLESS_MAX)
2988afcf38b2SMasatake YAMATO {
2989afcf38b2SMasatake YAMATO error (WARNING, "mtable<%s/%s>: the input cursor stays at %u in %s so long though the tables are switched",
2990afcf38b2SMasatake YAMATO getLanguageName (lcb->owner),
2991afcf38b2SMasatake YAMATO table->name, offset, getInputFileName ());
2992afcf38b2SMasatake YAMATO break;
2993afcf38b2SMasatake YAMATO }
2994afcf38b2SMasatake YAMATO
2995042e4190SMasatake YAMATO if (table && (ptrArrayCount (lcb->tstack) > MTABLE_STACK_MAX_DEPTH))
2996042e4190SMasatake YAMATO {
2997042e4190SMasatake YAMATO unsigned int i;
2998042e4190SMasatake YAMATO struct regexTable *t;
2999042e4190SMasatake YAMATO
3000042e4190SMasatake YAMATO error (WARNING, "mtable<%s/%s>: the tenter/tleave stack overflows at %u in %s",
3001042e4190SMasatake YAMATO getLanguageName (lcb->owner),
3002042e4190SMasatake YAMATO table->name, offset, getInputFileName ());
3003042e4190SMasatake YAMATO error (WARNING, "DUMP FROM THE TOP:");
3004ebdbd8e2SK.Takata /* TODO: use dumpTstack */
3005042e4190SMasatake YAMATO for (i = ptrArrayCount(lcb->tstack); 0 < i; --i)
3006042e4190SMasatake YAMATO {
3007042e4190SMasatake YAMATO t = ptrArrayItem (lcb->tstack, i - 1);
3008042e4190SMasatake YAMATO error (WARNING, "%3u %s", i - 1, t->name);
3009042e4190SMasatake YAMATO }
3010042e4190SMasatake YAMATO
3011042e4190SMasatake YAMATO break;
3012042e4190SMasatake YAMATO }
301341e0b4f8SMasatake YAMATO }
301441e0b4f8SMasatake YAMATO
301541e0b4f8SMasatake YAMATO return true;
301641e0b4f8SMasatake YAMATO }
301741e0b4f8SMasatake YAMATO
makePromiseForAreaSpecifiedWithOffsets(const char * parser,off_t startOffset,off_t endOffset)3018b19716b4SMasatake YAMATO static int makePromiseForAreaSpecifiedWithOffsets (const char *parser,
3019b19716b4SMasatake YAMATO off_t startOffset,
3020b19716b4SMasatake YAMATO off_t endOffset)
3021b19716b4SMasatake YAMATO {
30226cdf5716SMasatake YAMATO unsigned long startLine = getInputLineNumberForFileOffset(startOffset);
30236cdf5716SMasatake YAMATO unsigned long endLine = getInputLineNumberForFileOffset(endOffset);
3024b19716b4SMasatake YAMATO unsigned long startLineOffset = getInputFileOffsetForLine (startLine);
3025b19716b4SMasatake YAMATO unsigned long endLineOffset = getInputFileOffsetForLine (endLine);
3026b19716b4SMasatake YAMATO
30278b459ed6SMasatake YAMATO Assert(startOffset >= startLineOffset);
30288b459ed6SMasatake YAMATO Assert(endOffset >= endLineOffset);
30298b459ed6SMasatake YAMATO
3030b19716b4SMasatake YAMATO return makePromise (parser,
3031b19716b4SMasatake YAMATO startLine, startOffset - startLineOffset,
3032b19716b4SMasatake YAMATO endLine, endOffset - endLineOffset,
3033b19716b4SMasatake YAMATO startOffset - startLineOffset);
3034b19716b4SMasatake YAMATO }
3035b19716b4SMasatake YAMATO
guestRequestNew(void)30366cdf5716SMasatake YAMATO static struct guestRequest *guestRequestNew (void)
30376cdf5716SMasatake YAMATO {
30386cdf5716SMasatake YAMATO struct guestRequest *r = xMalloc (1, struct guestRequest);
30396cdf5716SMasatake YAMATO
30406cdf5716SMasatake YAMATO
30416cdf5716SMasatake YAMATO guestRequestClear (r);
30426cdf5716SMasatake YAMATO return r;
30436cdf5716SMasatake YAMATO }
30446cdf5716SMasatake YAMATO
guestRequestDelete(struct guestRequest * r)30456cdf5716SMasatake YAMATO static void guestRequestDelete (struct guestRequest *r)
30466cdf5716SMasatake YAMATO {
30476cdf5716SMasatake YAMATO eFree (r);
30486cdf5716SMasatake YAMATO }
30496cdf5716SMasatake YAMATO
guestRequestIsFilled(struct guestRequest * r)30506cdf5716SMasatake YAMATO static bool guestRequestIsFilled(struct guestRequest *r)
30516cdf5716SMasatake YAMATO {
30526cdf5716SMasatake YAMATO return (r->lang_set && (r->boundary + 0)->offset_set && (r->boundary + 1)->offset_set);
30536cdf5716SMasatake YAMATO }
30546cdf5716SMasatake YAMATO
guestRequestClear(struct guestRequest * r)30556cdf5716SMasatake YAMATO static void guestRequestClear (struct guestRequest *r)
30566cdf5716SMasatake YAMATO {
30576cdf5716SMasatake YAMATO r->lang_set = false;
30586cdf5716SMasatake YAMATO r->boundary[BOUNDARY_START].offset_set = false;
30596cdf5716SMasatake YAMATO r->boundary[BOUNDARY_END].offset_set = false;
30606cdf5716SMasatake YAMATO }
30616cdf5716SMasatake YAMATO
guestRequestSubmit(struct guestRequest * r)30626cdf5716SMasatake YAMATO static void guestRequestSubmit (struct guestRequest *r)
30636cdf5716SMasatake YAMATO {
30646cdf5716SMasatake YAMATO const char *langName = getLanguageName (r->lang);
30656cdf5716SMasatake YAMATO verbose ("guestRequestSubmit: %s; "
3066540cbe83SK.Takata "range: %"PRId64" - %"PRId64"\n",
30676cdf5716SMasatake YAMATO langName,
3068540cbe83SK.Takata (int64_t)r->boundary[BOUNDARY_START].offset,
3069540cbe83SK.Takata (int64_t)r->boundary[BOUNDARY_END].offset);
30706cdf5716SMasatake YAMATO makePromiseForAreaSpecifiedWithOffsets (langName,
30716cdf5716SMasatake YAMATO r->boundary[BOUNDARY_START].offset,
30726cdf5716SMasatake YAMATO r->boundary[BOUNDARY_END].offset);
30736cdf5716SMasatake YAMATO }
30746cdf5716SMasatake YAMATO
3075668e3666SMasatake YAMATO /*
3076668e3666SMasatake YAMATO * Script related functions
3077668e3666SMasatake YAMATO */
30783d644137SMasatake YAMATO
3079668e3666SMasatake YAMATO /* This functions expects { code }} as input.
3080668e3666SMasatake YAMATO * Be care that curly brackets must be unbalanced.
3081668e3666SMasatake YAMATO */
scriptRead(OptVM * vm,const char * src)3082668e3666SMasatake YAMATO static EsObject *scriptRead (OptVM *vm, const char *src)
30833d644137SMasatake YAMATO {
3084668e3666SMasatake YAMATO size_t len = strlen (src);
3085668e3666SMasatake YAMATO Assert (len > 2);
3086668e3666SMasatake YAMATO Assert (src[len - 1] == '}');
3087668e3666SMasatake YAMATO Assert (src[len - 2] == '}');
3088668e3666SMasatake YAMATO
3089668e3666SMasatake YAMATO EsObject *obj = optscriptRead (vm, src + 1, len - 1 - 1);
3090668e3666SMasatake YAMATO if (es_error_p (obj))
3091668e3666SMasatake YAMATO error (FATAL, "failed in loading an optscript: %s", src);
3092668e3666SMasatake YAMATO return obj;
30933d644137SMasatake YAMATO }
30943d644137SMasatake YAMATO
scriptEval(OptVM * vm,EsObject * optscript)3095668e3666SMasatake YAMATO extern EsObject* scriptEval (OptVM *vm, EsObject *optscript)
30963d644137SMasatake YAMATO {
3097668e3666SMasatake YAMATO return optscriptEval (vm, optscript);
30983d644137SMasatake YAMATO }
30993d644137SMasatake YAMATO
scriptEvalHook(OptVM * vm,struct lregexControlBlock * lcb,enum scriptHook hook)3100b6124a60SMasatake YAMATO static void scriptEvalHook (OptVM *vm, struct lregexControlBlock *lcb, enum scriptHook hook)
3101fba3677cSMasatake YAMATO {
31021409a195SMasatake YAMATO if (ptrArrayCount (lcb->hook_code[hook]) == 0)
3103fba3677cSMasatake YAMATO {
31041409a195SMasatake YAMATO for (int i = 0; i < ptrArrayCount (lcb->hook[hook]); i++)
3105cda2e6c3SMasatake YAMATO {
31061409a195SMasatake YAMATO const char *src = ptrArrayItem (lcb->hook[hook], i);
3107668e3666SMasatake YAMATO EsObject *code = scriptRead (vm, src);
3108cda2e6c3SMasatake YAMATO if (es_error_p (code))
31091409a195SMasatake YAMATO error (FATAL, "error when reading hook[%d] code: %s", hook, src);
31101409a195SMasatake YAMATO ptrArrayAdd (lcb->hook_code[hook], es_object_ref (code));
3111668e3666SMasatake YAMATO es_object_unref (code);
3112668e3666SMasatake YAMATO }
3113cda2e6c3SMasatake YAMATO }
31141409a195SMasatake YAMATO for (int i = 0; i < ptrArrayCount (lcb->hook_code[hook]); i++)
3115cda2e6c3SMasatake YAMATO {
31161409a195SMasatake YAMATO EsObject *code = ptrArrayItem (lcb->hook_code[hook], i);
3117cda2e6c3SMasatake YAMATO EsObject * e = optscriptEval (vm, code);
3118cda2e6c3SMasatake YAMATO if (es_error_p (e))
31191409a195SMasatake YAMATO error (WARNING, "error when evaluating hook[%d] code: %s",
31201409a195SMasatake YAMATO hook, (char *)ptrArrayItem (lcb->hook[i], i));
3121cda2e6c3SMasatake YAMATO }
3122fba3677cSMasatake YAMATO }
3123fba3677cSMasatake YAMATO
scriptSetup(OptVM * vm,struct lregexControlBlock * lcb,int corkIndex,scriptWindow * window)31242bbd136eSMasatake YAMATO static void scriptSetup (OptVM *vm, struct lregexControlBlock *lcb, int corkIndex, scriptWindow *window)
3125fba3677cSMasatake YAMATO {
31262bbd136eSMasatake YAMATO lcb->window = window;
3127668e3666SMasatake YAMATO optscriptSetup (vm, lcb->local_dict, corkIndex);
3128fba3677cSMasatake YAMATO }
3129fba3677cSMasatake YAMATO
scriptTeardown(OptVM * vm,struct lregexControlBlock * lcb)3130668e3666SMasatake YAMATO static void scriptTeardown (OptVM *vm, struct lregexControlBlock *lcb)
3131fba3677cSMasatake YAMATO {
3132668e3666SMasatake YAMATO optscriptTeardown (vm, lcb->local_dict);
31332bbd136eSMasatake YAMATO lcb->window = NULL;
3134fba3677cSMasatake YAMATO }
3135fba3677cSMasatake YAMATO
addOptscriptToHook(struct lregexControlBlock * lcb,enum scriptHook hook,const char * code)3136b6124a60SMasatake YAMATO extern void addOptscriptToHook (struct lregexControlBlock *lcb, enum scriptHook hook, const char *code)
31375c872341SMasatake YAMATO {
3138b6124a60SMasatake YAMATO ptrArrayAdd (lcb->hook[hook], eStrdup (code));
31391409a195SMasatake YAMATO }
31401409a195SMasatake YAMATO
3141ce990805SThomas Braun /* Return true if available. */
checkRegex(void)3142ce990805SThomas Braun extern bool checkRegex (void)
3143d4c6f1e6SMasatake YAMATO {
3144a656c9bfSMasatake YAMATO #if defined (CHECK_REGCOMP)
3145d4c6f1e6SMasatake YAMATO {
3146d4c6f1e6SMasatake YAMATO /* Check for broken regcomp() on Cygwin */
3147d4c6f1e6SMasatake YAMATO regex_t patbuf;
3148d4c6f1e6SMasatake YAMATO int errcode;
3149d4c6f1e6SMasatake YAMATO if (regcomp (&patbuf, "/hello/", 0) != 0)
3150d4c6f1e6SMasatake YAMATO error (WARNING, "Disabling broken regex");
3151d4c6f1e6SMasatake YAMATO else
3152ce990805SThomas Braun regexAvailable = true;
3153d4c6f1e6SMasatake YAMATO }
3154d4c6f1e6SMasatake YAMATO #else
3155d4c6f1e6SMasatake YAMATO /* We are using bundled regex engine. */
3156ce990805SThomas Braun regexAvailable = true;
3157d4c6f1e6SMasatake YAMATO #endif
3158e8386a4eSMasatake YAMATO
3159d4c6f1e6SMasatake YAMATO return regexAvailable;
3160d4c6f1e6SMasatake YAMATO }
3161965b7025SMasatake YAMATO
316234deb294SMasatake YAMATO static EsObject *OPTSCRIPT_ERR_UNKNOWNKIND;
316334deb294SMasatake YAMATO
316434deb294SMasatake YAMATO /* name:str kind:name loc _TAG tag
316534deb294SMasatake YAMATO * name:str kind:name _TAG tag */
lrop_make_tag(OptVM * vm,EsObject * name)316634deb294SMasatake YAMATO static EsObject* lrop_make_tag (OptVM *vm, EsObject *name)
316734deb294SMasatake YAMATO {
316834deb294SMasatake YAMATO matchLoc *loc;
316934deb294SMasatake YAMATO
317034deb294SMasatake YAMATO if (opt_vm_ostack_count (vm) < 1)
317134deb294SMasatake YAMATO return OPT_ERR_UNDERFLOW;
317234deb294SMasatake YAMATO
317334deb294SMasatake YAMATO int index;
317434deb294SMasatake YAMATO EsObject *top = opt_vm_ostack_top (vm);
317534deb294SMasatake YAMATO if (es_object_get_type (top) == OPT_TYPE_MATCHLOC)
317634deb294SMasatake YAMATO {
317734deb294SMasatake YAMATO if (opt_vm_ostack_count (vm) < 3)
317834deb294SMasatake YAMATO return OPT_ERR_UNDERFLOW;
317934deb294SMasatake YAMATO loc = es_pointer_get (top);
318034deb294SMasatake YAMATO index = 1;
318134deb294SMasatake YAMATO }
318234deb294SMasatake YAMATO else
318334deb294SMasatake YAMATO {
318434deb294SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
318534deb294SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_SINGLE_LINE)
318634deb294SMasatake YAMATO return OPT_ERR_TYPECHECK;
318734deb294SMasatake YAMATO if (opt_vm_ostack_count (vm) < 2)
318834deb294SMasatake YAMATO return OPT_ERR_UNDERFLOW;
318934deb294SMasatake YAMATO loc = NULL;
319034deb294SMasatake YAMATO index = 0;
319134deb294SMasatake YAMATO }
319234deb294SMasatake YAMATO
319334deb294SMasatake YAMATO EsObject *kind = opt_vm_ostack_peek (vm, index++);
319434deb294SMasatake YAMATO if (es_object_get_type (kind) != OPT_TYPE_NAME)
319534deb294SMasatake YAMATO return OPT_ERR_TYPECHECK;
319634deb294SMasatake YAMATO EsObject *kind_sym = es_pointer_get (kind);
319734deb294SMasatake YAMATO const char *kind_str = es_symbol_get (kind_sym);
319834deb294SMasatake YAMATO kindDefinition* kind_def = getLanguageKindForName (getInputLanguage (),
319934deb294SMasatake YAMATO kind_str);
320034deb294SMasatake YAMATO if (!kind_def)
320134deb294SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNKIND;
320234deb294SMasatake YAMATO int kind_index = kind_def->id;
320334deb294SMasatake YAMATO
320434deb294SMasatake YAMATO EsObject *tname = opt_vm_ostack_peek (vm, index++);
320534deb294SMasatake YAMATO if (es_object_get_type (tname) != OPT_TYPE_STRING)
320634deb294SMasatake YAMATO return OPT_ERR_TYPECHECK;
320734deb294SMasatake YAMATO const char *n = opt_string_get_cstr (tname);
320834deb294SMasatake YAMATO if (n [0] == '\0')
3209820e8cc6SMasatake YAMATO return OPT_ERR_RANGECHECK; /* TODO */
321034deb294SMasatake YAMATO
321134deb294SMasatake YAMATO tagEntryInfo *e = xMalloc (1, tagEntryInfo);
321234deb294SMasatake YAMATO initRegexTag (e, eStrdup (n),
321334deb294SMasatake YAMATO kind_index, ROLE_DEFINITION_INDEX, CORK_NIL, 0,
321434deb294SMasatake YAMATO loc? loc->line: 0, loc? &loc->pos: NULL, XTAG_UNKNOWN);
321534deb294SMasatake YAMATO EsObject *obj = es_pointer_new (OPT_TYPE_TAG, e);
321634deb294SMasatake YAMATO if (es_error_p (obj))
321734deb294SMasatake YAMATO return obj;
321834deb294SMasatake YAMATO
321934deb294SMasatake YAMATO while (index-- > 0)
322034deb294SMasatake YAMATO opt_vm_ostack_pop (vm);
322134deb294SMasatake YAMATO
322234deb294SMasatake YAMATO opt_vm_ostack_push (vm, obj);
322334deb294SMasatake YAMATO es_object_unref (obj);
322434deb294SMasatake YAMATO return es_false;
322534deb294SMasatake YAMATO }
322634deb294SMasatake YAMATO
32277b347e74SMasatake YAMATO static EsObject *OPTSCRIPT_ERR_UNKNOWNROLE;
32287b347e74SMasatake YAMATO
lrop_make_reftag(OptVM * vm,EsObject * name)32297b347e74SMasatake YAMATO static EsObject* lrop_make_reftag (OptVM *vm, EsObject *name)
32307b347e74SMasatake YAMATO {
32317b347e74SMasatake YAMATO matchLoc *loc;
32327b347e74SMasatake YAMATO
32337b347e74SMasatake YAMATO if (opt_vm_ostack_count (vm) < 1)
32347b347e74SMasatake YAMATO return OPT_ERR_UNDERFLOW;
32357b347e74SMasatake YAMATO
32367b347e74SMasatake YAMATO int index;
32377b347e74SMasatake YAMATO EsObject *top = opt_vm_ostack_top (vm);
32387b347e74SMasatake YAMATO if (es_object_get_type (top) == OPT_TYPE_MATCHLOC)
32397b347e74SMasatake YAMATO {
32407b347e74SMasatake YAMATO if (opt_vm_ostack_count (vm) < 4)
32417b347e74SMasatake YAMATO return OPT_ERR_UNDERFLOW;
32427b347e74SMasatake YAMATO loc = es_pointer_get (top);
32437b347e74SMasatake YAMATO index = 1;
32447b347e74SMasatake YAMATO }
32457b347e74SMasatake YAMATO else
32467b347e74SMasatake YAMATO {
32477b347e74SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
32487b347e74SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_SINGLE_LINE)
32497b347e74SMasatake YAMATO return OPT_ERR_TYPECHECK;
32507b347e74SMasatake YAMATO if (opt_vm_ostack_count (vm) < 3)
32517b347e74SMasatake YAMATO return OPT_ERR_UNDERFLOW;
32527b347e74SMasatake YAMATO loc = NULL;
32537b347e74SMasatake YAMATO index = 0;
32547b347e74SMasatake YAMATO }
32557b347e74SMasatake YAMATO
32567b347e74SMasatake YAMATO EsObject *role = opt_vm_ostack_peek (vm, index++);
32577b347e74SMasatake YAMATO if (es_object_get_type (role) != OPT_TYPE_NAME)
32587b347e74SMasatake YAMATO return OPT_ERR_TYPECHECK;
32597b347e74SMasatake YAMATO
32607b347e74SMasatake YAMATO EsObject *kind = opt_vm_ostack_peek (vm, index++);
32617b347e74SMasatake YAMATO if (es_object_get_type (kind) != OPT_TYPE_NAME)
32627b347e74SMasatake YAMATO return OPT_ERR_TYPECHECK;
32637b347e74SMasatake YAMATO EsObject *kind_sym = es_pointer_get (kind);
32647b347e74SMasatake YAMATO const char *kind_str = es_symbol_get (kind_sym);
32657b347e74SMasatake YAMATO langType lang = getInputLanguage ();
32667b347e74SMasatake YAMATO kindDefinition* kind_def = getLanguageKindForName (lang, kind_str);
32677b347e74SMasatake YAMATO if (!kind_def)
32687b347e74SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNKIND;
32697b347e74SMasatake YAMATO int kind_index = kind_def->id;
32707b347e74SMasatake YAMATO
32717b347e74SMasatake YAMATO EsObject *role_sym = es_pointer_get (role);
32727b347e74SMasatake YAMATO const char *role_str = es_symbol_get (role_sym);
32737b347e74SMasatake YAMATO roleDefinition* role_def = getLanguageRoleForName (lang, kind_index, role_str);
32747b347e74SMasatake YAMATO if (!role_def)
32757b347e74SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNROLE;
32767b347e74SMasatake YAMATO int role_index = role_def->id;
32777b347e74SMasatake YAMATO
32787b347e74SMasatake YAMATO EsObject *tname = opt_vm_ostack_peek (vm, index++);
32797b347e74SMasatake YAMATO if (es_object_get_type (tname) != OPT_TYPE_STRING)
32807b347e74SMasatake YAMATO return OPT_ERR_TYPECHECK;
32817b347e74SMasatake YAMATO const char *n = opt_string_get_cstr (tname);
32827b347e74SMasatake YAMATO if (n [0] == '\0')
3283820e8cc6SMasatake YAMATO return OPT_ERR_RANGECHECK; /* TODO */
32847b347e74SMasatake YAMATO
32857b347e74SMasatake YAMATO tagEntryInfo *e = xMalloc (1, tagEntryInfo);
32867b347e74SMasatake YAMATO initRegexTag (e, eStrdup (n),
32877b347e74SMasatake YAMATO kind_index, role_index, CORK_NIL, 0,
32887b347e74SMasatake YAMATO loc? loc->line: 0, loc? &loc->pos: NULL,
32897b347e74SMasatake YAMATO role_index == ROLE_DEFINITION_INDEX
32907b347e74SMasatake YAMATO ? XTAG_UNKNOWN
32917b347e74SMasatake YAMATO : XTAG_REFERENCE_TAGS);
32927b347e74SMasatake YAMATO EsObject *obj = es_pointer_new (OPT_TYPE_TAG, e);
32937b347e74SMasatake YAMATO if (es_error_p (obj))
32947b347e74SMasatake YAMATO return obj;
32957b347e74SMasatake YAMATO
32967b347e74SMasatake YAMATO while (index-- > 0)
32977b347e74SMasatake YAMATO opt_vm_ostack_pop (vm);
32987b347e74SMasatake YAMATO
32997b347e74SMasatake YAMATO opt_vm_ostack_push (vm, obj);
33007b347e74SMasatake YAMATO es_object_unref (obj);
33017b347e74SMasatake YAMATO return es_false;
33027b347e74SMasatake YAMATO }
33037b347e74SMasatake YAMATO
330434deb294SMasatake YAMATO /* tag COMMIT int */
lrop_commit_tag(OptVM * vm,EsObject * name)330534deb294SMasatake YAMATO static EsObject* lrop_commit_tag (OptVM *vm, EsObject *name)
330634deb294SMasatake YAMATO {
330734deb294SMasatake YAMATO EsObject *tag = opt_vm_ostack_top (vm);
330834deb294SMasatake YAMATO if (es_object_get_type (tag) != OPT_TYPE_TAG)
330934deb294SMasatake YAMATO return OPT_ERR_TYPECHECK;
331034deb294SMasatake YAMATO
331134deb294SMasatake YAMATO tagEntryInfo *e = es_pointer_get (tag);
331234deb294SMasatake YAMATO int corkIndex = makeTagEntry (e);
331334deb294SMasatake YAMATO EsObject *n = es_integer_new (corkIndex);
331434deb294SMasatake YAMATO if (es_error_p (n))
331534deb294SMasatake YAMATO return n;
331634deb294SMasatake YAMATO opt_vm_ostack_pop (vm);
331734deb294SMasatake YAMATO opt_vm_ostack_push (vm, n);
331834deb294SMasatake YAMATO es_object_unref (n);
331934deb294SMasatake YAMATO return es_false;
332034deb294SMasatake YAMATO }
332134deb294SMasatake YAMATO
lrop_get_match_loc(OptVM * vm,EsObject * name)3322ed3202bdSMasatake YAMATO static EsObject* lrop_get_match_loc (OptVM *vm, EsObject *name)
3323ed3202bdSMasatake YAMATO {
3324ed3202bdSMasatake YAMATO
3325ed3202bdSMasatake YAMATO bool start;
3326ed3202bdSMasatake YAMATO EsObject *group;
3327ed3202bdSMasatake YAMATO
3328ed3202bdSMasatake YAMATO if (opt_vm_ostack_count (vm) < 1)
3329ed3202bdSMasatake YAMATO return OPT_ERR_UNDERFLOW;
3330ed3202bdSMasatake YAMATO
3331ed3202bdSMasatake YAMATO EsObject *tmp = opt_vm_ostack_top (vm);
3332ed3202bdSMasatake YAMATO
3333ed3202bdSMasatake YAMATO if (es_object_get_type (tmp) == ES_TYPE_INTEGER)
3334ed3202bdSMasatake YAMATO {
3335ed3202bdSMasatake YAMATO group = tmp;
3336ed3202bdSMasatake YAMATO start = true;
3337ed3202bdSMasatake YAMATO }
3338ed3202bdSMasatake YAMATO else
3339ed3202bdSMasatake YAMATO {
3340ed3202bdSMasatake YAMATO EsObject *pos = tmp;
3341ed3202bdSMasatake YAMATO
3342ed3202bdSMasatake YAMATO static EsObject *start_name, *end_name;
3343ed3202bdSMasatake YAMATO if (!start_name)
3344ed3202bdSMasatake YAMATO {
3345ed3202bdSMasatake YAMATO start_name = opt_name_new_from_cstr ("start");
3346ed3202bdSMasatake YAMATO end_name = opt_name_new_from_cstr ("end");
3347ed3202bdSMasatake YAMATO }
3348ed3202bdSMasatake YAMATO
3349ed3202bdSMasatake YAMATO if (es_object_equal (pos, start_name))
3350ed3202bdSMasatake YAMATO start = true;
3351ed3202bdSMasatake YAMATO else if (es_object_equal (pos, end_name))
3352ed3202bdSMasatake YAMATO start = false;
3353ed3202bdSMasatake YAMATO else
3354ed3202bdSMasatake YAMATO return OPT_ERR_TYPECHECK;
3355ed3202bdSMasatake YAMATO
3356ed3202bdSMasatake YAMATO if (opt_vm_ostack_count (vm) < 2)
3357ed3202bdSMasatake YAMATO return OPT_ERR_UNDERFLOW;
3358ed3202bdSMasatake YAMATO
3359ed3202bdSMasatake YAMATO group = opt_vm_ostack_peek (vm, 1);
3360ed3202bdSMasatake YAMATO if (es_object_get_type (group) != ES_TYPE_INTEGER)
3361ed3202bdSMasatake YAMATO return OPT_ERR_TYPECHECK;
3362ed3202bdSMasatake YAMATO }
3363ed3202bdSMasatake YAMATO
3364ed3202bdSMasatake YAMATO int g = es_integer_get (group);
3365ed3202bdSMasatake YAMATO if (g < 1)
3366ed3202bdSMasatake YAMATO return OPT_ERR_RANGECHECK;
3367ed3202bdSMasatake YAMATO
3368ed3202bdSMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
3369ed3202bdSMasatake YAMATO scriptWindow *window = lcb->window;
3370ed3202bdSMasatake YAMATO
3371cf6b3bb9SMasatake YAMATO matchLoc *mloc = make_mloc (window, g, start);
3372cf6b3bb9SMasatake YAMATO if (mloc == NULL)
3373ed3202bdSMasatake YAMATO return OPT_ERR_RANGECHECK;
3374ed3202bdSMasatake YAMATO
3375ed3202bdSMasatake YAMATO EsObject * mlocobj = es_pointer_new (OPT_TYPE_MATCHLOC, mloc);
3376ed3202bdSMasatake YAMATO if (es_error_p (mlocobj))
3377e02e1d1fSMasatake YAMATO {
3378e02e1d1fSMasatake YAMATO eFree (mloc);
3379ed3202bdSMasatake YAMATO return mlocobj;
3380e02e1d1fSMasatake YAMATO }
3381ed3202bdSMasatake YAMATO
3382ed3202bdSMasatake YAMATO if (group != tmp)
3383ed3202bdSMasatake YAMATO opt_vm_ostack_pop (vm);
3384ed3202bdSMasatake YAMATO opt_vm_ostack_pop (vm);
3385ed3202bdSMasatake YAMATO opt_vm_ostack_push (vm, mlocobj);
3386ed3202bdSMasatake YAMATO es_object_unref (mlocobj);
3387ed3202bdSMasatake YAMATO return es_false;
3388ed3202bdSMasatake YAMATO }
3389ed3202bdSMasatake YAMATO
ldrop_get_line_from_matchloc(OptVM * vm,EsObject * name)33901481c2d1SMasatake YAMATO static EsObject* ldrop_get_line_from_matchloc (OptVM *vm, EsObject *name)
33911481c2d1SMasatake YAMATO {
33921481c2d1SMasatake YAMATO EsObject *mlocobj = opt_vm_ostack_top (vm);
33931481c2d1SMasatake YAMATO if (es_object_get_type (mlocobj) != OPT_TYPE_MATCHLOC)
33941481c2d1SMasatake YAMATO return OPT_ERR_TYPECHECK;
33951481c2d1SMasatake YAMATO
33961481c2d1SMasatake YAMATO matchLoc *mloc = es_pointer_get (mlocobj);
33971481c2d1SMasatake YAMATO EsObject *lineobj = es_integer_new (mloc->line);
33981481c2d1SMasatake YAMATO if (es_error_p (lineobj))
33991481c2d1SMasatake YAMATO return lineobj;
34001481c2d1SMasatake YAMATO
34011481c2d1SMasatake YAMATO opt_vm_ostack_pop (vm);
34021481c2d1SMasatake YAMATO opt_vm_ostack_push (vm, lineobj);
34031481c2d1SMasatake YAMATO es_object_unref (lineobj);
34041481c2d1SMasatake YAMATO return es_false;
34051481c2d1SMasatake YAMATO }
34061481c2d1SMasatake YAMATO
make_mloc_from_tagEntryInfo(tagEntryInfo * e)340720b300feSMasatake YAMATO static matchLoc* make_mloc_from_tagEntryInfo(tagEntryInfo *e)
340820b300feSMasatake YAMATO {
340920b300feSMasatake YAMATO matchLoc *mloc = xMalloc (1, matchLoc);
341020b300feSMasatake YAMATO mloc->delta = 0;
341120b300feSMasatake YAMATO mloc->line = e->lineNumber;
341220b300feSMasatake YAMATO mloc->pos = e->filePosition;
341320b300feSMasatake YAMATO
341420b300feSMasatake YAMATO return mloc;
341520b300feSMasatake YAMATO }
341620b300feSMasatake YAMATO
lrop_get_tag_loc(OptVM * vm,EsObject * name)341720b300feSMasatake YAMATO static EsObject* lrop_get_tag_loc (OptVM *vm, EsObject *name)
341820b300feSMasatake YAMATO {
341920b300feSMasatake YAMATO EsObject *nobj = opt_vm_ostack_top (vm);
342020b300feSMasatake YAMATO
342120b300feSMasatake YAMATO if (es_object_get_type (nobj) != ES_TYPE_INTEGER)
342220b300feSMasatake YAMATO return OPT_ERR_TYPECHECK;
342320b300feSMasatake YAMATO
342420b300feSMasatake YAMATO int n = es_integer_get(nobj);
342520b300feSMasatake YAMATO if (! (CORK_NIL < n && n < countEntryInCorkQueue()))
342620b300feSMasatake YAMATO return OPT_ERR_RANGECHECK;
342720b300feSMasatake YAMATO
342820b300feSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (n);
342920b300feSMasatake YAMATO if (e == NULL)
343020b300feSMasatake YAMATO return OPT_ERR_TYPECHECK; /* ??? */
343120b300feSMasatake YAMATO
343220b300feSMasatake YAMATO matchLoc *mloc = make_mloc_from_tagEntryInfo (e);
343320b300feSMasatake YAMATO EsObject * mlocobj = es_pointer_new (OPT_TYPE_MATCHLOC, mloc);
343420b300feSMasatake YAMATO if (es_error_p (mlocobj))
343520b300feSMasatake YAMATO {
343620b300feSMasatake YAMATO eFree (mloc);
343720b300feSMasatake YAMATO return mlocobj;
343820b300feSMasatake YAMATO }
343920b300feSMasatake YAMATO
344020b300feSMasatake YAMATO opt_vm_ostack_pop (vm);
344120b300feSMasatake YAMATO opt_vm_ostack_push (vm, mlocobj);
344220b300feSMasatake YAMATO es_object_unref (mlocobj);
344320b300feSMasatake YAMATO return es_false;
344420b300feSMasatake YAMATO }
344520b300feSMasatake YAMATO
lrop_get_match_string_common(OptVM * vm,int i,int npop)34461908e776SMasatake YAMATO static EsObject* lrop_get_match_string_common (OptVM *vm, int i, int npop)
34472bbd136eSMasatake YAMATO {
34482bbd136eSMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
34492bbd136eSMasatake YAMATO scriptWindow *window = lcb->window;
345077bd99b5SMasatake YAMATO const char *cstr = make_match_string (window, i);
345177bd99b5SMasatake YAMATO if (!cstr)
34522bbd136eSMasatake YAMATO {
34531908e776SMasatake YAMATO for (; npop > 0; npop--)
34541908e776SMasatake YAMATO opt_vm_ostack_pop (vm);
34552bbd136eSMasatake YAMATO opt_vm_ostack_push (vm, es_false);
34562bbd136eSMasatake YAMATO return es_false;
34572bbd136eSMasatake YAMATO }
34582bbd136eSMasatake YAMATO EsObject *str = opt_string_new_from_cstr (cstr);
34592bbd136eSMasatake YAMATO eFree ((void *)cstr);
34602bbd136eSMasatake YAMATO
34611908e776SMasatake YAMATO for (; npop > 0; npop--)
34621908e776SMasatake YAMATO opt_vm_ostack_pop (vm);
34631908e776SMasatake YAMATO
34642bbd136eSMasatake YAMATO opt_vm_ostack_push (vm, str);
34652bbd136eSMasatake YAMATO es_object_unref (str);
34662bbd136eSMasatake YAMATO return es_false;
34672bbd136eSMasatake YAMATO }
34682bbd136eSMasatake YAMATO
34691908e776SMasatake YAMATO /* Handles \1, \2, ... */
lrop_get_match_string_named_group(OptVM * vm,EsObject * name)34701908e776SMasatake YAMATO static EsObject* lrop_get_match_string_named_group (OptVM *vm, EsObject *name)
34711908e776SMasatake YAMATO {
34721908e776SMasatake YAMATO void * data = es_symbol_get_data (name);
34731908e776SMasatake YAMATO int i = HT_PTR_TO_INT (data);
34741908e776SMasatake YAMATO
34751908e776SMasatake YAMATO return lrop_get_match_string_common (vm, i, 0);
34761908e776SMasatake YAMATO }
34771908e776SMasatake YAMATO
lrop_get_match_string_group_on_stack(OptVM * vm,EsObject * name)3478df8d88a5SMasatake YAMATO static EsObject* lrop_get_match_string_group_on_stack (OptVM *vm, EsObject *name)
34791908e776SMasatake YAMATO {
34801908e776SMasatake YAMATO EsObject *group = opt_vm_ostack_top (vm);
34811908e776SMasatake YAMATO if (!es_integer_p (group))
34821908e776SMasatake YAMATO return OPT_ERR_TYPECHECK;
34831908e776SMasatake YAMATO
34841908e776SMasatake YAMATO int g = es_integer_get (group);
34851908e776SMasatake YAMATO if (g < 1)
34861908e776SMasatake YAMATO return OPT_ERR_RANGECHECK;
34871908e776SMasatake YAMATO
34881908e776SMasatake YAMATO EsObject *r = lrop_get_match_string_common (vm, g, 1);
34891908e776SMasatake YAMATO if (es_error_p (r))
34901908e776SMasatake YAMATO return r;
34911908e776SMasatake YAMATO
34921908e776SMasatake YAMATO r = opt_vm_ostack_top (vm);
34931908e776SMasatake YAMATO if (es_object_get_type (r) == OPT_TYPE_STRING)
34941908e776SMasatake YAMATO opt_vm_ostack_push (vm, es_true);
34951908e776SMasatake YAMATO return es_false;
34961908e776SMasatake YAMATO }
34971908e776SMasatake YAMATO
make_match_string(scriptWindow * window,int group)349877bd99b5SMasatake YAMATO static char* make_match_string (scriptWindow *window, int group)
349977bd99b5SMasatake YAMATO {
350077bd99b5SMasatake YAMATO if (window == NULL
350177bd99b5SMasatake YAMATO || 0 >= group
350277bd99b5SMasatake YAMATO || window->nmatch <= group
350377bd99b5SMasatake YAMATO || window->pmatch [group].rm_so == -1)
350477bd99b5SMasatake YAMATO return NULL;
350577bd99b5SMasatake YAMATO
350677bd99b5SMasatake YAMATO const int len = window->pmatch [group].rm_eo - window->pmatch [group].rm_so;
350777bd99b5SMasatake YAMATO const char *start = window->line + window->pmatch [group].rm_so;
350877bd99b5SMasatake YAMATO
350977bd99b5SMasatake YAMATO return eStrndup (start, len);
351077bd99b5SMasatake YAMATO }
351177bd99b5SMasatake YAMATO
make_mloc(scriptWindow * window,int group,bool start)3512cf6b3bb9SMasatake YAMATO static matchLoc *make_mloc (scriptWindow *window, int group, bool start)
3513cf6b3bb9SMasatake YAMATO {
3514cf6b3bb9SMasatake YAMATO if (window == NULL
3515cf6b3bb9SMasatake YAMATO || 0 > group
3516cf6b3bb9SMasatake YAMATO || window->nmatch <= group
3517cf6b3bb9SMasatake YAMATO || window->pmatch [group].rm_so == -1)
3518cf6b3bb9SMasatake YAMATO return NULL;
3519cf6b3bb9SMasatake YAMATO
3520cf6b3bb9SMasatake YAMATO matchLoc *mloc = xMalloc (1, matchLoc);
3521cf6b3bb9SMasatake YAMATO if (window->patbuf->regptype == REG_PARSER_SINGLE_LINE)
3522cf6b3bb9SMasatake YAMATO {
3523cf6b3bb9SMasatake YAMATO mloc->delta = 0;
3524cf6b3bb9SMasatake YAMATO mloc->line = getInputLineNumber ();
3525cf6b3bb9SMasatake YAMATO mloc->pos = getInputFilePosition ();
3526cf6b3bb9SMasatake YAMATO }
3527cf6b3bb9SMasatake YAMATO else
3528cf6b3bb9SMasatake YAMATO {
3529cf6b3bb9SMasatake YAMATO mloc->delta = (start
3530cf6b3bb9SMasatake YAMATO ? window->pmatch [group].rm_so
3531cf6b3bb9SMasatake YAMATO : window->pmatch [group].rm_eo);
3532cf6b3bb9SMasatake YAMATO off_t offset = (window->line + mloc->delta) - window->start;
3533cf6b3bb9SMasatake YAMATO mloc->line = getInputLineNumberForFileOffset (offset);
3534cf6b3bb9SMasatake YAMATO mloc->pos = getInputFilePositionForLine (mloc->line);
3535cf6b3bb9SMasatake YAMATO }
3536cf6b3bb9SMasatake YAMATO return mloc;
3537cf6b3bb9SMasatake YAMATO }
3538cf6b3bb9SMasatake YAMATO
lrop_set_scope(OptVM * vm,EsObject * name)35397f9e4f22SMasatake YAMATO static EsObject* lrop_set_scope (OptVM *vm, EsObject *name)
35407f9e4f22SMasatake YAMATO {
35417f9e4f22SMasatake YAMATO EsObject *corkIndex = opt_vm_ostack_top (vm);
35427f9e4f22SMasatake YAMATO if (!es_integer_p (corkIndex))
35437f9e4f22SMasatake YAMATO return OPT_ERR_TYPECHECK;
35447f9e4f22SMasatake YAMATO
35457f9e4f22SMasatake YAMATO int n = es_integer_get (corkIndex);
35467f9e4f22SMasatake YAMATO if (n < 0)
35477f9e4f22SMasatake YAMATO return OPT_ERR_RANGECHECK;
35487f9e4f22SMasatake YAMATO
35497f9e4f22SMasatake YAMATO if (n >= countEntryInCorkQueue())
35507f9e4f22SMasatake YAMATO return OPT_ERR_RANGECHECK;
35517f9e4f22SMasatake YAMATO
35527f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
35537f9e4f22SMasatake YAMATO lcb->currentScope = n;
35547f9e4f22SMasatake YAMATO
35557f9e4f22SMasatake YAMATO opt_vm_ostack_pop (vm);
35567f9e4f22SMasatake YAMATO
35577f9e4f22SMasatake YAMATO return es_false;
35587f9e4f22SMasatake YAMATO }
35597f9e4f22SMasatake YAMATO
lrop_pop_scope(OptVM * vm,EsObject * name)35607f9e4f22SMasatake YAMATO static EsObject* lrop_pop_scope (OptVM *vm, EsObject *name)
35617f9e4f22SMasatake YAMATO {
35627f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
35637f9e4f22SMasatake YAMATO if (lcb->currentScope != CORK_NIL)
35647f9e4f22SMasatake YAMATO {
35657f9e4f22SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (lcb->currentScope);
35667f9e4f22SMasatake YAMATO if (e)
35677f9e4f22SMasatake YAMATO lcb->currentScope = e->extensionFields.scopeIndex;
35687f9e4f22SMasatake YAMATO }
35697f9e4f22SMasatake YAMATO return es_false;
35707f9e4f22SMasatake YAMATO }
35717f9e4f22SMasatake YAMATO
lrop_clear_scope(OptVM * vm,EsObject * name)35727f9e4f22SMasatake YAMATO static EsObject* lrop_clear_scope (OptVM *vm, EsObject *name)
35737f9e4f22SMasatake YAMATO {
35747f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
35757f9e4f22SMasatake YAMATO lcb->currentScope = CORK_NIL;
35767f9e4f22SMasatake YAMATO return es_false;
35777f9e4f22SMasatake YAMATO }
35787f9e4f22SMasatake YAMATO
lrop_ref0_scope(OptVM * vm,EsObject * name)35797f9e4f22SMasatake YAMATO static EsObject* lrop_ref0_scope (OptVM *vm, EsObject *name)
35807f9e4f22SMasatake YAMATO {
35817f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
35827f9e4f22SMasatake YAMATO
35837f9e4f22SMasatake YAMATO if (lcb->currentScope == 0)
35847f9e4f22SMasatake YAMATO {
35857f9e4f22SMasatake YAMATO opt_vm_ostack_push (vm, es_false);
35867f9e4f22SMasatake YAMATO return es_false;
35877f9e4f22SMasatake YAMATO }
35887f9e4f22SMasatake YAMATO
35897f9e4f22SMasatake YAMATO EsObject *q = es_integer_new (lcb->currentScope);
35907f9e4f22SMasatake YAMATO
35917f9e4f22SMasatake YAMATO if (es_error_p (q))
35927f9e4f22SMasatake YAMATO return q;
35937f9e4f22SMasatake YAMATO
35947f9e4f22SMasatake YAMATO opt_vm_ostack_push (vm, q);
35957f9e4f22SMasatake YAMATO es_object_unref (q);
35967f9e4f22SMasatake YAMATO opt_vm_ostack_push (vm, es_true);
35977f9e4f22SMasatake YAMATO return es_false;
35987f9e4f22SMasatake YAMATO }
35997f9e4f22SMasatake YAMATO
lrop_refN_scope(OptVM * vm,EsObject * name)36007f9e4f22SMasatake YAMATO static EsObject* lrop_refN_scope (OptVM *vm, EsObject *name)
36017f9e4f22SMasatake YAMATO {
36027f9e4f22SMasatake YAMATO EsObject *nobj = opt_vm_ostack_top (vm);
36037f9e4f22SMasatake YAMATO if (!es_integer_p (nobj))
36047f9e4f22SMasatake YAMATO return OPT_ERR_TYPECHECK;
36057f9e4f22SMasatake YAMATO
36067f9e4f22SMasatake YAMATO int n = es_integer_get(nobj);
36077f9e4f22SMasatake YAMATO
36087f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
36097f9e4f22SMasatake YAMATO int scope = lcb->currentScope;
36107f9e4f22SMasatake YAMATO
36117f9e4f22SMasatake YAMATO while (n--)
36127f9e4f22SMasatake YAMATO {
36137f9e4f22SMasatake YAMATO if (scope == CORK_NIL)
36147f9e4f22SMasatake YAMATO break;
36157f9e4f22SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scope);
36167f9e4f22SMasatake YAMATO if (e == NULL)
36177f9e4f22SMasatake YAMATO break;
36187f9e4f22SMasatake YAMATO
36197f9e4f22SMasatake YAMATO scope = e->extensionFields.scopeIndex;
36207f9e4f22SMasatake YAMATO }
36217f9e4f22SMasatake YAMATO
36227f9e4f22SMasatake YAMATO EsObject *q = es_integer_new (scope);
36237f9e4f22SMasatake YAMATO if (es_error_p(q))
36247f9e4f22SMasatake YAMATO return q;
36257f9e4f22SMasatake YAMATO
36267f9e4f22SMasatake YAMATO opt_vm_ostack_pop (vm);
36277f9e4f22SMasatake YAMATO opt_vm_ostack_push (vm, q);
36287f9e4f22SMasatake YAMATO es_object_unref (q);
36297f9e4f22SMasatake YAMATO
36307f9e4f22SMasatake YAMATO return es_false;
36317f9e4f22SMasatake YAMATO }
36327f9e4f22SMasatake YAMATO
lrop_get_scope_depth(OptVM * vm,EsObject * name)36337f9e4f22SMasatake YAMATO static EsObject* lrop_get_scope_depth (OptVM *vm, EsObject *name)
36347f9e4f22SMasatake YAMATO {
36357f9e4f22SMasatake YAMATO int n = 0;
36367f9e4f22SMasatake YAMATO
36377f9e4f22SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
36387f9e4f22SMasatake YAMATO int scope = lcb->currentScope;
36397f9e4f22SMasatake YAMATO
36407f9e4f22SMasatake YAMATO while (scope != CORK_NIL)
36417f9e4f22SMasatake YAMATO {
36427f9e4f22SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scope);
36437f9e4f22SMasatake YAMATO if (!e)
36447f9e4f22SMasatake YAMATO break;
36457f9e4f22SMasatake YAMATO
36467f9e4f22SMasatake YAMATO scope = e->extensionFields.scopeIndex;
36477f9e4f22SMasatake YAMATO n++;
36487f9e4f22SMasatake YAMATO }
36497f9e4f22SMasatake YAMATO
36507f9e4f22SMasatake YAMATO EsObject *q = es_integer_new (scope);
36517f9e4f22SMasatake YAMATO if (es_error_p(q))
36527f9e4f22SMasatake YAMATO return q;
36537f9e4f22SMasatake YAMATO
36547f9e4f22SMasatake YAMATO opt_vm_ostack_push (vm, q);
36557f9e4f22SMasatake YAMATO es_object_unref (q);
36567f9e4f22SMasatake YAMATO return es_false;
36577f9e4f22SMasatake YAMATO }
36587f9e4f22SMasatake YAMATO
lrop_repl(OptVM * vm,EsObject * name)365954bd7b53SMasatake YAMATO static EsObject* lrop_repl (OptVM *vm, EsObject *name)
366054bd7b53SMasatake YAMATO {
366154bd7b53SMasatake YAMATO char *old_prompt = opt_vm_set_prompt (vm, "\n% type \"quit\" for exiting from repl\nOPT");
366254bd7b53SMasatake YAMATO
366354bd7b53SMasatake YAMATO opt_vm_print_prompt (vm);
366454bd7b53SMasatake YAMATO opt_vm_set_prompt (vm, "OPT");
366554bd7b53SMasatake YAMATO
366654bd7b53SMasatake YAMATO while (true)
366754bd7b53SMasatake YAMATO {
366854bd7b53SMasatake YAMATO EsObject *o = opt_vm_read (vm, NULL);
366954bd7b53SMasatake YAMATO if (es_object_equal (o, ES_READER_EOF))
367054bd7b53SMasatake YAMATO {
367154bd7b53SMasatake YAMATO es_object_unref (o);
367254bd7b53SMasatake YAMATO break;
367354bd7b53SMasatake YAMATO }
367454bd7b53SMasatake YAMATO EsObject *e = opt_vm_eval (vm, o);
367554bd7b53SMasatake YAMATO es_object_unref (o);
367654bd7b53SMasatake YAMATO
367754bd7b53SMasatake YAMATO if (es_error_p (e))
367854bd7b53SMasatake YAMATO {
367954bd7b53SMasatake YAMATO if (!es_object_equal (e, OPT_ERR_QUIT))
368054bd7b53SMasatake YAMATO opt_vm_report_error (vm, e, NULL);
368154bd7b53SMasatake YAMATO break;
368254bd7b53SMasatake YAMATO }
368354bd7b53SMasatake YAMATO }
368454bd7b53SMasatake YAMATO
368554bd7b53SMasatake YAMATO opt_vm_set_prompt (vm, old_prompt);
368654bd7b53SMasatake YAMATO return es_false;
368754bd7b53SMasatake YAMATO }
368854bd7b53SMasatake YAMATO
36892b8d4c66SMasatake YAMATO static EsObject *OPTSCRIPT_ERR_UNKNOWNTABLE;
36902b8d4c66SMasatake YAMATO static EsObject *OPTSCRIPT_ERR_NOTMTABLEPTRN;
36912b8d4c66SMasatake YAMATO
getRegexTableForOptscriptName(struct lregexControlBlock * lcb,EsObject * tableName)36922b8d4c66SMasatake YAMATO static struct regexTable *getRegexTableForOptscriptName (struct lregexControlBlock *lcb,
36932b8d4c66SMasatake YAMATO EsObject *tableName)
36942b8d4c66SMasatake YAMATO {
36952b8d4c66SMasatake YAMATO EsObject *table_sym = es_pointer_get (tableName);
36962b8d4c66SMasatake YAMATO const char *table_str = es_symbol_get (table_sym);
36972b8d4c66SMasatake YAMATO int n = getTableIndexForName (lcb, table_str);
36982b8d4c66SMasatake YAMATO if (n < 0)
36992b8d4c66SMasatake YAMATO return NULL;
37002b8d4c66SMasatake YAMATO return ptrArrayItem (lcb->tables, n);
37012b8d4c66SMasatake YAMATO }
37022b8d4c66SMasatake YAMATO
lrop_tenter_common(OptVM * vm,EsObject * name,enum tableAction action)37032b8d4c66SMasatake YAMATO static EsObject* lrop_tenter_common (OptVM *vm, EsObject *name, enum tableAction action)
37042b8d4c66SMasatake YAMATO {
37052b8d4c66SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
37062b8d4c66SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_MULTI_TABLE)
37072b8d4c66SMasatake YAMATO {
37082b8d4c66SMasatake YAMATO error (WARNING, "Use table related operators only with mtable regular expression");
37092b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_NOTMTABLEPTRN;
37102b8d4c66SMasatake YAMATO }
37112b8d4c66SMasatake YAMATO
37122b8d4c66SMasatake YAMATO EsObject *table = opt_vm_ostack_top (vm);
37132b8d4c66SMasatake YAMATO if (es_object_get_type (table) != OPT_TYPE_NAME)
37142b8d4c66SMasatake YAMATO return OPT_ERR_TYPECHECK;
37152b8d4c66SMasatake YAMATO
37162b8d4c66SMasatake YAMATO struct regexTable *t = getRegexTableForOptscriptName (lcb, table);
37172b8d4c66SMasatake YAMATO if (t == NULL)
37182b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNTABLE;
37192b8d4c66SMasatake YAMATO
37202b8d4c66SMasatake YAMATO lcb->window->taction = (struct mTableActionSpec){
37212b8d4c66SMasatake YAMATO .action = action,
37222b8d4c66SMasatake YAMATO .table = t,
37232b8d4c66SMasatake YAMATO .continuation_table = NULL,
37242b8d4c66SMasatake YAMATO };
37252b8d4c66SMasatake YAMATO
37262b8d4c66SMasatake YAMATO opt_vm_ostack_pop (vm);
37272b8d4c66SMasatake YAMATO return es_false;
37282b8d4c66SMasatake YAMATO }
37292b8d4c66SMasatake YAMATO
lrop_tenter(OptVM * vm,EsObject * name)37302b8d4c66SMasatake YAMATO static EsObject* lrop_tenter (OptVM *vm, EsObject *name)
37312b8d4c66SMasatake YAMATO {
37322b8d4c66SMasatake YAMATO return lrop_tenter_common (vm, name, TACTION_ENTER);
37332b8d4c66SMasatake YAMATO }
37342b8d4c66SMasatake YAMATO
lrop_tenter_with_continuation(OptVM * vm,EsObject * name)37352b8d4c66SMasatake YAMATO static EsObject* lrop_tenter_with_continuation (OptVM *vm, EsObject *name)
37362b8d4c66SMasatake YAMATO {
37372b8d4c66SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
37382b8d4c66SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_MULTI_TABLE)
37392b8d4c66SMasatake YAMATO {
37402b8d4c66SMasatake YAMATO error (WARNING, "Use table related operators only with mtable regular expression");
37412b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_NOTMTABLEPTRN;
37422b8d4c66SMasatake YAMATO }
37432b8d4c66SMasatake YAMATO
37442b8d4c66SMasatake YAMATO EsObject *cont = opt_vm_ostack_top (vm);
37452b8d4c66SMasatake YAMATO EsObject *table = opt_vm_ostack_peek (vm, 1);
37462b8d4c66SMasatake YAMATO
37472b8d4c66SMasatake YAMATO if (es_object_get_type (table) != OPT_TYPE_NAME)
37482b8d4c66SMasatake YAMATO return OPT_ERR_TYPECHECK;
37492b8d4c66SMasatake YAMATO if (es_object_get_type (cont) != OPT_TYPE_NAME)
37502b8d4c66SMasatake YAMATO return OPT_ERR_TYPECHECK;
37512b8d4c66SMasatake YAMATO
37522b8d4c66SMasatake YAMATO struct regexTable *t = getRegexTableForOptscriptName (lcb, table);
37532b8d4c66SMasatake YAMATO if (t == NULL)
37542b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNTABLE;
37552b8d4c66SMasatake YAMATO struct regexTable *c = getRegexTableForOptscriptName (lcb, cont);
37562b8d4c66SMasatake YAMATO if (c == NULL)
37572b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNTABLE;
37582b8d4c66SMasatake YAMATO
37592b8d4c66SMasatake YAMATO lcb->window->taction = (struct mTableActionSpec){
37602b8d4c66SMasatake YAMATO .action = TACTION_ENTER,
37612b8d4c66SMasatake YAMATO .table = t,
37622b8d4c66SMasatake YAMATO .continuation_table = c,
37632b8d4c66SMasatake YAMATO };
37642b8d4c66SMasatake YAMATO
37652b8d4c66SMasatake YAMATO opt_vm_ostack_pop (vm);
37662b8d4c66SMasatake YAMATO opt_vm_ostack_pop (vm);
37672b8d4c66SMasatake YAMATO return es_false;
37682b8d4c66SMasatake YAMATO }
37692b8d4c66SMasatake YAMATO
lrop_tleave(OptVM * vm,EsObject * name)37702b8d4c66SMasatake YAMATO static EsObject* lrop_tleave (OptVM *vm, EsObject *name)
37712b8d4c66SMasatake YAMATO {
37722b8d4c66SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
37732b8d4c66SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_MULTI_TABLE)
37742b8d4c66SMasatake YAMATO {
37752b8d4c66SMasatake YAMATO error (WARNING, "Use table related operators only with mtable regular expression");
37762b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_NOTMTABLEPTRN;
37772b8d4c66SMasatake YAMATO }
37782b8d4c66SMasatake YAMATO
37792b8d4c66SMasatake YAMATO lcb->window->taction.action = TACTION_LEAVE;
37802b8d4c66SMasatake YAMATO return es_false;
37812b8d4c66SMasatake YAMATO }
37822b8d4c66SMasatake YAMATO
lrop_tjump(OptVM * vm,EsObject * name)37832b8d4c66SMasatake YAMATO static EsObject* lrop_tjump (OptVM *vm, EsObject *name)
37842b8d4c66SMasatake YAMATO {
37852b8d4c66SMasatake YAMATO return lrop_tenter_common (vm, name, TACTION_JUMP);
37862b8d4c66SMasatake YAMATO }
37872b8d4c66SMasatake YAMATO
lrop_treset(OptVM * vm,EsObject * name)37882b8d4c66SMasatake YAMATO static EsObject* lrop_treset (OptVM *vm, EsObject *name)
37892b8d4c66SMasatake YAMATO {
37902b8d4c66SMasatake YAMATO return lrop_tenter_common (vm, name, TACTION_RESET);
37912b8d4c66SMasatake YAMATO }
37922b8d4c66SMasatake YAMATO
lrop_tquit(OptVM * vm,EsObject * name)37932b8d4c66SMasatake YAMATO static EsObject* lrop_tquit (OptVM *vm, EsObject *name)
37942b8d4c66SMasatake YAMATO {
37952b8d4c66SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
37962b8d4c66SMasatake YAMATO if (lcb->window->patbuf->regptype != REG_PARSER_MULTI_TABLE)
37972b8d4c66SMasatake YAMATO {
37982b8d4c66SMasatake YAMATO error (WARNING, "Use table related operators only with mtable regular expression");
37992b8d4c66SMasatake YAMATO return OPTSCRIPT_ERR_NOTMTABLEPTRN;
38002b8d4c66SMasatake YAMATO }
38012b8d4c66SMasatake YAMATO
38022b8d4c66SMasatake YAMATO lcb->window->taction.action = TACTION_QUIT;
38032b8d4c66SMasatake YAMATO return es_false;
38042b8d4c66SMasatake YAMATO }
38052b8d4c66SMasatake YAMATO
lrop_traced(OptVM * vm,EsObject * name)380685021c5bSMasatake YAMATO static EsObject* lrop_traced (OptVM *vm, EsObject *name)
380785021c5bSMasatake YAMATO {
380885021c5bSMasatake YAMATO #ifdef DO_TRACING
380985021c5bSMasatake YAMATO langType lang = getInputLanguage ();
381085021c5bSMasatake YAMATO if (isLanguageTraced (lang))
381185021c5bSMasatake YAMATO opt_vm_ostack_push (vm, es_true);
381285021c5bSMasatake YAMATO else
381385021c5bSMasatake YAMATO opt_vm_ostack_push (vm, es_false);
381485021c5bSMasatake YAMATO #else
381585021c5bSMasatake YAMATO opt_vm_ostack_push (vm, es_false);
381685021c5bSMasatake YAMATO #endif
381785021c5bSMasatake YAMATO return false;
381885021c5bSMasatake YAMATO }
381985021c5bSMasatake YAMATO
38208cfef1a8SMasatake YAMATO EsObject *OPTSCRIPT_ERR_UNKNOWNEXTRA;
lrop_extraenabled(OptVM * vm,EsObject * name)38218cfef1a8SMasatake YAMATO static EsObject* lrop_extraenabled (OptVM *vm, EsObject *name)
38228cfef1a8SMasatake YAMATO {
38238cfef1a8SMasatake YAMATO EsObject *extra = opt_vm_ostack_top (vm);
38248cfef1a8SMasatake YAMATO if (es_object_get_type (extra) != OPT_TYPE_NAME)
38258cfef1a8SMasatake YAMATO return OPT_ERR_TYPECHECK;
38268cfef1a8SMasatake YAMATO
38278cfef1a8SMasatake YAMATO xtagType xt = optscriptGetXtagType (extra);
38288cfef1a8SMasatake YAMATO if (xt == XTAG_UNKNOWN)
38298cfef1a8SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNEXTRA;
38308cfef1a8SMasatake YAMATO
38318cfef1a8SMasatake YAMATO EsObject *r = isXtagEnabled (xt)? es_true: es_false;
38328cfef1a8SMasatake YAMATO opt_vm_ostack_pop (vm);
38338cfef1a8SMasatake YAMATO opt_vm_ostack_push (vm, r);
38348cfef1a8SMasatake YAMATO return es_false;
38358cfef1a8SMasatake YAMATO }
38368cfef1a8SMasatake YAMATO
lrop_markextra(OptVM * vm,EsObject * name)3837ecfb2683SMasatake YAMATO static EsObject *lrop_markextra (OptVM *vm, EsObject *name)
3838ecfb2683SMasatake YAMATO {
3839ecfb2683SMasatake YAMATO EsObject *tag = opt_vm_ostack_peek (vm, 1);
3840ecfb2683SMasatake YAMATO tagEntryInfo *e;
3841ecfb2683SMasatake YAMATO if (es_integer_p (tag))
3842ecfb2683SMasatake YAMATO {
3843ecfb2683SMasatake YAMATO int n = es_integer_get (tag);
3844ecfb2683SMasatake YAMATO if (! (CORK_NIL < n && n < countEntryInCorkQueue()))
3845ecfb2683SMasatake YAMATO return OPT_ERR_RANGECHECK;
3846ecfb2683SMasatake YAMATO e = getEntryInCorkQueue (n);
3847ecfb2683SMasatake YAMATO }
3848ecfb2683SMasatake YAMATO else if (es_object_get_type (tag) == OPT_TYPE_TAG)
3849ecfb2683SMasatake YAMATO e = es_pointer_get (tag);
3850ecfb2683SMasatake YAMATO else
3851ecfb2683SMasatake YAMATO return OPT_ERR_TYPECHECK;
3852ecfb2683SMasatake YAMATO
3853ecfb2683SMasatake YAMATO if (e == NULL)
3854ecfb2683SMasatake YAMATO return OPTSCRIPT_ERR_NOTAGENTRY;
3855ecfb2683SMasatake YAMATO
3856ecfb2683SMasatake YAMATO EsObject *extra = opt_vm_ostack_top (vm);
3857ecfb2683SMasatake YAMATO if (es_object_get_type (extra) != OPT_TYPE_NAME)
3858ecfb2683SMasatake YAMATO return OPT_ERR_TYPECHECK;
3859ecfb2683SMasatake YAMATO
3860ecfb2683SMasatake YAMATO xtagType xt = optscriptGetXtagType (extra);
3861ecfb2683SMasatake YAMATO if (xt == XTAG_UNKNOWN)
3862ecfb2683SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNEXTRA;
3863ecfb2683SMasatake YAMATO
3864ecfb2683SMasatake YAMATO langType lang = getXtagOwner (xt);
3865ecfb2683SMasatake YAMATO if (lang != LANG_IGNORE && e->langType != lang)
3866ecfb2683SMasatake YAMATO {
3867ecfb2683SMasatake YAMATO error (WARNING,
3868ecfb2683SMasatake YAMATO "mismatch in the language of the tag (%s) and the language of field (%s)",
3869ecfb2683SMasatake YAMATO getLanguageName (e->langType), getLanguageName (lang));
3870ecfb2683SMasatake YAMATO return OPTSCRIPT_ERR_UNKNOWNEXTRA;
3871ecfb2683SMasatake YAMATO }
3872ecfb2683SMasatake YAMATO
3873ecfb2683SMasatake YAMATO markTagExtraBit (e, xt);
3874ecfb2683SMasatake YAMATO
3875ecfb2683SMasatake YAMATO opt_vm_ostack_pop (vm);
3876ecfb2683SMasatake YAMATO opt_vm_ostack_pop (vm);
3877ecfb2683SMasatake YAMATO
3878ecfb2683SMasatake YAMATO return es_false;
3879ecfb2683SMasatake YAMATO }
3880ecfb2683SMasatake YAMATO
lrop_advanceto(OptVM * vm,EsObject * name)3881653692b7SMasatake YAMATO static EsObject *lrop_advanceto (OptVM *vm, EsObject *name)
3882653692b7SMasatake YAMATO {
3883653692b7SMasatake YAMATO struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
3884653692b7SMasatake YAMATO if (lcb->window->patbuf->regptype == REG_PARSER_SINGLE_LINE)
3885820e8cc6SMasatake YAMATO {
3886820e8cc6SMasatake YAMATO error (WARNING, "don't use `%s' operator in --regex-<LANG> option",
3887820e8cc6SMasatake YAMATO es_symbol_get (name));
3888820e8cc6SMasatake YAMATO return OPTSCRIPT_ERR_NOTMTABLEPTRN; /* TODO */
3889820e8cc6SMasatake YAMATO }
3890653692b7SMasatake YAMATO
3891653692b7SMasatake YAMATO EsObject *mlocobj = opt_vm_ostack_top (vm);
3892653692b7SMasatake YAMATO if (es_object_get_type (mlocobj) != OPT_TYPE_MATCHLOC)
3893653692b7SMasatake YAMATO return OPT_ERR_TYPECHECK;
3894653692b7SMasatake YAMATO
3895653692b7SMasatake YAMATO matchLoc *loc = es_pointer_get (mlocobj);
3896653692b7SMasatake YAMATO lcb->window->advanceto = true;
3897653692b7SMasatake YAMATO lcb->window->advanceto_delta = loc->delta;
3898653692b7SMasatake YAMATO
3899653692b7SMasatake YAMATO return es_true;
3900653692b7SMasatake YAMATO }
3901653692b7SMasatake YAMATO
lrop_markplaceholder(OptVM * vm,EsObject * name)3902d0d07afbSMasatake YAMATO static EsObject *lrop_markplaceholder (OptVM *vm, EsObject *name)
3903d0d07afbSMasatake YAMATO {
3904d0d07afbSMasatake YAMATO EsObject *tag = opt_vm_ostack_top (vm);
3905d0d07afbSMasatake YAMATO
3906d0d07afbSMasatake YAMATO if (!es_integer_p (tag))
3907d0d07afbSMasatake YAMATO return OPT_ERR_TYPECHECK;
3908d0d07afbSMasatake YAMATO
3909d0d07afbSMasatake YAMATO int n = es_integer_get (tag);
3910d0d07afbSMasatake YAMATO if (! (CORK_NIL < n && n < countEntryInCorkQueue()))
3911d0d07afbSMasatake YAMATO return OPT_ERR_RANGECHECK;
3912d0d07afbSMasatake YAMATO
3913d0d07afbSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (n);
3914d0d07afbSMasatake YAMATO if (e == NULL)
3915d0d07afbSMasatake YAMATO return OPTSCRIPT_ERR_NOTAGENTRY;
3916d0d07afbSMasatake YAMATO
3917d0d07afbSMasatake YAMATO markTagPlaceholder (e, true);
3918d0d07afbSMasatake YAMATO
3919d0d07afbSMasatake YAMATO opt_vm_ostack_pop (vm);
3920d0d07afbSMasatake YAMATO return es_false;
3921d0d07afbSMasatake YAMATO }
3922d0d07afbSMasatake YAMATO
3923f13d16e1SMasatake YAMATO static struct optscriptOperatorRegistration lropOperators [] = {
3924f13d16e1SMasatake YAMATO {
39251908e776SMasatake YAMATO .name = "_matchstr",
3926df8d88a5SMasatake YAMATO .fn = lrop_get_match_string_group_on_stack,
39271908e776SMasatake YAMATO .arity = 1,
39281908e776SMasatake YAMATO .help_str = "group:int _MATCHSTR string true%"
39291908e776SMasatake YAMATO "group:int _MATCHSTR false",
39301908e776SMasatake YAMATO },
39311908e776SMasatake YAMATO {
3932f13d16e1SMasatake YAMATO .name = "_matchloc",
3933f13d16e1SMasatake YAMATO .fn = lrop_get_match_loc,
3934f13d16e1SMasatake YAMATO .arity = -1,
3935f13d16e1SMasatake YAMATO .help_str = "group:int /start|/end _MATCHLOC matchloc%"
3936f13d16e1SMasatake YAMATO "group:int _MATCHLOC matchloc",
3937f13d16e1SMasatake YAMATO },
3938f13d16e1SMasatake YAMATO {
39391481c2d1SMasatake YAMATO .name = "_matchloc2line",
39401481c2d1SMasatake YAMATO .fn = ldrop_get_line_from_matchloc,
39411481c2d1SMasatake YAMATO .arity = 1,
39421481c2d1SMasatake YAMATO .help_str = "matchloc _MATCHLOC2LINE int:line",
39431481c2d1SMasatake YAMATO },
39441481c2d1SMasatake YAMATO {
394520b300feSMasatake YAMATO .name = "_tagloc",
394620b300feSMasatake YAMATO .fn = lrop_get_tag_loc,
394720b300feSMasatake YAMATO .arity = 1,
394820b300feSMasatake YAMATO .help_str = "index:int _TAGLOC matchloc",
394920b300feSMasatake YAMATO },
395020b300feSMasatake YAMATO {
3951f13d16e1SMasatake YAMATO .name = "_tag",
3952f13d16e1SMasatake YAMATO .fn = lrop_make_tag,
3953f13d16e1SMasatake YAMATO .arity = -1,
3954f13d16e1SMasatake YAMATO .help_str = "name:str kind:name matchloc _TAG tag%"
3955f13d16e1SMasatake YAMATO "name:str kind:name _TAG tag",
3956f13d16e1SMasatake YAMATO },
3957f13d16e1SMasatake YAMATO {
39587b347e74SMasatake YAMATO .name = "_reftag",
39597b347e74SMasatake YAMATO .fn = lrop_make_reftag,
39607b347e74SMasatake YAMATO .arity = -1,
39617b347e74SMasatake YAMATO .help_str = "name:str kind:name role:name matchloc _REFTAG tag%"
39627b347e74SMasatake YAMATO "name:str kind:name role:name _REFTAG tag%",
39637b347e74SMasatake YAMATO },
39647b347e74SMasatake YAMATO {
3965f13d16e1SMasatake YAMATO .name = "_commit",
3966f13d16e1SMasatake YAMATO .fn = lrop_commit_tag,
3967f13d16e1SMasatake YAMATO .arity = 1,
3968f13d16e1SMasatake YAMATO .help_str = "tag _COMMIT int",
3969f13d16e1SMasatake YAMATO },
39707f9e4f22SMasatake YAMATO {
39717f9e4f22SMasatake YAMATO .name = "_scopeset",
39727f9e4f22SMasatake YAMATO .fn = lrop_set_scope,
39737f9e4f22SMasatake YAMATO .arity = 1,
39747f9e4f22SMasatake YAMATO .help_str = "int _SCOPESET -",
39757f9e4f22SMasatake YAMATO },
39767f9e4f22SMasatake YAMATO {
39777f9e4f22SMasatake YAMATO .name = "_scopepop",
39787f9e4f22SMasatake YAMATO .fn = lrop_pop_scope,
39797f9e4f22SMasatake YAMATO .arity = 0,
39807f9e4f22SMasatake YAMATO .help_str = "- _SCOPEPOP -",
39817f9e4f22SMasatake YAMATO },
39827f9e4f22SMasatake YAMATO {
39837f9e4f22SMasatake YAMATO .name = "_scopeclear",
39847f9e4f22SMasatake YAMATO .fn = lrop_clear_scope,
39857f9e4f22SMasatake YAMATO .arity = 0,
39867f9e4f22SMasatake YAMATO .help_str = "- _SCOPECLEAR -",
39877f9e4f22SMasatake YAMATO },
39887f9e4f22SMasatake YAMATO {
39897f9e4f22SMasatake YAMATO .name = "_scopetop",
39907f9e4f22SMasatake YAMATO .fn = lrop_ref0_scope,
39917f9e4f22SMasatake YAMATO .arity = 0,
39927f9e4f22SMasatake YAMATO .help_str = "- _SCOPETOP int true%"
39937f9e4f22SMasatake YAMATO "- _SCOPETOP false",
39947f9e4f22SMasatake YAMATO },
39957f9e4f22SMasatake YAMATO {
39967f9e4f22SMasatake YAMATO .name = "_scopeNth",
39977f9e4f22SMasatake YAMATO .fn = lrop_refN_scope,
39987f9e4f22SMasatake YAMATO .arity = 1,
39997f9e4f22SMasatake YAMATO .help_str = "index:int _SCOPENTH int",
40007f9e4f22SMasatake YAMATO },
40017f9e4f22SMasatake YAMATO {
40027f9e4f22SMasatake YAMATO .name = "_scopedepth",
40037f9e4f22SMasatake YAMATO .fn = lrop_get_scope_depth,
40047f9e4f22SMasatake YAMATO .arity = 0,
40057f9e4f22SMasatake YAMATO .help_str = "- _SCOPEDEPTH int",
40067f9e4f22SMasatake YAMATO },
400754bd7b53SMasatake YAMATO {
400854bd7b53SMasatake YAMATO .name = "_repl",
400954bd7b53SMasatake YAMATO .fn = lrop_repl,
401054bd7b53SMasatake YAMATO .arity = 0,
401154bd7b53SMasatake YAMATO .help_str = "- _repl -",
40122b8d4c66SMasatake YAMATO },
40132b8d4c66SMasatake YAMATO {
40142b8d4c66SMasatake YAMATO .name = "_tenter",
40152b8d4c66SMasatake YAMATO .fn = lrop_tenter,
40162b8d4c66SMasatake YAMATO .arity = 1,
40172b8d4c66SMasatake YAMATO .help_str = "table:name _TENTER -",
40182b8d4c66SMasatake YAMATO },
40192b8d4c66SMasatake YAMATO {
40202b8d4c66SMasatake YAMATO .name = "_tentercont",
40212b8d4c66SMasatake YAMATO .fn = lrop_tenter_with_continuation,
40222b8d4c66SMasatake YAMATO .arity = 2,
40232b8d4c66SMasatake YAMATO .help_str = "table:name cont:name _TENTERCONT -",
40242b8d4c66SMasatake YAMATO },
40252b8d4c66SMasatake YAMATO {
40262b8d4c66SMasatake YAMATO .name = "_tleave",
40272b8d4c66SMasatake YAMATO .fn = lrop_tleave,
40282b8d4c66SMasatake YAMATO .arity = 0,
40292b8d4c66SMasatake YAMATO .help_str = "- _TLEAVE -",
40302b8d4c66SMasatake YAMATO },
40312b8d4c66SMasatake YAMATO {
40322b8d4c66SMasatake YAMATO .name = "_tjump",
40332b8d4c66SMasatake YAMATO .fn = lrop_tjump,
40342b8d4c66SMasatake YAMATO .arity = 1,
40352b8d4c66SMasatake YAMATO .help_str = "table:name _TJUMP -",
40362b8d4c66SMasatake YAMATO },
40372b8d4c66SMasatake YAMATO {
40382b8d4c66SMasatake YAMATO .name = "_treset",
40392b8d4c66SMasatake YAMATO .fn = lrop_treset,
40402b8d4c66SMasatake YAMATO .arity = 1,
40412b8d4c66SMasatake YAMATO .help_str = "table:name _TRESET -",
40422b8d4c66SMasatake YAMATO },
40432b8d4c66SMasatake YAMATO {
40442b8d4c66SMasatake YAMATO .name = "_tquit",
40452b8d4c66SMasatake YAMATO .fn = lrop_tquit,
40462b8d4c66SMasatake YAMATO .arity = 0,
40472b8d4c66SMasatake YAMATO .help_str = "- _TQUIT -",
40482b8d4c66SMasatake YAMATO },
40498cfef1a8SMasatake YAMATO {
40508cfef1a8SMasatake YAMATO .name = "_extraenabled",
40518cfef1a8SMasatake YAMATO .fn = lrop_extraenabled,
40528cfef1a8SMasatake YAMATO .arity = 1,
40538cfef1a8SMasatake YAMATO .help_str = "extra:name _extraenabled bool%"
40548cfef1a8SMasatake YAMATO "language.extra _extraenabled bool",
40558cfef1a8SMasatake YAMATO },
4056ecfb2683SMasatake YAMATO {
4057ecfb2683SMasatake YAMATO .name = "_markextra",
4058ecfb2683SMasatake YAMATO .fn = lrop_markextra,
4059ecfb2683SMasatake YAMATO .arity = 2,
4060ecfb2683SMasatake YAMATO .help_str = "tag:int|tag:tag extra:name _MARKEXTRA -%"
4061ecfb2683SMasatake YAMATO "tag:int|tag:tag lang.extra:name _MARKEXTRA -",
4062653692b7SMasatake YAMATO },
4063653692b7SMasatake YAMATO {
4064653692b7SMasatake YAMATO .name = "_advanceto",
4065653692b7SMasatake YAMATO .fn = lrop_advanceto,
4066653692b7SMasatake YAMATO .arity = 1,
40679de3d788SMasatake YAMATO .help_str = "matchloc _ADVANCETO -%"
4068653692b7SMasatake YAMATO },
406985021c5bSMasatake YAMATO {
407085021c5bSMasatake YAMATO .name = "_traced",
407185021c5bSMasatake YAMATO .fn = lrop_traced,
407285021c5bSMasatake YAMATO .arity = 0,
407385021c5bSMasatake YAMATO .help_str = "- _TRACED true|false",
407485021c5bSMasatake YAMATO },
4075d0d07afbSMasatake YAMATO {
4076d0d07afbSMasatake YAMATO .name = "_markplaceholder",
4077d0d07afbSMasatake YAMATO .fn = lrop_markplaceholder,
4078d0d07afbSMasatake YAMATO .arity = 1,
4079d0d07afbSMasatake YAMATO .help_str = "tag:int _MARKPLACEHOLDER -",
4080d0d07afbSMasatake YAMATO }
4081f13d16e1SMasatake YAMATO };
4082f13d16e1SMasatake YAMATO
initRegexOptscript(void)4083965b7025SMasatake YAMATO extern void initRegexOptscript (void)
4084965b7025SMasatake YAMATO {
4085965b7025SMasatake YAMATO if (!regexAvailable)
4086965b7025SMasatake YAMATO return;
4087965b7025SMasatake YAMATO
4088965b7025SMasatake YAMATO if (optvm)
4089965b7025SMasatake YAMATO return;
4090965b7025SMasatake YAMATO
4091965b7025SMasatake YAMATO optvm = optscriptInit ();
4092965b7025SMasatake YAMATO lregex_dict = opt_dict_new (17);
409334deb294SMasatake YAMATO
40942b8d4c66SMasatake YAMATO OPTSCRIPT_ERR_UNKNOWNTABLE = es_error_intern ("unknowntable");
40952b8d4c66SMasatake YAMATO OPTSCRIPT_ERR_NOTMTABLEPTRN = es_error_intern ("notmtableptrn");
40968cfef1a8SMasatake YAMATO OPTSCRIPT_ERR_UNKNOWNEXTRA = es_error_intern ("unknownextra");
40978cfef1a8SMasatake YAMATO OPTSCRIPT_ERR_UNKNOWNLANGUAGE = es_error_intern ("unknownlanguage");
409834deb294SMasatake YAMATO OPTSCRIPT_ERR_UNKNOWNKIND = es_error_intern ("unknownkind");
40997b347e74SMasatake YAMATO OPTSCRIPT_ERR_UNKNOWNROLE = es_error_intern ("unknownrole");
410034deb294SMasatake YAMATO
41011908e776SMasatake YAMATO optscriptInstallProcs (lregex_dict, lrop_get_match_string_named_group);
4102ed3202bdSMasatake YAMATO
4103f13d16e1SMasatake YAMATO optscriptRegisterOperators (lregex_dict,
4104f13d16e1SMasatake YAMATO lropOperators, ARRAY_SIZE(lropOperators));
4105431a587eSMasatake YAMATO
4106431a587eSMasatake YAMATO extern const char ctagsCommonPrelude[];
4107431a587eSMasatake YAMATO opt_vm_dstack_push (optvm, lregex_dict);
4108431a587eSMasatake YAMATO MIO *mio = mio_new_memory ((unsigned char*)ctagsCommonPrelude, strlen (ctagsCommonPrelude), NULL, NULL);
4109431a587eSMasatake YAMATO EsObject *e = optscriptLoad (optvm, mio);
4110431a587eSMasatake YAMATO if (es_error_p (e))
4111431a587eSMasatake YAMATO error (FATAL, "failed in loading built-in procedures");
4112431a587eSMasatake YAMATO mio_unref (mio);
4113431a587eSMasatake YAMATO opt_vm_dstack_pop (optvm);
4114965b7025SMasatake YAMATO }
4115965b7025SMasatake YAMATO
listRegexOpscriptOperators(FILE * fp)4116965b7025SMasatake YAMATO extern void listRegexOpscriptOperators (FILE *fp)
4117965b7025SMasatake YAMATO {
4118f02ab9fbSMasatake YAMATO EsObject *procdocs;
4119f02ab9fbSMasatake YAMATO if (!opt_dict_known_and_get_cstr (lregex_dict,
4120f02ab9fbSMasatake YAMATO "__procdocs",
4121f02ab9fbSMasatake YAMATO &procdocs))
4122f02ab9fbSMasatake YAMATO procdocs = NULL;
4123f02ab9fbSMasatake YAMATO
4124965b7025SMasatake YAMATO opt_vm_dstack_push (optvm, lregex_dict);
4125f02ab9fbSMasatake YAMATO optscriptHelp (optvm, fp, procdocs);
4126965b7025SMasatake YAMATO opt_vm_dstack_pop (optvm);
4127965b7025SMasatake YAMATO }
4128