📄 etags.c
字号:
{ 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 + -