2
* $Id: pascal.c,v 1.6 2006/05/30 04:37:12 darren Exp $
4
* Copyright (c) 2001-2002, Darren Hiebert
6
* This source code is released for free distribution under the terms of the
7
* GNU General Public License.
9
* This module contains functions for generating tags for the Pascal language,
10
* including some extensions for Object Pascal.
16
#include "general.h" /* must always come first */
29
K_FUNCTION, K_PROCEDURE
32
static kindOption PascalKinds [] = {
33
{ TRUE, 'f', "function", "functions"},
34
{ TRUE, 'p', "procedure", "procedures"}
38
* FUNCTION DEFINITIONS
41
static void createPascalTag (
42
tagEntryInfo* const tag, const vString* const name, const int kind)
44
if (PascalKinds [kind].enabled && name != NULL && vStringLength (name) > 0)
46
initTagEntry (tag, vStringValue (name));
47
tag->kindName = PascalKinds [kind].name;
48
tag->kind = PascalKinds [kind].letter;
51
initTagEntry (tag, NULL);
54
static void makePascalTag (const tagEntryInfo* const tag)
56
if (tag->name != NULL)
60
static const unsigned char* dbp;
62
#define starttoken(c) (isalpha ((int) c) || (int) c == '_')
63
#define intoken(c) (isalnum ((int) c) || (int) c == '_' || (int) c == '.')
64
#define endtoken(c) (! intoken (c) && ! isdigit ((int) c))
66
static boolean tail (const char *cp)
68
boolean result = FALSE;
71
while (*cp != '\0' && tolower ((int) *cp) == tolower ((int) dbp [len]))
73
if (*cp == '\0' && !intoken (dbp [len]))
81
/* Algorithm adapted from from GNU etags.
82
* Locates tags for procedures & functions. Doesn't do any type- or
83
* var-definitions. It does look for the keyword "extern" or "forward"
84
* immediately following the procedure statement; if found, the tag is
87
static void findPascalTags (void)
89
vString *name = vStringNew ();
91
pascalKind kind = K_FUNCTION;
92
/* each of these flags is TRUE iff: */
93
boolean incomment = FALSE; /* point is inside a comment */
94
int comment_char = '\0'; /* type of current comment */
95
boolean inquote = FALSE; /* point is inside '..' string */
96
boolean get_tagname = FALSE;/* point is after PROCEDURE/FUNCTION
97
keyword, so next item = potential tag */
98
boolean found_tag = FALSE; /* point is after a potential tag */
99
boolean inparms = FALSE; /* point is within parameter-list */
100
boolean verify_tag = FALSE;
101
/* point has passed the parm-list, so the next token will determine
102
* whether this is a FORWARD/EXTERN to be ignored, or whether it is a
106
dbp = fileReadLine ();
111
if (c == '\0') /* if end of line */
113
dbp = fileReadLine ();
114
if (dbp == NULL || *dbp == '\0')
116
if (!((found_tag && verify_tag) || get_tagname))
118
/* only if don't need *dbp pointing to the beginning of
119
* the name of the procedure or function
124
if (comment_char == '{' && c == '}')
126
else if (comment_char == '(' && c == '*' && *dbp == ')')
142
inquote = TRUE; /* found first quote */
144
case '{': /* found open { comment */
149
if (*dbp == '*') /* found open (* comment */
155
else if (found_tag) /* found '(' after tag, i.e., parm-list */
158
case ')': /* end of parms list */
163
if (found_tag && !inparms) /* end of proc or fn stmt */
170
if (found_tag && verify_tag && *dbp != ' ')
172
/* check if this is an "extern" declaration */
175
if (tolower ((int) *dbp == 'e'))
177
if (tail ("extern")) /* superfluous, really! */
183
else if (tolower ((int) *dbp) == 'f')
185
if (tail ("forward")) /* check for forward reference */
191
if (found_tag && verify_tag) /* not external proc, so make tag */
195
makePascalTag (&tag);
199
if (get_tagname) /* grab name of proc or fn */
201
const unsigned char *cp;
206
/* grab block name */
207
while (isspace ((int) *dbp))
209
for (cp = dbp ; *cp != '\0' && !endtoken (*cp) ; cp++)
211
vStringNCopyS (name, (const char*) dbp, cp - dbp);
212
createPascalTag (&tag, name, kind);
213
dbp = cp; /* set dbp to e-o-token */
216
/* and proceed to check for "extern" */
218
else if (!incomment && !inquote && !found_tag)
220
switch (tolower ((int) c))
223
if (tail ("onstructor"))
230
if (tail ("estructor"))
237
if (tail ("rocedure"))
244
if (tail ("unction"))
251
} /* while not eof */
255
extern parserDefinition* PascalParser (void)
257
static const char *const extensions [] = { "p", "pas", NULL };
258
parserDefinition* def = parserNew ("Pascal");
259
def->extensions = extensions;
260
def->kinds = PascalKinds;
261
def->kindCount = KIND_COUNT (PascalKinds);
262
def->parser = findPascalTags;
266
/* vi:set tabstop=4 shiftwidth=4: */