⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etags.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
free_tree (node)     register NODE *node;{  while (node)    {      register NODE *node_right = node->right;      free_tree (node->left);      free (node->name);      free (node->pat);      free ((char *) node);      node = node_right;    }}/* * add_node () *	Adds a node to the tree of nodes.  In etags mode, we don't keep *	it sorted; we just keep a linear list.  In ctags mode, maintain *	an ordered tree, with no attempt at balancing. * *	add_node is the only function allowed to add nodes, so it can *	maintain state. */voidadd_node (node, cur_node_p)     NODE *node, **cur_node_p;{  register int dif;  register NODE *cur_node = *cur_node_p;  static NODE *last_node = NULL;/* careful */  if (cur_node == NULL)    {      *cur_node_p = node;      last_node = node;      return;    }  if (emacs_tags_format)    {      /* Etags Mode */      if (!last_node)	fatal ("internal error in add_node");      last_node->right = node;      last_node = node;    }  else    {      /* Ctags Mode */      dif = strcmp (node->name, cur_node->name);      /*       * If this tag name matches an existing one, then       * do not add the node, but maybe print a warning.       */      if (!dif)	{	  if (node->file == cur_node->file)	    {	      if (!no_warnings)		{		  fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",			   node->file, lineno, node->name);		  fprintf (stderr, "Second entry ignored\n");		}	      return;	    }	  if (!cur_node->been_warned && !no_warnings)	    {	      fprintf (stderr,		  "Duplicate entry in files %s and %s: %s (Warning only)\n",		       node->file, cur_node->file, node->name);	    }	  cur_node->been_warned = TRUE;	  return;	}      /* Maybe refuse to add duplicate nodes.  */      if (!permit_duplicates)	{	  if (!strcmp (node->name, cur_node->name)	      && !strcmp (node->file, cur_node->file))	    return;	}      /* Actually add the node */      add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);    }}voidput_entries (node)     reg NODE *node;{  reg char *sp;  if (node == NULL)    return;  /* Output subentries that precede this one */  put_entries (node->left);  /* Output this entry */  if (emacs_tags_format)    {      if (node->rewritten)	{	  fprintf (outf, "%s\177%s\001%d,%d\n",		   node->name, node->pat, node->lno, node->cno);	}      else	{	  fprintf (outf, "%s\177%d,%d\n",		   node->pat, node->lno, node->cno);	}    }  else if (!cxref_style)    {      fprintf (outf, "%s\t%s\t",	       node->name, node->file);      if (node->is_func)	{			/* a function */	  putc (searchar, outf);	  putc ('^', outf);	  for (sp = node->pat; *sp; sp++)	    {	      if (*sp == '\\' || *sp == searchar)		putc ('\\', outf);	      putc (*sp, outf);	    }	  putc (searchar, outf);	}      else	{			/* a typedef; text pattern inadequate */	  fprintf (outf, "%d", node->lno);	}      putc ('\n', outf);    }  else if (vgrind_style)    fprintf (stdout, "%s %s %d\n",	     node->name, node->file, (node->lno + 63) / 64);  else    fprintf (stdout, "%-16s %3d %-16s %s\n",	     node->name, node->lno, node->file, node->pat);  /* Output subentries that follow this one */  put_entries (node->right);}/* Length of a number's decimal representation. */intnumber_len (num)     long num;{  int len = 0;  if (!num)    return 1;  for (; num; num /= 10)    ++len;  return len;}/* * Return total number of characters that put_entries will output for * the nodes in the subtree of the specified node.  Works only if emacs_tags_format * is set, but called only in that case.  This count is irrelevant with * the new tags.el, but is still supplied for backward compatibility. */inttotal_size_of_entries (node)     reg NODE *node;{  reg int total;  if (node == NULL)    return 0;  total = 0;  for (; node; node = node->right)    {      /* Count left subentries. */      total += total_size_of_entries (node->left);      /* Count this entry */      total += strlen (node->pat) + 1;      total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;      if (node->rewritten)	total += 1 + strlen (node->name);	/* \001name */    }  return total;}/* * The C symbol tables. */Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;/* * SYNOPSIS *	Stab *get_C_stab (int c_ext); */#define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab :		\			   c_ext ? C_PLPL_stab :			\			   C_stab)voidadd_keyword (stab, sym, type)     Stab *stab;     char *sym;     enum sym_type type;{  stab_search (stab, sym, strlen (sym))->type = type;}Stab *C_create_stab (c_ext)     int c_ext;{  Stab *stab;  stab = stab_create ();  /* C, C++ and C* */  if (c_ext & C_PLPL)    add_keyword (stab, "class", st_C_struct);  if (c_ext & C_STAR)    add_keyword (stab, "domain", st_C_struct);  add_keyword (stab, "union", st_C_struct);  add_keyword (stab, "struct", st_C_struct);  add_keyword (stab, "enum", st_C_enum);  add_keyword (stab, "typedef", st_C_typedef);  add_keyword (stab, "define", st_C_define);  add_keyword (stab, "long", st_C_typespec);  add_keyword (stab, "short", st_C_typespec);  add_keyword (stab, "int", st_C_typespec);  add_keyword (stab, "char", st_C_typespec);  add_keyword (stab, "float", st_C_typespec);  add_keyword (stab, "double", st_C_typespec);  add_keyword (stab, "signed", st_C_typespec);  add_keyword (stab, "unsigned", st_C_typespec);  add_keyword (stab, "const", st_C_typespec);  add_keyword (stab, "volatile", st_C_typespec);  return stab;}voidC_create_stabs (){  C_stab = C_create_stab (0);  C_PLPL_stab = C_create_stab (C_PLPL);  C_STAR_stab = C_create_stab (C_STAR | C_PLPL);}/* * C_entries () *	This routine finds functions and typedefs in C syntax and adds them *	to the list. */#define CNL_SAVE_DEFINEDEF						\{									\  prev_linepos = linepos;						\  SET_FILEPOS (linepos, inf, charno);					\  lineno++;								\  charno += readline (&lb, inf);					\  lp = lb.buffer;							\}#define CNL								\{									\  CNL_SAVE_DEFINEDEF;							\  definedef = dnone;							\}voidC_entries (c_ext)     int c_ext;			/* extension of C? */{  register int c;		/* latest char read; '\0' for end of line */  register int tokoff;		/* offset in line of beginning of latest token */  register int toklen;		/* length of latest token */  register char *lp;		/* pointer one beyond the character `c' */  logical incomm, inquote, inchar, midtoken;  int level;			/* current curly brace level */  char tokb[BUFSIZ];  lineno = 0;  charno = 0;  lp = lb.buffer;  *lp = 0;  definedef = dnone;  gotone = midtoken = inquote = inchar = incomm = FALSE;  level = 0;  tydef = none;  next_token_is_func = 0;  C_create_stabs ();  while (!feof (inf))    {      c = *lp++;      if (c == '\\')	{	  /* If we're at the end of the line, the next character is a	     '\0'; don't skip it, because it's the thing that tells us	     to read the next line.  */	  if (*lp == 0)	    continue;	  lp++;	  c = ' ';	}      else if (incomm)	{	  if (c == '*' && *lp == '/')	    {	      c = *lp++;	      incomm = FALSE;	    }	}      else if (inquote)	{	  if (c == '"')	    inquote = FALSE;	  else if (c == '\\')	    c = *lp++;	}      else if (inchar)	{	  if (c == '\'')	    inchar = FALSE;	  continue;	}      else	switch (c)	  {	  case '"':	    inquote = TRUE;	    continue;	  case '\'':	    inchar = TRUE;	    continue;	  case '/':	    if (*lp == '*')	      {		lp++;		incomm = TRUE;	      }	    else if (c_ext && *lp == '/')	      {		c = 0;		break;	      }	    continue;	  case '#':	    if (lp == lb.buffer + 1 && definedef == dnone)	      definedef = dsharpseen;	    continue;	    /*	     * The next two are to help the strucdef state machine.	     * They break when they are finished, so they don't interfere	     * with anything else that is going on.	     */	  case ':':	    if (structdef == stagseen)	      structdef = scolonseen;	    break;	    /* Not a struct definition when semicolon seen in non-sinbody context. */	  case ';':	    if (structdef != snone && structdef != sinbody)	      {		structdef = snone;		(void) strcpy (structtag, "<error 1>");	      }	    break;	  case '{':	    if (tydef == begin)	      {		tydef = middle;	      }	    switch (structdef)	      {	      case skeyseen:	/* unnamed struct */		structtag[0] = '\0';		/* FALLTHRU */	      case stagseen:	      case scolonseen:	/* named struct */		structdef = sinbody;		break;	      }	    level++;	    continue;	  case '}':	    if (!noindentypedefs && lp == lb.buffer + 1)	      level = 0;	/* reset level if first column */	    else if (level > 0)	      level--;	    if (level == 0 && tydef == middle)	      {		tydef = end;	      }	    if (level == 0)	      {		structdef = snone;		(void) strcpy (structtag, "<error 2>");	      }	    continue;	  }      if (LEVEL_OK_FOR_FUNCDEF () && !inquote && !incomm && gotone == FALSE)	{	  if (midtoken)	    {	      if (endtoken (c))		{		  if (c_ext && c == ':' && *lp == ':' && intoken (*(lp + 1)))		    {		      /*		       * This handles :: in the middle, but not at beginning		       * of an identifier.		       */		      lp += 2;		      toklen += 3;		    }		  else		    {		      /* The following is no longer true,			 now that we advance to the next line			 at the end of processing the character.  */		      /*		       * We've just finished lexing an identifier.		       * Note that if `c' is '\0', `lb' is the NEXT		       * line, `lp' points to the beginning of it, and		       * old pointers into `lb.buffer' may no longer be		       * valid, since `lb.buffer' may have been		       * reallocated.  In this case (which corresponds		       * to an identifier followed immediately by a		       * newline), we re-read the line into lb1.		       *		       * This would be faster if the previous line's		       * buffer were always saved.		       */		      logical is_func;		      char *tok_linebuf;		      TOKEN tok;		      logical bingo, tok_at_end_of_line;		      char *lp_tmp;	/* addressable */#if 0		      if (c == '\0')			{			  getline (GET_COOKIE (prev_linepos));			  tok_linebuf = lb1.buffer;			  tok_at_end_of_line = TRUE;			  tok.linestart = prev_linepos;			  tok.lineno = lineno - 1;			}		      else#endif			{			  tok_linebuf = lb.buffer;			  tok_at_end_of_line = FALSE;			  tok.linestart = linepos;			  tok.lineno = lineno;			}		      tok.p = tok_linebuf + tokoff;		      tok.len = toklen;		      tok.rewritten = FALSE;		      lp_tmp = lp;		      bingo = consider_token (c, &lp_tmp, &tok,					      &is_func, c_ext, level);		      lp = lp_tmp;		      if (bingo)			{			  if (GET_CHARNO (tok.linestart) != GET_CHARNO (linepos)			      && !tok_at_end_of_line)			    {			      /*			       * Resynchronize tok.p to point into the right			       * linebuffer.			       */			      getline (GET_COOKIE (tok.linestart));			      if (!tok.rewritten)				tok.p = lb1.buffer + (tok.p - tok_linebuf);			      tok_linebuf = lb1.buffer;			    }			  if (structdef == sinbody && definedef == dnone && is_func)			    {	/* function defined in C++ class body */			      sprintf (tokb, "%s::%.*s",				       structtag[0] == '\0' ? "_anonymous_"				       : structtag,				       tok.len, tok.p);			      tok.rewritten = TRUE;			    }			  else			    {			      sprintf (tokb, "%.*s", tok.len, tok.p);			    }			  pfnote (tokb, is_func, tok.rewritten, tok_linebuf,			     tokoff + toklen + (tok_at_end_of_line ? 0 : 1),				  tok.lineno, GET_CHARNO (tok.linestart));			  gotone = is_func;	/* function */			}		      midtoken = FALSE;		    }		}	      else if (intoken (c))		toklen++;	    }	  else if (begtoken (c))	    {	      tokoff = lp - 1 - lb.buffer;	      toklen = 1;	      midtoken = TRUE;	    }	}      /* Detect end of line, after having handled the last token on the line.  */      if (c == 0)	{	  CNL;	  gotone = FALSE;	}      if (c == ';' && tydef == end)	/* clean with typedefs */	tydef = none;    }}/* * consider_token () *	checks to see if the current token is at the start of a *	function, or corresponds to a typedef.  It updates the input *	line pointer *LPP so that the '(' will be in it when it returns. * *	*IS_FUNC gets TRUE iff the token is a function. *	C_EXT is which language we are looking at. * *	In the future we will need some way to adjust where the end of *	the token is; for instance, implementing the C++ keyword *	`operator' properly will adjust the end of the token to be after *	whatever follows `operator'. * * Globals *	structdef	IN OUT *	definedef	IN OUT *	tydef		IN OUT */logicalconsider_token (c, lpp, tokp, is_func, c_ext, level)     reg char c;		/* IN: first char after the token */     char **lpp;		/* IN OUT: *lpp points to 2nd char after the token */     reg TOKEN *tokp;		/* IN */     logical *is_func;		/* OUT */     int c_ext;			/* IN */     int level;			/* IN */{  reg char *lp = *lpp;  logical firsttok;		/* TRUE if have seen first token in ()'s */  Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);  enum sym_type toktype = stab_type (tokse);  *is_func = TRUE;		/* a function */  /*   * Advance the definedef state machine.  We set `gotone' for good measure;   * it's redundant.   */  switch (definedef)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -