aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorFrancesco Potortì1994-03-23 18:27:19 +0000
committerFrancesco Potortì1994-03-23 18:27:19 +0000
commit46c145db6c5561a7fd6871108d9ca239dc88a3f9 (patch)
treead41feb6c393968b5ab3c016e9311794b1717536 /lib-src
parent6af6cbb5306f58a93da8e141d0dfe0a0d6cd454d (diff)
downloademacs-46c145db6c5561a7fd6871108d9ca239dc88a3f9.tar.gz
emacs-46c145db6c5561a7fd6871108d9ca239dc88a3f9.zip
* etags.c (cwd, outfiledir): vars added.
(relative_filename, absolute_filename, absolute_dirname): functions added to compute filenames in tags files. (process_file): filenames in tags file are relative to the directory where the tags file is (useful with the -o option). (main): initialise the outfiledir var. (TYPEDST): added the `tignore' value. (C_entries): corrected various small bugs.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c257
1 files changed, 212 insertions, 45 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index f65336f3c45..461d9dc6042 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -25,9 +25,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
25 * Gnu Emacs TAGS format and modifications by RMS? 25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++. 26 * Sam Kendall added C++.
27 * 27 *
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 10.7 28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
29 */ 29 */
30 30
31char etags_version[] = "@(#) pot revision number is 10.15";
32
31#ifdef MSDOS 33#ifdef MSDOS
32#include <fcntl.h> 34#include <fcntl.h>
33#endif /* MSDOS */ 35#endif /* MSDOS */
@@ -48,9 +50,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
48#include "getopt.h" 50#include "getopt.h"
49 51
50extern char *getenv (); 52extern char *getenv ();
53extern char *getcwd ();
51 54
52char *etags_index (), *etags_rindex ();
53char *savenstr ();
54 55
55/* Define the symbol ETAGS to make the program "etags", 56/* Define the symbol ETAGS to make the program "etags",
56 which makes emacs-style tag tables by default. 57 which makes emacs-style tag tables by default.
@@ -151,19 +152,20 @@ struct nd_st
151 struct nd_st *left, *right; /* left and right sons */ 152 struct nd_st *left, *right; /* left and right sons */
152}; 153};
153 154
154long ftell ();
155typedef struct nd_st NODE; 155typedef struct nd_st NODE;
156 156
157logical header_file; /* TRUE if .h file, FALSE o.w. */ 157logical header_file; /* TRUE if .h file, FALSE o.w. */
158/* boolean "functions" (see init) */ 158/* boolean "functions" (see init) */
159logical _wht[0177], _etk[0177], _itk[0177], _btk[0177]; 159logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
160 160
161char cwd [BUFSIZ]; /* current working directory */
162char *outfiledir; /* directory of tagfile */
161 163
162char *concat (); 164char *concat ();
163char *savenstr (); 165char *savenstr (), *savestr ();
164char *savestr (); 166char *etags_index (), *etags_rindex ();
165char *xmalloc (); 167char *relative_filename (), *absolute_filename (), *absolute_dirname ();
166char *xrealloc (); 168char *xmalloc (), *xrealloc ();
167int L_isdef (), L_isquote (); 169int L_isdef (), L_isquote ();
168int PF_funcs (); 170int PF_funcs ();
169int total_size_of_entries (); 171int total_size_of_entries ();
@@ -241,7 +243,7 @@ char *curfile, /* current input file name */
241 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */ 243 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
242 /* token starting chars */ 244 /* token starting chars */
243 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~", 245 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
244 /* valid in-token chars */ 246 /* valid in-token chars */
245 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; 247 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
246 248
247int append_to_tagfile; /* -a: append to tags */ 249int append_to_tagfile; /* -a: append to tags */
@@ -442,7 +444,7 @@ main (argc, argv)
442 extern char *gfnames (); 444 extern char *gfnames ();
443 extern char *massage_name (); 445 extern char *massage_name ();
444#endif 446#endif
445 447
446#ifdef MSDOS 448#ifdef MSDOS
447 _fmode = O_BINARY; /* all of files are treated as binary files */ 449 _fmode = O_BINARY; /* all of files are treated as binary files */
448#endif /* MSDOS */ 450#endif /* MSDOS */
@@ -465,7 +467,7 @@ main (argc, argv)
465 for (;;) 467 for (;;)
466 { 468 {
467 int opt; 469 int opt;
468 opt = getopt_long (argc, argv, "aACdDo:f:StTi:BFuvxwVH", longopts, 0); 470 opt = getopt_long (argc, argv, "aCdDo:f:StTi:BFuvxwVH", longopts, 0);
469 471
470 if (opt == EOF) 472 if (opt == EOF)
471 break; 473 break;
@@ -569,10 +571,20 @@ main (argc, argv)
569 exit (BAD); 571 exit (BAD);
570 } 572 }
571 573
572 if (outfile == 0) 574 if (outfile == NULL)
573 { 575 {
574 outfile = emacs_tags_format ? "TAGS" : "tags"; 576 outfile = emacs_tags_format ? "TAGS" : "tags";
575 } 577 }
578 getcwd (cwd, BUFSIZ); /* the current working directory */
579 strcat (cwd, "/");
580 if (streq (outfile, "-"))
581 {
582 outfiledir = cwd;
583 }
584 else
585 {
586 outfiledir = absolute_dirname (outfile, cwd);
587 }
576 588
577 init (); /* set up boolean "functions" */ 589 init (); /* set up boolean "functions" */
578 590
@@ -619,18 +631,18 @@ main (argc, argv)
619 this_file = argv[optind]; 631 this_file = argv[optind];
620#endif 632#endif
621 /* Input file named "-" means read file names from stdin and use them. */ 633 /* Input file named "-" means read file names from stdin and use them. */
622 if (streq (this_file, "-")) 634 if (streq (this_file, "-"))
635 {
636 while (!feof (stdin))
623 { 637 {
624 while (!feof (stdin)) 638 (void) readline (&filename_lb, stdin);
625 { 639 if (strlen (filename_lb.buffer) > 0)
626 (void) readline (&filename_lb, stdin); 640 process_file (filename_lb.buffer);
627 if (strlen (filename_lb.buffer) > 0)
628 process_file (filename_lb.buffer);
629 }
630 } 641 }
631 else
632 process_file (this_file);
633 } 642 }
643 else
644 process_file (this_file);
645 }
634 646
635 if (emacs_tags_format) 647 if (emacs_tags_format)
636 { 648 {
@@ -701,7 +713,20 @@ process_file (file)
701 } 713 }
702 if (emacs_tags_format) 714 if (emacs_tags_format)
703 { 715 {
704 fprintf (outf, "\f\n%s,%d\n", file, total_size_of_entries (head)); 716 char *filename;
717
718 if (file[0] == '/')
719 {
720 /* file is an absolute filename. Canonicalise it. */
721 filename = absolute_filename (file, cwd);
722 }
723 else
724 {
725 /* file is a filename relative to cwd. Make it relative
726 to the directory of the tags file. */
727 filename = relative_filename (file, outfiledir);
728 }
729 fprintf (outf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
705 put_entries (head); 730 put_entries (head);
706 free_tree (head); 731 free_tree (head);
707 head = NULL; 732 head = NULL;
@@ -1318,7 +1343,8 @@ typedef enum
1318FUNCST funcdef; 1343FUNCST funcdef;
1319 1344
1320 1345
1321 /* typedefs are recognized using a simple finite automaton. 1346 /*
1347 * typedefs are recognized using a simple finite automaton.
1322 * typeddef is its state variable. 1348 * typeddef is its state variable.
1323 */ 1349 */
1324typedef enum 1350typedef enum
@@ -1326,16 +1352,16 @@ typedef enum
1326 tnone, /* nothing seen */ 1352 tnone, /* nothing seen */
1327 ttypedseen, /* typedef keyword seen */ 1353 ttypedseen, /* typedef keyword seen */
1328 tinbody, /* inside typedef body */ 1354 tinbody, /* inside typedef body */
1329 tend /* just before typedef tag */ 1355 tend, /* just before typedef tag */
1356 tignore /* junk after typedef tag */
1330} TYPEDST; 1357} TYPEDST;
1331TYPEDST typdef; 1358TYPEDST typdef;
1332 1359
1333 1360
1334 /* struct tags for C++ are recognized using another simple 1361 /*
1335 * finite automaton. `structdef' is its state variable. 1362 * struct-like structures (enum, struct and union) are recognized
1336 * This machinery is only invoked for C++; otherwise structdef 1363 * using another simple finite automaton. `structdef' is its state
1337 * should remain snone. However, this machinery can easily be 1364 * variable.
1338 * adapted to find structure tags in normal C code.
1339 */ 1365 */
1340typedef enum 1366typedef enum
1341{ 1367{
@@ -1346,6 +1372,7 @@ typedef enum
1346 sinbody /* in struct body: recognize member func defs*/ 1372 sinbody /* in struct body: recognize member func defs*/
1347} STRUCTST; 1373} STRUCTST;
1348STRUCTST structdef; 1374STRUCTST structdef;
1375
1349/* 1376/*
1350 * When structdef is stagseen, scolonseen, or sinbody, structtag is the 1377 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1351 * struct tag, and structtype is the type of the preceding struct-like 1378 * struct tag, and structtype is the type of the preceding struct-like
@@ -1448,7 +1475,7 @@ C_entries (c_ext)
1448 lp = curlb.buffer; 1475 lp = curlb.buffer;
1449 *lp = 0; 1476 *lp = 0;
1450 1477
1451 definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone; 1478 definedef = dnone; funcdef = fnone; typdef = tnone; structdef = snone;
1452 next_token_is_func = yacc_rules = FALSE; 1479 next_token_is_func = yacc_rules = FALSE;
1453 midtoken = inquote = inchar = incomm = quotednl = FALSE; 1480 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1454 cblev = 0; 1481 cblev = 0;
@@ -1515,7 +1542,7 @@ C_entries (c_ext)
1515 CNL; 1542 CNL;
1516 /* FALLTHRU */ 1543 /* FALLTHRU */
1517 case '\'': 1544 case '\'':
1518 inchar = FALSE; 1545 inchar = FALSE;
1519 break; 1546 break;
1520 } 1547 }
1521 continue; 1548 continue;
@@ -1553,7 +1580,7 @@ C_entries (c_ext)
1553 /* entering or exiting rules section in yacc file */ 1580 /* entering or exiting rules section in yacc file */
1554 lp++; 1581 lp++;
1555 definedef = dnone; funcdef = fnone; 1582 definedef = dnone; funcdef = fnone;
1556 typdef= tnone; structdef= snone; 1583 typdef = tnone; structdef = snone;
1557 next_token_is_func = FALSE; 1584 next_token_is_func = FALSE;
1558 midtoken = inquote = inchar = incomm = quotednl = FALSE; 1585 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1559 cblev = 0; 1586 cblev = 0;
@@ -1572,9 +1599,10 @@ C_entries (c_ext)
1572 /* Consider token only if some complicated conditions are satisfied. */ 1599 /* Consider token only if some complicated conditions are satisfied. */
1573 if (((cblev == 0 && structdef != scolonseen) 1600 if (((cblev == 0 && structdef != scolonseen)
1574 || (cblev == 1 && cplpl && structdef == sinbody)) 1601 || (cblev == 1 && cplpl && structdef == sinbody))
1602 && typdef != tignore
1575 && definedef != dignorerest 1603 && definedef != dignorerest
1576 && (funcdef != finlist 1604 && (funcdef != finlist
1577 || (definedef != dnone && definedef != dignorerest))) 1605 || definedef != dnone))
1578 { 1606 {
1579 if (midtoken) 1607 if (midtoken)
1580 { 1608 {
@@ -1714,19 +1742,37 @@ C_entries (c_ext)
1714 case ';': 1742 case ';':
1715 if (definedef != dnone) 1743 if (definedef != dnone)
1716 break; 1744 break;
1717 if (cblev == 0 && typdef == tend) 1745 if (cblev == 0)
1718 { 1746 switch (typdef)
1719 typdef = tnone; 1747 {
1720 MAKE_TAG_FROM_OTH_LB (FALSE); 1748 case tend:
1721 } 1749 MAKE_TAG_FROM_OTH_LB (FALSE);
1750 /* FALLTHRU */
1751 default:
1752 typdef = tnone;
1753 }
1722 if (funcdef != fignore) 1754 if (funcdef != fignore)
1723 funcdef = fnone; 1755 funcdef = fnone;
1724 /* FALLTHRU */ 1756 if (structdef == stagseen)
1757 structdef = snone;
1758 break;
1725 case ',': 1759 case ',':
1726 /* FALLTHRU */ 1760 if (definedef != dnone)
1761 break;
1762 if (funcdef != finlist && funcdef != fignore)
1763 funcdef = fnone;
1764 if (structdef == stagseen)
1765 structdef = snone;
1766 break;
1727 case '[': 1767 case '[':
1728 if (definedef != dnone) 1768 if (definedef != dnone)
1729 break; 1769 break;
1770 if (cblev == 0 && typdef == tend)
1771 {
1772 typdef = tignore;
1773 MAKE_TAG_FROM_OTH_LB (FALSE);
1774 break;
1775 }
1730 if (funcdef != finlist && funcdef != fignore) 1776 if (funcdef != finlist && funcdef != fignore)
1731 funcdef = fnone; 1777 funcdef = fnone;
1732 if (structdef == stagseen) 1778 if (structdef == stagseen)
@@ -1758,6 +1804,11 @@ C_entries (c_ext)
1758 funcdef = flistseen; 1804 funcdef = flistseen;
1759 break; 1805 break;
1760 } 1806 }
1807 if (cblev == 0 && typdef == tend)
1808 {
1809 typdef = tignore;
1810 MAKE_TAG_FROM_OTH_LB (FALSE);
1811 }
1761 } 1812 }
1762 else if (parlev < 0) /* can happen due to ill-conceived #if's. */ 1813 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
1763 parlev = 0; 1814 parlev = 0;
@@ -1786,6 +1837,11 @@ C_entries (c_ext)
1786 /* FALLTHRU */ 1837 /* FALLTHRU */
1787 case fignore: 1838 case fignore:
1788 funcdef = fnone; 1839 funcdef = fnone;
1840 break;
1841 case fnone:
1842 /* Neutralize `extern "C" {' grot.
1843 if (cblev == 0 && structdef == snone && typdef == tnone)
1844 cblev--; */;
1789 } 1845 }
1790 cblev++; 1846 cblev++;
1791 break; 1847 break;
@@ -1910,6 +1966,7 @@ consider_token (c, tokp, c_ext, cblev, is_func)
1910 { 1966 {
1911 if (typedefs) 1967 if (typedefs)
1912 typdef = ttypedseen; 1968 typdef = ttypedseen;
1969 funcdef = fnone;
1913 return (FALSE); 1970 return (FALSE);
1914 } 1971 }
1915 break; 1972 break;
@@ -2015,7 +2072,8 @@ consider_token (c, tokp, c_ext, cblev, is_func)
2015 switch (toktype) 2072 switch (toktype)
2016 { 2073 {
2017 case st_C_typespec: 2074 case st_C_typespec:
2018 funcdef = fnone; /* should be useless */ 2075 if (funcdef != finlist && funcdef != fignore)
2076 funcdef = fnone; /* should be useless */
2019 return (FALSE); 2077 return (FALSE);
2020 default: 2078 default:
2021 if (funcdef == fnone) 2079 if (funcdef == fnone)
@@ -2176,7 +2234,7 @@ getit (fi)
2176 dbp++; 2234 dbp++;
2177 } 2235 }
2178 if (!isalpha (*dbp) 2236 if (!isalpha (*dbp)
2179 && *dbp != '_' 2237 && *dbp != '_'
2180 && *dbp != '$') 2238 && *dbp != '$')
2181 return; 2239 return;
2182 for (cp = dbp + 1; 2240 for (cp = dbp + 1;
@@ -2364,7 +2422,7 @@ PAS_funcs (fi)
2364 verify_tag = FALSE; 2422 verify_tag = FALSE;
2365 } 2423 }
2366 } 2424 }
2367 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */ 2425 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2368 { 2426 {
2369 found_tag = FALSE; 2427 found_tag = FALSE;
2370 verify_tag = FALSE; 2428 verify_tag = FALSE;
@@ -3073,7 +3131,8 @@ error (s1, s2)
3073 fprintf (stderr, "\n"); 3131 fprintf (stderr, "\n");
3074} 3132}
3075 3133
3076/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ 3134/* Return a newly-allocated string whose contents
3135 concatenate those of s1, s2, s3. */
3077 3136
3078char * 3137char *
3079concat (s1, s2, s3) 3138concat (s1, s2, s3)
@@ -3085,11 +3144,119 @@ concat (s1, s2, s3)
3085 strcpy (result, s1); 3144 strcpy (result, s1);
3086 strcpy (result + len1, s2); 3145 strcpy (result + len1, s2);
3087 strcpy (result + len1 + len2, s3); 3146 strcpy (result + len1 + len2, s3);
3088 *(result + len1 + len2 + len3) = 0; 3147 result[len1 + len2 + len3] = '\0';
3089 3148
3090 return result; 3149 return result;
3091} 3150}
3092 3151
3152/* Return a newly allocated string containing the filename of FILE relative
3153 to the absolute directory DIR (which should end with a slash). */
3154
3155char *
3156relative_filename (file, dir)
3157 char *file, *dir;
3158{
3159 char *fp, *dp, *res;
3160
3161 /* Find the common root of file and dir. */
3162 fp = absolute_filename (file, cwd);
3163 dp = dir;
3164 while (*fp++ == *dp++)
3165 continue;
3166 do
3167 {
3168 fp--;
3169 dp--;
3170 }
3171 while (*fp != '/');
3172
3173 /* Build a sequence of "../" strings for the resulting relative filename. */
3174 for (dp = etags_index (dp + 1, '/'), res = "";
3175 dp != NULL;
3176 dp = etags_index (dp + 1, '/'))
3177 {
3178 res = concat (res, "../", "");
3179 }
3180
3181 /* Add the filename relative to the common root of file and dir. */
3182 res = concat (res, fp + 1, "");
3183
3184 return res; /* temporary stub */
3185}
3186
3187/* Return a newly allocated string containing the
3188 absolute filename of FILE given CWD (which should end with a slash). */
3189char *
3190absolute_filename (file, cwd)
3191 char *file, *cwd;
3192{
3193 char *slashp, *cp, *res;
3194
3195 if (file[0] == '/')
3196 res = concat (file, "", "");
3197 else
3198 res = concat (cwd, file, "");
3199
3200 /* Delete the "/dirname/.." and "/." substrings. */
3201 slashp = etags_index (res, '/');
3202 while (slashp != NULL && slashp[0] != '\0')
3203 {
3204 if (slashp[1] == '.')
3205 {
3206 if (slashp[2] == '.'
3207 && (slashp[3] == '/' || slashp[3] == '\0'))
3208 {
3209 cp = slashp;
3210 do
3211 cp--;
3212 while (cp >= res && *cp != '/');
3213 if (*cp == '/')
3214 {
3215 strcpy (cp, slashp + 3);
3216 }
3217 else /* else (cp == res) */
3218 {
3219 if (slashp[3] != NULL)
3220 strcpy (cp, slashp + 4);
3221 else
3222 return ".";
3223 }
3224 slashp = cp;
3225 }
3226 else if (slashp[2] == '/' || slashp[2] == '\0')
3227 {
3228 strcpy (slashp, slashp + 2);
3229 }
3230 }
3231 else
3232 {
3233 slashp = etags_index (slashp + 1, '/');
3234 }
3235 }
3236
3237 return res;
3238}
3239
3240/* Return a newly allocated string containing the absolute filename
3241 of dir where FILE resides given CWD (which should end with a slash). */
3242char *
3243absolute_dirname (file, cwd)
3244 char *file, *cwd;
3245{
3246 char *slashp, *res;
3247 char save;
3248
3249 slashp = etags_rindex (file, '/');
3250 if (slashp == NULL)
3251 return cwd;
3252 save = slashp[1];
3253 slashp[1] = '\0';
3254 res = absolute_filename (file, cwd);
3255 slashp[1] = save;
3256
3257 return res;
3258}
3259
3093/* Like malloc but get fatal error if memory is exhausted. */ 3260/* Like malloc but get fatal error if memory is exhausted. */
3094 3261
3095char * 3262char *