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

📄 etags.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    {    case dnone:      /* We're not on a preprocessor line. */      break;    case dsharpseen:      if (toktype == st_C_define)	{	  definedef = ddefineseen;	  gotone = FALSE;	}      else	{	  definedef = dignorerest;	  gotone = TRUE;	}      goto badone;    case ddefineseen:      /*       * Make a tag for any macro.       * This will flub up if there is a newline immediately following       * the macro name.       */      *is_func = (c == '(');      definedef = dignorerest;      gotone = TRUE;      if (!*is_func && !constantypedefs)	goto badone;      goto goodone;    case dignorerest:      goto badone;    default:      error ("internal error: definedef value");    }  /*   * Skip whitespace and comments after the token.  This loop should   * also skip C++ comments.   */  while (1)    {      /* At whitespace => skip it.  */      if (iswhite (c))	{	  c = *lp++;	}      /* At a comment => skip to end of comment.  */      else if (c == '/' && *lp == '*')	{	  /* If we find a comment, skip it.  */	  while (!(c == '*' && *lp == '/'))	    {	      c = *lp++;	      if (c == 0)		{		  lp--;		  break;		}	    }	  if (c == '*' && *lp == '/')	    {	      lp++;		/* lp now points past the '/' */	      c = *lp++;	/* c is now the --whatever-- after the '/' */	    }	}      else	break;      /* If we arrived at eof or eol, decide which one it is.	 If it's eol, advance to the next line.  */      if (c == 0)	{	  lp--;	  break;	}    }  /*   * If you have custom token types, or when configuration files can   * define custom token types, this switch will be larger.   */  switch (toktype)    {    case st_C_typedef:      if (typedefs)	{	  tydef = begin;	  goto badone;	}      break;    case st_C_typespec:      if (tydef == begin || tydef == end)	{	  tydef = end;	  goto badone;	}      break;    }  /*   * This structdef business is currently only invoked when level==0.   * It should be recursively invoked whatever the level, and a stack of   * states kept, to allow for definitions of structs within structs.   *   * This structdef business is NOT invoked when we are ctags and the   * file is plain C.  This is because a struct tag may have the same   * name as another tag, and this loses with ctags.   *   * This if statement deals with the tydef state machine as follows: if   * tydef==begin and token is struct/union/class/enum, goto badone.   * All the other code here is for the structdef state machine.   */  switch (toktype)    {    case st_C_struct:    case st_C_enum:      if (tydef == begin || (typedefs_and_cplusplus && level == 0 && structdef == snone))	{	  structdef = skeyseen;	  structkey = tokse;	}      goto badone;    }  if (structdef == skeyseen)    {      /* If next char is '{' or (for C++) ':', found a structure tag. */      if (c == '{' || (c_ext && c == ':'))	{	  /*	   * We should do this slightly differently for straight C:	   * instead of defining `tag', as we now do, we should define	   * `struct tag'.  (Do this only if the find-tag defaulting is	   * done on a sophisticated per-mode basis, so that if the user	   * says meta-. anywhere in `struct foo', the default comes out	   * `struct foo', not `struct' or `foo'.)  This will require	   * remembering which keyword (struct/union/class/enum) we saw, as a	   * Stab_entry* -- this will also make it possible to merge the	   * skeyseen and senumseen states, if we want.	   */	  if (stab_type (structkey) == st_C_struct)	    {	      (void) strncpy (structtag, tokp->p, tokp->len);	      structtag[tokp->len] = '\0';	/* for struct/union/class */	      structdef = stagseen;	    }	  else	    {	      structtag[0] = '\0';	/* for enum */	    }	  *is_func = FALSE;	/* not a function */	  goto goodone;	}      else	{	  /* Not a definition: reset structdef */	  structdef = snone;	  (void) strcpy (structtag, "<error 3>");	}      /* Now what?  And how does/should this stuff interact with tydef?? */      /* Also maybe reset lp to *lpp for benefit of the function finding code. */    }  if (tydef == begin)    {      tydef = end;      goto badone;    }  if (tydef == end)    {      *is_func = 0;      goto goodone;    }  /* Detect GNUmacs's function-defining macros. */  if (definedef == dnone)    {      if (strneq (tokp->p, "DEF", 3)	  || strneq (tokp->p, "ENTRY", 5)	  || strneq (tokp->p, "SYSCALL", 7)	  || strneq (tokp->p, "PSEUDO", 6))	{	  next_token_is_func = TRUE;	  goto badone;	}      else if (strneq (tokp->p, "EXFUN", 5))	{	  next_token_is_func = FALSE;	  goto badone;	}    }  if (next_token_is_func)    {      next_token_is_func = FALSE;      goto goodone;    }  if (c != '(')    goto badone;  firsttok = FALSE;  while ((c = *lp++) != ')')    {      if (c == 0)	{	  lp--;	  break;	}      /*	* This line used to confuse ctags:	*	int	(*oldhup)();	* This fixes it. A nonwhite char before the first	* token, other than a / (in case of a comment in there)	* makes this not a declaration.	*/      if (begtoken (c) || c == '/')	firsttok++;      else if (!iswhite (c) && !firsttok)	goto badone;    }  while (iswhite (c = *lp++))    {      if (c == 0)	{	  lp--;	  break;	}    }  if (!isgood (c))    goto badone;goodone:  *lpp = lp - 1;  return TRUE;badone:  *lpp = lp - 1;  return FALSE;}voidgetline (atcookie)     long atcookie;{  long saveftell = ftell (inf);  (void) fseek (inf, atcookie, 0);  (void) readline (&lb1, inf);  (void) fseek (inf, saveftell, 0);}/* Fortran parsing */char *dbp;int pfcnt;intPF_funcs (fi)     FILE *fi;{  lineno = 0;  charno = 0;  pfcnt = 0;  while (!feof (fi))    {      lineno++;      linecharno = charno;      charno += readline (&lb, fi);      dbp = lb.buffer;      if (*dbp == '%')	dbp++;			/* Ratfor escape to fortran */      while (isspace (*dbp))	dbp++;      if (*dbp == 0)	continue;      switch (*dbp | ' ')	{	case 'i':	  if (tail ("integer"))	    takeprec ();	  break;	case 'r':	  if (tail ("real"))	    takeprec ();	  break;	case 'l':	  if (tail ("logical"))	    takeprec ();	  break;	case 'c':	  if (tail ("complex") || tail ("character"))	    takeprec ();	  break;	case 'd':	  if (tail ("double"))	    {	      while (isspace (*dbp))		dbp++;	      if (*dbp == 0)		continue;	      if (tail ("precision"))		break;	      continue;	    }	  break;	}      while (isspace (*dbp))	dbp++;      if (*dbp == 0)	continue;      switch (*dbp | ' ')	{	case 'f':	  if (tail ("function"))	    getit ();	  continue;	case 's':	  if (tail ("subroutine"))	    getit ();	  continue;	case 'p':	  if (tail ("program"))	    {	      getit ();	      continue;	    }	  if (tail ("procedure"))	    getit ();	  continue;	}    }  return (pfcnt);}logicaltail (cp)     char *cp;{  register int len = 0;  while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))    cp++, len++;  if (*cp == 0)    {      dbp += len;      return (1);    }  return (0);}voidtakeprec (){  while (isspace (*dbp))    dbp++;  if (*dbp != '*')    return;  dbp++;  while (isspace (*dbp))    dbp++;  if (!isdigit (*dbp))    {      --dbp;			/* force failure */      return;    }  do    dbp++;  while (isdigit (*dbp));}voidgetit (){  register char *cp;  char c;  char nambuf[BUFSIZ];  while (isspace (*dbp))    dbp++;  if (*dbp == 0      || (!isalpha (*dbp)	  && *dbp != '_'	  && *dbp != '$'))    return;  for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)			     || (*cp == '_') || (*cp == '$')); cp++)    continue;  c = cp[0];  cp[0] = 0;  (void) strcpy (nambuf, dbp);  cp[0] = c;  pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);  pfcnt++;}/* Handle a file of assembler code.  */voidAsm_funcs (fi)     FILE *fi;{  int i;  register char c;  lineno = 0;  charno = 0;  pfcnt = 0;  while (!feof (fi))    {      lineno++;      linecharno = charno;      charno += readline (&lb, fi);      dbp = lb.buffer;      for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)	;      if ((i > 0) && (c == ':'))	getit ();    }}/* Added by Mosur Mohan, 4/22/88 *//* Pascal parsing                */#define GET_NEW_LINE \{ \  linecharno = charno; lineno++; \  charno += 1 + readline (&lb, inf); \  dbp = lb.buffer; \}/*  Locates tags for procedures & functions. *  Doesn't do any type- or var-definitions. *  It does look for the keyword "extern" or "forward" *  immediately following the procedure statement; *  if found, the tag is skipped. */voidPAS_funcs (fi)     FILE *fi;{  struct linebuffer tline;	/* mostly copied from C_entries */  long save_lcno;  int save_lineno;  char c, *cp;  char nambuf[BUFSIZ];  logical			/* each of these flags is TRUE iff: */    incomm1,			/* point is inside {..} comment */    incomm2,			/* point is inside (*..*) comment */    inquote,			/* point is inside '..' string */    get_tagname,		/* point is after PROCEDURE/FUNCTION */  /*   keyword, so next item = potential tag */    found_tag,			/* point is after a potential tag */    inparms,			/* point is within parameter-list */    verify_tag;			/* point has passed the parm-list, so the */  /*   next token will determine whether    */  /*   this is a FORWARD/EXTERN to be       */  /*   ignored, or whether it is a real tag */  lineno = 0;  charno = 0;  dbp = lb.buffer;  *dbp = 0;  initbuffer (&tline);  incomm1 = incomm2 = inquote = FALSE;  found_tag = FALSE;		/* have a proc name; check if extern */  get_tagname = FALSE;		/* have found "procedure" keyword    */  inparms = FALSE;		/* found '(' after "proc"            */  verify_tag = FALSE;		/* check if "extern" is ahead        */  /* long main loop to get next char */  while (!feof (fi))    {      c = *dbp++;      if (c == 0)		/* if end of line */	{	  GET_NEW_LINE;	  if (*dbp == 0)	    continue;	  if (!((found_tag && verify_tag) ||		get_tagname))	    c = *dbp++;		/* only if don't need *dbp pointing */	  /* to the beginning of the name of  */	  /* the procedure or function        */	}      if (incomm1)		/* within { - } comments */	{	  if (c == '}')	    incomm1 = FALSE;	  continue;	}      else if (incomm2)		/* within (* - *) comments */	{	  if (c == '*')	    {	      while ((c = *dbp++) == '*')		continue;	      if (c == 0)		GET_NEW_LINE;	      if (c == ')')		incomm2 = FALSE;	    }	  continue;	}      else if (inquote)	{	  if (c == '\'')	    inquote = FALSE;	  continue;	}      else	switch (c)	  {	  case '\'':	    inquote = TRUE;	/* found first quote */	    continue;	  case '{':		/* found open-{-comment */	    incomm1 = TRUE;	    continue;	  case '(':	    if (*dbp == '*')	/* found open-(*-comment */	      {		incomm2 = TRUE;		dbp++;	      }	    else if (found_tag)	/* found '(' after tag, i.e., parm-list */	      inparms = TRUE;	    continue;	  case ')':		/* end of parms list */	    if (inparms)	      inparms = FALSE;	    continue;	  case ';':	    if ((found_tag) && (!inparms))	/* end of proc or fn stmt */	      {		verify_tag = TRUE;		break;	      }	    continue;	  }      if ((found_tag) && (verify_tag) && (*dbp != ' '))	{	  /* check if this is an "extern" declaration */	  if (*dbp == 0)	    continue;	  if ((*dbp == 'e') || (*dbp == 'E'))	    {	      if (tail ("extern"))	/* superfluous, really! */		{		  found_tag = FALSE;		  verify_tag = FALSE;		}	    }	  else if ((*dbp == 'f') || (*dbp == 'F'))	    {	      if (tail ("forward"))	/*  check for forward reference */		{		  found_tag = FALSE;		  verify_tag = FALSE;		}	    }	  if ((found_tag) && (verify_tag))	/* not external proc, so make tag */	    {	      found_tag = FALSE;	      verify_tag = FALSE;	      pfnote (nambuf, TRUE, FALSE,		      tline.buffer, cp - tline.buffer + 1,		      save_lineno, save_lcno);	      continue;	    }	}      if (get_tagname)		/* grab name of proc or fn */	{

⌨️ 快捷键说明

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