Mercurial > emacs
comparison lib-src/etags.c @ 17602:39b58a508be6
* etags.c [TeX_named_tokens]: Set to FALSE if undefined.
(struct linebuffer): New member `len' is the length of the string.
(find_entries, Pascal_functions, TeX_functions, TEX_getit):
Use it instead of strlen.
(TEX_getit): Declare and define unconditionally as static.
(TeX_functions): Use if instead of #if TeX_named_tokens.
(add_regex): Set RE_INTERVALS flag for regex compilation.
(substitute): Code cleanup.
(readline_internal): Code cleanup, set new member `len'.
(readline): Bug corrected.
author | Francesco Potortì <pot@gnu.org> |
---|---|
date | Wed, 30 Apr 1997 14:57:39 +0000 |
parents | 1b5cc3740793 |
children | c3ff4c535c9c |
comparison
equal
deleted
inserted
replaced
17601:2dd1c9442974 | 17602:39b58a508be6 |
---|---|
29 * Regexp tags by Tom Tromey. | 29 * Regexp tags by Tom Tromey. |
30 * | 30 * |
31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer. | 31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer. |
32 */ | 32 */ |
33 | 33 |
34 char pot_etags_version[] = "@(#) pot revision number is $Revision: 11.84 $"; | 34 char pot_etags_version[] = "@(#) pot revision number is 11.85"; |
35 | 35 |
36 #define TRUE 1 | 36 #define TRUE 1 |
37 #define FALSE 0 | 37 #define FALSE 0 |
38 | 38 |
39 #ifndef DEBUG | 39 #ifndef DEBUG |
40 # define DEBUG FALSE | 40 # define DEBUG FALSE |
41 #endif | |
42 | |
43 #ifndef TeX_named_tokens | |
44 # define TeX_named_tokens FALSE | |
41 #endif | 45 #endif |
42 | 46 |
43 #ifdef MSDOS | 47 #ifdef MSDOS |
44 # include <string.h> | 48 # include <string.h> |
45 # include <fcntl.h> | 49 # include <fcntl.h> |
243 | 247 |
244 /* | 248 /* |
245 * A `struct linebuffer' is a structure which holds a line of text. | 249 * A `struct linebuffer' is a structure which holds a line of text. |
246 * `readline' reads a line from a stream into a linebuffer and works | 250 * `readline' reads a line from a stream into a linebuffer and works |
247 * regardless of the length of the line. | 251 * regardless of the length of the line. |
252 * SIZE is the size of BUFFER, LEN is the length of the string in | |
253 * BUFFER after readline reads it. | |
248 */ | 254 */ |
249 struct linebuffer | 255 struct linebuffer |
250 { | 256 { |
251 long size; | 257 long size; |
258 int len; | |
252 char *buffer; | 259 char *buffer; |
253 }; | 260 }; |
254 | 261 |
255 struct linebuffer lb; /* the current line */ | 262 struct linebuffer lb; /* the current line */ |
256 struct linebuffer token_name; /* used by C_entries as a temporary area */ | 263 struct linebuffer token_name; /* used by C_entries as a temporary area */ |
1204 return; | 1211 return; |
1205 } | 1212 } |
1206 } | 1213 } |
1207 | 1214 |
1208 /* Look for sharp-bang as the first two characters. */ | 1215 /* Look for sharp-bang as the first two characters. */ |
1209 if (readline_internal (&lb, inf) > 2 | 1216 if (readline_internal (&lb, inf) |
1217 && lb.len >= 2 | |
1210 && lb.buffer[0] == '#' | 1218 && lb.buffer[0] == '#' |
1211 && lb.buffer[1] == '!') | 1219 && lb.buffer[1] == '!') |
1212 { | 1220 { |
1213 char *lp; | 1221 char *lp; |
1214 | 1222 |
3112 { | 3120 { |
3113 if (*dbp == '\0') | 3121 if (*dbp == '\0') |
3114 continue; | 3122 continue; |
3115 | 3123 |
3116 /* save all values for later tagging */ | 3124 /* save all values for later tagging */ |
3117 grow_linebuffer (&tline, strlen (lb.buffer) + 1); | 3125 grow_linebuffer (&tline, lb.len + 1); |
3118 strcpy (tline.buffer, lb.buffer); | 3126 strcpy (tline.buffer, lb.buffer); |
3119 save_lineno = lineno; | 3127 save_lineno = lineno; |
3120 save_lcno = linecharno; | 3128 save_lcno = linecharno; |
3121 | 3129 |
3122 /* grab block name */ | 3130 /* grab block name */ |
3339 :part:appendix:entry:index"; | 3347 :part:appendix:entry:index"; |
3340 | 3348 |
3341 void TEX_mode (); | 3349 void TEX_mode (); |
3342 struct TEX_tabent *TEX_decode_env (); | 3350 struct TEX_tabent *TEX_decode_env (); |
3343 int TEX_Token (); | 3351 int TEX_Token (); |
3344 #if TeX_named_tokens | 3352 static void TEX_getit (); |
3345 void TEX_getit (); | |
3346 #endif | |
3347 | 3353 |
3348 char TEX_esc = '\\'; | 3354 char TEX_esc = '\\'; |
3349 char TEX_opgrp = '{'; | 3355 char TEX_opgrp = '{'; |
3350 char TEX_clgrp = '}'; | 3356 char TEX_clgrp = '}'; |
3351 | 3357 |
3385 lasthit = dbp; | 3391 lasthit = dbp; |
3386 i = TEX_Token (lasthit); | 3392 i = TEX_Token (lasthit); |
3387 if (0 <= i) | 3393 if (0 <= i) |
3388 { | 3394 { |
3389 pfnote ((char *)NULL, TRUE, | 3395 pfnote ((char *)NULL, TRUE, |
3390 lb.buffer, strlen (lb.buffer), lineno, linecharno); | 3396 lb.buffer, lb.len, lineno, linecharno); |
3391 #if TeX_named_tokens | 3397 if (TeX_named_tokens) |
3392 TEX_getit (lasthit, TEX_toktab[i].len); | 3398 TEX_getit (lasthit, TEX_toktab[i].len); |
3393 #endif | |
3394 break; /* We only save a line once */ | 3399 break; /* We only save a line once */ |
3395 } | 3400 } |
3396 } | 3401 } |
3397 } | 3402 } |
3398 } | 3403 } |
3483 } | 3488 } |
3484 } | 3489 } |
3485 return tab; | 3490 return tab; |
3486 } | 3491 } |
3487 | 3492 |
3488 #if TeX_named_tokens | |
3489 /* Record a tag defined by a TeX command of length LEN and starting at NAME. | 3493 /* Record a tag defined by a TeX command of length LEN and starting at NAME. |
3490 The name being defined actually starts at (NAME + LEN + 1). | 3494 The name being defined actually starts at (NAME + LEN + 1). |
3491 But we seem to include the TeX command in the tag name. */ | 3495 But we seem to include the TeX command in the tag name. */ |
3492 void | 3496 static void |
3493 TEX_getit (name, len) | 3497 TEX_getit (name, len) |
3494 char *name; | 3498 char *name; |
3495 int len; | 3499 int len; |
3496 { | 3500 { |
3497 char *p = name + len; | 3501 char *p = name + len; |
3501 | 3505 |
3502 /* Let tag name extend to next group close (or end of line) */ | 3506 /* Let tag name extend to next group close (or end of line) */ |
3503 while (*p && *p != TEX_clgrp) | 3507 while (*p && *p != TEX_clgrp) |
3504 p++; | 3508 p++; |
3505 pfnote (savenstr (name, p-name), TRUE, | 3509 pfnote (savenstr (name, p-name), TRUE, |
3506 lb.buffer, strlen (lb.buffer), lineno, linecharno); | 3510 lb.buffer, lb.len, lineno, linecharno); |
3507 } | 3511 } |
3508 #endif | |
3509 | 3512 |
3510 /* If the text at CP matches one of the tag-defining TeX command names, | 3513 /* If the text at CP matches one of the tag-defining TeX command names, |
3511 return the pointer to the first occurrence of that command in TEX_toktab. | 3514 return the pointer to the first occurrence of that command in TEX_toktab. |
3512 Otherwise return -1. | 3515 Otherwise return -1. |
3513 Keep the capital `T' in `Token' for dumb truncating compilers | 3516 Keep the capital `T' in `Token' for dumb truncating compilers |
4013 patbuf->translate = NULL; | 4016 patbuf->translate = NULL; |
4014 patbuf->fastmap = NULL; | 4017 patbuf->fastmap = NULL; |
4015 patbuf->buffer = NULL; | 4018 patbuf->buffer = NULL; |
4016 patbuf->allocated = 0; | 4019 patbuf->allocated = 0; |
4017 | 4020 |
4021 re_syntax_options = RE_INTERVALS; | |
4018 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); | 4022 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); |
4019 if (err != NULL) | 4023 if (err != NULL) |
4020 { | 4024 { |
4021 error ("%s while compiling pattern", err); | 4025 error ("%s while compiling pattern", err); |
4022 return; | 4026 return; |
4042 substitute (in, out, regs) | 4046 substitute (in, out, regs) |
4043 char *in, *out; | 4047 char *in, *out; |
4044 struct re_registers *regs; | 4048 struct re_registers *regs; |
4045 { | 4049 { |
4046 char *result, *t; | 4050 char *result, *t; |
4047 int size, i; | 4051 int size, dig, diglen; |
4048 | 4052 |
4049 result = NULL; | 4053 result = NULL; |
4050 size = strlen (out); | 4054 size = strlen (out); |
4051 | 4055 |
4052 /* Pass 1: figure out how much size to allocate. */ | 4056 /* Pass 1: figure out how much to allocate by finding all \N strings. */ |
4053 if (out[strlen (out) - 1] == '\\') | 4057 if (out[size - 1] == '\\') |
4054 fatal ("pattern error in %s", out); | 4058 fatal ("pattern error in \"%s\"", out); |
4055 for (t = out; *t != '\0'; ++t) | 4059 for (t = etags_strchr (out, '\\'); |
4056 if (*t == '\\' && isdigit (*++t)) | 4060 t != NULL; |
4061 t = etags_strchr (t + 2, '\\')) | |
4062 if (isdigit (t[1])) | |
4057 { | 4063 { |
4058 int dig = *t - '0'; | 4064 dig = t[1] - '0'; |
4059 size += regs->end[dig] - regs->start[dig] - 2; | 4065 diglen = regs->end[dig] - regs->start[dig]; |
4066 size += diglen - 2; | |
4060 } | 4067 } |
4068 else | |
4069 size -= 1; | |
4061 | 4070 |
4062 /* Allocate space and do the substitutions. */ | 4071 /* Allocate space and do the substitutions. */ |
4063 result = xnew (size + 1, char); | 4072 result = xnew (size + 1, char); |
4064 for (i = 0; *out != '\0'; ++out) | 4073 |
4065 { | 4074 for (t = result; *out != '\0'; out++) |
4066 if (*out == '\\' && isdigit (*++out)) | 4075 if (*out == '\\' && isdigit (*++out)) |
4067 { | 4076 { |
4068 /* Using "dig2" satisfies my debugger. Bleah. */ | 4077 /* Using "dig2" satisfies my debugger. Bleah. */ |
4069 int dig2 = *out - '0'; | 4078 dig = *out - '0'; |
4070 int diglen = regs->end[dig2] - regs->start[dig2]; | 4079 diglen = regs->end[dig] - regs->start[dig]; |
4071 strncpy (result + i, in + regs->start[dig2], diglen); | 4080 strncpy (t, in + regs->start[dig], diglen); |
4072 i += diglen; | 4081 t += diglen; |
4073 } | 4082 } |
4074 else | 4083 else |
4075 result[i++] = *out; | 4084 *t++ = *out; |
4076 } | 4085 *t = '\0'; |
4077 result[i] = '\0'; | 4086 |
4078 if (DEBUG && i > size) | 4087 if (DEBUG && (t > result + size || t - result != strlen (result))) |
4079 abort (); | 4088 abort (); |
4080 | 4089 |
4081 return result; | 4090 return result; |
4082 } | 4091 } |
4083 | 4092 |
4127 } | 4136 } |
4128 if (c == '\n') | 4137 if (c == '\n') |
4129 { | 4138 { |
4130 if (p > buffer && p[-1] == '\r') | 4139 if (p > buffer && p[-1] == '\r') |
4131 { | 4140 { |
4132 *--p = '\0'; | 4141 p -= 1; |
4133 #ifdef DOS_NT | 4142 #ifdef DOS_NT |
4134 /* Assume CRLF->LF translation will be performed by Emacs | 4143 /* Assume CRLF->LF translation will be performed by Emacs |
4135 when loading this file, so CRs won't appear in the buffer. | 4144 when loading this file, so CRs won't appear in the buffer. |
4136 It would be cleaner to compensate within Emacs; | 4145 It would be cleaner to compensate within Emacs; |
4137 however, Emacs does not know how many CRs were deleted | 4146 however, Emacs does not know how many CRs were deleted |
4141 chars_deleted = 2; | 4150 chars_deleted = 2; |
4142 #endif | 4151 #endif |
4143 } | 4152 } |
4144 else | 4153 else |
4145 { | 4154 { |
4146 *p = '\0'; | |
4147 chars_deleted = 1; | 4155 chars_deleted = 1; |
4148 } | 4156 } |
4157 *p = '\0'; | |
4149 break; | 4158 break; |
4150 } | 4159 } |
4151 *p++ = c; | 4160 *p++ = c; |
4152 } | 4161 } |
4153 | 4162 linebuffer->len = p - buffer; |
4154 return p - buffer + chars_deleted; | 4163 |
4155 } | 4164 return linebuffer->len + chars_deleted; |
4156 | 4165 } |
4157 /* | 4166 |
4158 * Like readline_internal, above, but try to match the input | 4167 /* |
4159 * line against any existing regular expressions. | 4168 * Like readline_internal, above, but in addition try to match the |
4169 * input line against any existing regular expressions. | |
4160 */ | 4170 */ |
4161 long | 4171 long |
4162 readline (linebuffer, stream) | 4172 readline (linebuffer, stream) |
4163 struct linebuffer *linebuffer; | 4173 struct linebuffer *linebuffer; |
4164 FILE *stream; | 4174 FILE *stream; |
4167 long result = readline_internal (linebuffer, stream); | 4177 long result = readline_internal (linebuffer, stream); |
4168 #ifdef ETAGS_REGEXPS | 4178 #ifdef ETAGS_REGEXPS |
4169 int i; | 4179 int i; |
4170 | 4180 |
4171 /* Match against all listed patterns. */ | 4181 /* Match against all listed patterns. */ |
4172 for (i = 0; i < num_patterns; ++i) | 4182 if (linebuffer->len > 0) |
4173 { | 4183 for (i = 0; i < num_patterns; ++i) |
4174 int match = re_match (patterns[i].pattern, linebuffer->buffer, | 4184 { |
4175 (int)result, 0, &patterns[i].regs); | 4185 int match = re_match (patterns[i].pattern, linebuffer->buffer, |
4176 switch (match) | 4186 linebuffer->len, 0, &patterns[i].regs); |
4177 { | 4187 switch (match) |
4178 case -2: | 4188 { |
4179 /* Some error. */ | 4189 case -2: |
4180 if (!patterns[i].error_signaled) | 4190 /* Some error. */ |
4181 { | 4191 if (!patterns[i].error_signaled) |
4182 error ("error while matching pattern %d", i); | 4192 { |
4183 patterns[i].error_signaled = TRUE; | 4193 error ("error while matching pattern %d", i); |
4184 } | 4194 patterns[i].error_signaled = TRUE; |
4185 break; | 4195 } |
4186 case -1: | 4196 break; |
4187 /* No match. */ | 4197 case -1: |
4188 break; | 4198 /* No match. */ |
4189 default: | 4199 break; |
4190 /* Match occurred. Construct a tag. */ | 4200 default: |
4191 if (patterns[i].name_pattern[0] != '\0') | 4201 /* Match occurred. Construct a tag. */ |
4192 { | 4202 if (patterns[i].name_pattern[0] != '\0') |
4193 /* Make a named tag. */ | 4203 { |
4194 char *name = substitute (linebuffer->buffer, | 4204 /* Make a named tag. */ |
4195 patterns[i].name_pattern, | 4205 char *name = substitute (linebuffer->buffer, |
4196 &patterns[i].regs); | 4206 patterns[i].name_pattern, |
4197 if (name != NULL) | 4207 &patterns[i].regs); |
4198 pfnote (name, TRUE, | 4208 if (name != NULL) |
4209 pfnote (name, TRUE, | |
4210 linebuffer->buffer, match, lineno, linecharno); | |
4211 } | |
4212 else | |
4213 { | |
4214 /* Make an unnamed tag. */ | |
4215 pfnote ((char *)NULL, TRUE, | |
4199 linebuffer->buffer, match, lineno, linecharno); | 4216 linebuffer->buffer, match, lineno, linecharno); |
4200 } | 4217 } |
4201 else | 4218 break; |
4202 { | 4219 } |
4203 /* Make an unnamed tag. */ | 4220 } |
4204 pfnote ((char *)NULL, TRUE, | |
4205 linebuffer->buffer, match, lineno, linecharno); | |
4206 } | |
4207 break; | |
4208 } | |
4209 } | |
4210 #endif /* ETAGS_REGEXPS */ | 4221 #endif /* ETAGS_REGEXPS */ |
4211 | 4222 |
4212 return result; | 4223 return result; |
4213 } | 4224 } |
4214 | 4225 |
4215 /* | 4226 /* |
4216 * Read a file, but do no processing. This is used to do regexp | 4227 * Read a file, but do no processing. This is used to do regexp |