📄 misc1.c
字号:
while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
*dst++ = *src++;
/* skip separator */
while ((*src == ' ' || *src == ',') && --dstlen > 0)
*dst++ = *src++;
}
/* if (dstlen == 0) out of space, what to do??? */
*dst = NUL;
}
/*
* Like home_replace, store the replaced string in allocated memory.
* When something fails, NULL is returned.
*/
char_u *
home_replace_save(buf, src)
BUF *buf; /* when not NULL, check for help files */
char_u *src; /* input file name */
{
char_u *dst;
unsigned len;
len = 3; /* space for "~/" and trailing NUL */
if (src != NULL) /* just in case */
len += STRLEN(src);
dst = alloc(len);
if (dst != NULL)
home_replace(buf, src, dst, len, TRUE);
return dst;
}
/*
* Compare two file names and return:
* FPC_SAME if they both exist and are the same file.
* FPC_SAMEX if they both don't exist and have the same file name.
* FPC_DIFF if they both exist and are different files.
* FPC_NOTX if they both don't exist.
* FPC_DIFFX if one of them doesn't exist.
* For the first name environment variables are expanded
*/
int
fullpathcmp(s1, s2, checkname)
char_u *s1, *s2;
int checkname; /* when both don't exist, check file names */
{
#ifdef UNIX
char_u exp1[MAXPATHL];
char_u full1[MAXPATHL];
char_u full2[MAXPATHL];
struct stat st1, st2;
int r1, r2;
expand_env(s1, exp1, MAXPATHL);
r1 = stat((char *)exp1, &st1);
r2 = stat((char *)s2, &st2);
if (r1 != 0 && r2 != 0)
{
/* if stat() doesn't work, may compare the names */
if (checkname)
{
if (fnamecmp(exp1, s2) == 0)
return FPC_SAMEX;
r1 = mch_FullName(exp1, full1, MAXPATHL, FALSE);
r2 = mch_FullName(s2, full2, MAXPATHL, FALSE);
if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
return FPC_SAMEX;
}
return FPC_NOTX;
}
if (r1 != 0 || r2 != 0)
return FPC_DIFFX;
if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
return FPC_SAME;
return FPC_DIFF;
#else
char_u *exp1; /* expanded s1 */
char_u *full1; /* full path of s1 */
char_u *full2; /* full path of s2 */
int retval = FPC_DIFF;
int r1, r2;
/* allocate one buffer to store three paths (alloc()/free() is slow!) */
if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
{
full1 = exp1 + MAXPATHL;
full2 = full1 + MAXPATHL;
expand_env(s1, exp1, MAXPATHL);
r1 = mch_FullName(exp1, full1, MAXPATHL, FALSE);
r2 = mch_FullName(s2, full2, MAXPATHL, FALSE);
/* If mch_FullName() fails, the file probably doesn't exist. */
if (r1 != OK && r2 != OK)
{
if (checkname && fnamecmp(exp1, s2) == 0)
return FPC_SAMEX;
retval = FPC_NOTX;
}
else if (r1 != OK || r2 != OK)
retval = FPC_DIFFX;
else if (fnamecmp(full1, full2))
retval = FPC_DIFF;
else
retval = FPC_SAME;
}
vim_free(exp1);
return retval;
#endif
}
/*
* get the tail of a path: the file name.
*/
char_u *
gettail(fname)
char_u *fname;
{
char_u *p1, *p2;
if (fname == NULL)
return (char_u *)"";
for (p1 = p2 = fname; *p2; ++p2) /* find last part of path */
{
if (vim_ispathsep(*p2))
p1 = p2 + 1;
}
return p1;
}
/*
* get the next path component (just after the next path separator).
*/
char_u *
getnextcomp(fname)
char_u *fname;
{
while (*fname && !vim_ispathsep(*fname))
++fname;
if (*fname)
++fname;
return fname;
}
/*
* Get a pointer to one character past the head of a path name.
* Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
* If there is no head, path is returned.
*/
char_u *
get_past_head(path)
char_u *path;
{
char_u *retval;
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
/* may skip "c:" */
if (isalpha(path[0]) && path[1] == ':')
retval = path + 2;
else
retval = path;
#else
# if defined(AMIGA)
/* may skip "label:" */
retval = vim_strchr(path, ':');
if (retval == NULL)
retval = path;
# else /* Unix */
retval = path;
# endif
#endif
while (vim_ispathsep(*retval))
++retval;
return retval;
}
/*
* return TRUE if 'c' is a path separator.
*/
int
vim_ispathsep(c)
int c;
{
#ifdef RISCOS
return (c == '.' || c == ':');
#else
# ifdef UNIX
return (c == '/'); /* UNIX has ':' inside file names */
# else
# ifdef BACKSLASH_IN_FILENAME
return (c == ':' || c == '/' || c == '\\');
# else
# ifdef VMS
return (c == ':' || c == '[' || c == ']' || c == '/');
# else
# ifdef COLON_AS_PATHSEP
return (c == ':');
# else /* Amiga */
return (c == ':' || c == '/');
# endif
# endif /* VMS */
# endif
# endif
#endif /* RISC OS */
}
/*
* Concatenate file names fname1 and fname2 into allocated memory.
* Only add a '/' or '\\' when 'sep' is TRUE and it is neccesary.
*/
char_u *
concat_fnames(fname1, fname2, sep)
char_u *fname1;
char_u *fname2;
int sep;
{
char_u *dest;
dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3));
if (dest != NULL)
{
STRCPY(dest, fname1);
if (sep && *dest && !vim_ispathsep(*(dest + STRLEN(dest) - 1)))
STRCAT(dest, PATHSEPSTR);
STRCAT(dest, fname2);
}
return dest;
}
/*
* FullName_save - Make an allocated copy of a full file name.
* Returns NULL when out of memory.
*/
char_u *
FullName_save(fname, force)
char_u *fname;
int force; /* force expansion, even when it already looks
like a full path name */
{
char_u *buf;
char_u *new_fname = NULL;
if (fname == NULL)
return NULL;
buf = alloc((unsigned)MAXPATHL);
if (buf != NULL)
{
if (mch_FullName(fname, buf, MAXPATHL, force) != FAIL)
new_fname = vim_strsave(buf);
else
new_fname = vim_strsave(fname);
vim_free(buf);
}
return new_fname;
}
#if defined(CINDENT) || defined(SYNTAX_HL)
static char_u *skip_string __ARGS((char_u *p));
/*
* Find the start of a comment, not knowing if we are in a comment right now.
* Search starts at w_cursor.lnum and goes backwards.
*/
FPOS *
find_start_comment(ind_maxcomment) /* XXX */
int ind_maxcomment;
{
FPOS *pos;
char_u *line;
char_u *p;
if ((pos = findmatchlimit(NULL, '*', FM_BACKWARD, ind_maxcomment)) == NULL)
return NULL;
/*
* Check if the comment start we found is inside a string.
*/
line = ml_get(pos->lnum);
for (p = line; *p && (unsigned)(p - line) < pos->col; ++p)
p = skip_string(p);
if ((unsigned)(p - line) > pos->col)
return NULL;
return pos;
}
/*
* Skip over a "string" and a 'c' character.
*/
static char_u *
skip_string(p)
char_u *p;
{
int i;
/*
* We loop, because strings may be concatenated: "date""time".
*/
for ( ; ; ++p)
{
if (p[0] == '\'') /* 'c' or '\n' or '\000' */
{
if (!p[1]) /* ' at end of line */
break;
i = 2;
if (p[1] == '\\') /* '\n' or '\000' */
{
++i;
while (isdigit(p[i - 1])) /* '\000' */
++i;
}
if (p[i] == '\'') /* check for trailing ' */
{
p += i;
continue;
}
}
else if (p[0] == '"') /* start of string */
{
for (++p; p[0]; ++p)
{
if (p[0] == '\\' && p[1])
++p;
else if (p[0] == '"') /* end of string */
break;
}
continue;
}
break; /* no string found */
}
if (!*p)
--p; /* backup from NUL */
return p;
}
#endif /* CINDENT || SYNTAX_HL */
#ifdef CINDENT
/*
* Functions for C-indenting.
* Most of this originally comes from Eric Fischer.
*/
/*
* Below "XXX" means that this function may unlock the current line.
*/
static int cin_isdefault __ARGS((char_u *));
static char_u *after_label __ARGS((char_u *l));
static int get_indent_nolabel __ARGS((linenr_t lnum));
static int skip_label __ARGS((linenr_t, char_u **pp, int ind_maxcomment));
static int cin_ispreproc __ARGS((char_u *));
static int cin_iscomment __ARGS((char_u *));
static int commentorempty __ARGS((char_u *));
static int cin_isterminated __ARGS((char_u *, int));
static int cin_isfuncdecl __ARGS((char_u *));
static int cin_isif __ARGS((char_u *));
static int cin_iselse __ARGS((char_u *));
static int cin_isdo __ARGS((char_u *));
static int cin_iswhileofdo __ARGS((char_u *, linenr_t, int));
static FPOS *find_start_brace __ARGS((int));
static FPOS *find_match_paren __ARGS((int, int));
static int find_last_paren __ARGS((char_u *l));
static int find_match __ARGS((int lookfor, linenr_t ourscope, int ind_maxparen, int ind_maxcomment));
/*
* Recognize a label: "label:".
* Note: curwin->w_cursor must be where we are looking for the label.
*/
int
cin_islabel(ind_maxcomment) /* XXX */
int ind_maxcomment;
{
char_u *s;
s = skipwhite(ml_get_curline());
/*
* Exclude "default" from labels, since it should be indented
* like a switch label. Same for C++ scope declarations.
*/
if (cin_isdefault(s))
return FALSE;
if (cin_isscopedecl(s))
return FALSE;
if (!vim_isIDc(*s)) /* need at least one ID character */
return FALSE;
while (vim_isIDc(*s))
s++;
s = skipwhite(s);
/* "::" is not a label, it's C++ */
if (*s == ':' && s[1] != ':')
{
/*
* Only accept a label if the previous line is terminated or is a case
* label.
*/
FPOS cursor_save;
FPOS *trypos;
char_u *line;
cursor_save = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1)
{
--curwin->w_cursor.lnum;
/*
* If we're in a comment now, skip to the start of the comment.
*/
curwin->w_cursor.col = 0;
if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
curwin->w_cursor = *trypos;
line = ml_get_curline();
if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */
continue;
if (commentorempty(line))
continue;
curwin->w_cursor = cursor_save;
if (cin_isterminated(line, TRUE) || cin_isscopedecl(line)
|| cin_iscase(line))
return TRUE;
return FALSE;
}
curwin->w_cursor = cursor_save;
return TRUE; /* label at start of file??? */
}
return FALSE;
}
/*
* Recognize a switch label: "case .*:" or "default:".
*/
int
cin_iscase(s)
char_u *s;
{
s = skipwhite(s);
if (STRNCMP(s, "case", 4) == 0 && !vim_isIDc(s[4]))
{
for (s += 4; *s; ++s)
{
if (*s == ':')
{
if (s[1] == ':') /* skip over "::" for C++ */
++s;
else
return TRUE;
}
if (*s == '\'' && s[1] && s[2] == '\'')
s += 2; /* skip over '.' */
else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
return FALSE; /* stop at comment */
else if (*s == '"')
return FALSE; /* stop at string */
}
return FALSE;
}
if (cin_isdefault(s))
return TRUE;
return FALSE;
}
/*
* Recognize a "default" switch label.
*/
static int
cin_isdefault(s)
char_u *s;
{
return (STRNCMP(s, "default", 7) == 0 &&
*(s = skipwhite(s + 7)) == ':' &&
s[1] != ':');
}
/*
* Recognize a "public/private/proctected" scope declaration label.
*/
int
cin_isscopedecl(s)
char_u *s;
{
int i;
s = skipwhite(s);
if (STRNCMP(s, "public", 6) == 0)
i = 6;
else if (STRNCMP(s, "protected", 9) == 0)
i = 9;
else if (STRNCMP(s, "private", 7) == 0)
i = 7;
else
return FALSE;
return (*(s = skipwhite(s + i)) == ':' && s[1] != ':');
}
/*
* Return a pointer to the first non-empty non-comment character after a ':'.
* Return NULL if not found.
* case 234: a = b;
* ^
*/
static char_u *
after_label(l)
char_u *l;
{
for ( ; *l; ++l)
{
if (*l == ':')
{
if (l[1] == ':') /* skip over "::" for C++ */
++l;
else
break;
}
if (*l == '\'' && l[1] && l[2] == '\'')
l += 2; /* skip over 'x' */
}
if (*l == NUL)
return NULL;
l = skipwhite(l + 1);
if (commentorempty(l))
return NULL;
return l;
}
/*
* Get indent of line "lnum", skipping a label.
* Return 0 if there is nothing after the label.
*/
static int
get_indent_nolabel(lnum)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -