File: test.c

package info (click to toggle)
tclex 1.2a1-15
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 568 kB
  • ctags: 438
  • sloc: ansic: 3,772; tcl: 452; makefile: 101; sh: 85; lex: 48
file content (302 lines) | stat: -rw-r--r-- 9,874 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/* 
 * tcLex.h --
 *
 *  This is the header file for the module that implements lexer for Tcl.
 *  This file defines the public interface of the tcLex module.
 *
 * Copyright (c) 1998 Frdric BONNET <frederic.bonnet@ciril.fr>
 *
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#ifndef _TCLEX_H_
#define _TCLEX_H_


#include <tcl.h>

/*
 * if the BUILD_tcLex macro is defined, the assumption is that we are
 * building the dynamic library.
 */

#ifdef BUILD_tcLex
#  undef TCL_STORAGE_CLASS
#  define TCL_STORAGE_CLASS DLLEXPORT
#endif

/*
 *--------------------------------------------------------------
 *
 * Various stuff
 *
 *--------------------------------------------------------------
 */

#define EXPORT(a,b) a b

#ifdef WIN32
#   define WIN32_LEAN_AND_MEAN
#   include <windows.h>
#   undef WIN32_LEAN_AND_MEAN

#   ifndef STATIC_BUILD
#       if defined(__BORLANDC__)
#           undef EXPORT
#           define EXPORT(a,b) a _export b
#       endif
#   endif
#endif	/* WIN32 */


/*
 *--------------------------------------------------------------
 *
 * Structures
 *
 *--------------------------------------------------------------
 */

/* 
 * Lexer rules
 *
 * Each lexer is made by a collection of rules. Each rule is
 * described by the TcLex_Rule structure.
 */
typedef struct TcLex_Rule {
  /*
   * Each rule is active only within one or several conditions.
   * Here we store the indices of the valid conditions in the
   * array <conditionsIndices> of length <conditionsIndicesLength>,
   * w.r.t the lexer's TcLex_Lexer <inclusiveConditions> and
   * <exclusiveConditions> arrays
   */
  int *conditionsIndices;
  int conditionsIndicesLength;

  Tcl_Obj    *reObj;     /* Object containing the regexp */
  Tcl_RegExp re;         /* Regular expression of the rule */
  Tcl_Obj    *matchVars; /* List of match var names */
  int        nbRanges;   /* Max number of ranges in the regexp, approximately */
                         /* equal to the number of parentheses pairs */
  Tcl_Obj    *script;    /* Script eval'd when the rule is matched */

} TcLex_Rule;


/* 
 * Lexer buffers
 *
 * Buffers are used to handle input: Tcl strings, files, channels...
 */
#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0)
typedef char Char;
#else
typedef Tcl_UniChar Char;
#endif

typedef struct TcLex_Buffer {
  Tcl_DString chars;

  int index;            /* Current byte position within <chars> */
  int nextIndex;

  int bMatchedEmpty;    /* Set when we match an empty string 
                         * (such as an empty line). To avoid
                         * endless loops we can't match two
                         * consecutive empty strings */
} TcLex_Buffer;

/* 
 * Lexer states
 *
 * When a lexer is active, its state is described using the
 * TcLex_State structure. It is used when the same lexer is
 * called recursively or in parallel (eg. incrementally)
 */
typedef struct TcLex_State {
  /*
   * The lexer's condition can change during its execution. We
   * need to store these conditions in a stack
   */
  int *conditionsStack;       /* Array used to store conditions,
                               * current condition is the last
                               * element */
  int conditionsStackLength;  /* Length of the above stack */

  char *bFailed;              /* Rule failure indicators. We need to
                               * store it for incremental processing
                               * to work properly */

  Tcl_HashTable *varTablePtr; /* Used to store the lexer's local
                               * variables for continuation,
                               * eg. for incremental evaluation */

  TcLex_Buffer inputBuffer;   /* Buffer from which to take input */
  TcLex_Buffer *currentBuffer;

  int bRejected;        /* Used when the rule is rejected, using 
                         * the "reject" subcommand */
  
  int nbRanges;         /* Number of matches ranges/subranges */
  int *startIndices;    /* When a rule matches, used to store */
  int *endIndices;      /* the matching strings' indices */

  Tcl_Obj *pendingResult;     /* Used when the lexer returns a
                               * result before reaching the end of
                               * the string */
} TcLex_State;


/* 
 * Lexer
 */

#define LEXER_FLAG_LINES    1
#define LEXER_FLAG_NOCASE   2
#define LEXER_FLAG_LONGEST  4

typedef struct TcLex_Lexer {
  Tcl_Command command; /* Token to the created Tcl command, used
                        * with [lexer current] */

  /*
   * There are 2 types of conditions: inclusive, and exclusive.
   * We store both types in the <conditions> array. Inclusive
   * conditions are stored in the first <nbInclusiveConditions>
   * elements, and the remaining <nbExclusiveConditions> elements
   * are used to store exclusive conditions. We also pre-process
   * the active rules for each condition in the <activeRules> array
   * for optimization; that way we don't have to search for active
   * rules at every match, we just look into the <activeRules> array.
   */
  Tcl_Obj **conditions;
  int **activeRules;
  int nbInclusiveConditions, nbExclusiveConditions;

  int flags;            /* OR-ed values of LEXER_FLAG_????? */

  /*
   * The scripts <preScript> and <postScript> are evaluated
   * resp. before and after the string lexing. <preScript> is
   * mainly used for initialization, and <postScript> for
   * returning a result.
   * The script <midScript> is only evaluated during an incremental
   * lexing, at the end of each intermediary lexing, ie calls to
   * "start" or "continue". A call to "finish" return the result
   * of <postScript>.
   * If none of these scripts return a value, the content of
   * the variable named <resultVariable> is returned, if any
   */
  Tcl_Obj *preScript, *midScript, *postScript;
  Tcl_Obj *args;
  Tcl_Obj *resultVariable;

  TcLex_Rule *rules;    /* Array used to store the lexer's rules */
  int nbRules;          /* Number of rules, ie length of the 
                         * above array */

  /*
   * Since one lexer can have several active instances at a time,
   * we need to store their states, in the <states> array
   */
  TcLex_State **states;
  int nbStates;         /* Length of the above array */
  int curState;         /* Index of the current state in the array */

} TcLex_Lexer;


/*
 *--------------------------------------------------------------
 *
 * Functions
 *
 *--------------------------------------------------------------
 */

/*
 * The main entry point
 */
EXTERN EXPORT(int,Tclex_Init)     _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN EXPORT(int,Tclex_SafeInit) _ANSI_ARGS_((Tcl_Interp *interp));


/*
 * Lexer Tcl command
 */
int LexerObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                             int objc, Tcl_Obj *CONST objv[]));


/*
 * Lexer management functions
 */
void          LexerDelete _ANSI_ARGS_((TcLex_Lexer *lexer));
TcLex_Lexer * LexerNew    _ANSI_ARGS_((Tcl_Interp *interp,
                                       Tcl_Obj *inclusiveConditions, Tcl_Obj *exclusiveConditions,
                                       Tcl_Obj *resultVariable,
                                       Tcl_Obj *preScript, Tcl_Obj *midScript, Tcl_Obj *postScript,
                                       Tcl_Obj *args, int flags, 
                                       int rulec, Tcl_Obj *CONST *rulev));

void  LexerCmdDeleteProc _ANSI_ARGS_((ClientData clientData));
int   LexerMainObjCmd    _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, 
                                      int objc, Tcl_Obj *CONST objv[]));
int   LexerCreateObjCmd  _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, 
                                      int objc, Tcl_Obj *CONST objv[], int start));
int   LexerCurrentObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, 
                                      int objc, Tcl_Obj *CONST objv[]));


/*
 * Conditions management functions
 */
int ConditionCurrent _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer));


/*
 * Lexer evaluation functions
 */

/* LexerEval op's */
#define LEXER_EVAL     0
#define LEXER_START    1
#define LEXER_CONTINUE 2
#define LEXER_FINISH   3

int LexerEval       _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer, 
                                 int bCheckOverrun));
int LexerEvalObjCmd _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer,
                                 int objc, Tcl_Obj *CONST objv[], int op));

/*
 * Lexer state functions
 */
int LexerBeginObjCmd      _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerEndObjCmd        _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerConditionsObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerRejectObjCmd     _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerIndexObjCmd      _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerInputObjCmd      _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));
int LexerUnputObjCmd      _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                                       int objc, Tcl_Obj *CONST objv[]));


/*
 * end of tcLex.h
 * reset TCL_STORAGE_CLASS to DLLIMPORT.
 */

# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLEX_H_ */