eustags.c
Go to the documentation of this file.
1 /* Tags file maker to go with GNUmacs
2  Copyright (C) 1984, 1987, 1988 Free Software Foundation, Inc. and Ken Arnold
3 
4  NO WARRANTY
5 
6  BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
7 NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
8 WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
9 RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
10 WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
11 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
12 FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
13 AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
14 DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
15 CORRECTION.
16 
17  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
18 STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
19 WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
20 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
21 OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
22 USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
23 DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
24 A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
25 PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
27 
28  GENERAL PUBLIC LICENSE TO COPY
29 
30  1. You may copy and distribute verbatim copies of this source file
31 as you receive it, in any medium, provided that you conspicuously
32 and appropriately publish on each copy a valid copyright notice
33 "Copyright (C) 1986 Free Software Foundation"; and include
34 following the copyright notice a verbatim copy of the above disclaimer
35 of warranty and of this License.
36 
37  2. You may modify your copy or copies of this source file or
38 any portion of it, and copy and distribute such modifications under
39 the terms of Paragraph 1 above, provided that you also do the following:
40 
41  a) cause the modified files to carry prominent notices stating
42  that you changed the files and the date of any change; and
43 
44  b) cause the whole of any work that you distribute or publish,
45  that in whole or in part contains or is a derivative of this
46  program or any part thereof, to be licensed at no charge to all
47  third parties on terms identical to those contained in this
48  License Agreement (except that you may choose to grant more extensive
49  warranty protection to some or all third parties, at your option).
50 
51  c) You may charge a distribution fee for the physical act of
52  transferring a copy, and you may at your option offer warranty
53  protection in exchange for a fee.
54 
55 Mere aggregation of another unrelated program with this program (or its
56 derivative) on a volume of a storage or distribution medium does not bring
57 the other program under the scope of these terms.
58 
59  3. You may copy and distribute this program (or a portion or derivative
60 of it, under Paragraph 2) in object code or executable form under the terms
61 of Paragraphs 1 and 2 above provided that you also do one of the following:
62 
63  a) accompany it with the complete corresponding machine-readable
64  source code, which must be distributed under the terms of
65  Paragraphs 1 and 2 above; or,
66 
67  b) accompany it with a written offer, valid for at least three
68  years, to give any third party free (except for a nominal
69  shipping charge) a complete machine-readable copy of the
70  corresponding source code, to be distributed under the terms of
71  Paragraphs 1 and 2 above; or,
72 
73  c) accompany it with the information you received as to where the
74  corresponding source code may be obtained. (This alternative is
75  allowed only for noncommercial distribution and only if you
76  received the program in object code or executable form alone.)
77 
78 For an executable file, complete source code means all the source code for
79 all modules it contains; but, as a special exception, it need not include
80 source code for modules which are standard libraries that accompany the
81 operating system on which the executable file runs.
82 
83  4. You may not copy, sublicense, distribute or transfer this program
84 except as expressly provided under this License Agreement. Any attempt
85 otherwise to copy, sublicense, distribute or transfer this program is void and
86 your rights to use the program under this License agreement shall be
87 automatically terminated. However, parties who have received computer
88 software programs from you with this License Agreement will not have
89 their licenses terminated so long as such parties remain in full compliance.
90 
91 In other words, you are welcome to use, share and improve this program.
92 You are forbidden to forbid anyone else to use, share and improve
93 what you give them. Help stamp out software-hoarding! */
94 
95 #include <stdio.h>
96 #include <ctype.h>
97 
98 /* Define the symbol ETAGS to make the program "etags",
99  which makes emacs-style tag tables by default.
100  Define CTAGS to make the program "ctags" compatible with the usual one.
101  Define neither one to get behavior that depends
102  on the name with which the program is invoked
103  (but we don't normally compile it that way). */
104 
105 /* On VMS, CTAGS is not useful, so always do ETAGS. */
106 #ifdef VMS
107 #ifndef ETAGS
108 #define ETAGS
109 #endif
110 #endif
111 
112 /* Exit codes for success and failure. */
113 
114 #ifdef VMS
115 #define GOOD (1)
116 #define BAD (0)
117 #else
118 #define GOOD (0)
119 #define BAD (1)
120 #endif
121 
122 #define reg register
123 #define logical char
124 
125 #define TRUE (1)
126 #define FALSE (0)
127 
128 #define iswhite(arg) (_wht[arg]) /* T if char is white */
129 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
130 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
131 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
132 #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
133 
134 #define max(I1,I2) (I1 > I2 ? I1 : I2)
135 
136 /* cause token checking for typedef, struct, union, enum to distinguish
137  keywords from identifier-prefixes (e.g. struct vs struct_tag). */
138 #define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
139 
140 struct nd_st { /* sorting structure */
141  char *name; /* function or type name */
142  char *file; /* file name */
143  logical f; /* use pattern or line no */
144  int lno; /* line number tag is on */
145  long cno; /* character number line starts on */
146  char *pat; /* search pattern */
147  logical been_warned; /* set if noticed dup */
148  struct nd_st *left,*right; /* left and right sons */
149 };
150 
151 long ftell();
152 typedef struct nd_st NODE;
153 
154 int number; /* tokens found so far on line starting with # (including #) */
155 logical gotone, /* found a func already on line */
156  /* boolean "func" (see init) */
157  _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
158 
159  /* typedefs are recognized using a simple finite automata,
160  * tydef is its state variable.
161  */
162 typedef enum {none, begin, tag_ok, middle, end } TYST;
163 
165 
166 char searchar = '/'; /* use /.../ searches */
167 
168 int lineno; /* line number of current line */
169 long charno; /* current character number */
170 long linecharno; /* character number of start of line */
171 
172 char *curfile, /* current input file name */
173  *outfile= 0, /* output file */
174  *white = " \f\t\n", /* white chars */
175  *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?",
176  /* token ending chars */
177  *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
178  /* token starting chars */
179  *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789",
180  /* valid in-token chars */
181  *notgd = ",;"; /* non-valid after-function chars */
182 
183 int file_num = 0; /* current file number */
184 int aflag = 0; /* -a: append to tags */
185 int tflag = 0; /* -t: create tags for typedefs */
186 int uflag = 0; /* -u: update tags */
187 int wflag = 0; /* -w: suppress warnings */
188 int vflag = 0; /* -v: create vgrind style index output */
189 int xflag = 0; /* -x: create cxref style output */
190 int eflag = 0; /* -e: emacs style output */
191 
192 /* Name this program was invoked with. */
193 char *progname;
194 
195 FILE *inf, /* ioptr for current input file */
196  *outf; /* ioptr for tags file */
197 
198 NODE *head; /* the head of the sorted binary tree */
199 
200 void init ();
201 void find_entries (char *file);
202 void free_tree (NODE *node);
203 void put_entries (NODE *node);
204 
205 char *savestr();
206 char *savenstr ();
207 // char *rindex();
208 //char *index();
209 char *concat ();
210 void initbuffer ();
211 long readline ();
212 
213 /* A `struct linebuffer' is a structure which holds a line of text.
214  `readline' reads a line from a stream into a linebuffer
215  and works regardless of the length of the line. */
216 
218  {
219  long size;
220  char *buffer;
221  };
222 
223 struct linebuffer lb, lb1;
224 
225 #if 0 /* VMS now provides the `system' function. */
226 #ifdef VMS
227 
228 #include <descrip.h>
229 
230 void
231 system (buf)
232  char *buf;
233 {
234  struct dsc$descriptor_s command =
235  {
236  strlen(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf
237  };
238 
239  LIB$SPAWN(&command);
240 }
241 #endif /* VMS */
242 #endif /* 0 */
243 
244 main(ac,av)
245  int ac;
246  char *av[];
247 {
248  char cmd[100];
249  int i;
250  int fflag = 0;
251  char *this_file;
252 #ifdef VMS
253  char got_err;
254 
255  extern char *gfnames();
256  extern char *massage_name();
257 #endif
258 
259  progname = av[0];
260 
261 #ifdef ETAGS
262  eflag = 1;
263 #else
264 #ifdef CTAGS
265  eflag = 0;
266 #else
267  {
268  char *subname = rindex (progname, '/');
269  if (subname++ == NULL)
270  subname = progname;
271  eflag = ! strcmp(subname, "ctags");
272  }
273 #endif
274 #endif
275 
276  while (ac > 1 && av[1][0] == '-')
277  {
278  for (i=1; av[1][i]; i++)
279  {
280  switch(av[1][i])
281  {
282 #ifndef VMS /* These options are useful only with ctags,
283  and VMS can't input them, so just omit them. */
284  case 'B':
285  searchar='?';
286  eflag = 0;
287  break;
288  case 'F':
289  searchar='/';
290  eflag = 0;
291  break;
292 #endif
293  case 'a':
294  aflag++;
295  break;
296  case 'e':
297  eflag++;
298  break;
299  case 'f':
300  if (fflag > 0)
301  {
302  fprintf(stderr,
303  "%s: -f flag may only be given once\n", progname);
304  goto usage;
305  }
306  fflag++, ac--; av++;
307  if (ac <= 1 || av[1][0] == '\0')
308  {
309  fprintf(stderr,
310  "%s: -f flag must be followed by a filename\n",
311  progname);
312  goto usage;
313  }
314  outfile = av[1];
315  goto end_loop;
316  case 't':
317  tflag++;
318  break;
319 #ifndef VMS
320  case 'u':
321  uflag++;
322  eflag = 0;
323  break;
324 #endif
325  case 'w':
326  wflag++;
327  break;
328  case 'v':
329  vflag++;
330  xflag++;
331  eflag = 0;
332  break;
333  case 'x':
334  xflag++;
335  eflag = 0;
336  break;
337  default:
338  goto usage;
339  }
340  }
341  end_loop: ;
342  ac--; av++;
343  }
344 
345  if (ac <= 1)
346  {
347  usage:
348 #ifdef VMS
349  fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
350 #else
351  fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname);
352 #endif
353  exit(BAD);
354  }
355 
356  if (outfile == 0)
357  {
358  outfile = eflag ? "TAGS" : "tags";
359  }
360 
361  init(); /* set up boolean "functions" */
362 
363  initbuffer (&lb);
364  initbuffer (&lb1);
365  /*
366  * loop through files finding functions
367  */
368  if (eflag)
369  {
370  outf = fopen (outfile, aflag ? "a" : "w");
371  if (!outf)
372  {
373  fprintf (stderr, "%s: ", progname);
374  perror (outfile);
375  exit (BAD);
376  }
377  }
378 
379  file_num = 1;
380 #ifdef VMS
381  for (ac--, av++;
382  (this_file = gfnames (&ac, &av, &got_err)) != NULL; file_num++)
383  {
384  if (got_err)
385  {
386  error("Can't find file %s\n", this_file);
387  ac--, av++;
388  }
389  else
390  {
391  this_file = massage_name (this_file);
392 #else
393  for (; file_num < ac; file_num++)
394  {
395  this_file = av[file_num];
396  if (1)
397  {
398 #endif
399  find_entries (this_file);
400  if (eflag)
401  {
402  fprintf (outf, "\f\n%s,%d\n",
403  this_file, total_size_of_entries (head));
404  put_entries (head);
405  free_tree (head);
406  head = NULL;
407  }
408  }
409  }
410 
411  if (eflag)
412  {
413  fclose (outf);
414  exit (GOOD);
415  }
416 
417  if (xflag)
418  {
419  put_entries(head);
420  exit(GOOD);
421  }
422  if (uflag)
423  {
424  for (i=1; i<ac; i++)
425  {
426  sprintf(cmd,
427  "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
428  outfile, av[i], outfile);
429  system(cmd);
430  }
431  aflag++;
432  }
433  outf = fopen(outfile, aflag ? "a" : "w");
434  if (outf == NULL)
435  {
436  fprintf (stderr, "%s: ", outfile);
437  perror(outfile);
438  exit(BAD);
439  }
440  put_entries(head);
441  fclose(outf);
442 #ifndef VMS
443  if (uflag)
444  {
445  sprintf(cmd, "sort %s -o %s", outfile, outfile);
446  system(cmd);
447  }
448 #endif
449  exit(GOOD);
450 }
451 
452 /*
453  * This routine sets up the boolean psuedo-functions which work
454  * by seting boolean flags dependent upon the corresponding character
455  * Every char which is NOT in that string is not a white char. Therefore,
456  * all of the array "_wht" is set to FALSE, and then the elements
457  * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
458  * of a char is TRUE if it is the string "white", else FALSE.
459  */
460 void
462 {
463 
464  reg char *sp;
465  reg int i;
466 
467  for (i = 0; i < 0177; i++)
468  {
469  _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
470  _gd[i] = TRUE;
471  }
472  for (sp = white; *sp; sp++)
473  _wht[*sp] = TRUE;
474  for (sp = endtk; *sp; sp++)
475  _etk[*sp] = TRUE;
476  for (sp = intk; *sp; sp++)
477  _itk[*sp] = TRUE;
478  for (sp = begtk; *sp; sp++)
479  _btk[*sp] = TRUE;
480  for (sp = notgd; *sp; sp++)
481  _gd[*sp] = FALSE;
482  _wht[0] = _wht['\n'];
483  _etk[0] = _etk['\n'];
484  _btk[0] = _btk['\n'];
485  _itk[0] = _itk['\n'];
486  _gd[0] = _gd['\n'];
487 }
488 
489 /*
490  * This routine opens the specified file and calls the function
491  * which finds the function and type definitions.
492  */
493 void TEX_funcs (FILE *fi);
494 void Scheme_funcs (FILE *fi);
495 void L_funcs (FILE *fi);
496 void C_entries ();
497 void
499  char *file;
500 {
501  char *cp;
502 
503  if ((inf=fopen(file,"r")) == NULL)
504  {
505  fprintf (stderr, "%s: ", progname);
506  perror(file);
507  return;
508  }
509  curfile = savestr(file);
510  cp = rindex(file, '.');
511  /* .tex, .aux or .bbl implies LaTeX source code */
512  if (cp && (!strcmp (cp + 1, "tex") || !strcmp (cp + 1, "aux")
513  || !strcmp (cp + 1, "bbl")))
514  {
515  TEX_funcs(inf);
516  fclose(inf);
517  return;
518  }
519  /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
520  if (cp && (!strcmp (cp + 1, "l") ||
521  !strcmp (cp + 1, "el") ||
522  !strcmp (cp + 1, "lsp") ||
523  !strcmp (cp + 1, "lisp") ||
524  !strcmp (cp + 1, "cl") ||
525  !strcmp (cp + 1, "clisp")))
526  {
527  L_funcs(inf);
528  fclose(inf);
529  return;
530  }
531  /* .scm or .sm or .scheme implies scheme source code */
532  if (cp && (!strcmp (cp + 1, "sm")
533  || !strcmp (cp + 1, "scm")
534  || !strcmp (cp + 1, "scheme")
535  || !strcmp (cp + 1, "t")
536  || !strcmp (cp + 1, "sch")
537  || !strcmp (cp + 1, "SM")
538  || !strcmp (cp + 1, "SCM")
539  /* The `SCM' or `scm' prefix with a version number */
540  || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's')
541  || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S')))
542  {
543  Scheme_funcs(inf);
544  fclose(inf);
545  return;
546  }
547  /* if not a .c or .h or .y file, try fortran */
548  if (cp && (cp[1] != 'c' && cp[1] != 'h' && cp[1] != 'y')
549  && cp[2] == '\0')
550  {
551  if (PF_funcs(inf) != 0)
552  {
553  fclose(inf);
554  return;
555  }
556  rewind(inf); /* no fortran tags found, try C */
557  }
558  C_entries();
559  fclose(inf);
560 }
561 
562 /* Record a tag on the current line.
563  name is the tag name,
564  f is nonzero to use a pattern, zero to use line number instead. */
565 
566 void put_entries (NODE *node);
567 void add_node (NODE *node, NODE *cur_node);
568 void
569 pfnote (name, f, linestart, linelen, lno, cno)
570  char *name;
571  logical f; /* f == TRUE when function */
572  char *linestart;
573  int linelen;
574  int lno;
575  long cno;
576 {
577  register char *fp;
578  register NODE *np;
579  char *altname;
580  char tem[51];
581 
582  if ((np = (NODE *) malloc (sizeof (NODE))) == NULL)
583  {
584  fprintf(stderr, "%s: too many entries to sort\n", progname);
585  put_entries(head);
586  free_tree(head);
587  head = NULL;
588  np = (NODE *) xmalloc(sizeof (NODE));
589  }
590  /* Change name "main" to M<thisfilename>. */
591  if (!eflag && !xflag && !strcmp(name, "main"))
592  {
593  fp = rindex(curfile, '/');
594  if (fp == 0)
595  fp = curfile;
596  else
597  fp++;
598  altname = concat ("M", fp, "");
599  fp = rindex(altname, '.');
600  if (fp && fp[2] == 0)
601  *fp = 0;
602  name = altname;
603  }
604  np->name = savestr(name);
605  np->file = curfile;
606  np->f = f;
607  np->lno = lno;
608  np->cno = cno;
609  np->left = np->right = 0;
610  if (eflag)
611  {
612  linestart[linelen] = 0;
613  }
614  else if (xflag == 0)
615  {
616  sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
617  linestart = tem;
618  }
619  np->pat = savestr (linestart);
620  if (head == NULL)
621  head = np;
622  else
623  add_node(np, head);
624 }
625 
626 void
628  NODE *node;
629 {
630  while (node)
631  {
632  free_tree(node->right);
633  free(node);
634  node = node->left;
635  }
636 }
637 
638 void
639 add_node(node, cur_node)
640  NODE *node,*cur_node;
641 {
642  register int dif;
643 
644  dif = strcmp(node->name, cur_node->name);
645 
646  /* If this tag name matches an existing one, then
647  unless -e was given, do not add the node, but maybe print a warning */
648  if (!eflag && !dif)
649  {
650  if (node->file == cur_node->file)
651  {
652  if (!wflag)
653  {
654  fprintf(stderr,"%s: Duplicate entry in file %s, line %d: %s\n",
655  progname, node->file,lineno,node->name);
656  fprintf(stderr,"Second entry ignored\n");
657  }
658  return;
659  }
660  if (!cur_node->been_warned)
661  if (!wflag)
662  fprintf(stderr,"%s: Duplicate entry in files %s and %s: %s (Warning only)\n",
663  progname, node->file, cur_node->file, node->name);
664  cur_node->been_warned = TRUE;
665  return;
666  }
667 
668  /* Actually add the node */
669  if (dif < 0)
670  {
671  if (cur_node->left != NULL)
672  add_node(node,cur_node->left);
673  else
674  cur_node->left = node;
675  return;
676  }
677  if (cur_node->right != NULL)
678  add_node(node,cur_node->right);
679  else
680  cur_node->right = node;
681 }
682 
683 void
685  reg NODE *node;
686 {
687  reg char *sp;
688 
689  if (node == NULL)
690  return;
691 
692  /* Output subentries that precede this one */
693  put_entries (node->left);
694 
695  /* Output this entry */
696 
697  if (eflag)
698  {
699  fprintf (outf, "%s%c%d,%d\n",
700  node->pat, 0177, node->lno, node->cno);
701  }
702  else if (!xflag)
703  {
704  fprintf (outf, "%s\t%s\t",
705  node->name, node->file);
706 
707  if (node->f)
708  { /* a function */
709  putc (searchar, outf);
710  putc ('^', outf);
711 
712  for (sp = node->pat; *sp; sp++)
713  {
714  if (*sp == '\\' || *sp == searchar)
715  putc ('\\', outf);
716  putc (*sp, outf);
717  }
718  putc (searchar, outf);
719  }
720  else
721  { /* a typedef; text pattern inadequate */
722  fprintf (outf, "%d", node->lno);
723  }
724  putc ('\n', outf);
725  }
726  else if (vflag)
727  fprintf (stdout, "%s %s %d\n",
728  node->name, node->file, (node->lno+63)/64);
729  else
730  fprintf (stdout, "%-16s%4d %-16s %s\n",
731  node->name, node->lno, node->file, node->pat);
732 
733  /* Output subentries that follow this one */
734  put_entries (node->right);
735 }
736 
737 /* Return total number of characters that put_entries will output for
738  the nodes in the subtree of the specified node.
739  Works only if eflag is set, but called only in that case. */
740 
741 int
743  reg NODE *node;
744 {
745  reg int total = 0;
746  reg long num;
747 
748  if (node == NULL)
749  return 0;
750 
751  /* Count subentries that precede this one */
752  total = total_size_of_entries (node->left);
753 
754  /* Count subentries that follow this one */
755  total += total_size_of_entries (node->right);
756 
757  /* Count this entry */
758 
759  total += strlen (node->pat) + 3;
760 
761  num = node->lno;
762  while (num)
763  {
764  total++;
765  num /= 10;
766  }
767 
768  num = node->cno;
769  if (!num) total++;
770  while (num)
771  {
772  total++;
773  num /= 10;
774  }
775  return total;
776 }
777 
778 /*
779  * This routine finds functions and typedefs in C syntax and adds them
780  * to the list.
781  */
782 #ifdef VMS
783 long vmslinecharno;
784 #define VMS_SET_LINECHARNO (vmslinecharno = ftell(inf))
785 #else
786 #define VMS_SET_LINECHARNO
787 #endif
788 
789 #define CNL_SAVE_NUMBER \
790 { \
791  VMS_SET_LINECHARNO; \
792  linecharno = charno; lineno++; \
793  charno += 1 + readline (&lb, inf); \
794  lp = lb.buffer; \
795 }
796 
797 #define CNL \
798 { \
799  CNL_SAVE_NUMBER; \
800  number = 0; \
801 }
802 
803 void e_getline (long atchar);
804 void
806 {
807  register int c;
808  register char *token, *tp, *lp;
809  logical incomm, inquote, inchar, midtoken;
810  int level;
811  char tok[BUFSIZ];
812 
813  lineno = 0;
814  charno = 0;
815  lp = lb.buffer;
816  *lp = 0;
817 
818  number = 0;
819  gotone = midtoken = inquote = inchar = incomm = FALSE;
820  level = 0;
821 
822  while (!feof (inf))
823  {
824  c = *lp++;
825  if (c == 0)
826  {
827  CNL;
828  gotone = FALSE;
829  }
830  if (c == '\\')
831  {
832  c = *lp++;
833  if (c == 0)
835  c = ' ';
836  }
837  else if (incomm)
838  {
839  if (c == '*')
840  {
841  while ((c = *lp++) == '*')
842  continue;
843  if (c == 0)
844  CNL;
845  if (c == '/')
846  incomm = FALSE;
847  }
848  }
849  else if (inquote)
850  {
851  /*
852  * Too dumb to know about \" not being magic, but
853  * they usually occur in pairs anyway.
854  */
855  if (c == '"')
856  inquote = FALSE;
857  continue;
858  }
859  else if (inchar)
860  {
861  if (c == '\'')
862  inchar = FALSE;
863  continue;
864  }
865  else switch (c)
866  {
867  case '"':
868  inquote = TRUE;
869  continue;
870  case '\'':
871  inchar = TRUE;
872  continue;
873  case '/':
874  if (*lp == '*')
875  {
876  lp++;
877  incomm = TRUE;
878  }
879  continue;
880  case '#':
881  if (lp == lb.buffer + 1)
882  number = 1;
883  continue;
884  case '{':
885  if (tydef == tag_ok)
886  {
887  tydef=middle;
888  }
889  level++;
890  continue;
891  case '}':
892  if (lp == lb.buffer + 1)
893  level = 0; /* reset */
894  else
895  level--;
896  if (!level && tydef==middle)
897  {
898  tydef=end;
899  }
900  continue;
901  }
902  if (!level && !inquote && !incomm && gotone == FALSE)
903  {
904  if (midtoken)
905  {
906  if (endtoken(c))
907  {
908  int f;
909  char *buf = lb.buffer;
910  int endpos = lp - lb.buffer;
911  char *lp1 = lp;
912  int line = lineno;
913  long linestart = linecharno;
914 #ifdef VMS
915  long vmslinestart = vmslinecharno;
916 #endif
917  int tem = consider_token (&lp1, token, &f, level);
918  lp = lp1;
919  if (tem)
920  {
921  if (linestart != linecharno)
922  {
923 #ifdef VMS
924  e_getline (vmslinestart);
925 #else
926  e_getline (linestart);
927 #endif
928  strncpy (tok, token + (lb1.buffer - buf),
929  tp-token+1);
930  tok[tp-token+1] = 0;
931  pfnote(tok, f, lb1.buffer, endpos, line, linestart);
932  }
933  else
934  {
935  strncpy (tok, token, tp-token+1);
936  tok[tp-token+1] = 0;
937  pfnote(tok, f, lb.buffer, endpos, line, linestart);
938  }
939  gotone = f; /* function */
940  }
941  midtoken = FALSE;
942  token = lp - 1;
943  }
944  else if (intoken(c))
945  tp++;
946  }
947  else if (begtoken(c))
948  {
949  token = tp = lp - 1;
950  midtoken = TRUE;
951  }
952  }
953  if (c == ';' && tydef==end) /* clean with typedefs */
954  tydef=none;
955  }
956 }
957 
958 /*
959  * This routine checks to see if the current token is
960  * at the start of a function, or corresponds to a typedef
961  * It updates the input line * so that the '(' will be
962  * in it when it returns.
963  */
964 int
965 consider_token (lpp, token, f, level)
966  char **lpp, *token;
967  int *f, level;
968 {
969  reg char *lp = *lpp;
970  reg char c;
971  static logical next_token_is_func;
972  logical firsttok; /* T if have seen first token in ()'s */
973  int bad, win;
974 
975  *f = 1; /* a function */
976  c = lp[-1];
977  bad = FALSE;
978  if (!number)
979  { /* space is not allowed in macro defs */
980  while (iswhite(c))
981  {
982  c = *lp++;
983  if (c == 0)
984  {
985  if (feof (inf))
986  break;
987  CNL;
988  }
989  }
990  /* the following tries to make it so that a #define a b(c) */
991  /* doesn't count as a define of b. */
992  }
993  else
994  {
995  number++;
996  if (number >= 4 || (number==2 && strncmp (token, "define", 6)))
997  {
998  gotone = TRUE;
999  badone:
1000  bad = TRUE;
1001  goto ret;
1002  }
1003  }
1004  /* check for the typedef cases */
1005  if (tflag && istoken(token, "typedef", 7))
1006  {
1007  tydef=begin;
1008  goto badone;
1009  }
1010  if (tydef==begin && (istoken(token, "struct", 6) ||
1011  istoken(token, "union", 5) || istoken(token, "enum", 4)))
1012  {
1013  tydef=tag_ok;
1014  goto badone;
1015  }
1016  if (tydef==tag_ok)
1017  {
1018  tydef=middle;
1019  goto badone;
1020  }
1021  if (tydef==begin) /* e.g. typedef ->int<- */
1022  {
1023  tydef=end;
1024  goto badone;
1025  }
1026  if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
1027  {
1028  tydef=end;
1029  }
1030  if (tydef==end)
1031  {
1032  *f = 0;
1033  win = 1;
1034  goto ret;
1035  }
1036  /* Detect GNUmacs's function-defining macros. */
1037  if (!number && !strncmp (token, "DEF", 3))
1038 
1039  {
1040  next_token_is_func = 1;
1041  goto badone;
1042  }
1043  if (next_token_is_func)
1044  {
1045  next_token_is_func = 0;
1046  win = 1;
1047  goto ret;
1048  }
1049  if (c != '(')
1050  goto badone;
1051  firsttok = FALSE;
1052  while ((c = *lp++) != ')')
1053  {
1054  if (c == 0)
1055  {
1056  if (feof (inf))
1057  break;
1058  CNL;
1059  }
1060  /*
1061  * This line used to confuse ctags:
1062  * int (*oldhup)();
1063  * This fixes it. A nonwhite char before the first
1064  * token, other than a / (in case of a comment in there)
1065  * makes this not a declaration.
1066  */
1067  if (begtoken(c) || c=='/') firsttok++;
1068  else if (!iswhite(c) && !firsttok) goto badone;
1069  }
1070  while (iswhite (c = *lp++))
1071  {
1072  if (c == 0)
1073  {
1074  if (feof (inf))
1075  break;
1076  CNL;
1077  }
1078  }
1079  win = isgood (c);
1080 ret:
1081  *lpp = lp - 1;
1082  return !bad && win;
1083 }
1084 
1085 void
1086 e_getline (atchar)
1087  long atchar;
1088 {
1089  long saveftell = ftell (inf);
1090 
1091  fseek (inf, atchar, 0);
1092  readline (&lb1, inf);
1093  fseek (inf, saveftell, 0);
1094 }
1095 
1096 /* Fortran parsing */
1097 
1098 char *dbp;
1099 int pfcnt;
1100 void getit ();
1101 void takeprec ();
1102 
1103 int
1105  FILE *fi;
1106 {
1107  lineno = 0;
1108  charno = 0;
1109  pfcnt = 0;
1110 
1111  while (!feof (fi))
1112  {
1113  lineno++;
1114  linecharno = charno;
1115  charno += readline (&lb, fi) + 1;
1116  dbp = lb.buffer;
1117  if (*dbp == '%') dbp++ ; /* Ratfor escape to fortran */
1118  while (isspace(*dbp))
1119  dbp++;
1120  if (*dbp == 0)
1121  continue;
1122  switch (*dbp |' ')
1123  {
1124  case 'i':
1125  if (tail("integer"))
1126  takeprec();
1127  break;
1128  case 'r':
1129  if (tail("real"))
1130  takeprec();
1131  break;
1132  case 'l':
1133  if (tail("logical"))
1134  takeprec();
1135  break;
1136  case 'c':
1137  if (tail("complex") || tail("character"))
1138  takeprec();
1139  break;
1140  case 'd':
1141  if (tail("double"))
1142  {
1143  while (isspace(*dbp))
1144  dbp++;
1145  if (*dbp == 0)
1146  continue;
1147  if (tail("precision"))
1148  break;
1149  continue;
1150  }
1151  break;
1152  }
1153  while (isspace(*dbp))
1154  dbp++;
1155  if (*dbp == 0)
1156  continue;
1157  switch (*dbp|' ')
1158  {
1159  case 'f':
1160  if (tail("function"))
1161  getit();
1162  continue;
1163  case 's':
1164  if (tail("subroutine"))
1165  getit();
1166  continue;
1167  case 'p':
1168  if (tail("program"))
1169  {
1170  getit();
1171  continue;
1172  }
1173  if (tail("procedure"))
1174  getit();
1175  continue;
1176  }
1177  }
1178  return (pfcnt);
1179 }
1180 
1181 tail(cp)
1182  char *cp;
1183 {
1184  register int len = 0;
1185 
1186  while (*cp && (*cp&~' ') == ((*(dbp+len))&~' '))
1187  cp++, len++;
1188  if (*cp == 0)
1189  {
1190  dbp += len;
1191  return (1);
1192  }
1193  return (0);
1194 }
1195 
1196 void
1198 {
1199  while (isspace(*dbp))
1200  dbp++;
1201  if (*dbp != '*')
1202  return;
1203  dbp++;
1204  while (isspace(*dbp))
1205  dbp++;
1206  if (!isdigit(*dbp))
1207  {
1208  --dbp; /* force failure */
1209  return;
1210  }
1211  do
1212  dbp++;
1213  while (isdigit(*dbp));
1214 }
1215 
1216 void
1218 {
1219  register char *cp;
1220  char c;
1221  char nambuf[BUFSIZ];
1222 
1223  while (isspace(*dbp))
1224  dbp++;
1225  if (*dbp == 0 || !isalpha(*dbp))
1226  return;
1227  for (cp = dbp+1; *cp && (isalpha(*cp) || isdigit(*cp)); cp++)
1228  continue;
1229  c = cp[0];
1230  cp[0] = 0;
1231  strcpy(nambuf, dbp);
1232  cp[0] = c;
1233  pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
1234  pfcnt++;
1235 }
1236 
1237 /*
1238  * lisp tag functions
1239  * just look for (def or (DEF
1240  */
1241 
1242 void L_getit ();
1243 void
1245  FILE *fi;
1246 {
1247  lineno = 0;
1248  charno = 0;
1249  pfcnt = 0;
1250 
1251  while (!feof (fi))
1252  {
1253  lineno++;
1254  linecharno = charno;
1255  charno += readline (&lb, fi) + 1;
1256  dbp = lb.buffer;
1257  while (isspace(*dbp)) dbp++;
1258  if (dbp[0] == '(' &&
1259  (dbp[1] == 'D' || dbp[1] == 'd') &&
1260  (dbp[2] == 'E' || dbp[2] == 'e') &&
1261  (dbp[3] == 'F' || dbp[3] == 'f'))
1262  {
1263  while (!isspace(*dbp)) dbp++;
1264  while (isspace(*dbp)) dbp++;
1265  L_getit();
1266  }
1267  if (dbp[0] == '(' &&
1268  (dbp[1] == ':'))
1269  {
1270  while (!isspace(*dbp)) dbp++;
1271  while (isspace(*dbp)) dbp++;
1272  L_getit();
1273  }
1274 
1275  }
1276 }
1277 
1278 void
1280 {
1281  register char *cp;
1282  char c;
1283  char nambuf[BUFSIZ];
1284 
1285  if (*dbp == 0) return;
1286  for (cp = dbp+1; *cp && *cp != '(' && *cp != ' '; cp++)
1287  continue;
1288  c = cp[0];
1289  cp[0] = 0;
1290  strcpy(nambuf, dbp);
1291  cp[0] = c;
1292  pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
1293  pfcnt++;
1294 }
1295 
1296 /*
1297  * Scheme tag functions
1298  * look for (def... xyzzy
1299  * look for (def... (xyzzy
1300  * look for (def ... ((...(xyzzy ....
1301  * look for (set! xyzzy
1302  */
1303 
1304 void static get_scheme ();
1305 void
1307  FILE *fi;
1308 {
1309  lineno = 0;
1310  charno = 0;
1311  pfcnt = 0;
1312 
1313  while (!feof (fi))
1314  {
1315  lineno++;
1316  linecharno = charno;
1317  charno += readline (&lb, fi) + 1;
1318  dbp = lb.buffer;
1319  if (dbp[0] == '(' &&
1320  (dbp[1] == 'D' || dbp[1] == 'd') &&
1321  (dbp[2] == 'E' || dbp[2] == 'e') &&
1322  (dbp[3] == 'F' || dbp[3] == 'f'))
1323  {
1324  while (!isspace(*dbp)) dbp++;
1325  /* Skip over open parens and white space */
1326  while (*dbp && (isspace(*dbp) || *dbp == '(')) dbp++;
1327  get_scheme ();
1328  }
1329  if (dbp[0] == '(' &&
1330  (dbp[1] == 'S' || dbp[1] == 's') &&
1331  (dbp[2] == 'E' || dbp[2] == 'e') &&
1332  (dbp[3] == 'T' || dbp[3] == 't') &&
1333  (dbp[4] == '!' || dbp[4] == '!') &&
1334  (isspace(dbp[5])))
1335  {
1336  while (!isspace(*dbp)) dbp++;
1337  /* Skip over white space */
1338  while (isspace(*dbp)) dbp++;
1339  get_scheme ();
1340  }
1341  }
1342 }
1343 
1344 void
1345 static
1347 {
1348  register char *cp;
1349  char c;
1350  char nambuf[BUFSIZ];
1351 
1352  if (*dbp == 0) return;
1353  /* Go till you get to white space or a syntactic break */
1354  for (cp = dbp+1; *cp && *cp != '(' && *cp != ')' && !isspace(*cp); cp++)
1355  continue;
1356  /* Null terminate the string there. */
1357  c = cp[0];
1358  cp[0] = 0;
1359  /* Copy the string */
1360  strcpy(nambuf, dbp);
1361  /* Unterminate the string */
1362  cp[0] = c;
1363  /* Announce the change */
1364  pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
1365  pfcnt++;
1366 }
1367 
1368 /* Find tags in TeX and LaTeX input files. */
1369 
1370 /* TEX_toktab is a table of TeX control sequences that define tags.
1371  Each TEX_tabent records one such control sequence. */
1372 
1374 {
1375  char *name;
1376  int len;
1377 };
1378 
1379 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
1380 
1381 /* Default set of control sequences to put into TEX_toktab.
1382  The value of environment var TEXTAGS is prepended to this. */
1383 
1384 static char *TEX_defenv =
1385  ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
1386 
1387 struct TEX_tabent *TEX_decode_env ();
1388 
1389 static char TEX_esc = '\\';
1390 static char TEX_opgrp = '{';
1391 static char TEX_clgrp = '}';
1392 
1393 /*
1394  * TeX/LaTeX scanning loop.
1395  */
1396 
1397 void TEX_mode (FILE *f);
1398 void TEX_getit (char *name, int len);
1399 void
1401  FILE *fi;
1402 {
1403  char *lasthit;
1404 
1405  lineno = 0;
1406  charno = 0;
1407  pfcnt = 0;
1408 
1409  /* Select either \ or ! as escape character. */
1410  TEX_mode (fi);
1411 
1412  /* Initialize token table once from environment. */
1413  if (!TEX_toktab)
1414  TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
1415 
1416  while (!feof (fi))
1417  {
1418  lineno++;
1419  linecharno = charno;
1420  charno += readline (&lb, fi) + 1;
1421  dbp = lb.buffer;
1422  lasthit = dbp;
1423 
1424  while (!feof (fi))
1425  { /* Scan each line in file */
1426  lineno++;
1427  linecharno = charno;
1428  charno += readline (&lb, fi) + 1;
1429  dbp = lb.buffer;
1430  lasthit = dbp;
1431  while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */
1432  {
1433  register int i;
1434 
1435  if (! *(++dbp))
1436  break;
1437  linecharno += dbp - lasthit;
1438  lasthit = dbp;
1439  i = TEX_Token (lasthit);
1440  if (0 <= i)
1441  {
1442  TEX_getit (lasthit, TEX_toktab[i].len);
1443  break; /* We only save a line once */
1444  }
1445  }
1446  }
1447  }
1448 }
1449 
1450 #define TEX_LESC '\\'
1451 #define TEX_SESC '!'
1452 
1453 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
1454 /* chars accordingly. */
1455 
1456 void
1458  FILE *f;
1459 {
1460  int c;
1461 
1462  while ((c = getc (f)) != EOF)
1463  if (c == TEX_LESC || c == TEX_SESC)
1464  break;
1465 
1466  if (c == TEX_LESC)
1467  {
1468  TEX_esc = TEX_LESC;
1469  TEX_opgrp = '{';
1470  TEX_clgrp = '}';
1471  }
1472  else
1473  {
1474  TEX_esc = TEX_SESC;
1475  TEX_opgrp = '<';
1476  TEX_clgrp = '>';
1477  }
1478  rewind (f);
1479 }
1480 
1481 /* Read environment and prepend it to the default string. */
1482 /* Build token table. */
1483 
1484 struct TEX_tabent *
1485 TEX_decode_env (evarname, defenv)
1486  char *evarname;
1487  char *defenv;
1488 {
1489  register char *env, *p;
1490  extern char *savenstr (), *index ();
1491 
1492  struct TEX_tabent *tab;
1493  int size, i;
1494 
1495  /* Append deafult string to environment. */
1496  env = (char *) getenv (evarname);
1497  if (!env)
1498  env = defenv;
1499  else
1500  env = concat (env, defenv, "");
1501 
1502  /* Allocate a token table */
1503  for (size = 1, p=env; p;)
1504  if ((p = index (p, ':')) && *(++p))
1505  size++;
1506  tab = (struct TEX_tabent *) xmalloc (size * sizeof (struct TEX_tabent));
1507 
1508  /* Unpack environment string into token table. Be careful about */
1509  /* zero-length strings (leading ':', "::" and trailing ':') */
1510  for (i = 0; *env;)
1511  {
1512  p = index (env, ':');
1513  if (!p) /* End of environment string. */
1514  p = env + strlen (env);
1515  if (p - env > 0)
1516  { /* Only non-zero strings. */
1517  tab[i].name = savenstr (env, p - env);
1518  tab[i].len = strlen (tab[i].name);
1519  i++;
1520  }
1521  if (*p)
1522  env = p + 1;
1523  else
1524  {
1525  tab[i].name = NULL; /* Mark end of table. */
1526  tab[i].len = 0;
1527  break;
1528  }
1529  }
1530  return tab;
1531 }
1532 
1533 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
1534  The name being defined actually starts at (NAME + LEN + 1).
1535  But we seem to include the TeX command in the tag name. */
1536 
1537 void
1539  char *name;
1540  int len;
1541 {
1542  char *p = name + len;
1543  char nambuf[BUFSIZ];
1544 
1545  if (*name == 0) return;
1546 
1547  /* Let tag name extend to next group close (or end of line) */
1548  while (*p && *p != TEX_clgrp)
1549  p++;
1550  strncpy (nambuf, name, p - name);
1551  nambuf[p - name] = 0;
1552 
1553  pfnote (nambuf, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
1554  pfcnt++;
1555 }
1556 
1557 /* If the text at CP matches one of the tag-defining TeX command names,
1558  return the index of that command in TEX_toktab.
1559  Otherwise return -1. */
1560 
1561 /* Keep the capital `T' in `Token' for dumb truncating compilers
1562  (this distinguishes it from `TEX_toktab' */
1563 int
1565  char *cp;
1566 {
1567  int i;
1568 
1569  for (i = 0; TEX_toktab[i].len > 0; i++)
1570  if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
1571  return i;
1572  return -1;
1573 }
1574 
1575 /* Initialize a linebuffer for use */
1576 
1577 void
1579  struct linebuffer *linebuffer;
1580 {
1581  linebuffer->size = 200;
1582  linebuffer->buffer = (char *) xmalloc (200);
1583 }
1584 
1585 /* Read a line of text from `stream' into `linebuffer'.
1586  Return the length of the line. */
1587 
1588 long
1590  struct linebuffer *linebuffer;
1591  register FILE *stream;
1592 {
1593  char *buffer = linebuffer->buffer;
1594  register char *p = linebuffer->buffer;
1595  register char *pend = p + linebuffer->size;
1596 
1597  while (1)
1598  {
1599  int c = getc (stream);
1600  if (p == pend)
1601  {
1602  linebuffer->size *= 2;
1603  buffer = (char *) xrealloc (buffer, linebuffer->size);
1604  p += buffer - linebuffer->buffer;
1605  pend = buffer + linebuffer->size;
1606  linebuffer->buffer = buffer;
1607  }
1608  if (c < 0 || c == '\n')
1609  {
1610  *p = 0;
1611  break;
1612  }
1613  *p++ = c;
1614  }
1615 
1616  return p - buffer;
1617 }
1618 
1619 char *
1621  char *cp;
1622 {
1623  return savenstr (cp, strlen (cp));
1624 }
1625 
1626 char *
1628  char *cp;
1629  int len;
1630 {
1631  register char *dp;
1632 
1633  dp = (char *) xmalloc (len + 1);
1634  strncpy (dp, cp, len);
1635  dp[len] = '\0';
1636  return dp;
1637 }
1638 
1639 /*
1640  * Return the ptr in sp at which the character c last
1641  * appears; NULL if not found
1642  *
1643  * Identical to v7 rindex, included for portability.
1644  */
1645 
1646 char *
1647 rindex(sp, c)
1648  char *sp, c;
1649 {
1650  char *r;
1651 
1652  r = NULL;
1653  do
1654  {
1655  if (*sp == c)
1656  r = sp;
1657  } while (*sp++);
1658  return(r);
1659 }
1660 
1661 /*
1662  * Return the ptr in sp at which the character c first
1663  * appears; NULL if not found
1664  *
1665  * Identical to v7 index, included for portability.
1666  */
1667 
1668 char *
1669 index(sp, c)
1670  register char *sp, c;
1671 {
1672  do
1673  {
1674  if (*sp == c)
1675  return (sp);
1676  } while (*sp++);
1677  return (NULL);
1678 }
1679 
1680 /* Print error message and exit. */
1681 
1682 void error (char *s1, char *s2);
1683 void
1684 fatal (s1, s2)
1685  char *s1, *s2;
1686 {
1687  error (s1, s2);
1688  exit (BAD);
1689 }
1690 
1691 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
1692 
1693 void
1694 error (s1, s2)
1695  char *s1, *s2;
1696 {
1697  fprintf (stderr, "%s: ", progname);
1698  fprintf (stderr, s1, s2);
1699  fprintf (stderr, "\n");
1700 }
1701 
1702 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
1703 
1704 char *
1705 concat (s1, s2, s3)
1706  char *s1, *s2, *s3;
1707 {
1708  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
1709  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
1710 
1711  strcpy (result, s1);
1712  strcpy (result + len1, s2);
1713  strcpy (result + len1 + len2, s3);
1714  *(result + len1 + len2 + len3) = 0;
1715 
1716  return result;
1717 }
1718 
1719 /* Like malloc but get fatal error if memory is exhausted. */
1720 
1721 int
1722 xmalloc (size)
1723  int size;
1724 {
1725  int result = malloc (size);
1726  if (!result)
1727  fatal ("virtual memory exhausted", 0);
1728  return result;
1729 }
1730 
1731 int
1732 xrealloc (ptr, size)
1733  char *ptr;
1734  int size;
1735 {
1736  int result = realloc (ptr, size);
1737  if (!result)
1738  fatal ("virtual memory exhausted");
1739  return result;
1740 }
char * rindex(char *sp, char c)
Definition: eustags.c:1647
#define CNL_SAVE_NUMBER
Definition: eustags.c:789
int vflag
Definition: eustags.c:188
struct linebuffer lb lb1
Definition: eustags.c:223
char * white
Definition: eustags.c:174
int wflag
Definition: eustags.c:187
long readline()
int xflag
Definition: eustags.c:189
char * concat()
long size
Definition: eustags.c:219
logical gotone
Definition: eustags.c:155
int PF_funcs(FILE *fi)
Definition: eustags.c:1104
int xrealloc(char *ptr, int size)
Definition: eustags.c:1732
char * curfile
Definition: eustags.c:172
logical f
Definition: eustags.c:143
logical _wht[0177]
Definition: eustags.c:155
Definition: eustags.c:162
#define TRUE
Definition: eustags.c:125
TYST tydef
Definition: eustags.c:164
char * file
Definition: eustags.c:142
void L_funcs(FILE *fi)
Definition: eustags.c:1244
long linecharno
Definition: eustags.c:170
int aflag
Definition: eustags.c:184
void init()
Definition: eustags.c:461
#define TEX_SESC
Definition: eustags.c:1451
long cno
Definition: eustags.c:145
void add_node(NODE *node, NODE *cur_node)
Definition: eustags.c:639
long charno
Definition: eustags.c:169
#define iswhite(arg)
Definition: eustags.c:128
void takeprec()
Definition: eustags.c:1197
logical _etk[0177]
Definition: eustags.c:155
#define istoken(s, tok, len)
Definition: eustags.c:138
int pfcnt
Definition: eustags.c:1099
static char * TEX_defenv
Definition: eustags.c:1384
#define begtoken(arg)
Definition: eustags.c:129
void TEX_getit(char *name, int len)
Definition: eustags.c:1538
char * savenstr()
void free_tree(NODE *node)
Definition: eustags.c:627
struct nd_st * left
Definition: eustags.c:148
Definition: eustags.c:162
void pfnote(char *name, logical f, char *linestart, int linelen, int lno, long cno)
Definition: eustags.c:569
struct nd_st * right
Definition: eustags.c:148
NODE * head
Definition: eustags.c:198
Definition: eustags.c:140
static char TEX_esc
Definition: eustags.c:1389
char * endtk
Definition: eustags.c:175
char * name
Definition: eustags.c:1375
char * buffer
Definition: eustags.c:220
Definition: arith.h:33
void e_getline(long atchar)
Definition: eustags.c:1086
#define intoken(arg)
Definition: eustags.c:130
void TEX_funcs(FILE *fi)
Definition: eustags.c:1400
logical _btk[0177]
Definition: eustags.c:155
int number
Definition: eustags.c:154
logical _itk[0177]
Definition: eustags.c:155
void Scheme_funcs(FILE *fi)
Definition: eustags.c:1306
#define reg
Definition: eustags.c:122
static void usage(void)
Definition: scube.c:195
TYST
Definition: eustags.c:162
struct TEX_tabent * TEX_toktab
Definition: eustags.c:1379
void C_entries()
Definition: eustags.c:805
char searchar
Definition: eustags.c:166
static char TEX_clgrp
Definition: eustags.c:1391
static void get_scheme()
Definition: eustags.c:1346
char * dbp
Definition: eustags.c:1098
int uflag
Definition: eustags.c:186
pointer buffer
Definition: eus.h:274
char * savestr()
Definition: eustags.c:162
void TEX_mode(FILE *f)
Definition: eustags.c:1457
#define CNL
Definition: eustags.c:797
void L_getit()
Definition: eustags.c:1279
Definition: eus.h:271
struct TEX_tabent * TEX_decode_env()
main(int ac, av)
Definition: eustags.c:244
void getit()
Definition: eustags.c:1217
int eflag
Definition: eustags.c:190
int file_num
Definition: eustags.c:183
FILE * outf
Definition: eustags.c:195
int lineno
Definition: eustags.c:168
#define isgood(arg)
Definition: eustags.c:132
int xmalloc(int size)
Definition: eustags.c:1722
char * begtk
Definition: eustags.c:177
tail(char *cp)
Definition: eustags.c:1181
char * outfile
Definition: eustags.c:173
char * name
Definition: eustags.c:141
char * index(char *sp, char c)
Definition: eustags.c:1669
#define TEX_LESC
Definition: eustags.c:1450
void find_entries(char *file)
Definition: eustags.c:498
char * intk
Definition: eustags.c:179
void fatal(char *s1, char *s2)
Definition: eustags.c:1684
int consider_token(char **lpp, char *token, int *f, int level)
Definition: eustags.c:965
#define GOOD
Definition: eustags.c:118
#define NULL
Definition: transargv.c:8
FILE * inf
Definition: eustags.c:195
void error(char *s1, char *s2)
Definition: eustags.c:1694
logical _gd[0177]
Definition: eustags.c:155
int lno
Definition: eustags.c:144
char * notgd
Definition: eustags.c:181
void put_entries(NODE *node)
int TEX_Token(char *cp)
Definition: eustags.c:1564
static char buf[CHAR_SIZE]
Definition: helpsub.c:23
void initbuffer()
#define FALSE
Definition: eustags.c:126
char * progname
Definition: eustags.c:193
char * pat
Definition: eustags.c:146
#define logical
Definition: eustags.c:123
logical been_warned
Definition: eustags.c:147
long ftell()
int total_size_of_entries(reg NODE *node)
Definition: eustags.c:742
#define endtoken(arg)
Definition: eustags.c:131
static char TEX_opgrp
Definition: eustags.c:1390
#define BAD
Definition: eustags.c:119
int tflag
Definition: eustags.c:185


euslisp
Author(s): Toshihiro Matsui
autogenerated on Fri Feb 21 2020 03:20:54