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,106 @@
1
+ /*
2
+ * $Id: qdos.c 443 2006-05-30 04:37:13Z darren $
3
+ *
4
+ * Copyright (c) 1999, Thierry Godefroy <godefroy@imaginet.fr>
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 to handle wildcard expansion and file name
10
+ * conversion under QDOS.
11
+ */
12
+
13
+ #include <stdio.h>
14
+ #include <stdlib.h>
15
+ #include <unistd.h>
16
+ #include <fcntl.h>
17
+ #include <qdos.h>
18
+ #include <string.h>
19
+ #include <errno.h>
20
+ #include "ctags.h"
21
+
22
+ /* Translate the filenames from UNIX to QDOS conventions on open calls */
23
+ int (*_Open) (const char *, int, ...) = qopen;
24
+
25
+ long _stack = 24576; /* Plenty of stack space */
26
+ long _memincr = 10240; /* Big increments to cut fragmentation */
27
+ char _prog_name [] = "ctags";
28
+ char _version [] = PROGRAM_VERSION;
29
+ char _copyright [32] = __DATE__;
30
+ char *_endmsg = "\nPress a key to exit.";
31
+ int custom_expand (char * param, char ***argvptr, int *argcptr);
32
+ int (*_cmdwildcard) () = custom_expand;
33
+
34
+
35
+ struct WINDOWDEF _condetails = { 208, 1, 0, 7, 512, 256, 0, 0};
36
+ void (*_consetup) () = consetup_title;
37
+
38
+ /* custom cmdexpand: also expands directory names */
39
+
40
+ #define FILEBUF_INIT 1024 /* Initial allocation size for buffer */
41
+ #define FILEBUF_INCR 1024 /* Increment size for buffer */
42
+
43
+ int custom_expand (char * param, char ***argvptr, int *argcptr)
44
+ {
45
+ int count,sl;
46
+ size_t bufsize;
47
+ char *filenamebuf;
48
+ char *ptr,*safeptr;
49
+
50
+ /*
51
+ * Check to see if we should do wild card expansion.
52
+ * We only perform wildcard expansion if the parameter
53
+ * was not a string and if it contains one of the
54
+ * wild card characters.
55
+ *
56
+ * We also do not expand any option that starts with '-'
57
+ * as we then assume that it is a unix stylew option.
58
+ */
59
+ if ((*param == '-') || (strpbrk (param,"*?") == NULL) ) {
60
+ return 0;
61
+ }
62
+
63
+ if ((filenamebuf = malloc (bufsize = FILEBUF_INIT)) == NULL) {
64
+ return -1;
65
+ }
66
+ TRYAGAIN:
67
+ count = getfnl (param, filenamebuf, bufsize, QDR_ALL);
68
+ if (count == -1 && errno == ENOMEM) {
69
+ /*
70
+ * We have overflowed the buffer, so we try
71
+ * to get a bigger buffer and try again.
72
+ */
73
+ bufsize += FILEBUF_INCR;
74
+ if ((filenamebuf = realloc (filenamebuf, bufsize)) == NULL) {
75
+ return -1;
76
+ } else {
77
+ goto TRYAGAIN;
78
+ }
79
+ }
80
+ /*
81
+ * If no files were found, then return unexpanded.
82
+ */
83
+ if (count == 0) {
84
+ free (filenamebuf);
85
+ return 0;
86
+ }
87
+ /*
88
+ * Files were found, so add these to the list instead
89
+ * of the original parameter typed by the user.
90
+ */
91
+ for ( ptr=filenamebuf ; count > 0 ; count -- ) {
92
+ *argvptr = (char **) realloc (*argvptr, (size_t) (((*argcptr) + 2) * sizeof (char *)));
93
+ safeptr= (char *) malloc ((size_t) (sl=strlen (ptr) + 1));
94
+ if (safeptr == NULL || *argvptr == NULL) {
95
+ return -1;
96
+ }
97
+ (void) memcpy (safeptr,ptr, (size_t) sl);
98
+ (*argvptr) [*argcptr] = safeptr;
99
+ *argcptr += 1;
100
+ ptr += sl;
101
+ }
102
+ free (filenamebuf);
103
+ return *argcptr;
104
+ }
105
+
106
+ /* vi:set tabstop=4 shiftwidth=4: */
@@ -0,0 +1,569 @@
1
+ /*
2
+ * $Id: read.c 708 2009-07-04 05:29:02Z dhiebert $
3
+ *
4
+ * Copyright (c) 1996-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 low level source and tag file read functions (newline
10
+ * conversion for source files are performed at this level).
11
+ */
12
+
13
+ /*
14
+ * INCLUDE FILES
15
+ */
16
+ #include "general.h" /* must always come first */
17
+
18
+ #include <string.h>
19
+ #include <ctype.h>
20
+
21
+ #define FILE_WRITE
22
+ #include "read.h"
23
+ #include "debug.h"
24
+ #include "entry.h"
25
+ #include "main.h"
26
+ #include "routines.h"
27
+ #include "options.h"
28
+
29
+ /*
30
+ * DATA DEFINITIONS
31
+ */
32
+ inputFile File; /* globally read through macros */
33
+ static fpos_t StartOfLine; /* holds deferred position of start of line */
34
+
35
+ /*
36
+ * FUNCTION DEFINITIONS
37
+ */
38
+
39
+ extern void freeSourceFileResources (void)
40
+ {
41
+ if (File.name != NULL)
42
+ vStringDelete (File.name);
43
+ if (File.path != NULL)
44
+ vStringDelete (File.path);
45
+ if (File.source.name != NULL)
46
+ vStringDelete (File.source.name);
47
+ if (File.source.tagPath != NULL)
48
+ eFree (File.source.tagPath);
49
+ if (File.line != NULL)
50
+ vStringDelete (File.line);
51
+ }
52
+
53
+ /*
54
+ * Source file access functions
55
+ */
56
+
57
+ static void setInputFileName (const char *const fileName)
58
+ {
59
+ const char *const head = fileName;
60
+ const char *const tail = baseFilename (head);
61
+
62
+ if (File.name != NULL)
63
+ vStringDelete (File.name);
64
+ File.name = vStringNewInit (fileName);
65
+
66
+ if (File.path != NULL)
67
+ vStringDelete (File.path);
68
+ if (tail == head)
69
+ File.path = NULL;
70
+ else
71
+ {
72
+ const size_t length = tail - head - 1;
73
+ File.path = vStringNew ();
74
+ vStringNCopyS (File.path, fileName, length);
75
+ }
76
+ }
77
+
78
+ static void setSourceFileParameters (vString *const fileName)
79
+ {
80
+ if (File.source.name != NULL)
81
+ vStringDelete (File.source.name);
82
+ File.source.name = fileName;
83
+
84
+ if (File.source.tagPath != NULL)
85
+ eFree (File.source.tagPath);
86
+ if (! Option.tagRelative || isAbsolutePath (vStringValue (fileName)))
87
+ File.source.tagPath = eStrdup (vStringValue (fileName));
88
+ else
89
+ File.source.tagPath =
90
+ relativeFilename (vStringValue (fileName), TagFile.directory);
91
+
92
+ if (vStringLength (fileName) > TagFile.max.file)
93
+ TagFile.max.file = vStringLength (fileName);
94
+
95
+ File.source.isHeader = isIncludeFile (vStringValue (fileName));
96
+ File.source.language = getFileLanguage (vStringValue (fileName));
97
+ }
98
+
99
+ static boolean setSourceFileName (vString *const fileName)
100
+ {
101
+ boolean result = FALSE;
102
+ if (getFileLanguage (vStringValue (fileName)) != LANG_IGNORE)
103
+ {
104
+ vString *pathName;
105
+ if (isAbsolutePath (vStringValue (fileName)) || File.path == NULL)
106
+ pathName = vStringNewCopy (fileName);
107
+ else
108
+ pathName = combinePathAndFile (
109
+ vStringValue (File.path), vStringValue (fileName));
110
+ setSourceFileParameters (pathName);
111
+ result = TRUE;
112
+ }
113
+ return result;
114
+ }
115
+
116
+ /*
117
+ * Line directive parsing
118
+ */
119
+
120
+ static int skipWhite (void)
121
+ {
122
+ int c;
123
+ do
124
+ c = getc (File.fp);
125
+ while (c == ' ' || c == '\t');
126
+ return c;
127
+ }
128
+
129
+ static unsigned long readLineNumber (void)
130
+ {
131
+ unsigned long lNum = 0;
132
+ int c = skipWhite ();
133
+ while (c != EOF && isdigit (c))
134
+ {
135
+ lNum = (lNum * 10) + (c - '0');
136
+ c = getc (File.fp);
137
+ }
138
+ ungetc (c, File.fp);
139
+ if (c != ' ' && c != '\t')
140
+ lNum = 0;
141
+
142
+ return lNum;
143
+ }
144
+
145
+ /* While ANSI only permits lines of the form:
146
+ * # line n "filename"
147
+ * Earlier compilers generated lines of the form
148
+ * # n filename
149
+ * GNU C will output lines of the form:
150
+ * # n "filename"
151
+ * So we need to be fairly flexible in what we accept.
152
+ */
153
+ static vString *readFileName (void)
154
+ {
155
+ vString *const fileName = vStringNew ();
156
+ boolean quoteDelimited = FALSE;
157
+ int c = skipWhite ();
158
+
159
+ if (c == '"')
160
+ {
161
+ c = getc (File.fp); /* skip double-quote */
162
+ quoteDelimited = TRUE;
163
+ }
164
+ while (c != EOF && c != '\n' &&
165
+ (quoteDelimited ? (c != '"') : (c != ' ' && c != '\t')))
166
+ {
167
+ vStringPut (fileName, c);
168
+ c = getc (File.fp);
169
+ }
170
+ if (c == '\n')
171
+ ungetc (c, File.fp);
172
+ vStringPut (fileName, '\0');
173
+
174
+ return fileName;
175
+ }
176
+
177
+ static boolean parseLineDirective (void)
178
+ {
179
+ boolean result = FALSE;
180
+ int c = skipWhite ();
181
+ DebugStatement ( const char* lineStr = ""; )
182
+
183
+ if (isdigit (c))
184
+ {
185
+ ungetc (c, File.fp);
186
+ result = TRUE;
187
+ }
188
+ else if (c == 'l' && getc (File.fp) == 'i' &&
189
+ getc (File.fp) == 'n' && getc (File.fp) == 'e')
190
+ {
191
+ c = getc (File.fp);
192
+ if (c == ' ' || c == '\t')
193
+ {
194
+ DebugStatement ( lineStr = "line"; )
195
+ result = TRUE;
196
+ }
197
+ }
198
+ if (result)
199
+ {
200
+ const unsigned long lNum = readLineNumber ();
201
+ if (lNum == 0)
202
+ result = FALSE;
203
+ else
204
+ {
205
+ vString *const fileName = readFileName ();
206
+ if (vStringLength (fileName) == 0)
207
+ {
208
+ File.source.lineNumber = lNum - 1; /* applies to NEXT line */
209
+ DebugStatement ( debugPrintf (DEBUG_RAW, "#%s %ld", lineStr, lNum); )
210
+ }
211
+ else if (setSourceFileName (fileName))
212
+ {
213
+ File.source.lineNumber = lNum - 1; /* applies to NEXT line */
214
+ DebugStatement ( debugPrintf (DEBUG_RAW, "#%s %ld \"%s\"",
215
+ lineStr, lNum, vStringValue (fileName)); )
216
+ }
217
+
218
+ if (Option.include.fileNames && vStringLength (fileName) > 0 &&
219
+ lNum == 1)
220
+ {
221
+ tagEntryInfo tag;
222
+ initTagEntry (&tag, baseFilename (vStringValue (fileName)));
223
+
224
+ tag.isFileEntry = TRUE;
225
+ tag.lineNumberEntry = TRUE;
226
+ tag.lineNumber = 1;
227
+ tag.kindName = "file";
228
+ tag.kind = 'F';
229
+
230
+ makeTagEntry (&tag);
231
+ }
232
+ vStringDelete (fileName);
233
+ result = TRUE;
234
+ }
235
+ }
236
+ return result;
237
+ }
238
+
239
+ /*
240
+ * Source file I/O operations
241
+ */
242
+
243
+ /* This function opens a source file, and resets the line counter. If it
244
+ * fails, it will display an error message and leave the File.fp set to NULL.
245
+ */
246
+ extern boolean fileOpen (const char *const fileName, const langType language)
247
+ {
248
+ #ifdef VMS
249
+ const char *const openMode = "r";
250
+ #else
251
+ const char *const openMode = "rb";
252
+ #endif
253
+ boolean opened = FALSE;
254
+
255
+ /* If another file was already open, then close it.
256
+ */
257
+ if (File.fp != NULL)
258
+ {
259
+ fclose (File.fp); /* close any open source file */
260
+ File.fp = NULL;
261
+ }
262
+
263
+ if (Option.stdinFileName) {
264
+ File.fp = stdin;
265
+ } else {
266
+ File.fp = fopen (fileName, openMode);
267
+ }
268
+
269
+ if (File.fp == NULL)
270
+ error (WARNING | PERROR, "cannot open \"%s\"", fileName);
271
+ else
272
+ {
273
+ opened = TRUE;
274
+
275
+ setInputFileName (fileName);
276
+ fgetpos (File.fp, &StartOfLine);
277
+ fgetpos (File.fp, &File.filePosition);
278
+ File.currentLine = NULL;
279
+ File.language = language;
280
+ File.lineNumber = 0L;
281
+ File.eof = FALSE;
282
+ File.newLine = TRUE;
283
+
284
+ if (File.line != NULL)
285
+ vStringClear (File.line);
286
+
287
+ setSourceFileParameters (vStringNewInit (fileName));
288
+ File.source.lineNumber = 0L;
289
+
290
+ verbose ("OPENING %s as %s language %sfile\n", fileName,
291
+ getLanguageName (language),
292
+ File.source.isHeader ? "include " : "");
293
+ }
294
+ return opened;
295
+ }
296
+
297
+ extern void fileClose (void)
298
+ {
299
+ if (File.fp != NULL)
300
+ {
301
+ /* The line count of the file is 1 too big, since it is one-based
302
+ * and is incremented upon each newline.
303
+ */
304
+ if (Option.printTotals)
305
+ {
306
+ fileStatus *status = eStat (vStringValue (File.name));
307
+ addTotals (0, File.lineNumber - 1L, status->size);
308
+ }
309
+ fclose (File.fp);
310
+ File.fp = NULL;
311
+ }
312
+ }
313
+
314
+ extern boolean fileEOF (void)
315
+ {
316
+ return File.eof;
317
+ }
318
+
319
+ /* Action to take for each encountered source newline.
320
+ */
321
+ static void fileNewline (void)
322
+ {
323
+ File.filePosition = StartOfLine;
324
+ File.newLine = FALSE;
325
+ File.lineNumber++;
326
+ File.source.lineNumber++;
327
+ DebugStatement ( if (Option.breakLine == File.lineNumber) lineBreak (); )
328
+ DebugStatement ( debugPrintf (DEBUG_RAW, "%6ld: ", File.lineNumber); )
329
+ }
330
+
331
+ /* This function reads a single character from the stream, performing newline
332
+ * canonicalization.
333
+ */
334
+ static int iFileGetc (void)
335
+ {
336
+ int c;
337
+ readnext:
338
+ c = getc (File.fp);
339
+
340
+ /* If previous character was a newline, then we're starting a line.
341
+ */
342
+ if (File.newLine && c != EOF)
343
+ {
344
+ fileNewline ();
345
+ if (c == '#' && Option.lineDirectives)
346
+ {
347
+ if (parseLineDirective ())
348
+ goto readnext;
349
+ else
350
+ {
351
+ fsetpos (File.fp, &StartOfLine);
352
+ c = getc (File.fp);
353
+ }
354
+ }
355
+ }
356
+
357
+ if (c == EOF)
358
+ File.eof = TRUE;
359
+ else if (c == NEWLINE)
360
+ {
361
+ File.newLine = TRUE;
362
+ fgetpos (File.fp, &StartOfLine);
363
+ }
364
+ else if (c == CRETURN)
365
+ {
366
+ /* Turn line breaks into a canonical form. The three commonly
367
+ * used forms if line breaks: LF (UNIX/Mac OS X), CR (Mac OS 9),
368
+ * and CR-LF (MS-DOS) are converted into a generic newline.
369
+ */
370
+ #ifndef macintosh
371
+ const int next = getc (File.fp); /* is CR followed by LF? */
372
+ if (next != NEWLINE)
373
+ ungetc (next, File.fp);
374
+ else
375
+ #endif
376
+ {
377
+ c = NEWLINE; /* convert CR into newline */
378
+ File.newLine = TRUE;
379
+ fgetpos (File.fp, &StartOfLine);
380
+ }
381
+ }
382
+ DebugStatement ( debugPutc (DEBUG_RAW, c); )
383
+ return c;
384
+ }
385
+
386
+ extern void fileUngetc (int c)
387
+ {
388
+ File.ungetch = c;
389
+ }
390
+
391
+ static vString *iFileGetLine (void)
392
+ {
393
+ vString *result = NULL;
394
+ int c;
395
+ if (File.line == NULL)
396
+ File.line = vStringNew ();
397
+ vStringClear (File.line);
398
+ do
399
+ {
400
+ c = iFileGetc ();
401
+ if (c != EOF)
402
+ vStringPut (File.line, c);
403
+ if (c == '\n' || (c == EOF && vStringLength (File.line) > 0))
404
+ {
405
+ vStringTerminate (File.line);
406
+ #ifdef HAVE_REGEX
407
+ if (vStringLength (File.line) > 0)
408
+ matchRegex (File.line, File.source.language);
409
+ #endif
410
+ result = File.line;
411
+ break;
412
+ }
413
+ } while (c != EOF);
414
+ Assert (result != NULL || File.eof);
415
+ return result;
416
+ }
417
+
418
+ /* Do not mix use of fileReadLine () and fileGetc () for the same file.
419
+ */
420
+ extern int fileGetc (void)
421
+ {
422
+ int c;
423
+
424
+ /* If there is an ungotten character, then return it. Don't do any
425
+ * other processing on it, though, because we already did that the
426
+ * first time it was read through fileGetc ().
427
+ */
428
+ if (File.ungetch != '\0')
429
+ {
430
+ c = File.ungetch;
431
+ File.ungetch = '\0';
432
+ return c; /* return here to avoid re-calling debugPutc () */
433
+ }
434
+ do
435
+ {
436
+ if (File.currentLine != NULL)
437
+ {
438
+ c = *File.currentLine++;
439
+ if (c == '\0')
440
+ File.currentLine = NULL;
441
+ }
442
+ else
443
+ {
444
+ vString* const line = iFileGetLine ();
445
+ if (line != NULL)
446
+ File.currentLine = (unsigned char*) vStringValue (line);
447
+ if (File.currentLine == NULL)
448
+ c = EOF;
449
+ else
450
+ c = '\0';
451
+ }
452
+ } while (c == '\0');
453
+ DebugStatement ( debugPutc (DEBUG_READ, c); )
454
+ return c;
455
+ }
456
+
457
+ extern int fileSkipToCharacter (int c)
458
+ {
459
+ int d;
460
+ do
461
+ {
462
+ d = fileGetc ();
463
+ } while (d != EOF && d != c);
464
+ return d;
465
+ }
466
+
467
+ /* An alternative interface to fileGetc (). Do not mix use of fileReadLine()
468
+ * and fileGetc() for the same file. The returned string does not contain
469
+ * the terminating newline. A NULL return value means that all lines in the
470
+ * file have been read and we are at the end of file.
471
+ */
472
+ extern const unsigned char *fileReadLine (void)
473
+ {
474
+ vString* const line = iFileGetLine ();
475
+ const unsigned char* result = NULL;
476
+ if (line != NULL)
477
+ {
478
+ result = (const unsigned char*) vStringValue (line);
479
+ vStringStripNewline (line);
480
+ DebugStatement ( debugPrintf (DEBUG_READ, "%s\n", result); )
481
+ }
482
+ return result;
483
+ }
484
+
485
+ /*
486
+ * Source file line reading with automatic buffer sizing
487
+ */
488
+ extern char *readLine (vString *const vLine, FILE *const fp)
489
+ {
490
+ char *result = NULL;
491
+
492
+ vStringClear (vLine);
493
+ if (fp == NULL) /* to free memory allocated to buffer */
494
+ error (FATAL, "NULL file pointer");
495
+ else
496
+ {
497
+ boolean reReadLine;
498
+
499
+ /* If reading the line places any character other than a null or a
500
+ * newline at the last character position in the buffer (one less
501
+ * than the buffer size), then we must resize the buffer and
502
+ * reattempt to read the line.
503
+ */
504
+ do
505
+ {
506
+ char *const pLastChar = vStringValue (vLine) + vStringSize (vLine) -2;
507
+ fpos_t startOfLine;
508
+
509
+ fgetpos (fp, &startOfLine);
510
+ reReadLine = FALSE;
511
+ *pLastChar = '\0';
512
+ result = fgets (vStringValue (vLine), (int) vStringSize (vLine), fp);
513
+ if (result == NULL)
514
+ {
515
+ if (! feof (fp))
516
+ error (FATAL | PERROR, "Failure on attempt to read file");
517
+ }
518
+ else if (*pLastChar != '\0' &&
519
+ *pLastChar != '\n' && *pLastChar != '\r')
520
+ {
521
+ /* buffer overflow */
522
+ reReadLine = vStringAutoResize (vLine);
523
+ if (reReadLine)
524
+ fsetpos (fp, &startOfLine);
525
+ else
526
+ error (FATAL | PERROR, "input line too big; out of memory");
527
+ }
528
+ else
529
+ {
530
+ char* eol;
531
+ vStringSetLength (vLine);
532
+ /* canonicalize new line */
533
+ eol = vStringValue (vLine) + vStringLength (vLine) - 1;
534
+ if (*eol == '\r')
535
+ *eol = '\n';
536
+ else if (*(eol - 1) == '\r' && *eol == '\n')
537
+ {
538
+ *(eol - 1) = '\n';
539
+ *eol = '\0';
540
+ --vLine->length;
541
+ }
542
+ }
543
+ } while (reReadLine);
544
+ }
545
+ return result;
546
+ }
547
+
548
+ /* Places into the line buffer the contents of the line referenced by
549
+ * "location".
550
+ */
551
+ extern char *readSourceLine (
552
+ vString *const vLine, fpos_t location, long *const pSeekValue)
553
+ {
554
+ fpos_t orignalPosition;
555
+ char *result;
556
+
557
+ fgetpos (File.fp, &orignalPosition);
558
+ fsetpos (File.fp, &location);
559
+ if (pSeekValue != NULL)
560
+ *pSeekValue = ftell (File.fp);
561
+ result = readLine (vLine, File.fp);
562
+ if (result == NULL)
563
+ error (FATAL, "Unexpected end of file: %s", vStringValue (File.name));
564
+ fsetpos (File.fp, &orignalPosition);
565
+
566
+ return result;
567
+ }
568
+
569
+ /* vi:set tabstop=4 shiftwidth=4: */