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