aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorFrancesco Potortì2002-08-28 10:35:51 +0000
committerFrancesco Potortì2002-08-28 10:35:51 +0000
commit61a1f6fa606ddaeec05718b8d96244f7bac97232 (patch)
tree0caab0edce648b84f4522ec34a2d072a4e369847 /lib-src
parent87046df8c763660ac9c81307de5195b6761e2329 (diff)
downloademacs-61a1f6fa606ddaeec05718b8d96244f7bac97232.tar.gz
emacs-61a1f6fa606ddaeec05718b8d96244f7bac97232.zip
Two bug corrections and one new feature.
(Ada_funcs): Do not tag "use type Xxxx;". New language HTML. (make_tag): Never generate null length tag names. (linebuffer_init): Renamed from initbuffer. All callers changed. (pattern): Structure renamed to `regexp', member regex renamed to pattern. (node_st): Member pat renamed to regex. (pattern); New member force_explicit_name, for future use. Now always set to true, cannot be reset. (add_regex, regex_tag_multiline, readline): Use it. (main): Free some global structures. (fdesc): New member `written'. (readline, process_file): Initialise it. (put_entries): Set it. (main): Use it to create entries for files without tags. (total_size_of_entries): Do not count invalid tags. (etags_strcasecmp): Like BSD's, for compatibility. (strcaseeq): Make it into a macro.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c501
1 files changed, 345 insertions, 156 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index e6ca44d968e..2e3ac148379 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -35,7 +35,7 @@
35 * 35 *
36 */ 36 */
37 37
38char pot_etags_version[] = "@(#) pot revision number is 16.32"; 38char pot_etags_version[] = "@(#) pot revision number is 16.42";
39 39
40#define TRUE 1 40#define TRUE 1
41#define FALSE 0 41#define FALSE 0
@@ -187,15 +187,17 @@ If you want regular expression support, you should delete this notice and
187#endif 187#endif
188 188
189#define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t)) 189#define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
190#define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
190#define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n)) 191#define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
192#define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
191 193
192#define CHARS 256 /* 2^sizeof(char) */ 194#define CHARS 256 /* 2^sizeof(char) */
193#define CHAR(x) ((unsigned int)(x) & (CHARS - 1)) 195#define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
194#define iswhite(c) (_wht[CHAR(c)]) /* c is white */ 196#define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
195#define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ 197#define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
196#define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ 198#define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
197#define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ 199#define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
198#define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ 200#define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
199 201
200#define ISALNUM(c) isalnum (CHAR(c)) 202#define ISALNUM(c) isalnum (CHAR(c))
201#define ISALPHA(c) isalpha (CHAR(c)) 203#define ISALPHA(c) isalpha (CHAR(c))
@@ -254,6 +256,7 @@ typedef struct fdesc
254 language *lang; /* language of file */ 256 language *lang; /* language of file */
255 char *prop; /* file properties to write in tagfile */ 257 char *prop; /* file properties to write in tagfile */
256 bool usecharno; /* etags tags shall contain char number */ 258 bool usecharno; /* etags tags shall contain char number */
259 bool written; /* entry written in the tags file */
257} fdesc; 260} fdesc;
258 261
259typedef struct node_st 262typedef struct node_st
@@ -261,9 +264,9 @@ typedef struct node_st
261 struct node_st *left, *right; /* left and right sons */ 264 struct node_st *left, *right; /* left and right sons */
262 fdesc *fdp; /* description of file to whom tag belongs */ 265 fdesc *fdp; /* description of file to whom tag belongs */
263 char *name; /* tag name */ 266 char *name; /* tag name */
264 char *pat; /* search pattern */ 267 char *regex; /* search regexp */
265 bool valid; /* write this tag on the tag file */ 268 bool valid; /* write this tag on the tag file */
266 bool is_func; /* function tag: use pattern in CTAGS mode */ 269 bool is_func; /* function tag: use regexp in CTAGS mode */
267 bool been_warned; /* warning already given for duplicated tag */ 270 bool been_warned; /* warning already given for duplicated tag */
268 int lno; /* line number tag is on */ 271 int lno; /* line number tag is on */
269 long cno; /* character number line starts on */ 272 long cno; /* character number line starts on */
@@ -298,18 +301,19 @@ typedef struct
298 301
299#ifdef ETAGS_REGEXPS 302#ifdef ETAGS_REGEXPS
300/* Structure defining a regular expression. */ 303/* Structure defining a regular expression. */
301typedef struct pattern 304typedef struct regexp
302{ 305{
303 struct pattern *p_next; 306 struct regexp *p_next; /* pointer to next in list */
304 language *lang; 307 language *lang; /* if set, use only for this language */
305 char *regex; 308 char *pattern; /* the regexp pattern */
306 struct re_pattern_buffer *pat; 309 char *name; /* tag name */
307 struct re_registers regs; 310 struct re_pattern_buffer *pat; /* the compiled pattern */
308 char *name_pattern; 311 struct re_registers regs; /* re registers */
309 bool error_signaled; 312 bool error_signaled; /* already signaled for this regexp */
310 bool ignore_case; 313 bool force_explicit_name; /* do not allow implict tag name */
311 bool multi_line; 314 bool ignore_case; /* ignore case when matching */
312} pattern; 315 bool multi_line; /* do a multi-line match on the whole file */
316} regexp;
313#endif /* ETAGS_REGEXPS */ 317#endif /* ETAGS_REGEXPS */
314 318
315 319
@@ -327,7 +331,7 @@ static void Cplusplus_entries __P((FILE *));
327static void Cstar_entries __P((FILE *)); 331static void Cstar_entries __P((FILE *));
328static void Erlang_functions __P((FILE *)); 332static void Erlang_functions __P((FILE *));
329static void Fortran_functions __P((FILE *)); 333static void Fortran_functions __P((FILE *));
330static void Yacc_entries __P((FILE *)); 334static void HTML_labels __P((FILE *));
331static void Lisp_functions __P((FILE *)); 335static void Lisp_functions __P((FILE *));
332static void Makefile_targets __P((FILE *)); 336static void Makefile_targets __P((FILE *));
333static void Pascal_functions __P((FILE *)); 337static void Pascal_functions __P((FILE *));
@@ -339,6 +343,7 @@ static void Python_functions __P((FILE *));
339static void Scheme_functions __P((FILE *)); 343static void Scheme_functions __P((FILE *));
340static void TeX_commands __P((FILE *)); 344static void TeX_commands __P((FILE *));
341static void Texinfo_nodes __P((FILE *)); 345static void Texinfo_nodes __P((FILE *));
346static void Yacc_entries __P((FILE *));
342static void just_read_file __P((FILE *)); 347static void just_read_file __P((FILE *));
343 348
344static void print_language_names __P((void)); 349static void print_language_names __P((void));
@@ -357,7 +362,7 @@ static void get_tag __P((char *, char **));
357 362
358#ifdef ETAGS_REGEXPS 363#ifdef ETAGS_REGEXPS
359static void analyse_regex __P((char *)); 364static void analyse_regex __P((char *));
360static void free_patterns __P((void)); 365static void free_regexps __P((void));
361static void regex_tag_multiline __P((void)); 366static void regex_tag_multiline __P((void));
362#endif /* ETAGS_REGEXPS */ 367#endif /* ETAGS_REGEXPS */
363static void error __P((const char *, const char *)); 368static void error __P((const char *, const char *));
@@ -367,7 +372,6 @@ static void pfatal __P((char *));
367static void add_node __P((node *, node **)); 372static void add_node __P((node *, node **));
368 373
369static void init __P((void)); 374static void init __P((void));
370static void initbuffer __P((linebuffer *));
371static void process_file_name __P((char *, language *)); 375static void process_file_name __P((char *, language *));
372static void process_file __P((FILE *, char *, language *)); 376static void process_file __P((FILE *, char *, language *));
373static void find_entries __P((FILE *)); 377static void find_entries __P((FILE *));
@@ -385,13 +389,15 @@ static char *savenstr __P((char *, int));
385static char *savestr __P((char *)); 389static char *savestr __P((char *));
386static char *etags_strchr __P((const char *, int)); 390static char *etags_strchr __P((const char *, int));
387static char *etags_strrchr __P((const char *, int)); 391static char *etags_strrchr __P((const char *, int));
388static bool strcaseeq __P((const char *, const char *)); 392static int etags_strcasecmp __P((const char *, const char *));
393static int etags_strncasecmp __P((const char *, const char *, int));
389static char *etags_getcwd __P((void)); 394static char *etags_getcwd __P((void));
390static char *relative_filename __P((char *, char *)); 395static char *relative_filename __P((char *, char *));
391static char *absolute_filename __P((char *, char *)); 396static char *absolute_filename __P((char *, char *));
392static char *absolute_dirname __P((char *, char *)); 397static char *absolute_dirname __P((char *, char *));
393static bool filename_is_absolute __P((char *f)); 398static bool filename_is_absolute __P((char *f));
394static void canonicalize_filename __P((char *)); 399static void canonicalize_filename __P((char *));
400static void linebuffer_init __P((linebuffer *));
395static void linebuffer_setlen __P((linebuffer *, int)); 401static void linebuffer_setlen __P((linebuffer *, int));
396static PTR xmalloc __P((unsigned int)); 402static PTR xmalloc __P((unsigned int));
397static PTR xrealloc __P((char *, unsigned int)); 403static PTR xrealloc __P((char *, unsigned int));
@@ -419,6 +425,7 @@ static node *last_node; /* the last node created */
419 425
420static linebuffer lb; /* the current line */ 426static linebuffer lb; /* the current line */
421static linebuffer filebuf; /* a buffer containing the whole file */ 427static linebuffer filebuf; /* a buffer containing the whole file */
428static linebuffer token_name; /* a buffer containing a tag name */
422 429
423/* boolean "functions" (see init) */ 430/* boolean "functions" (see init) */
424static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; 431static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
@@ -459,7 +466,7 @@ static bool packages_only; /* --packages-only: in Ada, only tag packages*/
459static bool parsing_stdin; /* --parse-stdin used */ 466static bool parsing_stdin; /* --parse-stdin used */
460 467
461#ifdef ETAGS_REGEXPS 468#ifdef ETAGS_REGEXPS
462static pattern *p_head; /* list of all regexps */ 469static regexp *p_head; /* list of all regexps */
463static bool need_filebuf; /* some regexes are multi-line */ 470static bool need_filebuf; /* some regexes are multi-line */
464#else 471#else
465# define need_filebuf FALSE 472# define need_filebuf FALSE
@@ -566,6 +573,9 @@ static char *Erlang_suffixes [] =
566static char *Fortran_suffixes [] = 573static char *Fortran_suffixes [] =
567 { "F", "f", "f90", "for", NULL }; 574 { "F", "f", "f90", "for", NULL };
568 575
576static char *HTML_suffixes [] =
577 { "htm", "html", "shtml", NULL };
578
569static char *Lisp_suffixes [] = 579static char *Lisp_suffixes [] =
570 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL }; 580 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
571 581
@@ -629,6 +639,7 @@ static language lang_names [] =
629 { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL }, 639 { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL },
630 { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL }, 640 { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL },
631 { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL }, 641 { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL },
642 { "html", FALSE, HTML_labels, NULL, HTML_suffixes, NULL },
632 { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL }, 643 { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL },
633 { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL }, 644 { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL },
634 { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL }, 645 { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL },
@@ -1142,9 +1153,10 @@ main (argc, argv)
1142 1153
1143 init (); /* set up boolean "functions" */ 1154 init (); /* set up boolean "functions" */
1144 1155
1145 initbuffer (&lb); 1156 linebuffer_init (&lb);
1146 initbuffer (&filename_lb); 1157 linebuffer_init (&filename_lb);
1147 initbuffer (&filebuf); 1158 linebuffer_init (&filebuf);
1159 linebuffer_init (&token_name);
1148 1160
1149 if (!CTAGS) 1161 if (!CTAGS)
1150 { 1162 {
@@ -1222,9 +1234,11 @@ main (argc, argv)
1222 } 1234 }
1223 1235
1224#ifdef ETAGS_REGEXPS 1236#ifdef ETAGS_REGEXPS
1225 free_patterns (); 1237 free_regexps ();
1226#endif /* ETAGS_REGEXPS */ 1238#endif /* ETAGS_REGEXPS */
1239 free (lb.buffer);
1227 free (filebuf.buffer); 1240 free (filebuf.buffer);
1241 free (token_name.buffer);
1228 1242
1229 if (!CTAGS || cxref_style) 1243 if (!CTAGS || cxref_style)
1230 { 1244 {
@@ -1232,8 +1246,17 @@ main (argc, argv)
1232 free_tree (nodehead); 1246 free_tree (nodehead);
1233 nodehead = NULL; 1247 nodehead = NULL;
1234 if (!CTAGS) 1248 if (!CTAGS)
1235 while (nincluded_files-- > 0) 1249 {
1236 fprintf (tagf, "\f\n%s,include\n", *included_files++); 1250 fdesc *fdp;
1251
1252 /* Output file entries that have no tags. */
1253 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
1254 if (!fdp->written)
1255 fprintf (tagf, "\f\n%s,0\n", fdp->taggedfname);
1256
1257 while (nincluded_files-- > 0)
1258 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1259 }
1237 1260
1238 if (fclose (tagf) == EOF) 1261 if (fclose (tagf) == EOF)
1239 pfatal (tagfile); 1262 pfatal (tagfile);
@@ -1562,6 +1585,7 @@ process_file (fh, fn, lang)
1562 } 1585 }
1563 fdp->usecharno = TRUE; /* use char position when making tags */ 1586 fdp->usecharno = TRUE; /* use char position when making tags */
1564 fdp->prop = NULL; 1587 fdp->prop = NULL;
1588 fdp->written = FALSE; /* not written on tags file yet */
1565 1589
1566 fdhead = fdp; 1590 fdhead = fdp;
1567 curfdp = fdhead; /* the current file description */ 1591 curfdp = fdhead; /* the current file description */
@@ -1761,7 +1785,7 @@ find_entries (inf)
1761 assert (parser != NULL); 1785 assert (parser != NULL);
1762 1786
1763 /* Generic initialisations before reading from file. */ 1787 /* Generic initialisations before reading from file. */
1764 filebuf.len = 0; /* reset the file buffer */ 1788 linebuffer_setlen (&filebuf, 0); /* reset the file buffer */
1765 1789
1766 /* Generic initialisations before parsing file with readline. */ 1790 /* Generic initialisations before parsing file with readline. */
1767 lineno = 0; /* reset global line number */ 1791 lineno = 0; /* reset global line number */
@@ -1809,9 +1833,11 @@ make_tag (name, namelen, is_func, linestart, linelen, lno, cno)
1809 int lno; /* line number */ 1833 int lno; /* line number */
1810 long cno; /* character number */ 1834 long cno; /* character number */
1811{ 1835{
1812 bool named = TRUE; 1836 bool named = (name != NULL && namelen > 0);
1813 1837
1814 if (!CTAGS && name != NULL && namelen > 0) 1838 if (!CTAGS && named) /* maybe set named to false */
1839 /* Let's try to make an implicit tag name, that is, create an unnamed tag
1840 such that etags.el can guess a name from it. */
1815 { 1841 {
1816 int i; 1842 int i;
1817 register char *cp = name; 1843 register char *cp = name;
@@ -1885,12 +1911,12 @@ pfnote (name, is_func, linestart, linelen, lno, cno)
1885 if (CTAGS && !cxref_style) 1911 if (CTAGS && !cxref_style)
1886 { 1912 {
1887 if (strlen (linestart) < 50) 1913 if (strlen (linestart) < 50)
1888 np->pat = concat (linestart, "$", ""); 1914 np->regex = concat (linestart, "$", "");
1889 else 1915 else
1890 np->pat = savenstr (linestart, 50); 1916 np->regex = savenstr (linestart, 50);
1891 } 1917 }
1892 else 1918 else
1893 np->pat = savenstr (linestart, linelen); 1919 np->regex = savenstr (linestart, linelen);
1894 1920
1895 add_node (np, &nodehead); 1921 add_node (np, &nodehead);
1896} 1922}
@@ -1909,7 +1935,7 @@ free_tree (np)
1909 free_tree (np->left); 1935 free_tree (np->left);
1910 if (np->name != NULL) 1936 if (np->name != NULL)
1911 free (np->name); 1937 free (np->name);
1912 free (np->pat); 1938 free (np->regex);
1913 free (np); 1939 free (np);
1914 np = node_right; 1940 np = node_right;
1915 } 1941 }
@@ -2083,15 +2109,16 @@ total_size_of_entries (np)
2083 register int total = 0; 2109 register int total = 0;
2084 2110
2085 for (; np != NULL; np = np->right) 2111 for (; np != NULL; np = np->right)
2086 { 2112 if (np->valid)
2087 total += strlen (np->pat) + 1; /* pat\177 */ 2113 {
2088 if (np->name != NULL) 2114 total += strlen (np->regex) + 1; /* pat\177 */
2089 total += strlen (np->name) + 1; /* name\001 */ 2115 if (np->name != NULL)
2090 total += number_len ((long) np->lno) + 1; /* lno, */ 2116 total += strlen (np->name) + 1; /* name\001 */
2091 if (np->cno != invalidcharno) /* cno */ 2117 total += number_len ((long) np->lno) + 1; /* lno, */
2092 total += number_len (np->cno); 2118 if (np->cno != invalidcharno) /* cno */
2093 total += 1; /* newline */ 2119 total += number_len (np->cno);
2094 } 2120 total += 1; /* newline */
2121 }
2095 2122
2096 return total; 2123 return total;
2097} 2124}
@@ -2121,8 +2148,9 @@ put_entries (np)
2121 fdp = np->fdp; 2148 fdp = np->fdp;
2122 fprintf (tagf, "\f\n%s,%d\n", 2149 fprintf (tagf, "\f\n%s,%d\n",
2123 fdp->taggedfname, total_size_of_entries (np)); 2150 fdp->taggedfname, total_size_of_entries (np));
2151 fdp->written = TRUE;
2124 } 2152 }
2125 fputs (np->pat, tagf); 2153 fputs (np->regex, tagf);
2126 fputc ('\177', tagf); 2154 fputc ('\177', tagf);
2127 if (np->name != NULL) 2155 if (np->name != NULL)
2128 { 2156 {
@@ -2147,7 +2175,7 @@ put_entries (np)
2147 np->name, np->fdp->taggedfname, (np->lno + 63) / 64); 2175 np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
2148 else 2176 else
2149 fprintf (stdout, "%-16s %3d %-16s %s\n", 2177 fprintf (stdout, "%-16s %3d %-16s %s\n",
2150 np->name, np->lno, np->fdp->taggedfname, np->pat); 2178 np->name, np->lno, np->fdp->taggedfname, np->regex);
2151 } 2179 }
2152 else 2180 else
2153 { 2181 {
@@ -2158,7 +2186,7 @@ put_entries (np)
2158 putc (searchar, tagf); 2186 putc (searchar, tagf);
2159 putc ('^', tagf); 2187 putc ('^', tagf);
2160 2188
2161 for (sp = np->pat; *sp; sp++) 2189 for (sp = np->regex; *sp; sp++)
2162 { 2190 {
2163 if (*sp == '\\' || *sp == searchar) 2191 if (*sp == '\\' || *sp == searchar)
2164 putc ('\\', tagf); 2192 putc ('\\', tagf);
@@ -2550,7 +2578,6 @@ static struct tok
2550 long linepos; 2578 long linepos;
2551 char *line; 2579 char *line;
2552} token; /* latest token read */ 2580} token; /* latest token read */
2553static linebuffer token_name; /* its name */
2554 2581
2555/* 2582/*
2556 * Variables and functions for dealing with nested structures. 2583 * Variables and functions for dealing with nested structures.
@@ -3030,9 +3057,8 @@ C_entries (c_ext, inf)
3030 struct tok savetoken; /* token saved during preprocessor handling */ 3057 struct tok savetoken; /* token saved during preprocessor handling */
3031 3058
3032 3059
3033 initbuffer (&token_name); 3060 linebuffer_init (&lbs[0].lb);
3034 initbuffer (&lbs[0].lb); 3061 linebuffer_init (&lbs[1].lb);
3035 initbuffer (&lbs[1].lb);
3036 if (cstack.size == 0) 3062 if (cstack.size == 0)
3037 { 3063 {
3038 cstack.size = (DEBUG) ? 1 : 4; 3064 cstack.size = (DEBUG) ? 1 : 4;
@@ -3765,7 +3791,6 @@ C_entries (c_ext, inf)
3765 3791
3766 } /* while not eof */ 3792 } /* while not eof */
3767 3793
3768 free (token_name.buffer);
3769 free (lbs[0].lb.buffer); 3794 free (lbs[0].lb.buffer);
3770 free (lbs[1].lb.buffer); 3795 free (lbs[1].lb.buffer);
3771} 3796}
@@ -3981,7 +4006,7 @@ Fortran_functions (inf)
3981/* 4006/*
3982 * Ada parsing 4007 * Ada parsing
3983 * Original code by 4008 * Original code by
3984 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998) 4009 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.int> (1998)
3985 */ 4010 */
3986 4011
3987static void Ada_getit __P((FILE *, char *)); 4012static void Ada_getit __P((FILE *, char *));
@@ -4058,6 +4083,7 @@ Ada_funcs (inf)
4058 FILE *inf; 4083 FILE *inf;
4059{ 4084{
4060 bool inquote = FALSE; 4085 bool inquote = FALSE;
4086 bool skip_till_semicolumn = FALSE;
4061 4087
4062 LOOP_ON_INPUT_LINES (inf, lb, dbp) 4088 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4063 { 4089 {
@@ -4094,6 +4120,14 @@ Ada_funcs (inf)
4094 continue; 4120 continue;
4095 } 4121 }
4096 4122
4123 if (skip_till_semicolumn)
4124 {
4125 if (*dbp == ';')
4126 skip_till_semicolumn = FALSE;
4127 dbp++;
4128 continue; /* advance char */
4129 }
4130
4097 /* Search for beginning of a token. */ 4131 /* Search for beginning of a token. */
4098 if (!begtoken (*dbp)) 4132 if (!begtoken (*dbp))
4099 { 4133 {
@@ -4120,6 +4154,16 @@ Ada_funcs (inf)
4120 else 4154 else
4121 break; /* from switch */ 4155 break; /* from switch */
4122 continue; /* advance char */ 4156 continue; /* advance char */
4157
4158 case 'u':
4159 if (typedefs && !packages_only && nocase_tail ("use"))
4160 {
4161 /* when tagging types, avoid tagging use type Pack.Typename;
4162 for this, we will skip everything till a ; */
4163 skip_till_semicolumn = TRUE;
4164 continue; /* advance char */
4165 }
4166
4123 case 't': 4167 case 't':
4124 if (!packages_only && nocase_tail ("task")) 4168 if (!packages_only && nocase_tail ("task"))
4125 Ada_getit (inf, "/k"); 4169 Ada_getit (inf, "/k");
@@ -4456,7 +4500,7 @@ Pascal_functions (inf)
4456 name = NULL; /* keep compiler quiet */ 4500 name = NULL; /* keep compiler quiet */
4457 dbp = lb.buffer; 4501 dbp = lb.buffer;
4458 *dbp = '\0'; 4502 *dbp = '\0';
4459 initbuffer (&tline); 4503 linebuffer_init (&tline);
4460 4504
4461 incomment = inquote = FALSE; 4505 incomment = inquote = FALSE;
4462 found_tag = FALSE; /* have a proc name; check if extern */ 4506 found_tag = FALSE; /* have a proc name; check if extern */
@@ -4542,7 +4586,7 @@ Pascal_functions (inf)
4542 } 4586 }
4543 else if (lowcase (*dbp) == 'f') 4587 else if (lowcase (*dbp) == 'f')
4544 { 4588 {
4545 if (nocase_tail ("forward")) /* check for forward reference */ 4589 if (nocase_tail ("forward")) /* check for forward reference */
4546 { 4590 {
4547 found_tag = FALSE; 4591 found_tag = FALSE;
4548 verify_tag = FALSE; 4592 verify_tag = FALSE;
@@ -4925,6 +4969,127 @@ Texinfo_nodes (inf)
4925} 4969}
4926 4970
4927 4971
4972/* Similar to LOOKING_AT but does not use notinname, does not skip */
4973#define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \
4974 (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4975 && ((cp) += sizeof(kw)-1)) /* skip spaces */
4976
4977/*
4978 * HTML support.
4979 * Contents of <title>, <h1>, <h2>, <h3> are tags.
4980 * Contents of <a name=xxx> are tags with name xxx.
4981 *
4982 * Francesco Potortì, 2002.
4983 */
4984static void
4985HTML_labels (inf)
4986 FILE * inf;
4987{
4988 bool getnext = FALSE; /* next text outside of HTML tags is a tag */
4989 bool ignoretag = FALSE; /* skip to the end of the current HTML tag */
4990 bool inanchor = FALSE; /* inside an A HTML tag, looking for NAME= */
4991 char *end;
4992
4993
4994 linebuffer_setlen (&token_name, 0); /* no name in buffer */
4995
4996 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4997 {
4998 for (;;) /* loop on the same line */
4999
5000 if (ignoretag) /* skip HTML tag */
5001 {
5002 while (*dbp != '\0' && *dbp != '>')
5003 dbp++;
5004 if (*dbp == '>')
5005 {
5006 dbp += 1;
5007 ignoretag = FALSE;
5008 continue; /* look on the same line */
5009 }
5010 break; /* go to next line */
5011 }
5012
5013 else if (inanchor) /* look for "name=" */
5014 {
5015 while (*dbp != '\0' && *dbp != '>' && lowcase (*dbp) != 'n')
5016 dbp++;
5017 if (*dbp == '\0')
5018 break; /* go to next line */
5019 if (*dbp == '>')
5020 {
5021 dbp += 1;
5022 inanchor = FALSE;
5023 continue; /* look on the same line */
5024 }
5025 dbp += 1;
5026 if (LOOKING_AT_NOCASE (dbp, "ame="))
5027 {
5028 bool quoted = (dbp[0] == '"');
5029
5030 if (quoted)
5031 for (end = ++dbp; *end != '\0' && *end != '"'; end++)
5032 continue;
5033 else
5034 for (end = dbp; *end != '\0' && intoken (*end); end++)
5035 continue;
5036 linebuffer_setlen (&token_name, end - dbp);
5037 strncpy (token_name.buffer, dbp, end - dbp);
5038 token_name.buffer[end - dbp] = '\0';
5039
5040 dbp = end;
5041 inanchor = FALSE; /* we found what we looked for */
5042 ignoretag = TRUE; /* skip to the end of the anchor */
5043 getnext = TRUE; /* then grab the text */
5044 continue; /* look on the same line */
5045 }
5046 }
5047
5048 else if (getnext) /* grab next tokens and tag them */
5049 {
5050 dbp = skip_spaces (dbp);
5051 if (*dbp == '\0')
5052 break; /* go to next line */
5053 if (*dbp == '<')
5054 {
5055 if (lowcase (dbp[1]) == 'a' && !intoken (dbp[2]))
5056 inanchor = TRUE;
5057 else
5058 ignoretag = TRUE;
5059 continue; /* look on the same line */
5060 }
5061
5062 for (end = dbp + 1; *end != '\0' && *end != '<'; end++)
5063 continue;
5064 make_tag (token_name.buffer, token_name.len, TRUE,
5065 dbp, end - dbp, lineno, linecharno);
5066 linebuffer_setlen (&token_name, 0); /* no name in buffer */
5067 getnext = FALSE;
5068 break; /* go to next line */
5069 }
5070
5071 else /* look for an interesting HTML tag */
5072 {
5073 while (*dbp != '\0' && *dbp != '<')
5074 dbp++;
5075 if (*dbp == '\0')
5076 break; /* go to next line */
5077 dbp += 1;
5078 if (lowcase (dbp[0]) == 'a' && !intoken (dbp[1]))
5079 inanchor = TRUE;
5080 else if (LOOKING_AT_NOCASE (dbp, "title>")
5081 || LOOKING_AT_NOCASE (dbp, "h1>")
5082 || LOOKING_AT_NOCASE (dbp, "h2>")
5083 || LOOKING_AT_NOCASE (dbp, "h3>"))
5084 {
5085 getnext = TRUE;
5086 continue; /* look on the same line */
5087 }
5088 }
5089 }
5090}
5091
5092
4928/* 5093/*
4929 * Prolog support 5094 * Prolog support
4930 * 5095 *
@@ -5315,7 +5480,7 @@ analyse_regex (regex_arg)
5315{ 5480{
5316 if (regex_arg == NULL) 5481 if (regex_arg == NULL)
5317 { 5482 {
5318 free_patterns (); /* --no-regex: remove existing regexps */ 5483 free_regexps (); /* --no-regex: remove existing regexps */
5319 return; 5484 return;
5320 } 5485 }
5321 5486
@@ -5343,7 +5508,7 @@ analyse_regex (regex_arg)
5343 pfatal (regexfile); 5508 pfatal (regexfile);
5344 return; 5509 return;
5345 } 5510 }
5346 initbuffer (&regexbuf); 5511 linebuffer_init (&regexbuf);
5347 while (readline_internal (&regexbuf, regexfp) > 0) 5512 while (readline_internal (&regexbuf, regexfp) > 0)
5348 analyse_regex (regexbuf.buffer); 5513 analyse_regex (regexbuf.buffer);
5349 free (regexbuf.buffer); 5514 free (regexbuf.buffer);
@@ -5379,8 +5544,8 @@ analyse_regex (regex_arg)
5379 } 5544 }
5380} 5545}
5381 5546
5382/* Turn a name, which is an ed-style (but Emacs syntax) regular 5547/* Separate the regexp pattern, compile it,
5383 expression, into a real regular expression by compiling it. */ 5548 and care for optional name and modifiers. */
5384static void 5549static void
5385add_regex (regexp_pattern, lang) 5550add_regex (regexp_pattern, lang)
5386 char *regexp_pattern; 5551 char *regexp_pattern;
@@ -5390,8 +5555,12 @@ add_regex (regexp_pattern, lang)
5390 char sep, *pat, *name, *modifiers; 5555 char sep, *pat, *name, *modifiers;
5391 const char *err; 5556 const char *err;
5392 struct re_pattern_buffer *patbuf; 5557 struct re_pattern_buffer *patbuf;
5393 pattern *pp; 5558 regexp *rp;
5394 bool ignore_case, multi_line, single_line; 5559 bool
5560 force_explicit_name = TRUE, /* do not use implicit tag names */
5561 ignore_case = FALSE, /* case is significant */
5562 multi_line = FALSE, /* matches are done one line at a time */
5563 single_line = FALSE; /* dot does not match newline */
5395 5564
5396 5565
5397 if (strlen(regexp_pattern) < 3) 5566 if (strlen(regexp_pattern) < 3)
@@ -5421,12 +5590,14 @@ add_regex (regexp_pattern, lang)
5421 modifiers += 1; /* skip separator */ 5590 modifiers += 1; /* skip separator */
5422 5591
5423 /* Parse regex modifiers. */ 5592 /* Parse regex modifiers. */
5424 ignore_case = FALSE; /* case is significant */
5425 multi_line = FALSE; /* matches are done one line at a time */
5426 single_line = FALSE; /* dot does not match newline */
5427 for (; modifiers[0] != '\0'; modifiers++) 5593 for (; modifiers[0] != '\0'; modifiers++)
5428 switch (modifiers[0]) 5594 switch (modifiers[0])
5429 { 5595 {
5596 case 'N':
5597 if (modifiers == name)
5598 error ("forcing explicit tag name but no name, ignoring", NULL);
5599 force_explicit_name = TRUE;
5600 break;
5430 case 'i': 5601 case 'i':
5431 ignore_case = TRUE; 5602 ignore_case = TRUE;
5432 break; 5603 break;
@@ -5477,14 +5648,15 @@ add_regex (regexp_pattern, lang)
5477 return; 5648 return;
5478 } 5649 }
5479 5650
5480 pp = p_head; 5651 rp = p_head;
5481 p_head = xnew (1, pattern); 5652 p_head = xnew (1, regexp);
5482 p_head->regex = savestr (regexp_pattern); 5653 p_head->pattern = savestr (regexp_pattern);
5483 p_head->p_next = pp; 5654 p_head->p_next = rp;
5484 p_head->lang = lang; 5655 p_head->lang = lang;
5485 p_head->pat = patbuf; 5656 p_head->pat = patbuf;
5486 p_head->name_pattern = savestr (name); 5657 p_head->name = savestr (name);
5487 p_head->error_signaled = FALSE; 5658 p_head->error_signaled = FALSE;
5659 p_head->force_explicit_name = force_explicit_name;
5488 p_head->ignore_case = ignore_case; 5660 p_head->ignore_case = ignore_case;
5489 p_head->multi_line = multi_line; 5661 p_head->multi_line = multi_line;
5490} 5662}
@@ -5539,18 +5711,18 @@ substitute (in, out, regs)
5539 return result; 5711 return result;
5540} 5712}
5541 5713
5542/* Deallocate all patterns. */ 5714/* Deallocate all regexps. */
5543static void 5715static void
5544free_patterns () 5716free_regexps ()
5545{ 5717{
5546 pattern *pp; 5718 regexp *rp;
5547 while (p_head != NULL) 5719 while (p_head != NULL)
5548 { 5720 {
5549 pp = p_head->p_next; 5721 rp = p_head->p_next;
5550 free (p_head->regex); 5722 free (p_head->pattern);
5551 free (p_head->name_pattern); 5723 free (p_head->name);
5552 free (p_head); 5724 free (p_head);
5553 p_head = pp; 5725 p_head = rp;
5554 } 5726 }
5555 return; 5727 return;
5556} 5728}
@@ -5566,13 +5738,14 @@ static void
5566regex_tag_multiline () 5738regex_tag_multiline ()
5567{ 5739{
5568 char *buffer = filebuf.buffer; 5740 char *buffer = filebuf.buffer;
5569 pattern *pp; 5741 regexp *rp;
5742 char *name;
5570 5743
5571 for (pp = p_head; pp != NULL; pp = pp->p_next) 5744 for (rp = p_head; rp != NULL; rp = rp->p_next)
5572 { 5745 {
5573 int match = 0; 5746 int match = 0;
5574 5747
5575 if (!pp->multi_line) 5748 if (!rp->multi_line)
5576 continue; /* skip normal regexps */ 5749 continue; /* skip normal regexps */
5577 5750
5578 /* Generic initialisations before parsing file from memory. */ 5751 /* Generic initialisations before parsing file from memory. */
@@ -5581,62 +5754,55 @@ regex_tag_multiline ()
5581 linecharno = 0; /* reset global char number of line start */ 5754 linecharno = 0; /* reset global char number of line start */
5582 5755
5583 /* Only use generic regexps or those for the current language. */ 5756 /* Only use generic regexps or those for the current language. */
5584 if (pp->lang != NULL && pp->lang != curfdp->lang) 5757 if (rp->lang != NULL && rp->lang != curfdp->lang)
5585 continue; 5758 continue;
5586 5759
5587 while (match >= 0 && match < filebuf.len) 5760 while (match >= 0 && match < filebuf.len)
5588 { 5761 {
5589 match = re_search (pp->pat, buffer, filebuf.len, charno, 5762 match = re_search (rp->pat, buffer, filebuf.len, charno,
5590 filebuf.len - match, &pp->regs); 5763 filebuf.len - match, &rp->regs);
5591 switch (match) 5764 switch (match)
5592 { 5765 {
5593 case -2: 5766 case -2:
5594 /* Some error. */ 5767 /* Some error. */
5595 if (!pp->error_signaled) 5768 if (!rp->error_signaled)
5596 { 5769 {
5597 error ("regexp stack overflow while matching \"%s\"", 5770 error ("regexp stack overflow while matching \"%s\"",
5598 pp->regex); 5771 rp->pattern);
5599 pp->error_signaled = TRUE; 5772 rp->error_signaled = TRUE;
5600 } 5773 }
5601 break; 5774 break;
5602 case -1: 5775 case -1:
5603 /* No match. */ 5776 /* No match. */
5604 break; 5777 break;
5605 default: 5778 default:
5606 if (match == pp->regs.end[0]) 5779 if (match == rp->regs.end[0])
5607 { 5780 {
5608 if (!pp->error_signaled) 5781 if (!rp->error_signaled)
5609 { 5782 {
5610 error ("regexp matches the empty string: \"%s\"", 5783 error ("regexp matches the empty string: \"%s\"",
5611 pp->regex); 5784 rp->pattern);
5612 pp->error_signaled = TRUE; 5785 rp->error_signaled = TRUE;
5613 } 5786 }
5614 match = -3; /* exit from while loop */ 5787 match = -3; /* exit from while loop */
5615 break; 5788 break;
5616 } 5789 }
5617 5790
5618 /* Match occurred. Construct a tag. */ 5791 /* Match occurred. Construct a tag. */
5619 while (charno < pp->regs.end[0]) 5792 while (charno < rp->regs.end[0])
5620 if (buffer[charno++] == '\n') 5793 if (buffer[charno++] == '\n')
5621 lineno++, linecharno = charno; 5794 lineno++, linecharno = charno;
5622 if (pp->name_pattern[0] != '\0') 5795 name = rp->name;
5623 { 5796 if (name[0] != '\0')
5624 /* Make a named tag. 5797 /* Make a named tag. */
5625 Do not use make_tag here, as it would make the name 5798 name = substitute (buffer, rp->name, &rp->regs);
5626 implicit if possible, while we want to respect the user's 5799 if (rp->force_explicit_name)
5627 request to create an explicit tag name. */ 5800 /* Force explicit tag name, if a name is there. */
5628 char *name = substitute (buffer, 5801 pfnote (name, TRUE, buffer + linecharno,
5629 pp->name_pattern, &pp->regs); 5802 charno - linecharno + 1, lineno, linecharno);
5630 if (name != NULL)
5631 pfnote (name, TRUE, buffer + linecharno,
5632 charno - linecharno + 1, lineno, linecharno);
5633 }
5634 else 5803 else
5635 { 5804 make_tag (name, strlen (name), TRUE, buffer + linecharno,
5636 /* Make an unnamed tag. */
5637 pfnote ((char *)NULL, TRUE, buffer + linecharno,
5638 charno - linecharno + 1, lineno, linecharno); 5805 charno - linecharno + 1, lineno, linecharno);
5639 }
5640 break; 5806 break;
5641 } 5807 }
5642 } 5808 }
@@ -5682,17 +5848,6 @@ get_tag (bp, namepp)
5682 *namepp = savenstr (bp, cp - bp); 5848 *namepp = savenstr (bp, cp - bp);
5683} 5849}
5684 5850
5685/* Initialize a linebuffer for use */
5686static void
5687initbuffer (lbp)
5688 linebuffer *lbp;
5689{
5690 lbp->size = (DEBUG) ? 3 : 200;
5691 lbp->buffer = xnew (lbp->size, char);
5692 lbp->buffer[0] = '\0';
5693 lbp->len = 0;
5694}
5695
5696/* 5851/*
5697 * Read a line of text from `stream' into `lbp', excluding the 5852 * Read a line of text from `stream' into `lbp', excluding the
5698 * newline or CR-NL, if any. Return the number of characters read from 5853 * newline or CR-NL, if any. Return the number of characters read from
@@ -5889,6 +6044,8 @@ readline (lbp, stream)
5889 fdhead->infabsdir = savestr (curfdp->infabsdir); 6044 fdhead->infabsdir = savestr (curfdp->infabsdir);
5890 fdhead->taggedfname = taggedfname; 6045 fdhead->taggedfname = taggedfname;
5891 fdhead->usecharno = FALSE; 6046 fdhead->usecharno = FALSE;
6047 fdhead->prop = NULL;
6048 fdhead->written = FALSE;
5892 curfdp = fdhead; 6049 curfdp = fdhead;
5893 } 6050 }
5894 } 6051 }
@@ -5919,29 +6076,30 @@ readline (lbp, stream)
5919#ifdef ETAGS_REGEXPS 6076#ifdef ETAGS_REGEXPS
5920 { 6077 {
5921 int match; 6078 int match;
5922 pattern *pp; 6079 regexp *rp;
6080 char *name;
5923 6081
5924 /* Match against relevant patterns. */ 6082 /* Match against relevant regexps. */
5925 if (lbp->len > 0) 6083 if (lbp->len > 0)
5926 for (pp = p_head; pp != NULL; pp = pp->p_next) 6084 for (rp = p_head; rp != NULL; rp = rp->p_next)
5927 { 6085 {
5928 /* Only use generic regexps or those for the current language. 6086 /* Only use generic regexps or those for the current language.
5929 Also do not use multiline regexps, which is the job of 6087 Also do not use multiline regexps, which is the job of
5930 regex_tag_multiline. */ 6088 regex_tag_multiline. */
5931 if ((pp->lang != NULL && pp->lang != fdhead->lang) 6089 if ((rp->lang != NULL && rp->lang != fdhead->lang)
5932 || pp->multi_line) 6090 || rp->multi_line)
5933 continue; 6091 continue;
5934 6092
5935 match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs); 6093 match = re_match (rp->pat, lbp->buffer, lbp->len, 0, &rp->regs);
5936 switch (match) 6094 switch (match)
5937 { 6095 {
5938 case -2: 6096 case -2:
5939 /* Some error. */ 6097 /* Some error. */
5940 if (!pp->error_signaled) 6098 if (!rp->error_signaled)
5941 { 6099 {
5942 error ("regexp stack overflow while matching \"%s\"", 6100 error ("regexp stack overflow while matching \"%s\"",
5943 pp->regex); 6101 rp->pattern);
5944 pp->error_signaled = TRUE; 6102 rp->error_signaled = TRUE;
5945 } 6103 }
5946 break; 6104 break;
5947 case -1: 6105 case -1:
@@ -5949,32 +6107,24 @@ readline (lbp, stream)
5949 break; 6107 break;
5950 case 0: 6108 case 0:
5951 /* Empty string matched. */ 6109 /* Empty string matched. */
5952 if (!pp->error_signaled) 6110 if (!rp->error_signaled)
5953 { 6111 {
5954 error ("regexp matches the empty string: \"%s\"", 6112 error ("regexp matches the empty string: \"%s\"", rp->pattern);
5955 pp->regex); 6113 rp->error_signaled = TRUE;
5956 pp->error_signaled = TRUE;
5957 } 6114 }
5958 break; 6115 break;
5959 default: 6116 default:
5960 /* Match occurred. Construct a tag. */ 6117 /* Match occurred. Construct a tag. */
5961 if (pp->name_pattern[0] != '\0') 6118 name = rp->name;
5962 { 6119 if (name[0] != '\0')
5963 /* Make a named tag. 6120 /* Make a named tag. */
5964 Do not use make_tag here, as it would make the name 6121 name = substitute (lbp->buffer, rp->name, &rp->regs);
5965 implicit if possible, while we want to respect the user's 6122 if (rp->force_explicit_name)
5966 request to create an explicit tag name. */ 6123 /* Force explicit tag name, if a name is there. */
5967 char *name = substitute (lbp->buffer, 6124 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5968 pp->name_pattern, &pp->regs);
5969 if (name != NULL)
5970 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5971 }
5972 else 6125 else
5973 { 6126 make_tag (name, strlen (name), TRUE,
5974 /* Make an unnamed tag. */
5975 pfnote ((char *)NULL, TRUE,
5976 lbp->buffer, match, lineno, linecharno); 6127 lbp->buffer, match, lineno, linecharno);
5977 }
5978 break; 6128 break;
5979 } 6129 }
5980 } 6130 }
@@ -6053,13 +6203,12 @@ etags_strchr (sp, c)
6053} 6203}
6054 6204
6055/* 6205/*
6056 * Return TRUE if the two strings are equal, ignoring case for alphabetic 6206 * Compare two strings, ignoring case for alphabetic characters.
6057 * characters.
6058 * 6207 *
6059 * Analogous to BSD's strcasecmp, included for portability. 6208 * Same as BSD's strcasecmp, included for portability.
6060 */ 6209 */
6061static bool 6210static int
6062strcaseeq (s1, s2) 6211etags_strcasecmp (s1, s2)
6063 register const char *s1; 6212 register const char *s1;
6064 register const char *s2; 6213 register const char *s2;
6065{ 6214{
@@ -6069,7 +6218,35 @@ strcaseeq (s1, s2)
6069 : *s1 == *s2)) 6218 : *s1 == *s2))
6070 s1++, s2++; 6219 s1++, s2++;
6071 6220
6072 return (*s1 == *s2); 6221 return (ISALPHA (*s1) && ISALPHA (*s2)
6222 ? lowcase (*s1) - lowcase (*s2)
6223 : *s1 - *s2);
6224}
6225
6226/*
6227 * Compare two strings, ignoring case for alphabetic characters.
6228 * Stop after a given number of characters
6229 *
6230 * Same as BSD's strncasecmp, included for portability.
6231 */
6232static int
6233etags_strncasecmp (s1, s2, n)
6234 register const char *s1;
6235 register const char *s2;
6236 register int n;
6237{
6238 while (*s1 != '\0' && n-- > 0
6239 && (ISALPHA (*s1) && ISALPHA (*s2)
6240 ? lowcase (*s1) == lowcase (*s2)
6241 : *s1 == *s2))
6242 s1++, s2++;
6243
6244 if (n < 0)
6245 return 0;
6246 else
6247 return (ISALPHA (*s1) && ISALPHA (*s2)
6248 ? lowcase (*s1) - lowcase (*s2)
6249 : *s1 - *s2);
6073} 6250}
6074 6251
6075/* Skip spaces, return new pointer. */ 6252/* Skip spaces, return new pointer. */
@@ -6190,7 +6367,7 @@ etags_getcwd ()
6190 linebuffer path; 6367 linebuffer path;
6191 FILE *pipe; 6368 FILE *pipe;
6192 6369
6193 initbuffer (&path); 6370 linebuffer_init (&path);
6194 pipe = (FILE *) popen ("pwd 2>/dev/null", "r"); 6371 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
6195 if (pipe == NULL || readline_internal (&path, pipe) == 0) 6372 if (pipe == NULL || readline_internal (&path, pipe) == 0)
6196 pfatal ("pwd"); 6373 pfatal ("pwd");
@@ -6356,6 +6533,18 @@ canonicalize_filename (fn)
6356#endif 6533#endif
6357} 6534}
6358 6535
6536
6537/* Initialize a linebuffer for use */
6538static void
6539linebuffer_init (lbp)
6540 linebuffer *lbp;
6541{
6542 lbp->size = (DEBUG) ? 3 : 200;
6543 lbp->buffer = xnew (lbp->size, char);
6544 lbp->buffer[0] = '\0';
6545 lbp->len = 0;
6546}
6547
6359/* Set the minimum size of a string contained in a linebuffer. */ 6548/* Set the minimum size of a string contained in a linebuffer. */
6360static void 6549static void
6361linebuffer_setlen (lbp, toksize) 6550linebuffer_setlen (lbp, toksize)
@@ -6370,7 +6559,7 @@ linebuffer_setlen (lbp, toksize)
6370 lbp->len = toksize; 6559 lbp->len = toksize;
6371} 6560}
6372 6561
6373/* Like malloc but get fatal error if memory is exhausted. */ 6562/* Like malloc but get fatal error if memory is exhausted. */
6374static PTR 6563static PTR
6375xmalloc (size) 6564xmalloc (size)
6376 unsigned int size; 6565 unsigned int size;
@@ -6398,6 +6587,6 @@ xrealloc (ptr, size)
6398 * indent-tabs-mode: t 6587 * indent-tabs-mode: t
6399 * tab-width: 8 6588 * tab-width: 8
6400 * fill-column: 79 6589 * fill-column: 79
6401 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "pattern") 6590 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")
6402 * End: 6591 * End:
6403 */ 6592 */