comparison lib-src/etags.c @ 10404:631f1dac6f7a

Global polishing, some bugs corrected, dynamic allocation used instead of fixed length static buffers in many places. * etags.c (FILEPOS, GET_CHARNO, GET_FILEPOS, max, LINENO): Deleted. (append_to_tagfile, typedefs, typedefs_and_cplusplus, constantypedefs, update, vgrind_style, no_warnings, cxref_style, cplusplus, noindentypedefs): Were int, now logical. (permit_duplicates): Was a var, now a #define. (filename_lb): Was global, now local to main. (main): Open the tag file when in cxref mode. Use a BUFSIZ size buffer for making the shell commands. Look at the return value from the system routine. Exit when cannot open the tag file. (process_file): Open the file and pass the FILE* to find_entries. (find_entries): Now void, because does not open the file itself. (pfnote): Recovering from lack of memory does not work. Removed. Use savenstr and simplify the code. (free_tree): Only free the name space if node is named. (structtag): Now a pointer, not a fixed length array of chars. (consider_token): Don't take a token as argument. Use savenstr when saving a tag in structtag. Callers changed. (TOKEN): Structure changed. Now used only in C_entries. (TOKEN_SAVED_P, SAVE_TOKEN, RESTORE_TOKEN): Deleted. (C_entries): nameb and savenameb deleted. Use dinamic allocation. (pfcnt): Deleted. Users updated. (getit, Asm_labels, Pascal_functions, L_getit, get_scheme, TEX_getit, prolog_getit): Use dinamic allocation for storing the tag instead of a fixed size buffer.
author Francesco Potortì <pot@gnu.org>
date Thu, 12 Jan 1995 17:05:37 +0000
parents fb23ac6e6199
children 2266157d9bcc
comparison
equal deleted inserted replaced
10403:c0e27466fb3f 10404:631f1dac6f7a
29 #endif 29 #endif
30 * 30 *
31 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 31 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
32 */ 32 */
33 33
34 char pot_etags_version[] = "@(#) pot revision number is 11.14"; 34 char pot_etags_version[] = "@(#) pot revision number is 11.15";
35 35
36 #ifdef MSDOS 36 #ifdef MSDOS
37 #include <fcntl.h> 37 #include <fcntl.h>
38 #include <sys/param.h> 38 #include <sys/param.h>
39 #endif /* MSDOS */ 39 #endif /* MSDOS */
69 69
70 #ifdef ETAGS_REGEXPS 70 #ifdef ETAGS_REGEXPS
71 #include <regex.h> 71 #include <regex.h>
72 #endif /* ETAGS_REGEXPS */ 72 #endif /* ETAGS_REGEXPS */
73 73
74 extern char *getenv (); 74 #define TRUE 1
75 #define FALSE 0
75 76
76 /* Define CTAGS to make the program "ctags" compatible with the usual one. 77 /* Define CTAGS to make the program "ctags" compatible with the usual one.
77 Let it undefined to make the program "etags", which makes emacs-style 78 Let it undefined to make the program "etags", which makes emacs-style
78 tag tables and tags typedefs, #defines and struct/union/enum by default. */ 79 tag tables and tags typedefs, #defines and struct/union/enum by default. */
79 #ifdef CTAGS 80 #ifdef CTAGS
90 #else 91 #else
91 #define GOOD 0 92 #define GOOD 0
92 #define BAD 1 93 #define BAD 1
93 #endif 94 #endif
94 95
95 /* 96 /* C extensions. */
96 * The FILEPOS abstract type, which represents a position in a file, 97 #define C_PLPL 0x00001 /* C++ */
97 * plus the following accessor functions: 98 #define C_STAR 0x00003 /* C* */
98 * 99 #define YACC 0x10000 /* yacc file */
99 * long GET_CHARNO (pos)
100 * returns absolute char number.
101 * void SET_FILEPOS (pos, fp, charno)
102 * FILE *fp; long charno;
103 * sets `pos' from the current file
104 * position of `fp' and from `charno',
105 * which must be the absolute character
106 * number corresponding to the current
107 * position of `fp'.
108 *
109 * The `pos' parameter is an lvalue expression of type FILEPOS.
110 * Parameters to the accessor functions are evaluated 0 or more times,
111 * and so must have no side effects.
112 *
113 * FILEPOS objects can also be assigned and passed to and from
114 * functions in the normal C manner.
115 *
116 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
117 */
118
119 #ifndef DEBUG
120 #define DEBUG FALSE
121
122 /* real implementation */
123 typedef long FILEPOS;
124 #define GET_CHARNO(pos) ((pos) + 0)
125 #define SET_FILEPOS(pos,fp,cno) ((void) ((pos) = (cno)))
126
127 #else
128 #undef DEBUG
129 #define DEBUG TRUE
130
131 /* debugging implementation */
132 typedef struct
133 {
134 long charno;
135 } FILEPOS;
136
137 #define GET_CHARNO(pos) ((pos).charno + 0)
138 #define SET_FILEPOS(pos,fp,cno) \
139 ((void) ((pos).charno = (cno), \
140 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
141 : 0))
142 #endif
143 100
144 #define streq(s,t) (strcmp (s, t) == 0) 101 #define streq(s,t) (strcmp (s, t) == 0)
145 #define strneq(s,t,n) (strncmp (s, t, n) == 0) 102 #define strneq(s,t,n) (strncmp (s, t, n) == 0)
146
147 #define TRUE 1
148 #define FALSE 0
149 103
150 #define iswhite(arg) (_wht[arg]) /* T if char is white */ 104 #define iswhite(arg) (_wht[arg]) /* T if char is white */
151 #define begtoken(arg) (_btk[arg]) /* T if char can start token */ 105 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
152 #define intoken(arg) (_itk[arg]) /* T if char can be in token */ 106 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
153 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ 107 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
154 108
155 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2)) 109 /*
110 * xnew -- allocate storage
111 *
112 * SYNOPSIS: Type *xnew (int n, Type);
113 */
114 #define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
156 115
157 typedef int logical; 116 typedef int logical;
158 117
159 struct nd_st 118 typedef struct nd_st
160 { /* sorting structure */ 119 { /* sorting structure */
161 char *name; /* function or type name */ 120 char *name; /* function or type name */
162 char *file; /* file name */ 121 char *file; /* file name */
163 logical is_func; /* use pattern or line no */ 122 logical is_func; /* use pattern or line no */
164 logical named; /* list name separately */ 123 logical named; /* list name separately */
165 logical been_warned; /* set if noticed dup */ 124 logical been_warned; /* set if noticed dup */
166 int lno; /* line number tag is on */ 125 int lno; /* line number tag is on */
167 long cno; /* character number line starts on */ 126 long cno; /* character number line starts on */
168 char *pat; /* search pattern */ 127 char *pat; /* search pattern */
169 struct nd_st *left, *right; /* left and right sons */ 128 struct nd_st *left, *right; /* left and right sons */
170 }; 129 } NODE;
171 130
172 typedef struct nd_st NODE; 131 extern char *getenv ();
173
174 /* boolean "functions" (see init) */
175 logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
176
177 char *cwd; /* current working directory */
178 char *tagfiledir; /* directory of tagfile */
179 132
180 char *concat (); 133 char *concat ();
181 char *savenstr (), *savestr (); 134 char *savenstr (), *savestr ();
182 char *etags_strchr (), *etags_strrchr (); 135 char *etags_strchr (), *etags_strrchr ();
183 char *etags_getcwd (); 136 char *etags_getcwd ();
223 void add_regex (); 176 void add_regex ();
224 #endif 177 #endif
225 void add_node (); 178 void add_node ();
226 void error (); 179 void error ();
227 void fatal (), pfatal (); 180 void fatal (), pfatal ();
228 logical find_entries (); 181 void find_entries ();
229 void free_tree (); 182 void free_tree ();
230 void getit (); 183 void getit ();
231 void init (); 184 void init ();
232 void initbuffer (); 185 void initbuffer ();
233 void pfnote (); 186 void pfnote ();
234 void process_file (); 187 void process_file ();
235 void put_entries (); 188 void put_entries ();
236 void takeprec (); 189 void takeprec ();
237 190
191
192 char searchar = '/'; /* use /.../ searches */
193
194 int lineno; /* line number of current line */
195 long charno; /* current character number */
196
197 long linecharno; /* charno of start of line; not used by C,
198 but by every other language. */
199
200 char *curfile; /* current input file name */
201 char *tagfile; /* output file */
202 char *progname; /* name this program was invoked with */
203 char *cwd; /* current working directory */
204 char *tagfiledir; /* directory of tagfile */
205
206 FILE *tagf; /* ioptr for tags file */
207 NODE *head; /* the head of the binary tree of tags */
208
238 /* 209 /*
239 * MACRO 210 * A `struct linebuffer' is a structure which holds a line of text.
240 * xnew -- allocate storage 211 * `readline' reads a line from a stream into a linebuffer and works
241 * 212 * regardless of the length of the line.
242 * SYNOPSIS
243 * Type *xnew (int n, Type);
244 */ 213 */
245 #define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) 214 struct linebuffer
246 215 {
247 /* 216 long size;
248 * Symbol table types. 217 char *buffer;
249 */
250 enum sym_type
251 {
252 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
253 }; 218 };
254 219
255 220 struct linebuffer lb; /* the current line */
256 221 struct
257 typedef int LINENO; 222 {
258 223 long linepos;
259 typedef struct 224 struct linebuffer lb; /* used by C_entries instead of lb */
260 { 225 } lbs[2];
261 char *p; 226
262 int len; 227 /* boolean "functions" (see init) */
263 LINENO lineno; 228 logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
264 logical named; 229 char
265 } TOKEN;
266
267 /* C extensions.
268 */
269 #define C_PLPL 0x00001 /* C++ */
270 #define C_STAR 0x00003 /* C* */
271 #define YACC 0x10000 /* yacc file */
272
273 char searchar = '/'; /* use /.../ searches */
274
275 LINENO lineno; /* line number of current line */
276 long charno; /* current character number */
277
278 long linecharno; /* charno of start of line; not used by C, but
279 * by every other language.
280 */
281
282 char *curfile, /* current input file name */
283 *tagfile, /* output file */
284 *white = " \f\t\n\013", /* white chars */ 230 *white = " \f\t\n\013", /* white chars */
285 *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */ 231 *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
286 /* token starting chars */ 232 /* token starting chars */
287 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~", 233 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
288 /* valid in-token chars */ 234 /* valid in-token chars */
289 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; 235 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
290 236
291 int append_to_tagfile; /* -a: append to tags */ 237 logical append_to_tagfile; /* -a: append to tags */
292 /* The following three default to 1 for etags, but to 0 for ctags. */ 238 /* The following three default to TRUE for etags, but to FALSE for ctags. */
293 int typedefs; /* -t: create tags for typedefs */ 239 logical typedefs; /* -t: create tags for typedefs */
294 int typedefs_and_cplusplus; /* -T: create tags for typedefs, level */ 240 logical typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
295 /* 0 struct/enum/union decls, and C++ */ 241 /* 0 struct/enum/union decls, and C++ */
296 /* member functions. */ 242 /* member functions. */
297 int constantypedefs; /* -d: create tags for C #define and enum */ 243 logical constantypedefs; /* -d: create tags for C #define and enum */
298 /* constants. Enum consts not implemented. */ 244 /* constants. Enum consts not implemented. */
299 /* -D: opposite of -d. Default under ctags. */ 245 /* -D: opposite of -d. Default under ctags. */
300 int update; /* -u: update tags */ 246 logical update; /* -u: update tags */
301 int vgrind_style; /* -v: create vgrind style index output */ 247 logical vgrind_style; /* -v: create vgrind style index output */
302 int no_warnings; /* -w: suppress warnings */ 248 logical no_warnings; /* -w: suppress warnings */
303 int cxref_style; /* -x: create cxref style output */ 249 logical cxref_style; /* -x: create cxref style output */
304 int cplusplus; /* .[hc] means C++, not C */ 250 logical cplusplus; /* .[hc] means C++, not C */
305 int noindentypedefs; /* -S: ignore indentation in C */ 251 logical noindentypedefs; /* -S: ignore indentation in C */
306 252 #define permit_duplicates TRUE /* allow duplicate tags */
307 /* Name this program was invoked with. */
308 char *progname;
309 253
310 struct option longopts[] = 254 struct option longopts[] =
311 { 255 {
312 { "append", no_argument, NULL, 'a' }, 256 { "append", no_argument, NULL, 'a' },
313 { "backward-search", no_argument, NULL, 'B' }, 257 { "backward-search", no_argument, NULL, 'B' },
329 { "update", no_argument, NULL, 'u' }, 273 { "update", no_argument, NULL, 'u' },
330 { "version", no_argument, NULL, 'V' }, 274 { "version", no_argument, NULL, 'V' },
331 { "vgrind", no_argument, NULL, 'v' }, 275 { "vgrind", no_argument, NULL, 'v' },
332 { 0 } 276 { 0 }
333 }; 277 };
334
335 FILE *tagf; /* ioptr for tags file */
336 NODE *head; /* the head of the binary tree of tags */
337 logical permit_duplicates = TRUE; /* allow duplicate tags */
338
339 /*
340 * A `struct linebuffer' is a structure which holds a line of text.
341 * `readline' reads a line from a stream into a linebuffer and works
342 * regardless of the length of the line.
343 */
344 struct linebuffer
345 {
346 long size;
347 char *buffer;
348 };
349
350 struct linebuffer lb; /* the current line */
351 struct linebuffer filename_lb; /* used to read in filenames */
352 struct
353 {
354 FILEPOS linepos;
355 struct linebuffer lb; /* used by C_entries instead of lb */
356 } lbs[2];
357 278
358 #ifdef ETAGS_REGEXPS 279 #ifdef ETAGS_REGEXPS
359 /* Structure defining a regular expression. Elements are 280 /* Structure defining a regular expression. Elements are
360 the compiled pattern, and the name string. */ 281 the compiled pattern, and the name string. */
361 struct pattern 282 struct pattern
752 void 673 void
753 main (argc, argv) 674 main (argc, argv)
754 int argc; 675 int argc;
755 char *argv[]; 676 char *argv[];
756 { 677 {
757 char cmd[100];
758 int i; 678 int i;
759 unsigned int nincluded_files = 0; 679 unsigned int nincluded_files = 0;
760 char **included_files = xnew (argc, char *); 680 char **included_files = xnew (argc, char *);
761 char *this_file; 681 char *this_file;
762 ARGUMENT *argbuffer; 682 ARGUMENT *argbuffer;
763 int current_arg = 0, file_count = 0; 683 int current_arg = 0, file_count = 0;
684 struct linebuffer filename_lb;
764 #ifdef VMS 685 #ifdef VMS
765 logical got_err; 686 logical got_err;
766 #endif 687 #endif
767 688
768 #ifdef DOS_NT 689 #ifdef DOS_NT
783 /* 704 /*
784 * If etags, always find typedefs and structure tags. Why not? 705 * If etags, always find typedefs and structure tags. Why not?
785 * Also default is to find macro constants. 706 * Also default is to find macro constants.
786 */ 707 */
787 if (!CTAGS) 708 if (!CTAGS)
788 typedefs = typedefs_and_cplusplus = constantypedefs = 1; 709 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
789 710
790 while (1) 711 while (1)
791 { 712 {
792 int opt = getopt_long (argc, argv, 713 int opt = getopt_long (argc, argv,
793 "-aCdDf:l:o:r:RStTi:BuvxwVhH", longopts, 0); 714 "-aCdDf:l:o:r:RStTi:BuvxwVhH", longopts, 0);
810 ++file_count; 731 ++file_count;
811 break; 732 break;
812 733
813 /* Common options. */ 734 /* Common options. */
814 case 'a': 735 case 'a':
815 append_to_tagfile++; 736 append_to_tagfile = TRUE;
816 break; 737 break;
817 case 'C': 738 case 'C':
818 cplusplus = 1; 739 cplusplus = TRUE;
819 break; 740 break;
820 case 'd': 741 case 'd':
821 constantypedefs = 1; 742 constantypedefs = TRUE;
822 break; 743 break;
823 case 'D': 744 case 'D':
824 constantypedefs = 0; 745 constantypedefs = FALSE;
825 break; 746 break;
826 case 'f': /* for compatibility with old makefiles */ 747 case 'f': /* for compatibility with old makefiles */
827 case 'o': 748 case 'o':
828 if (tagfile) 749 if (tagfile)
829 { 750 {
854 argbuffer[current_arg].what = NULL; 775 argbuffer[current_arg].what = NULL;
855 ++current_arg; 776 ++current_arg;
856 break; 777 break;
857 #endif /* ETAGS_REGEXPS */ 778 #endif /* ETAGS_REGEXPS */
858 case 'S': 779 case 'S':
859 noindentypedefs++; 780 noindentypedefs = TRUE;
860 break; 781 break;
861 case 'V': 782 case 'V':
862 print_version (); 783 print_version ();
863 break; 784 break;
864 case 'h': 785 case 'h':
865 case 'H': 786 case 'H':
866 print_help (); 787 print_help ();
867 break; 788 break;
868 case 't': 789 case 't':
869 typedefs++; 790 typedefs = TRUE;
870 break; 791 break;
871 case 'T': 792 case 'T':
872 typedefs++; 793 typedefs = typedefs_and_cplusplus = TRUE;
873 typedefs_and_cplusplus++;
874 break; 794 break;
875 #if (!CTAGS) 795 #if (!CTAGS)
876 /* Etags options */ 796 /* Etags options */
877 case 'i': 797 case 'i':
878 included_files[nincluded_files++] = optarg; 798 included_files[nincluded_files++] = optarg;
881 /* Ctags options. */ 801 /* Ctags options. */
882 case 'B': 802 case 'B':
883 searchar = '?'; 803 searchar = '?';
884 break; 804 break;
885 case 'u': 805 case 'u':
886 update++; 806 update = TRUE;
887 break; 807 break;
888 case 'v': 808 case 'v':
889 vgrind_style++; 809 vgrind_style = TRUE;
890 /*FALLTHRU*/ 810 /*FALLTHRU*/
891 case 'x': 811 case 'x':
892 cxref_style++; 812 cxref_style = TRUE;
893 break; 813 break;
894 case 'w': 814 case 'w':
895 no_warnings++; 815 no_warnings = TRUE;
896 break; 816 break;
897 #endif /* CTAGS */ 817 #endif /* CTAGS */
898 default: 818 default:
899 fprintf (stderr, 819 fprintf (stderr,
900 "%s: -%c flag not recognised.\n", progname, opt); 820 "%s: -%c flag not recognised.\n", progname, opt);
987 and use them. */ 907 and use them. */
988 if (streq (this_file, "-")) 908 if (streq (this_file, "-"))
989 { 909 {
990 while (!feof (stdin)) 910 while (!feof (stdin))
991 { 911 {
992 /* Use readline_internal so that regexp matching */
993 /* is not done on filenames. */
994 (void) readline_internal (&filename_lb, stdin); 912 (void) readline_internal (&filename_lb, stdin);
995 if (strlen (filename_lb.buffer) > 0) 913 if (strlen (filename_lb.buffer) > 0)
996 process_file (filename_lb.buffer); 914 process_file (filename_lb.buffer);
997 } 915 }
998 } 916 }
1008 if (!CTAGS) 926 if (!CTAGS)
1009 { 927 {
1010 while (nincluded_files-- > 0) 928 while (nincluded_files-- > 0)
1011 fprintf (tagf, "\f\n%s,include\n", *included_files++); 929 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1012 930
1013 (void) fclose (tagf); 931 fclose (tagf);
1014 exit (GOOD); 932 exit (GOOD);
1015 } 933 }
1016 934
935 /* If CTAGS, we are here. process_file did not write the tags yet,
936 because we want them ordered. Let's do it now. */
1017 if (cxref_style) 937 if (cxref_style)
1018 { 938 {
939 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
940 if (tagf == NULL)
941 pfatal (tagfile);
1019 put_entries (head); 942 put_entries (head);
1020 exit (GOOD); 943 exit (GOOD);
1021 } 944 }
945
1022 if (update) 946 if (update)
1023 { 947 {
948 char cmd[BUFSIZ];
1024 for (i = 0; i < current_arg; ++i) 949 for (i = 0; i < current_arg; ++i)
1025 { 950 {
1026 if (argbuffer[i].arg_type == at_language) 951 if (argbuffer[i].arg_type != at_filename)
1027 continue; 952 continue;
1028 sprintf (cmd, 953 sprintf (cmd,
1029 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS", 954 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1030 tagfile, argbuffer[i].what, tagfile); 955 tagfile, argbuffer[i].what, tagfile);
1031 (void) system (cmd); 956 if (system (cmd) != GOOD)
1032 } 957 fatal ("failed to execute shell command");
1033 append_to_tagfile++; 958 }
1034 } 959 append_to_tagfile = TRUE;
960 }
961
1035 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); 962 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1036 if (tagf == NULL) 963 if (tagf == NULL)
1037 { 964 pfatal (tagfile);
1038 perror (tagfile);
1039 exit (GOOD);
1040 }
1041 put_entries (head); 965 put_entries (head);
1042 (void) fclose (tagf); 966 fclose (tagf);
967
1043 if (update) 968 if (update)
1044 { 969 {
970 char cmd[BUFSIZ];
1045 sprintf (cmd, "sort %s -o %s", tagfile, tagfile); 971 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1046 (void) system (cmd); 972 exit (system (cmd));
1047 } 973 }
1048 exit (GOOD); 974 exit (GOOD);
1049 } 975 }
1050 976
1051 977
1078 void 1004 void
1079 process_file (file) 1005 process_file (file)
1080 char *file; 1006 char *file;
1081 { 1007 {
1082 struct stat stat_buf; 1008 struct stat stat_buf;
1009 FILE *inf;
1083 1010
1084 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode)) 1011 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1085 { 1012 {
1086 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file); 1013 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
1087 return; 1014 return;
1089 if (streq (file, tagfile) && !streq (tagfile, "-")) 1016 if (streq (file, tagfile) && !streq (tagfile, "-"))
1090 { 1017 {
1091 fprintf (stderr, "Skipping inclusion of %s in self.\n", file); 1018 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
1092 return; 1019 return;
1093 } 1020 }
1094 if (!find_entries (file)) 1021 inf = fopen (file, "r");
1095 { 1022 if (inf == NULL)
1023 {
1024 perror (file);
1096 return; 1025 return;
1097 } 1026 }
1027
1028 find_entries (file, inf);
1029
1098 if (!CTAGS) 1030 if (!CTAGS)
1099 { 1031 {
1100 char *filename; 1032 char *filename;
1101 1033
1102 if (file[0] == '/') 1034 if (file[0] == '/')
1149 1081
1150 /* 1082 /*
1151 * This routine opens the specified file and calls the function 1083 * This routine opens the specified file and calls the function
1152 * which finds the function and type definitions. 1084 * which finds the function and type definitions.
1153 */ 1085 */
1154 logical 1086 void
1155 find_entries (file) 1087 find_entries (file, inf)
1156 char *file; 1088 char *file;
1157 { 1089 FILE *inf;
1158 FILE *inf; 1090 {
1159 char *cp; 1091 char *cp;
1160 struct lang_entry *lang; 1092 struct lang_entry *lang;
1161 NODE *old_last_node; 1093 NODE *old_last_node;
1162 extern NODE *last_node; 1094 extern NODE *last_node;
1163 1095
1164 inf = fopen (file, "r");
1165 if (inf == NULL)
1166 {
1167 perror (file);
1168 return FALSE;
1169 }
1170 curfile = savestr (file); 1096 curfile = savestr (file);
1171 cp = etags_strrchr (file, '.'); 1097 cp = etags_strrchr (file, '.');
1172 1098
1173 /* If user specified a language, use it. */ 1099 /* If user specified a language, use it. */
1174 if (lang_func != NULL) 1100 if (lang_func != NULL)
1175 { 1101 {
1176 lang_func (inf); 1102 lang_func (inf);
1177 fclose (inf); 1103 fclose (inf);
1178 return TRUE; 1104 return;
1179 } 1105 }
1180 1106
1181 if (cp) 1107 if (cp)
1182 { 1108 {
1183 ++cp; 1109 ++cp;
1185 { 1111 {
1186 if (streq (cp, lang->extension)) 1112 if (streq (cp, lang->extension))
1187 { 1113 {
1188 lang->function (inf); 1114 lang->function (inf);
1189 fclose (inf); 1115 fclose (inf);
1190 return TRUE; 1116 return;
1191 } 1117 }
1192 } 1118 }
1193 } 1119 }
1194 1120
1195 /* Try Fortran. */ 1121 /* Try Fortran. */
1198 1124
1199 /* No Fortran entries found. Try C. */ 1125 /* No Fortran entries found. Try C. */
1200 if (old_last_node == last_node) 1126 if (old_last_node == last_node)
1201 default_C_entries (inf); 1127 default_C_entries (inf);
1202 fclose (inf); 1128 fclose (inf);
1203 return TRUE;
1204 } 1129 }
1205 1130
1206 /* Record a tag. */ 1131 /* Record a tag. */
1207 /* Should take a TOKEN* instead!! */ 1132 /* Should take a TOKEN* instead!! */
1208 void 1133 void
1209 pfnote (name, is_func, named, linestart, linelen, lno, cno) 1134 pfnote (name, is_func, named, linestart, linelen, lno, cno)
1210 char *name; /* tag name */ 1135 char *name; /* tag name */
1211 logical is_func; /* function or type name? */ 1136 logical is_func; /* tag is a function */
1212 logical named; /* tag different from text of definition? */ 1137 logical named; /* tag different from text of definition */
1213 char *linestart; 1138 char *linestart; /* start of the line where tag is */
1214 int linelen; 1139 int linelen; /* length of the line where tag is */
1215 int lno; 1140 int lno; /* line number */
1216 long cno; 1141 long cno; /* character number */
1217 { 1142 {
1143 register NODE *np = xnew (1, NODE);
1218 register char *fp; 1144 register char *fp;
1219 register NODE *np; 1145
1220 char tem[51];
1221 char c;
1222
1223 np = xnew (1, NODE);
1224 if (np == NULL)
1225 {
1226 if (CTAGS)
1227 {
1228 /* It's okay to output early in etags -- it only disrupts the
1229 * character count of the tag entries, which is no longer used
1230 * by tags.el anyway.
1231 */
1232 error ("too many entries to sort", 0);
1233 }
1234 put_entries (head);
1235 free_tree (head);
1236 head = NULL;
1237 np = xnew (1, NODE);
1238 }
1239 /* If ctags mode, change name "main" to M<thisfilename>. */ 1146 /* If ctags mode, change name "main" to M<thisfilename>. */
1240 if (CTAGS && !cxref_style && streq (name, "main")) 1147 if (CTAGS && !cxref_style && streq (name, "main"))
1241 { 1148 {
1242 fp = etags_strrchr (curfile, '/'); 1149 fp = etags_strrchr (curfile, '/');
1243 name = concat ("M", fp == 0 ? curfile : fp + 1, ""); 1150 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1244 fp = etags_strrchr (name, '.'); 1151 fp = etags_strrchr (np->name, '.');
1245 if (fp && fp[1] != '\0' && fp[2] == '\0') 1152 if (fp && fp[1] != '\0' && fp[2] == '\0')
1246 *fp = 0; 1153 fp[0] = 0;
1247 named = TRUE; 1154 np->named = TRUE;
1248 } 1155 }
1249 np->name = savestr (name); 1156 else
1157 {
1158 np->name = name;
1159 np->named = named;
1160 }
1250 np->file = curfile; 1161 np->file = curfile;
1251 np->is_func = is_func; 1162 np->is_func = is_func;
1252 np->named = named;
1253 np->lno = lno; 1163 np->lno = lno;
1254 /* Our char numbers are 0-base, because of C language tradition? 1164 /* Our char numbers are 0-base, because of C language tradition?
1255 ctags compatibility? old versions compatibility? I don't know. 1165 ctags compatibility? old versions compatibility? I don't know.
1256 Anyway, since emacs's are 1-base we espect etags.el to take care 1166 Anyway, since emacs's are 1-base we espect etags.el to take care
1257 of the difference. If we wanted to have 1-based numbers, we would 1167 of the difference. If we wanted to have 1-based numbers, we would
1258 uncomment the +1 below. */ 1168 uncomment the +1 below. */
1259 np->cno = cno /* + 1 */ ; 1169 np->cno = cno /* + 1 */ ;
1260 np->left = np->right = 0; 1170 np->left = np->right = NULL;
1261 if (!CTAGS) 1171 np->pat = savenstr (linestart, ((CTAGS && !cxref_style) ? 50 : linelen));
1262 {
1263 c = linestart[linelen];
1264 linestart[linelen] = 0;
1265 }
1266 else if (cxref_style == 0)
1267 {
1268 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
1269 linestart = tem;
1270 }
1271 np->pat = savestr (linestart);
1272 if (!CTAGS)
1273 {
1274 linestart[linelen] = c;
1275 }
1276 1172
1277 add_node (np, &head); 1173 add_node (np, &head);
1278 } 1174 }
1279 1175
1280 /* 1176 /*
1287 { 1183 {
1288 while (node) 1184 while (node)
1289 { 1185 {
1290 register NODE *node_right = node->right; 1186 register NODE *node_right = node->right;
1291 free_tree (node->left); 1187 free_tree (node->left);
1292 free (node->name); 1188 if (node->named)
1189 free (node->name);
1293 free (node->pat); 1190 free (node->pat);
1294 free ((char *) node); 1191 free ((char *) node);
1295 node = node_right; 1192 node = node_right;
1296 } 1193 }
1297 } 1194 }
1482 } 1379 }
1483 1380
1484 /* 1381 /*
1485 * The C symbol tables. 1382 * The C symbol tables.
1486 */ 1383 */
1384 enum sym_type
1385 {
1386 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
1387 };
1487 1388
1488 /* Feed stuff between (but not including) %[ and %] lines to: 1389 /* Feed stuff between (but not including) %[ and %] lines to:
1489 gperf -c -k1,3 -o -p -r -t 1390 gperf -c -k1,3 -o -p -r -t
1490 %[ 1391 %[
1491 struct C_stab_entry { char *name; int c_ext; enum sym_type type; } 1392 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1678 /* 1579 /*
1679 * When structdef is stagseen, scolonseen, or sinbody, structtag is the 1580 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1680 * struct tag, and structtype is the type of the preceding struct-like 1581 * struct tag, and structtype is the type of the preceding struct-like
1681 * keyword. 1582 * keyword.
1682 */ 1583 */
1683 char structtag[BUFSIZ]; 1584 char *structtag = "<uninited>";
1684 enum sym_type structtype; 1585 enum sym_type structtype;
1685 1586
1686 /* 1587 /*
1687 * Yet another little state machine to deal with preprocessor lines. 1588 * Yet another little state machine to deal with preprocessor lines.
1688 */ 1589 */
1727 * typdef IN OUT 1628 * typdef IN OUT
1728 * next_token_is_func IN OUT 1629 * next_token_is_func IN OUT
1729 */ 1630 */
1730 1631
1731 logical 1632 logical
1732 consider_token (c, tokp, c_ext, cblev, is_func) 1633 consider_token (str, len, c, c_ext, cblev, is_func)
1634 register char *str; /* IN: token pointer */
1635 register int len; /* IN: token length */
1733 register char c; /* IN: first char after the token */ 1636 register char c; /* IN: first char after the token */
1734 register TOKEN *tokp; /* IN: token pointer */
1735 int c_ext; /* IN: C extensions mask */ 1637 int c_ext; /* IN: C extensions mask */
1736 int cblev; /* IN: curly brace level */ 1638 int cblev; /* IN: curly brace level */
1737 logical *is_func; /* OUT: function found */ 1639 logical *is_func; /* OUT: function found */
1738 { 1640 {
1739 enum sym_type toktype = C_symtype(tokp->p, tokp->len, c_ext); 1641 enum sym_type toktype = C_symtype (str, len, c_ext);
1740 1642
1741 /* 1643 /*
1742 * Advance the definedef state machine. 1644 * Advance the definedef state machine.
1743 */ 1645 */
1744 switch (definedef) 1646 switch (definedef)
1838 } 1740 }
1839 return FALSE; 1741 return FALSE;
1840 } 1742 }
1841 if (structdef == skeyseen) 1743 if (structdef == skeyseen)
1842 { 1744 {
1745 /* Save the tag for struct/union/class, for functions that may be
1746 defined inside. */
1843 if (structtype == st_C_struct) 1747 if (structtype == st_C_struct)
1844 { 1748 structtag = savenstr (str, len);
1845 strncpy (structtag, tokp->p, tokp->len);
1846 structtag[tokp->len] = '\0'; /* for struct/union/class */
1847 }
1848 else 1749 else
1849 { 1750 structtag = "<enum>";
1850 structtag[0] = '\0'; /* for enum (why is it treated differently?) */
1851 }
1852 structdef = stagseen; 1751 structdef = stagseen;
1853 return TRUE; 1752 return TRUE;
1854 } 1753 }
1855 1754
1856 /* Avoid entering funcdef stuff if typdef is going on. */ 1755 /* Avoid entering funcdef stuff if typdef is going on. */
1860 return FALSE; 1759 return FALSE;
1861 } 1760 }
1862 1761
1863 /* Detect GNU macros. */ 1762 /* Detect GNU macros. */
1864 if (definedef == dnone) 1763 if (definedef == dnone)
1865 if (strneq (tokp->p, "DEFUN", 5) /* Used in emacs */ 1764 if (strneq (str, "DEFUN", 5) /* Used in emacs */
1866 #if FALSE 1765 #if FALSE
1867 These are defined inside C functions, so currently they 1766 These are defined inside C functions, so currently they
1868 are not met anyway. 1767 are not met anyway.
1869 || strneq (tokp->p, "EXFUN", 5) /* Used in glibc */ 1768 || strneq (str, "EXFUN", 5) /* Used in glibc */
1870 || strneq (tokp->p, "DEFVAR_", 7) /* Used in emacs */ 1769 || strneq (str, "DEFVAR_", 7) /* Used in emacs */
1871 #endif 1770 #endif
1872 || strneq (tokp->p, "SYSCALL", 7) /* Used in glibc (mach) */ 1771 || strneq (str, "SYSCALL", 7) /* Used in glibc (mach) */
1873 || strneq (tokp->p, "ENTRY", 5) /* Used in glibc */ 1772 || strneq (str, "ENTRY", 5) /* Used in glibc */
1874 || strneq (tokp->p, "PSEUDO", 6)) /* Used in glibc */ 1773 || strneq (str, "PSEUDO", 6)) /* Used in glibc */
1875 1774
1876 { 1775 {
1877 next_token_is_func = TRUE; 1776 next_token_is_func = TRUE;
1878 return FALSE; 1777 return FALSE;
1879 } 1778 }
1908 * C_entries () 1807 * C_entries ()
1909 * This routine finds functions, typedefs, #define's and 1808 * This routine finds functions, typedefs, #define's and
1910 * struct/union/enum definitions in C syntax and adds them 1809 * struct/union/enum definitions in C syntax and adds them
1911 * to the list. 1810 * to the list.
1912 */ 1811 */
1812 typedef struct
1813 {
1814 char *str;
1815 logical named;
1816 int linelen;
1817 int lineno;
1818 } TOKEN;
1819
1820 #define current_lb_is_new (newndx == curndx)
1821 #define switch_line_buffers() (curndx = 1 - curndx)
1913 1822
1914 #define curlb (lbs[curndx].lb) 1823 #define curlb (lbs[curndx].lb)
1915 #define othlb (lbs[1-curndx].lb) 1824 #define othlb (lbs[1-curndx].lb)
1916 #define newlb (lbs[newndx].lb) 1825 #define newlb (lbs[newndx].lb)
1917 #define curlinepos (lbs[curndx].linepos) 1826 #define curlinepos (lbs[curndx].linepos)
1918 #define othlinepos (lbs[1-curndx].linepos) 1827 #define othlinepos (lbs[1-curndx].linepos)
1919 #define newlinepos (lbs[newndx].linepos) 1828 #define newlinepos (lbs[newndx].linepos)
1920 1829
1921 /* Save and restore token state. This is used when preprocessor defines
1922 are handled, to avoid disturbing active function/typedef/struct states. */
1923 #define TOKEN_SAVED_P (savetok.lineno > 0)
1924 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1925 savetok.len = toklen, strcpy(savenameb, nameb))
1926 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1927 toklen = tok.len, strcpy(nameb, savenameb), \
1928 savetok.lineno = 0)
1929
1930 #define CNL_SAVE_DEFINEDEF \ 1830 #define CNL_SAVE_DEFINEDEF \
1931 do { \ 1831 do { \
1932 SET_FILEPOS (curlinepos, inf, charno); \ 1832 curlinepos = charno; \
1933 lineno++; \ 1833 lineno++; \
1934 charno += readline (&curlb, inf); \ 1834 charno += readline (&curlb, inf); \
1935 lp = curlb.buffer; \ 1835 lp = curlb.buffer; \
1936 quotednl = FALSE; \ 1836 quotednl = FALSE; \
1937 newndx = curndx; \ 1837 newndx = curndx; \
1938 } while (0) 1838 } while (0)
1939 1839
1940 #define CNL \ 1840 #define CNL \
1941 do { \ 1841 do { \
1942 CNL_SAVE_DEFINEDEF; \ 1842 CNL_SAVE_DEFINEDEF; \
1943 if (TOKEN_SAVED_P) \ 1843 if (token_saved) \
1944 RESTORE_TOKEN; \ 1844 { \
1845 tok = savetok; \
1846 token_saved = FALSE; \
1847 } \
1945 definedef = dnone; \ 1848 definedef = dnone; \
1946 } while (0) 1849 } while (0)
1947 1850
1948 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \ 1851 #define make_tag_from_new_lb(isfun) pfnote (tok.str, isfun, tok.named, \
1949 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos)) 1852 newlb.buffer, tok.linelen, tok.lineno, newlinepos)
1950 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \ 1853 #define make_tag_from_oth_lb(isfun) pfnote (tok.str, isfun, tok.named, \
1951 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos)) 1854 othlb.buffer, tok.linelen, tok.lineno, othlinepos)
1952 1855
1953 void 1856 void
1954 C_entries (c_ext, inf) 1857 C_entries (c_ext, inf)
1955 int c_ext; /* extension of C */ 1858 int c_ext; /* extension of C */
1956 FILE *inf; /* input file */ 1859 FILE *inf; /* input file */
1957 { 1860 {
1958 register char c; /* latest char read; '\0' for end of line */ 1861 register char c; /* latest char read; '\0' for end of line */
1959 register char *lp; /* pointer one beyond the character `c' */ 1862 register char *lp; /* pointer one beyond the character `c' */
1960 int curndx, newndx; /* indices for current and new lb */ 1863 int curndx, newndx; /* indices for current and new lb */
1961 TOKEN tok; /* latest token read for funcdef & structdef */ 1864 TOKEN tok; /* latest token read */
1962 char nameb[BUFSIZ]; /* latest token name for funcdef & structdef */ 1865 register int tokoff; /* offset in line of start of current token */
1963 register int tokoff; /* offset in line of start of latest token */ 1866 register int toklen; /* length of current token */
1964 register int toklen; /* length of latest token */
1965 int cblev; /* current curly brace level */ 1867 int cblev; /* current curly brace level */
1966 int parlev; /* current parenthesis level */ 1868 int parlev; /* current parenthesis level */
1967 logical incomm, inquote, inchar, quotednl, midtoken; 1869 logical incomm, inquote, inchar, quotednl, midtoken;
1968 logical cplpl; 1870 logical cplpl;
1969 TOKEN savetok; /* saved token during preprocessor handling */ 1871 logical token_saved; /* token saved */
1970 char savenameb[BUFSIZ]; /* ouch! */ 1872 TOKEN savetok; /* token saved during preprocessor handling */
1971 1873
1972 savetok.lineno = 0;
1973 curndx = newndx = 0; 1874 curndx = newndx = 0;
1974 lineno = 0; 1875 lineno = 0;
1975 charno = 0; 1876 charno = 0;
1976 lp = curlb.buffer; 1877 lp = curlb.buffer;
1977 *lp = 0; 1878 *lp = 0;
1978 1879
1979 definedef = dnone; funcdef = fnone; typdef = tnone; structdef = snone; 1880 definedef = dnone; funcdef = fnone; typdef = tnone; structdef = snone;
1980 next_token_is_func = yacc_rules = FALSE; 1881 next_token_is_func = yacc_rules = token_saved = FALSE;
1981 midtoken = inquote = inchar = incomm = quotednl = FALSE; 1882 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1982 cblev = 0; 1883 cblev = 0;
1983 parlev = 0; 1884 parlev = 0;
1984 cplpl = c_ext & C_PLPL; 1885 cplpl = c_ext & C_PLPL;
1985 1886
2141 } 2042 }
2142 else 2043 else
2143 { 2044 {
2144 logical is_func = FALSE; 2045 logical is_func = FALSE;
2145 2046
2146 tok.lineno = lineno;
2147 tok.p = newlb.buffer + tokoff;
2148 tok.len = toklen;
2149 tok.named = FALSE;
2150 if (yacc_rules 2047 if (yacc_rules
2151 || consider_token (c, &tok, c_ext, cblev, &is_func)) 2048 || consider_token (newlb.buffer + tokoff, toklen,
2049 c, c_ext, cblev, &is_func))
2152 { 2050 {
2153 if (structdef == sinbody 2051 if (structdef == sinbody
2154 && definedef == dnone 2052 && definedef == dnone
2155 && is_func) 2053 && is_func)
2156 /* function defined in C++ class body */ 2054 /* function defined in C++ class body */
2157 { 2055 {
2158 sprintf (nameb, "%s::%.*s", 2056 char *cp = newlb.buffer + tokoff + toklen;
2159 ((structtag[0] == '\0') 2057 char c = *cp;
2160 ? "_anonymous_" : structtag), 2058 *cp = '\0';
2161 tok.len, tok.p); 2059 tok.str = concat (structtag, "::",
2060 newlb.buffer + tokoff);
2061 *cp = c;
2162 tok.named = TRUE; 2062 tok.named = TRUE;
2163 } 2063 }
2164 else 2064 else
2165 { 2065 {
2166 sprintf (nameb, "%.*s", tok.len, tok.p); 2066 tok.str = savenstr (newlb.buffer+tokoff, toklen);
2067 if (structdef == stagseen
2068 || typdef == tend
2069 || (is_func
2070 && definedef == dignorerest)) /* macro */
2071 tok.named = TRUE;
2072 else
2073 tok.named = FALSE;
2167 } 2074 }
2168 2075 tok.lineno = lineno;
2169 if (structdef == stagseen 2076 tok.linelen = tokoff + toklen + 1;
2170 || typdef == tend
2171 || (is_func
2172 && definedef == dignorerest)) /* macro */
2173 tok.named = TRUE;
2174 2077
2175 if (definedef == dnone 2078 if (definedef == dnone
2176 && (funcdef == ftagseen 2079 && (funcdef == ftagseen
2177 || structdef == stagseen 2080 || structdef == stagseen
2178 || typdef == tend)) 2081 || typdef == tend))
2179 { 2082 {
2180 if (newndx == curndx) 2083 if (current_lb_is_new)
2181 curndx = 1 - curndx; /* switch line buffers */ 2084 switch_line_buffers ();
2182 } 2085 }
2183 else 2086 else
2184 MAKE_TAG_FROM_NEW_LB (is_func); 2087 make_tag_from_new_lb (is_func);
2185 } 2088 }
2186 midtoken = FALSE; 2089 midtoken = FALSE;
2187 } 2090 }
2188 } /* if (endtoken (c)) */ 2091 } /* if (endtoken (c)) */
2189 else if (intoken (c)) 2092 else if (intoken (c))
2201 { 2104 {
2202 case fstartlist: 2105 case fstartlist:
2203 funcdef = finlist; 2106 funcdef = finlist;
2204 continue; 2107 continue;
2205 case flistseen: 2108 case flistseen:
2206 MAKE_TAG_FROM_OTH_LB (TRUE); 2109 make_tag_from_oth_lb (TRUE);
2207 funcdef = fignore; 2110 funcdef = fignore;
2208 break; 2111 break;
2209 case ftagseen: 2112 case ftagseen:
2210 funcdef = fnone; 2113 funcdef = fnone;
2211 break; 2114 break;
2218 so we can avoid saving the token when not absolutely 2121 so we can avoid saving the token when not absolutely
2219 necessary. [This is a speed hack.] */ 2122 necessary. [This is a speed hack.] */
2220 if (c == 'd' && strneq (lp, "efine", 5) 2123 if (c == 'd' && strneq (lp, "efine", 5)
2221 && iswhite (*(lp + 5))) 2124 && iswhite (*(lp + 5)))
2222 { 2125 {
2223 SAVE_TOKEN; 2126 savetok = tok;
2127 token_saved = TRUE;
2224 definedef = ddefineseen; 2128 definedef = ddefineseen;
2225 lp += 6; 2129 lp += 6;
2226 } 2130 }
2227 else 2131 else
2228 definedef = dignorerest; 2132 definedef = dignorerest;
2252 switch (funcdef) 2156 switch (funcdef)
2253 { 2157 {
2254 case ftagseen: 2158 case ftagseen:
2255 if (yacc_rules) 2159 if (yacc_rules)
2256 { 2160 {
2257 MAKE_TAG_FROM_OTH_LB (FALSE); 2161 make_tag_from_oth_lb (FALSE);
2258 funcdef = fignore; 2162 funcdef = fignore;
2259 } 2163 }
2260 break; 2164 break;
2261 case fstartlist: 2165 case fstartlist:
2262 funcdef = fnone; 2166 funcdef = fnone;
2268 break; 2172 break;
2269 if (cblev == 0) 2173 if (cblev == 0)
2270 switch (typdef) 2174 switch (typdef)
2271 { 2175 {
2272 case tend: 2176 case tend:
2273 MAKE_TAG_FROM_OTH_LB (FALSE); 2177 make_tag_from_oth_lb (FALSE);
2274 /* FALLTHRU */ 2178 /* FALLTHRU */
2275 default: 2179 default:
2276 typdef = tnone; 2180 typdef = tnone;
2277 } 2181 }
2278 if (funcdef != fignore) 2182 if (funcdef != fignore)
2292 if (definedef != dnone) 2196 if (definedef != dnone)
2293 break; 2197 break;
2294 if (cblev == 0 && typdef == tend) 2198 if (cblev == 0 && typdef == tend)
2295 { 2199 {
2296 typdef = tignore; 2200 typdef = tignore;
2297 MAKE_TAG_FROM_OTH_LB (FALSE); 2201 make_tag_from_oth_lb (FALSE);
2298 break; 2202 break;
2299 } 2203 }
2300 if (funcdef != finlist && funcdef != fignore) 2204 if (funcdef != finlist && funcdef != fignore)
2301 funcdef = fnone; 2205 funcdef = fnone;
2302 if (structdef == stagseen) 2206 if (structdef == stagseen)
2316 This handles constructs like: 2220 This handles constructs like:
2317 typedef void OperatorFun (int fun); */ 2221 typedef void OperatorFun (int fun); */
2318 if (*lp != '*') 2222 if (*lp != '*')
2319 { 2223 {
2320 typdef = tignore; 2224 typdef = tignore;
2321 MAKE_TAG_FROM_OTH_LB (FALSE); 2225 make_tag_from_oth_lb (FALSE);
2322 } 2226 }
2323 break; 2227 break;
2324 } /* switch (typdef) */ 2228 } /* switch (typdef) */
2325 break; 2229 break;
2326 case ftagseen: 2230 case ftagseen:
2345 break; 2249 break;
2346 } 2250 }
2347 if (cblev == 0 && typdef == tend) 2251 if (cblev == 0 && typdef == tend)
2348 { 2252 {
2349 typdef = tignore; 2253 typdef = tignore;
2350 MAKE_TAG_FROM_OTH_LB (FALSE); 2254 make_tag_from_oth_lb (FALSE);
2351 } 2255 }
2352 } 2256 }
2353 else if (parlev < 0) /* can happen due to ill-conceived #if's. */ 2257 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
2354 parlev = 0; 2258 parlev = 0;
2355 break; 2259 break;
2359 if (typdef == ttypedseen) 2263 if (typdef == ttypedseen)
2360 typdef = tinbody; 2264 typdef = tinbody;
2361 switch (structdef) 2265 switch (structdef)
2362 { 2266 {
2363 case skeyseen: /* unnamed struct */ 2267 case skeyseen: /* unnamed struct */
2364 structtag[0] = '\0'; 2268 structtag = "_anonymous_";
2365 structdef = sinbody; 2269 structdef = sinbody;
2366 break; 2270 break;
2367 case stagseen: 2271 case stagseen:
2368 case scolonseen: /* named struct */ 2272 case scolonseen: /* named struct */
2369 structdef = sinbody; 2273 structdef = sinbody;
2370 MAKE_TAG_FROM_OTH_LB (FALSE); 2274 make_tag_from_oth_lb (FALSE);
2371 break; 2275 break;
2372 } 2276 }
2373 switch (funcdef) 2277 switch (funcdef)
2374 { 2278 {
2375 case flistseen: 2279 case flistseen:
2376 MAKE_TAG_FROM_OTH_LB (TRUE); 2280 make_tag_from_oth_lb (TRUE);
2377 /* FALLTHRU */ 2281 /* FALLTHRU */
2378 case fignore: 2282 case fignore:
2379 funcdef = fnone; 2283 funcdef = fnone;
2380 break; 2284 break;
2381 case fnone: 2285 case fnone:
2403 cblev--; 2307 cblev--;
2404 if (cblev == 0) 2308 if (cblev == 0)
2405 { 2309 {
2406 if (typdef == tinbody) 2310 if (typdef == tinbody)
2407 typdef = tend; 2311 typdef = tend;
2312 #if FALSE /* too risky */
2313 if (structdef == sinbody)
2314 free (structtag);
2315 #endif
2408 structdef = snone; 2316 structdef = snone;
2409 strcpy (structtag, "<error 2>"); 2317 structtag = "<error>";
2410 } 2318 }
2411 break; 2319 break;
2412 case '=': 2320 case '=':
2413 case '#': case '+': case '-': case '~': case '&': case '%': case '/': 2321 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2414 case '|': case '^': case '!': case '<': case '>': case '.': case '?': 2322 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2466 } 2374 }
2467 2375
2468 /* Fortran parsing */ 2376 /* Fortran parsing */
2469 2377
2470 char *dbp; 2378 char *dbp;
2471 int pfcnt;
2472 2379
2473 logical 2380 logical
2474 tail (cp) 2381 tail (cp)
2475 char *cp; 2382 char *cp;
2476 { 2383 {
2511 void 2418 void
2512 getit (inf) 2419 getit (inf)
2513 FILE *inf; 2420 FILE *inf;
2514 { 2421 {
2515 register char *cp; 2422 register char *cp;
2516 char c;
2517 char nambuf[BUFSIZ];
2518 2423
2519 while (isspace (*dbp)) 2424 while (isspace (*dbp))
2520 dbp++; 2425 dbp++;
2521 if (*dbp == '\0') 2426 if (*dbp == '\0')
2522 { 2427 {
2537 for (cp = dbp + 1; 2442 for (cp = dbp + 1;
2538 (*cp 2443 (*cp
2539 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$'))); 2444 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
2540 cp++) 2445 cp++)
2541 continue; 2446 continue;
2542 c = *cp; 2447 pfnote (savenstr (dbp, cp-dbp), TRUE, FALSE, lb.buffer,
2543 *cp = '\0';
2544 strcpy (nambuf, dbp);
2545 *cp = c;
2546 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2547 cp - lb.buffer + 1, lineno, linecharno); 2448 cp - lb.buffer + 1, lineno, linecharno);
2548 pfcnt++;
2549 } 2449 }
2550 2450
2551 void 2451 void
2552 Fortran_functions (inf) 2452 Fortran_functions (inf)
2553 FILE *inf; 2453 FILE *inf;
2554 { 2454 {
2555 lineno = 0; 2455 lineno = 0;
2556 charno = 0; 2456 charno = 0;
2557 pfcnt = 0;
2558 2457
2559 while (!feof (inf)) 2458 while (!feof (inf))
2560 { 2459 {
2561 lineno++; 2460 lineno++;
2562 linecharno = charno; 2461 linecharno = charno;
2637 */ 2536 */
2638 void 2537 void
2639 Asm_labels (inf) 2538 Asm_labels (inf)
2640 FILE *inf; 2539 FILE *inf;
2641 { 2540 {
2642 char nambuf[BUFSIZ];
2643 register char *cp; 2541 register char *cp;
2644 char c;
2645 2542
2646 lineno = 0; 2543 lineno = 0;
2647 charno = 0; 2544 charno = 0;
2648 pfcnt = 0;
2649 2545
2650 while (!feof (inf)) 2546 while (!feof (inf))
2651 { 2547 {
2652 lineno++; 2548 lineno++;
2653 linecharno = charno; 2549 linecharno = charno;
2663 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$') 2559 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
2664 cp++; 2560 cp++;
2665 if (*cp == ':' || isspace (*cp)) 2561 if (*cp == ':' || isspace (*cp))
2666 { 2562 {
2667 /* Found end of label, so copy it and add it to the table. */ 2563 /* Found end of label, so copy it and add it to the table. */
2668 c = *cp; 2564 pfnote (savenstr (lb.buffer, cp-lb.buffer), TRUE, FALSE,
2669 *cp = '\0'; 2565 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2670 strcpy (nambuf, lb.buffer);
2671 *cp = c;
2672 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2673 cp - lb.buffer + 1, lineno, linecharno);
2674 pfcnt++;
2675 } 2566 }
2676 } 2567 }
2677 } 2568 }
2678 } 2569 }
2679 2570
2699 { 2590 {
2700 struct linebuffer tline; /* mostly copied from C_entries */ 2591 struct linebuffer tline; /* mostly copied from C_entries */
2701 long save_lcno; 2592 long save_lcno;
2702 int save_lineno; 2593 int save_lineno;
2703 char c, *cp; 2594 char c, *cp;
2704 char nambuf[BUFSIZ]; 2595 char *nambuf;
2705 2596
2706 logical /* each of these flags is TRUE iff: */ 2597 logical /* each of these flags is TRUE iff: */
2707 incomment, /* point is inside a comment */ 2598 incomment, /* point is inside a comment */
2708 inquote, /* point is inside '..' string */ 2599 inquote, /* point is inside '..' string */
2709 get_tagname, /* point is after PROCEDURE/FUNCTION */ 2600 get_tagname, /* point is after PROCEDURE/FUNCTION */
2729 2620
2730 /* long main loop to get next char */ 2621 /* long main loop to get next char */
2731 while (!feof (inf)) 2622 while (!feof (inf))
2732 { 2623 {
2733 c = *dbp++; 2624 c = *dbp++;
2734 if (c == 0) /* if end of line */ 2625 if (c == '\0') /* if end of line */
2735 { 2626 {
2736 GET_NEW_LINE; 2627 GET_NEW_LINE;
2737 if (*dbp == 0) 2628 if (*dbp == '\0')
2738 continue; 2629 continue;
2739 if (!((found_tag && verify_tag) || 2630 if (!((found_tag && verify_tag) ||
2740 get_tagname)) 2631 get_tagname))
2741 c = *dbp++; /* only if don't need *dbp pointing */ 2632 c = *dbp++; /* only if don't need *dbp pointing */
2742 /* to the beginning of the name of */ 2633 /* to the beginning of the name of */
2743 /* the procedure or function */ 2634 /* the procedure or function */
2744 } 2635 }
2745 if (incomment) 2636 if (incomment)
2746 { 2637 {
2747 if (c == '}') /* within { - } comments */ 2638 if (c == '}') /* within { - } comments */
2748 incomment = FALSE; 2639 incomment = FALSE;
2757 { 2648 {
2758 if (c == '\'') 2649 if (c == '\'')
2759 inquote = FALSE; 2650 inquote = FALSE;
2760 continue; 2651 continue;
2761 } 2652 }
2762 else 2653 else
2763 switch (c) 2654 switch (c)
2764 { 2655 {
2765 case '\'': 2656 case '\'':
2766 inquote = TRUE; /* found first quote */ 2657 inquote = TRUE; /* found first quote */
2767 continue; 2658 continue;
2812 } 2703 }
2813 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */ 2704 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2814 { 2705 {
2815 found_tag = FALSE; 2706 found_tag = FALSE;
2816 verify_tag = FALSE; 2707 verify_tag = FALSE;
2817 pfnote (nambuf, TRUE, FALSE, 2708 pfnote (nambuf, TRUE, FALSE, tline.buffer,
2818 tline.buffer, cp - tline.buffer + 1, 2709 cp - tline.buffer + 1, save_lineno, save_lcno);
2819 save_lineno, save_lcno);
2820 continue; 2710 continue;
2821 } 2711 }
2822 } 2712 }
2823 if (get_tagname) /* grab name of proc or fn */ 2713 if (get_tagname) /* grab name of proc or fn */
2824 { 2714 {
2832 save_lcno = linecharno; 2722 save_lcno = linecharno;
2833 2723
2834 /* grab block name */ 2724 /* grab block name */
2835 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++) 2725 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2836 continue; 2726 continue;
2837 c = cp[0]; 2727 nambuf = savenstr (dbp, cp-dbp);
2838 cp[0] = 0;
2839 strcpy (nambuf, dbp);
2840 cp[0] = c;
2841 dbp = cp; /* restore dbp to e-o-token */ 2728 dbp = cp; /* restore dbp to e-o-token */
2842 get_tagname = FALSE; 2729 get_tagname = FALSE;
2843 found_tag = TRUE; 2730 found_tag = TRUE;
2844 continue; 2731 continue;
2845 2732
2846 /* and proceed to check for "extern" */ 2733 /* and proceed to check for "extern" */
2847 } 2734 }
2848 if (!incomment && !inquote && !found_tag && !get_tagname) 2735 else if (!incomment && !inquote && !found_tag)
2849 { 2736 {
2850 /* check for proc/fn keywords */ 2737 /* check for proc/fn keywords */
2851 switch (c | ' ') 2738 switch (c | ' ')
2852 { 2739 {
2853 case 'p': 2740 case 'p':
2863 } /* while not eof */ 2750 } /* while not eof */
2864 } 2751 }
2865 2752
2866 /* 2753 /*
2867 * lisp tag functions 2754 * lisp tag functions
2868 * just look for (def or (DEF 2755 * look for (def or (DEF, quote or QUOTE
2869 */ 2756 */
2870
2871 int 2757 int
2872 L_isdef (tokp) 2758 L_isdef (strp)
2873 register char *tokp; 2759 register char *strp;
2874 { 2760 {
2875 return ((tokp[1] == 'd' || tokp[1] == 'D') 2761 return ((strp[1] == 'd' || strp[1] == 'D')
2876 && (tokp[2] == 'e' || tokp[2] == 'E') 2762 && (strp[2] == 'e' || strp[2] == 'E')
2877 && (tokp[3] == 'f' || tokp[3] == 'F')); 2763 && (strp[3] == 'f' || strp[3] == 'F'));
2878 } 2764 }
2879 2765
2880 int 2766 int
2881 L_isquote (tokp) 2767 L_isquote (strp)
2882 register char *tokp; 2768 register char *strp;
2883 { 2769 {
2884 return ((*(++tokp) == 'q' || *tokp == 'Q') 2770 return ((*(++strp) == 'q' || *strp == 'Q')
2885 && (*(++tokp) == 'u' || *tokp == 'U') 2771 && (*(++strp) == 'u' || *strp == 'U')
2886 && (*(++tokp) == 'o' || *tokp == 'O') 2772 && (*(++strp) == 'o' || *strp == 'O')
2887 && (*(++tokp) == 't' || *tokp == 'T') 2773 && (*(++strp) == 't' || *strp == 'T')
2888 && (*(++tokp) == 'e' || *tokp == 'E') 2774 && (*(++strp) == 'e' || *strp == 'E')
2889 && isspace(*(++tokp))); 2775 && isspace(*(++strp)));
2890 } 2776 }
2891 2777
2892 void 2778 void
2893 L_getit () 2779 L_getit ()
2894 { 2780 {
2895 register char *cp; 2781 register char *cp;
2896 char c;
2897 char nambuf[BUFSIZ];
2898 2782
2899 if (*dbp == '\'') /* Skip prefix quote */ 2783 if (*dbp == '\'') /* Skip prefix quote */
2900 dbp++; 2784 dbp++;
2901 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */ 2785 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
2902 { 2786 {
2903 dbp += 7; 2787 dbp += 7;
2904 while (isspace(*dbp)) 2788 while (isspace(*dbp))
2905 dbp++; 2789 dbp++;
2906 } 2790 }
2907 for (cp = dbp /*+1*/; *cp && *cp != '(' && *cp != ' ' && *cp != ')'; cp++) 2791 for (cp = dbp /*+1*/;
2792 *cp && *cp != '(' && *cp != ' ' && *cp != ')';
2793 cp++)
2908 continue; 2794 continue;
2909 if (cp == dbp) 2795 if (cp == dbp)
2910 return; 2796 return;
2911 2797
2912 c = cp[0]; 2798 pfnote (savenstr (dbp, cp-dbp), TRUE, FALSE, lb.buffer,
2913 cp[0] = 0;
2914 strcpy (nambuf, dbp);
2915 cp[0] = c;
2916 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2917 cp - lb.buffer + 1, lineno, linecharno); 2799 cp - lb.buffer + 1, lineno, linecharno);
2918 pfcnt++;
2919 } 2800 }
2920 2801
2921 void 2802 void
2922 Lisp_functions (inf) 2803 Lisp_functions (inf)
2923 FILE *inf; 2804 FILE *inf;
2924 { 2805 {
2925 lineno = 0; 2806 lineno = 0;
2926 charno = 0; 2807 charno = 0;
2927 pfcnt = 0;
2928 2808
2929 while (!feof (inf)) 2809 while (!feof (inf))
2930 { 2810 {
2931 lineno++; 2811 lineno++;
2932 linecharno = charno; 2812 linecharno = charno;
2983 Scheme_functions (inf) 2863 Scheme_functions (inf)
2984 FILE *inf; 2864 FILE *inf;
2985 { 2865 {
2986 lineno = 0; 2866 lineno = 0;
2987 charno = 0; 2867 charno = 0;
2988 pfcnt = 0;
2989 2868
2990 while (!feof (inf)) 2869 while (!feof (inf))
2991 { 2870 {
2992 lineno++; 2871 lineno++;
2993 linecharno = charno; 2872 linecharno = charno;
3024 2903
3025 void 2904 void
3026 get_scheme () 2905 get_scheme ()
3027 { 2906 {
3028 register char *cp; 2907 register char *cp;
3029 char c;
3030 char nambuf[BUFSIZ];
3031 2908
3032 if (*dbp == 0) 2909 if (*dbp == 0)
3033 return; 2910 return;
3034 /* Go till you get to white space or a syntactic break */ 2911 /* Go till you get to white space or a syntactic break */
3035 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++) 2912 for (cp = dbp + 1;
2913 *cp && *cp != '(' && *cp != ')' && !isspace (*cp);
2914 cp++)
3036 continue; 2915 continue;
3037 /* Null terminate the string there. */ 2916 pfnote (savenstr (dbp, cp-dbp), TRUE, FALSE,
3038 c = cp[0]; 2917 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3039 cp[0] = 0;
3040 /* Copy the string */
3041 strcpy (nambuf, dbp);
3042 /* Unterminate the string */
3043 cp[0] = c;
3044 /* Announce the change */
3045 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3046 pfcnt++;
3047 } 2918 }
3048 2919
3049 /* Find tags in TeX and LaTeX input files. */ 2920 /* Find tags in TeX and LaTeX input files. */
3050 2921
3051 /* TEX_toktab is a table of TeX control sequences that define tags. 2922 /* TEX_toktab is a table of TeX control sequences that define tags.
3083 { 2954 {
3084 char *lasthit; 2955 char *lasthit;
3085 2956
3086 lineno = 0; 2957 lineno = 0;
3087 charno = 0; 2958 charno = 0;
3088 pfcnt = 0;
3089 2959
3090 /* Select either \ or ! as escape character. */ 2960 /* Select either \ or ! as escape character. */
3091 TEX_mode (inf); 2961 TEX_mode (inf);
3092 2962
3093 /* Initialize token table once from environment. */ 2963 /* Initialize token table once from environment. */
3214 TEX_getit (name, len) 3084 TEX_getit (name, len)
3215 char *name; 3085 char *name;
3216 int len; 3086 int len;
3217 { 3087 {
3218 char *p = name + len; 3088 char *p = name + len;
3219 char nambuf[BUFSIZ];
3220 3089
3221 if (*name == 0) 3090 if (*name == 0)
3222 return; 3091 return;
3223 3092
3224 /* Let tag name extend to next group close (or end of line) */ 3093 /* Let tag name extend to next group close (or end of line) */
3225 while (*p && *p != TEX_clgrp) 3094 while (*p && *p != TEX_clgrp)
3226 p++; 3095 p++;
3227 strncpy (nambuf, name, p - name); 3096 pfnote (savenstr (name, p-name), TRUE, FALSE, lb.buffer,
3228 nambuf[p - name] = 0; 3097 strlen (lb.buffer), lineno, linecharno);
3229
3230 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
3231 pfcnt++;
3232 } 3098 }
3233 3099
3234 /* If the text at CP matches one of the tag-defining TeX command names, 3100 /* If the text at CP matches one of the tag-defining TeX command names,
3235 return the pointer to the first occurrence of that command in TEX_toktab. 3101 return the pointer to the first occurrence of that command in TEX_toktab.
3236 Otherwise return -1. 3102 Otherwise return -1.
3254 is gotten in compound term. */ 3120 is gotten in compound term. */
3255 void 3121 void
3256 prolog_getit (s) 3122 prolog_getit (s)
3257 char *s; 3123 char *s;
3258 { 3124 {
3259 char nambuf[BUFSIZ], *save_s, tmpc; 3125 char *save_s;
3260 int insquote, npar; 3126 int insquote, npar;
3261 3127
3262 save_s = s; 3128 save_s = s;
3263 insquote = FALSE; 3129 insquote = FALSE;
3264 npar = 0; 3130 npar = 0;
3265 while (1) 3131 while (1)
3266 { 3132 {
3267 if (*s == '\0') /* syntax error. */ 3133 if (s[0] == '\0') /* syntax error. */
3268 return; 3134 return;
3269 else if (insquote && *s == '\'' && *(s + 1) == '\'') 3135 else if (insquote && s[0] == '\'' && s[1] == '\'')
3270 s += 2; 3136 s += 2;
3271 else if (*s == '\'') 3137 else if (s[0] == '\'')
3272 { 3138 {
3273 insquote = !insquote; 3139 insquote = !insquote;
3274 s++; 3140 s++;
3275 } 3141 }
3276 else if (!insquote && *s == '(') 3142 else if (!insquote && s[0] == '(')
3277 { 3143 {
3278 npar++; 3144 npar++;
3279 s++; 3145 s++;
3280 } 3146 }
3281 else if (!insquote && *s == ')') 3147 else if (!insquote && s[0] == ')')
3282 { 3148 {
3283 npar--; 3149 npar--;
3284 s++; 3150 s++;
3285 if (npar == 0) 3151 if (npar == 0)
3286 break; 3152 break;
3287 else if (npar < 0) /* syntax error. */ 3153 else if (npar < 0) /* syntax error. */
3288 return; 3154 return;
3289 } 3155 }
3290 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0')) 3156 else if (!insquote && s[0] == '.'
3157 && (isspace (s[1]) || s[1] == '\0'))
3291 { /* fullstop. */ 3158 { /* fullstop. */
3292 if (npar != 0) /* syntax error. */ 3159 if (npar != 0) /* syntax error. */
3293 return; 3160 return;
3294 s++; 3161 s++;
3295 break; 3162 break;
3296 } 3163 }
3297 else 3164 else
3298 s++; 3165 s++;
3299 } 3166 }
3300 tmpc = *s; 3167 pfnote (savenstr (save_s, s-save_s), TRUE, FALSE,
3301 *s = '\0'; 3168 save_s, s-save_s, lineno, linecharno);
3302 strcpy (nambuf, save_s);
3303 *s = tmpc;
3304 pfnote (nambuf, TRUE, FALSE, save_s, strlen (nambuf), lineno, linecharno);
3305 } 3169 }
3306 3170
3307 /* It is assumed that prolog predicate starts from column 0. */ 3171 /* It is assumed that prolog predicate starts from column 0. */
3308 void 3172 void
3309 Prolog_functions (inf) 3173 Prolog_functions (inf)
3662 charno += readline (&lb, inf) + 1; 3526 charno += readline (&lb, inf) + 1;
3663 } 3527 }
3664 } 3528 }
3665 3529
3666 3530
3531 /*
3532 * Return a pointer to a space of size strlen(cp)+1 allocated
3533 * with xnew where the string CP has been copied.
3534 */
3667 char * 3535 char *
3668 savestr (cp) 3536 savestr (cp)
3669 char *cp; 3537 char *cp;
3670 { 3538 {
3671 return savenstr (cp, strlen (cp)); 3539 return savenstr (cp, strlen (cp));
3672 } 3540 }
3673 3541
3542 /*
3543 * Return a pointer to a space of size LEN+1 allocated with xnew where
3544 * the string CP has been copied for at most the first LEN characters.
3545 */
3674 char * 3546 char *
3675 savenstr (cp, len) 3547 savenstr (cp, len)
3676 char *cp; 3548 char *cp;
3677 int len; 3549 int len;
3678 { 3550 {