ctags.rb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. data/Gemfile +2 -0
  2. data/Rakefile +23 -0
  3. data/ctags.rb.gemspec +23 -0
  4. data/ext/.gitignore +3 -0
  5. data/ext/extconf.rb +15 -0
  6. data/ext/vendor/exuberant-ctags/.gitignore +6 -0
  7. data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
  8. data/ext/vendor/exuberant-ctags/COPYING +340 -0
  9. data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
  10. data/ext/vendor/exuberant-ctags/FAQ +371 -0
  11. data/ext/vendor/exuberant-ctags/INSTALL +215 -0
  12. data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
  13. data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
  14. data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
  15. data/ext/vendor/exuberant-ctags/NEWS +871 -0
  16. data/ext/vendor/exuberant-ctags/README +73 -0
  17. data/ext/vendor/exuberant-ctags/ant.c +42 -0
  18. data/ext/vendor/exuberant-ctags/argproc.c +505 -0
  19. data/ext/vendor/exuberant-ctags/args.c +274 -0
  20. data/ext/vendor/exuberant-ctags/args.h +63 -0
  21. data/ext/vendor/exuberant-ctags/asm.c +387 -0
  22. data/ext/vendor/exuberant-ctags/asp.c +328 -0
  23. data/ext/vendor/exuberant-ctags/awk.c +81 -0
  24. data/ext/vendor/exuberant-ctags/basic.c +203 -0
  25. data/ext/vendor/exuberant-ctags/beta.c +321 -0
  26. data/ext/vendor/exuberant-ctags/c.c +2932 -0
  27. data/ext/vendor/exuberant-ctags/cobol.c +50 -0
  28. data/ext/vendor/exuberant-ctags/config.h.in +277 -0
  29. data/ext/vendor/exuberant-ctags/configure +7704 -0
  30. data/ext/vendor/exuberant-ctags/configure.ac +532 -0
  31. data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
  32. data/ext/vendor/exuberant-ctags/ctags.h +28 -0
  33. data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
  34. data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
  35. data/ext/vendor/exuberant-ctags/debug.c +113 -0
  36. data/ext/vendor/exuberant-ctags/debug.h +70 -0
  37. data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
  38. data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
  39. data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
  40. data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
  41. data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
  42. data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
  43. data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
  44. data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
  45. data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
  46. data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
  47. data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
  48. data/ext/vendor/exuberant-ctags/entry.c +847 -0
  49. data/ext/vendor/exuberant-ctags/entry.h +103 -0
  50. data/ext/vendor/exuberant-ctags/erlang.c +189 -0
  51. data/ext/vendor/exuberant-ctags/flex.c +2243 -0
  52. data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
  53. data/ext/vendor/exuberant-ctags/general.h +127 -0
  54. data/ext/vendor/exuberant-ctags/get.c +669 -0
  55. data/ext/vendor/exuberant-ctags/get.h +50 -0
  56. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
  57. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
  58. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
  59. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
  60. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
  61. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
  62. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
  63. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
  64. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
  65. data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
  66. data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
  67. data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
  68. data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
  69. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
  70. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
  71. data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
  72. data/ext/vendor/exuberant-ctags/html.c +49 -0
  73. data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
  74. data/ext/vendor/exuberant-ctags/keyword.c +258 -0
  75. data/ext/vendor/exuberant-ctags/keyword.h +34 -0
  76. data/ext/vendor/exuberant-ctags/lisp.c +139 -0
  77. data/ext/vendor/exuberant-ctags/lregex.c +704 -0
  78. data/ext/vendor/exuberant-ctags/lua.c +133 -0
  79. data/ext/vendor/exuberant-ctags/mac.c +273 -0
  80. data/ext/vendor/exuberant-ctags/magic.diff +21 -0
  81. data/ext/vendor/exuberant-ctags/main.c +584 -0
  82. data/ext/vendor/exuberant-ctags/main.h +32 -0
  83. data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
  84. data/ext/vendor/exuberant-ctags/make.c +217 -0
  85. data/ext/vendor/exuberant-ctags/matlab.c +44 -0
  86. data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
  87. data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
  88. data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
  89. data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
  90. data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
  91. data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
  92. data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
  93. data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
  94. data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
  95. data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
  96. data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
  97. data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
  98. data/ext/vendor/exuberant-ctags/options.c +1842 -0
  99. data/ext/vendor/exuberant-ctags/options.h +155 -0
  100. data/ext/vendor/exuberant-ctags/parse.c +677 -0
  101. data/ext/vendor/exuberant-ctags/parse.h +129 -0
  102. data/ext/vendor/exuberant-ctags/parsers.h +63 -0
  103. data/ext/vendor/exuberant-ctags/pascal.c +267 -0
  104. data/ext/vendor/exuberant-ctags/perl.c +382 -0
  105. data/ext/vendor/exuberant-ctags/php.c +237 -0
  106. data/ext/vendor/exuberant-ctags/python.c +771 -0
  107. data/ext/vendor/exuberant-ctags/qdos.c +106 -0
  108. data/ext/vendor/exuberant-ctags/read.c +569 -0
  109. data/ext/vendor/exuberant-ctags/read.h +116 -0
  110. data/ext/vendor/exuberant-ctags/readtags.c +959 -0
  111. data/ext/vendor/exuberant-ctags/readtags.h +252 -0
  112. data/ext/vendor/exuberant-ctags/rexx.c +39 -0
  113. data/ext/vendor/exuberant-ctags/routines.c +891 -0
  114. data/ext/vendor/exuberant-ctags/routines.h +134 -0
  115. data/ext/vendor/exuberant-ctags/ruby.c +408 -0
  116. data/ext/vendor/exuberant-ctags/scheme.c +111 -0
  117. data/ext/vendor/exuberant-ctags/sh.c +115 -0
  118. data/ext/vendor/exuberant-ctags/slang.c +41 -0
  119. data/ext/vendor/exuberant-ctags/sml.c +212 -0
  120. data/ext/vendor/exuberant-ctags/sort.c +230 -0
  121. data/ext/vendor/exuberant-ctags/sort.h +32 -0
  122. data/ext/vendor/exuberant-ctags/source.mak +122 -0
  123. data/ext/vendor/exuberant-ctags/sql.c +2112 -0
  124. data/ext/vendor/exuberant-ctags/strlist.c +281 -0
  125. data/ext/vendor/exuberant-ctags/strlist.h +54 -0
  126. data/ext/vendor/exuberant-ctags/tcl.c +116 -0
  127. data/ext/vendor/exuberant-ctags/tex.c +524 -0
  128. data/ext/vendor/exuberant-ctags/verilog.c +340 -0
  129. data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
  130. data/ext/vendor/exuberant-ctags/vim.c +636 -0
  131. data/ext/vendor/exuberant-ctags/vstring.c +232 -0
  132. data/ext/vendor/exuberant-ctags/vstring.h +85 -0
  133. data/ext/vendor/exuberant-ctags/yacc.c +40 -0
  134. data/lib/ctags/exuberant.rb +45 -0
  135. data/lib/ctags/version.rb +3 -0
  136. data/lib/ctags.rb +6 -0
  137. data/test/test_ctags.rb +24 -0
  138. metadata +233 -0
@@ -0,0 +1,134 @@
1
+ /*
2
+ * $Id: routines.h 536 2007-06-02 06:09:00Z elliotth $
3
+ *
4
+ * Copyright (c) 2002, Darren Hiebert
5
+ *
6
+ * This source code is released for free distribution under the terms of the
7
+ * GNU General Public License.
8
+ *
9
+ * External interface to routines.c
10
+ */
11
+ #ifndef _ROUTINES_H
12
+ #define _ROUTINES_H
13
+
14
+ /*
15
+ * INCLUDE FILES
16
+ */
17
+ #include "general.h" /* must always come first */
18
+
19
+ /*
20
+ * MACROS
21
+ */
22
+ #define xMalloc(n,Type) (Type *)eMalloc((size_t)(n) * sizeof (Type))
23
+ #define xCalloc(n,Type) (Type *)eCalloc((size_t)(n), sizeof (Type))
24
+ #define xRealloc(p,n,Type) (Type *)eRealloc((p), (n) * sizeof (Type))
25
+
26
+ /*
27
+ * Portability macros
28
+ */
29
+ #ifndef PATH_SEPARATOR
30
+ # if defined (MSDOS_STYLE_PATH)
31
+ # define PATH_SEPARATOR '\\'
32
+ # elif defined (QDOS)
33
+ # define PATH_SEPARATOR '_'
34
+ # else
35
+ # define PATH_SEPARATOR '/'
36
+ # endif
37
+ #endif
38
+
39
+ #if defined (MSDOS_STYLE_PATH) && defined (UNIX_PATH_SEPARATOR)
40
+ # define OUTPUT_PATH_SEPARATOR '/'
41
+ #else
42
+ # define OUTPUT_PATH_SEPARATOR PATH_SEPARATOR
43
+ #endif
44
+
45
+ /*
46
+ * DATA DECLARATIONS
47
+ */
48
+ #if defined (MSDOS_STYLE_PATH) || defined (VMS)
49
+ extern const char *const PathDelimiters;
50
+ #endif
51
+ extern char *CurrentDirectory;
52
+ typedef int errorSelection;
53
+ enum eErrorTypes { FATAL = 1, WARNING = 2, PERROR = 4 };
54
+
55
+ typedef struct {
56
+ /* Name of file for which status is valid */
57
+ char* name;
58
+
59
+ /* Does file exist? If not, members below do not contain valid data. */
60
+ boolean exists;
61
+
62
+ /* is file path a symbolic link to another file? */
63
+ boolean isSymbolicLink;
64
+
65
+ /* Is file (pointed to) a directory? */
66
+ boolean isDirectory;
67
+
68
+ /* Is file (pointed to) a normal file? */
69
+ boolean isNormalFile;
70
+
71
+ /* Is file (pointed to) executable? */
72
+ boolean isExecutable;
73
+
74
+ /* Is file (pointed to) setuid? */
75
+ boolean isSetuid;
76
+
77
+ /* Size of file (pointed to) */
78
+ unsigned long size;
79
+ } fileStatus;
80
+
81
+ /*
82
+ * FUNCTION PROTOTYPES
83
+ */
84
+ extern void freeRoutineResources (void);
85
+ extern void setExecutableName (const char *const path);
86
+ extern const char *getExecutableName (void);
87
+ extern const char *getExecutablePath (void);
88
+ extern void error (const errorSelection selection, const char *const format, ...) __printf__ (2, 3);
89
+
90
+ /* Memory allocation functions */
91
+ #ifdef NEED_PROTO_MALLOC
92
+ extern void *malloc (size_t);
93
+ extern void *realloc (void *ptr, size_t);
94
+ #endif
95
+ extern void *eMalloc (const size_t size);
96
+ extern void *eCalloc (const size_t count, const size_t size);
97
+ extern void *eRealloc (void *const ptr, const size_t size);
98
+ extern void eFree (void *const ptr);
99
+
100
+ /* String manipulation functions */
101
+ extern int struppercmp (const char *s1, const char *s2);
102
+ extern int strnuppercmp (const char *s1, const char *s2, size_t n);
103
+ #ifndef HAVE_STRSTR
104
+ extern char* strstr (const char *str, const char *substr);
105
+ #endif
106
+ extern char* eStrdup (const char* str);
107
+ extern void toLowerString (char* str);
108
+ extern void toUpperString (char* str);
109
+ extern char* newLowerString (const char* str);
110
+ extern char* newUpperString (const char* str);
111
+
112
+ /* File system functions */
113
+ extern void setCurrentDirectory (void);
114
+ extern fileStatus *eStat (const char *const fileName);
115
+ extern void eStatFree (fileStatus *status);
116
+ extern boolean doesFileExist (const char *const fileName);
117
+ extern boolean isRecursiveLink (const char* const dirName);
118
+ extern boolean isSameFile (const char *const name1, const char *const name2);
119
+ #if defined(NEED_PROTO_FGETPOS)
120
+ extern int fgetpos (FILE *stream, fpos_t *pos);
121
+ extern int fsetpos (FILE *stream, fpos_t *pos);
122
+ #endif
123
+ extern const char *baseFilename (const char *const filePath);
124
+ extern const char *fileExtension (const char *const fileName);
125
+ extern boolean isAbsolutePath (const char *const path);
126
+ extern vString *combinePathAndFile (const char *const path, const char *const file);
127
+ extern char* absoluteFilename (const char *file);
128
+ extern char* absoluteDirname (char *file);
129
+ extern char* relativeFilename (const char *file, const char *dir);
130
+ extern FILE *tempFile (const char *const mode, char **const pName);
131
+
132
+ #endif /* _ROUTINES_H */
133
+
134
+ /* vi:set tabstop=4 shiftwidth=4: */
@@ -0,0 +1,408 @@
1
+ /*
2
+ * $Id: ruby.c 571 2007-06-24 23:32:14Z elliotth $
3
+ *
4
+ * Copyright (c) 2000-2001, Thaddeus Covert <sahuagin@mediaone.net>
5
+ * Copyright (c) 2002 Matthias Veit <matthias_veit@yahoo.de>
6
+ * Copyright (c) 2004 Elliott Hughes <enh@acm.org>
7
+ *
8
+ * This source code is released for free distribution under the terms of the
9
+ * GNU General Public License.
10
+ *
11
+ * This module contains functions for generating tags for Ruby language
12
+ * files.
13
+ */
14
+
15
+ /*
16
+ * INCLUDE FILES
17
+ */
18
+ #include "general.h" /* must always come first */
19
+
20
+ #include <string.h>
21
+
22
+ #include "entry.h"
23
+ #include "parse.h"
24
+ #include "read.h"
25
+ #include "vstring.h"
26
+
27
+ /*
28
+ * DATA DECLARATIONS
29
+ */
30
+ typedef enum {
31
+ K_UNDEFINED = -1, K_CLASS, K_METHOD, K_MODULE, K_SINGLETON
32
+ } rubyKind;
33
+
34
+ /*
35
+ * DATA DEFINITIONS
36
+ */
37
+ static kindOption RubyKinds [] = {
38
+ { TRUE, 'c', "class", "classes" },
39
+ { TRUE, 'f', "method", "methods" },
40
+ { TRUE, 'm', "module", "modules" },
41
+ { TRUE, 'F', "singleton method", "singleton methods" }
42
+ };
43
+
44
+ static stringList* nesting = 0;
45
+
46
+ /*
47
+ * FUNCTION DEFINITIONS
48
+ */
49
+
50
+ /*
51
+ * Returns a string describing the scope in 'list'.
52
+ * We record the current scope as a list of entered scopes.
53
+ * Scopes corresponding to 'if' statements and the like are
54
+ * represented by empty strings. Scopes corresponding to
55
+ * modules and classes are represented by the name of the
56
+ * module or class.
57
+ */
58
+ static vString* stringListToScope (const stringList* list)
59
+ {
60
+ unsigned int i;
61
+ unsigned int chunks_output = 0;
62
+ vString* result = vStringNew ();
63
+ const unsigned int max = stringListCount (list);
64
+ for (i = 0; i < max; ++i)
65
+ {
66
+ vString* chunk = stringListItem (list, i);
67
+ if (vStringLength (chunk) > 0)
68
+ {
69
+ vStringCatS (result, (chunks_output++ > 0) ? "." : "");
70
+ vStringCatS (result, vStringValue (chunk));
71
+ }
72
+ }
73
+ return result;
74
+ }
75
+
76
+ /*
77
+ * Attempts to advance 's' past 'literal'.
78
+ * Returns TRUE if it did, FALSE (and leaves 's' where
79
+ * it was) otherwise.
80
+ */
81
+ static boolean canMatch (const unsigned char** s, const char* literal)
82
+ {
83
+ const int literal_length = strlen (literal);
84
+ const unsigned char next_char = *(*s + literal_length);
85
+ if (strncmp ((const char*) *s, literal, literal_length) != 0)
86
+ {
87
+ return FALSE;
88
+ }
89
+ /* Additionally check that we're at the end of a token. */
90
+ if ( ! (next_char == 0 || isspace (next_char) || next_char == '('))
91
+ {
92
+ return FALSE;
93
+ }
94
+ *s += literal_length;
95
+ return TRUE;
96
+ }
97
+
98
+ /*
99
+ * Attempts to advance 'cp' past a Ruby operator method name. Returns
100
+ * TRUE if successful (and copies the name into 'name'), FALSE otherwise.
101
+ */
102
+ static boolean parseRubyOperator (vString* name, const unsigned char** cp)
103
+ {
104
+ static const char* RUBY_OPERATORS[] = {
105
+ "[]", "[]=",
106
+ "**",
107
+ "!", "~", "+@", "-@",
108
+ "*", "/", "%",
109
+ "+", "-",
110
+ ">>", "<<",
111
+ "&",
112
+ "^", "|",
113
+ "<=", "<", ">", ">=",
114
+ "<=>", "==", "===", "!=", "=~", "!~",
115
+ "`",
116
+ 0
117
+ };
118
+ int i;
119
+ for (i = 0; RUBY_OPERATORS[i] != 0; ++i)
120
+ {
121
+ if (canMatch (cp, RUBY_OPERATORS[i]))
122
+ {
123
+ vStringCatS (name, RUBY_OPERATORS[i]);
124
+ return TRUE;
125
+ }
126
+ }
127
+ return FALSE;
128
+ }
129
+
130
+ /*
131
+ * Emits a tag for the given 'name' of kind 'kind' at the current nesting.
132
+ */
133
+ static void emitRubyTag (vString* name, rubyKind kind)
134
+ {
135
+ tagEntryInfo tag;
136
+ vString* scope;
137
+
138
+ vStringTerminate (name);
139
+ scope = stringListToScope (nesting);
140
+
141
+ initTagEntry (&tag, vStringValue (name));
142
+ if (vStringLength (scope) > 0) {
143
+ tag.extensionFields.scope [0] = "class";
144
+ tag.extensionFields.scope [1] = vStringValue (scope);
145
+ }
146
+ tag.kindName = RubyKinds [kind].name;
147
+ tag.kind = RubyKinds [kind].letter;
148
+ makeTagEntry (&tag);
149
+
150
+ stringListAdd (nesting, vStringNewCopy (name));
151
+
152
+ vStringClear (name);
153
+ vStringDelete (scope);
154
+ }
155
+
156
+ /* Tests whether 'ch' is a character in 'list'. */
157
+ static boolean charIsIn (char ch, const char* list)
158
+ {
159
+ return (strchr (list, ch) != 0);
160
+ }
161
+
162
+ /* Advances 'cp' over leading whitespace. */
163
+ static void skipWhitespace (const unsigned char** cp)
164
+ {
165
+ while (isspace (**cp))
166
+ {
167
+ ++*cp;
168
+ }
169
+ }
170
+
171
+ /*
172
+ * Copies the characters forming an identifier from *cp into
173
+ * name, leaving *cp pointing to the character after the identifier.
174
+ */
175
+ static rubyKind parseIdentifier (
176
+ const unsigned char** cp, vString* name, rubyKind kind)
177
+ {
178
+ /* Method names are slightly different to class and variable names.
179
+ * A method name may optionally end with a question mark, exclamation
180
+ * point or equals sign. These are all part of the name.
181
+ * A method name may also contain a period if it's a singleton method.
182
+ */
183
+ const char* also_ok = (kind == K_METHOD) ? "_.?!=" : "_";
184
+
185
+ skipWhitespace (cp);
186
+
187
+ /* Check for an anonymous (singleton) class such as "class << HTTP". */
188
+ if (kind == K_CLASS && **cp == '<' && *(*cp + 1) == '<')
189
+ {
190
+ return K_UNDEFINED;
191
+ }
192
+
193
+ /* Check for operators such as "def []=(key, val)". */
194
+ if (kind == K_METHOD || kind == K_SINGLETON)
195
+ {
196
+ if (parseRubyOperator (name, cp))
197
+ {
198
+ return kind;
199
+ }
200
+ }
201
+
202
+ /* Copy the identifier into 'name'. */
203
+ while (**cp != 0 && (isalnum (**cp) || charIsIn (**cp, also_ok)))
204
+ {
205
+ char last_char = **cp;
206
+
207
+ vStringPut (name, last_char);
208
+ ++*cp;
209
+
210
+ if (kind == K_METHOD)
211
+ {
212
+ /* Recognize singleton methods. */
213
+ if (last_char == '.')
214
+ {
215
+ vStringTerminate (name);
216
+ vStringClear (name);
217
+ return parseIdentifier (cp, name, K_SINGLETON);
218
+ }
219
+
220
+ /* Recognize characters which mark the end of a method name. */
221
+ if (charIsIn (last_char, "?!="))
222
+ {
223
+ break;
224
+ }
225
+ }
226
+ }
227
+ return kind;
228
+ }
229
+
230
+ static void readAndEmitTag (const unsigned char** cp, rubyKind expected_kind)
231
+ {
232
+ if (isspace (**cp))
233
+ {
234
+ vString *name = vStringNew ();
235
+ rubyKind actual_kind = parseIdentifier (cp, name, expected_kind);
236
+
237
+ if (actual_kind == K_UNDEFINED || vStringLength (name) == 0)
238
+ {
239
+ /*
240
+ * What kind of tags should we create for code like this?
241
+ *
242
+ * %w(self.clfloor clfloor).each do |name|
243
+ * module_eval <<-"end;"
244
+ * def #{name}(x, y=1)
245
+ * q, r = x.divmod(y)
246
+ * q = q.to_i
247
+ * return q, r
248
+ * end
249
+ * end;
250
+ * end
251
+ *
252
+ * Or this?
253
+ *
254
+ * class << HTTP
255
+ *
256
+ * For now, we don't create any.
257
+ */
258
+ }
259
+ else
260
+ {
261
+ emitRubyTag (name, actual_kind);
262
+ }
263
+ vStringDelete (name);
264
+ }
265
+ }
266
+
267
+ static void enterUnnamedScope (void)
268
+ {
269
+ stringListAdd (nesting, vStringNewInit (""));
270
+ }
271
+
272
+ static void findRubyTags (void)
273
+ {
274
+ const unsigned char *line;
275
+ boolean inMultiLineComment = FALSE;
276
+
277
+ nesting = stringListNew ();
278
+
279
+ /* FIXME: this whole scheme is wrong, because Ruby isn't line-based.
280
+ * You could perfectly well write:
281
+ *
282
+ * def
283
+ * method
284
+ * puts("hello")
285
+ * end
286
+ *
287
+ * if you wished, and this function would fail to recognize anything.
288
+ */
289
+ while ((line = fileReadLine ()) != NULL)
290
+ {
291
+ const unsigned char *cp = line;
292
+
293
+ if (canMatch (&cp, "=begin"))
294
+ {
295
+ inMultiLineComment = TRUE;
296
+ continue;
297
+ }
298
+ if (canMatch (&cp, "=end"))
299
+ {
300
+ inMultiLineComment = FALSE;
301
+ continue;
302
+ }
303
+
304
+ skipWhitespace (&cp);
305
+
306
+ /* Avoid mistakenly starting a scope for modifiers such as
307
+ *
308
+ * return if <exp>
309
+ *
310
+ * FIXME: this is fooled by code such as
311
+ *
312
+ * result = if <exp>
313
+ * <a>
314
+ * else
315
+ * <b>
316
+ * end
317
+ *
318
+ * FIXME: we're also fooled if someone does something heinous such as
319
+ *
320
+ * puts("hello") \
321
+ * unless <exp>
322
+ */
323
+ if (canMatch (&cp, "case") || canMatch (&cp, "for") ||
324
+ canMatch (&cp, "if") || canMatch (&cp, "unless") ||
325
+ canMatch (&cp, "while"))
326
+ {
327
+ enterUnnamedScope ();
328
+ }
329
+
330
+ /*
331
+ * "module M", "class C" and "def m" should only be at the beginning
332
+ * of a line.
333
+ */
334
+ if (canMatch (&cp, "module"))
335
+ {
336
+ readAndEmitTag (&cp, K_MODULE);
337
+ }
338
+ else if (canMatch (&cp, "class"))
339
+ {
340
+ readAndEmitTag (&cp, K_CLASS);
341
+ }
342
+ else if (canMatch (&cp, "def"))
343
+ {
344
+ readAndEmitTag (&cp, K_METHOD);
345
+ }
346
+
347
+ while (*cp != '\0')
348
+ {
349
+ /* FIXME: we don't cope with here documents,
350
+ * or regular expression literals, or ... you get the idea.
351
+ * Hopefully, the restriction above that insists on seeing
352
+ * definitions at the starts of lines should keep us out of
353
+ * mischief.
354
+ */
355
+ if (inMultiLineComment || isspace (*cp))
356
+ {
357
+ ++cp;
358
+ }
359
+ else if (*cp == '#')
360
+ {
361
+ /* FIXME: this is wrong, but there *probably* won't be a
362
+ * definition after an interpolated string (where # doesn't
363
+ * mean 'comment').
364
+ */
365
+ break;
366
+ }
367
+ else if (canMatch (&cp, "begin") || canMatch (&cp, "do"))
368
+ {
369
+ enterUnnamedScope ();
370
+ }
371
+ else if (canMatch (&cp, "end") && stringListCount (nesting) > 0)
372
+ {
373
+ /* Leave the most recent scope. */
374
+ vStringDelete (stringListLast (nesting));
375
+ stringListRemoveLast (nesting);
376
+ }
377
+ else if (*cp == '"')
378
+ {
379
+ /* Skip string literals.
380
+ * FIXME: should cope with escapes and interpolation.
381
+ */
382
+ do {
383
+ ++cp;
384
+ } while (*cp != 0 && *cp != '"');
385
+ }
386
+ else if (*cp != '\0')
387
+ {
388
+ do
389
+ ++cp;
390
+ while (isalnum (*cp) || *cp == '_');
391
+ }
392
+ }
393
+ }
394
+ stringListDelete (nesting);
395
+ }
396
+
397
+ extern parserDefinition* RubyParser (void)
398
+ {
399
+ static const char *const extensions [] = { "rb", "ruby", NULL };
400
+ parserDefinition* def = parserNew ("Ruby");
401
+ def->kinds = RubyKinds;
402
+ def->kindCount = KIND_COUNT (RubyKinds);
403
+ def->extensions = extensions;
404
+ def->parser = findRubyTags;
405
+ return def;
406
+ }
407
+
408
+ /* vi:set tabstop=4 shiftwidth=4: */
@@ -0,0 +1,111 @@
1
+ /*
2
+ * $Id: scheme.c 443 2006-05-30 04:37:13Z darren $
3
+ *
4
+ * Copyright (c) 2000-2002, Darren Hiebert
5
+ *
6
+ * This source code is released for free distribution under the terms of the
7
+ * GNU General Public License.
8
+ *
9
+ * This module contains functions for generating tags for Scheme language
10
+ * files.
11
+ */
12
+
13
+ /*
14
+ * INCLUDE FILES
15
+ */
16
+ #include "general.h" /* must always come first */
17
+
18
+ #include <string.h>
19
+
20
+ #include "parse.h"
21
+ #include "read.h"
22
+ #include "vstring.h"
23
+
24
+ /*
25
+ * DATA DEFINITIONS
26
+ */
27
+ typedef enum {
28
+ K_FUNCTION, K_SET
29
+ } schemeKind;
30
+
31
+ static kindOption SchemeKinds [] = {
32
+ { TRUE, 'f', "function", "functions" },
33
+ { TRUE, 's', "set", "sets" }
34
+ };
35
+
36
+ /*
37
+ * FUNCTION DEFINITIONS
38
+ */
39
+
40
+ /* Algorithm adapted from from GNU etags.
41
+ * Scheme tag functions
42
+ * look for (def... xyzzy
43
+ * look for (def... (xyzzy
44
+ * look for (def ... ((... (xyzzy ....
45
+ * look for (set! xyzzy
46
+ */
47
+ static void readIdentifier (vString *const name, const unsigned char *cp)
48
+ {
49
+ const unsigned char *p;
50
+ vStringClear (name);
51
+ /* Go till you get to white space or a syntactic break */
52
+ for (p = cp; *p != '\0' && *p != '(' && *p != ')' && !isspace (*p); p++)
53
+ vStringPut (name, (int) *p);
54
+ vStringTerminate (name);
55
+ }
56
+
57
+ static void findSchemeTags (void)
58
+ {
59
+ vString *name = vStringNew ();
60
+ const unsigned char *line;
61
+
62
+ while ((line = fileReadLine ()) != NULL)
63
+ {
64
+ const unsigned char *cp = line;
65
+
66
+ if (cp [0] == '(' &&
67
+ (cp [1] == 'D' || cp [1] == 'd') &&
68
+ (cp [2] == 'E' || cp [2] == 'e') &&
69
+ (cp [3] == 'F' || cp [3] == 'f'))
70
+ {
71
+ while (!isspace (*cp))
72
+ cp++;
73
+ /* Skip over open parens and white space */
74
+ while (*cp != '\0' && (isspace (*cp) || *cp == '('))
75
+ cp++;
76
+ readIdentifier (name, cp);
77
+ makeSimpleTag (name, SchemeKinds, K_FUNCTION);
78
+ }
79
+ if (cp [0] == '(' &&
80
+ (cp [1] == 'S' || cp [1] == 's') &&
81
+ (cp [2] == 'E' || cp [2] == 'e') &&
82
+ (cp [3] == 'T' || cp [3] == 't') &&
83
+ (cp [4] == '!' || cp [4] == '!') &&
84
+ (isspace (cp [5])))
85
+ {
86
+ while (*cp != '\0' && !isspace (*cp))
87
+ cp++;
88
+ /* Skip over white space */
89
+ while (isspace (*cp))
90
+ cp++;
91
+ readIdentifier (name, cp);
92
+ makeSimpleTag (name, SchemeKinds, K_SET);
93
+ }
94
+ }
95
+ vStringDelete (name);
96
+ }
97
+
98
+ extern parserDefinition* SchemeParser (void)
99
+ {
100
+ static const char *const extensions [] = {
101
+ "SCM", "SM", "sch", "scheme", "scm", "sm", NULL
102
+ };
103
+ parserDefinition* def = parserNew ("Scheme");
104
+ def->kinds = SchemeKinds;
105
+ def->kindCount = KIND_COUNT (SchemeKinds);
106
+ def->extensions = extensions;
107
+ def->parser = findSchemeTags;
108
+ return def;
109
+ }
110
+
111
+ /* vi:set tabstop=4 shiftwidth=4: */