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: */