* admin/merge-gnulib (GNULIB_MODULES): Add strnlen.
* lib-src/etags.c (find_entries):
* src/emacs.c (main):
* src/nsmenu.m (parseKeyEquiv:):
* src/nsterm.m (ns_xlfd_to_fontname):
* src/term.c (vfatal):
Prefer !*X to !strlen (X).
* lib-src/etags.c (pfnote, add_regex):
* lib-src/pop.c (pop_open):
* lib-src/update-game-score.c (main):
* lwlib/lwlib.c (lw_separator_p):
* src/doprnt.c (doprnt):
* src/emacs.c (main):
* src/inotify.c (inotifyevent_to_event):
* src/keyboard.c (menu_separator_name_p, parse_tool_bar_item):
* src/sysdep.c (get_current_dir_name_or_unreachable):
* src/xdisp.c (store_mode_line_string):
Use strnlen to avoid unnecessary work with strlen.
* lib-src/etags.c (Prolog_functions, prolog_pr)
(Erlang_functions, erlang_func):
Prefer ptrdiff_t to size_t when either will do.
(prolog_pr, erlang_func): New arg LASTLEN, to avoid
unnecessary strlen call. All callers changed.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/strnlen.c, m4/strnlen.m4: New files, copied from Gnulib.
* lwlib/lwlib.c (lw_separator_p):
* src/json.c (json_has_prefix):
Use strncmp to avoid unecessary work with strlen + memcmp.
* src/process.c (set_socket_option): Use SBYTES instead of strlen.
manywarnings memmem-simple memrchr minmax mkostemp mktime nstrftime
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat regex
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
- stpcpy strtoimax symlink sys_stat sys_time
+ stpcpy strnlen strtoimax symlink sys_stat sys_time
tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
update-copyright unlocked-io utimens
vla warnings
}
*cp = '\0';
- if (strlen (lp) > 0)
+ if (*lp)
{
lang = get_language_from_interpreter (lp);
if (lang != NULL && lang->function != NULL)
np->left = np->right = NULL;
if (CTAGS && !cxref_style)
{
- if (strlen (linestart) < 50)
+ if (strnlen (linestart, 50) < 50)
np->regex = concat (linestart, "$", "");
else
np->regex = savenstr (linestart, 50);
* Original code by Sunichirou Sugou (1989)
* Rewritten by Anders Lindgren (1996)
*/
-static size_t prolog_pr (char *, char *);
+static ptrdiff_t prolog_pr (char *, char *, ptrdiff_t);
static void prolog_skip_comment (linebuffer *, FILE *);
static size_t prolog_atom (char *, size_t);
static void
Prolog_functions (FILE *inf)
{
- char *cp, *last;
- size_t len;
- size_t allocated;
-
- allocated = 0;
- len = 0;
- last = NULL;
+ char *cp, *last = NULL;
+ ptrdiff_t lastlen = 0, allocated = 0;
LOOP_ON_INPUT_LINES (inf, lb, cp)
{
continue;
else if (cp[0] == '/' && cp[1] == '*') /* comment. */
prolog_skip_comment (&lb, inf);
- else if ((len = prolog_pr (cp, last)) > 0)
+ else
{
- /* Predicate or rule. Store the function name so that we
- only generate a tag for the first clause. */
- if (last == NULL)
- last = xnew (len + 1, char);
- else if (len + 1 > allocated)
- xrnew (last, len + 1, char);
- allocated = len + 1;
- memcpy (last, cp, len);
- last[len] = '\0';
+ ptrdiff_t len = prolog_pr (cp, last, lastlen);
+ if (0 < len)
+ {
+ /* Store the predicate name to avoid generating duplicate
+ tags later. */
+ if (allocated <= len)
+ {
+ xrnew (last, len + 1, char);
+ allocated = len + 1;
+ }
+ memcpy (last, cp, len);
+ last[len] = '\0';
+ lastlen = len;
+ }
}
}
free (last);
* Return the size of the name of the predicate or rule, or 0 if no
* header was found.
*/
-static size_t
-prolog_pr (char *s, char *last)
-
- /* Name of last clause. */
+static ptrdiff_t
+prolog_pr (char *s, char *last, ptrdiff_t lastlen)
{
- size_t pos;
- size_t len;
-
- pos = prolog_atom (s, 0);
- if (! pos)
+ ptrdiff_t len = prolog_atom (s, 0);
+ if (len == 0)
return 0;
+ ptrdiff_t pos = skip_spaces (s + len) - s;
- len = pos;
- pos = skip_spaces (s + pos) - s;
-
+ /* Save only the first clause. */
if ((s[pos] == '.'
|| (s[pos] == '(' && (pos += 1))
|| (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2)))
- && (last == NULL /* save only the first clause */
- || len != strlen (last)
- || !strneq (s, last, len)))
- {
- make_tag (s, len, true, s, pos, lineno, linecharno);
- return len;
- }
- else
- return 0;
+ && ! (lastlen == len && memcmp (s, last, len) == 0))
+ {
+ make_tag (s, len, true, s, pos, lineno, linecharno);
+ return len;
+ }
+
+ return 0;
}
/*
* Assumes that Erlang functions start at column 0.
* Original code by Anders Lindgren (1996)
*/
-static int erlang_func (char *, char *, int *);
+static int erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *);
static void erlang_attribute (char *);
static int erlang_atom (char *);
static void
Erlang_functions (FILE *inf)
{
- char *cp, *last;
- int len;
- int allocated;
- int name_offset = 0;
-
- allocated = 0;
- len = 0;
- last = NULL;
+ char *cp, *last = NULL;
+ ptrdiff_t lastlen = 0, allocated = 0;
LOOP_ON_INPUT_LINES (inf, lb, cp)
{
last = NULL;
}
}
- else if ((len = erlang_func (cp, last, &name_offset)) > 0)
+ else
{
- /*
- * Function. Store the function name so that we only
- * generates a tag for the first clause.
- */
- if (last == NULL)
- last = xnew (len + 1, char);
- else if (len + 1 > allocated)
- xrnew (last, len + 1, char);
- allocated = len + 1;
- memcpy (last, cp + name_offset, len);
- last[len] = '\0';
+ ptrdiff_t name_offset;
+ ptrdiff_t len = erlang_func (cp, last, lastlen, &name_offset);
+ if (0 < len)
+ {
+ /* Store the function name to avoid generating duplicate
+ tags later. */
+ if (allocated <= len)
+ {
+ xrnew (last, len + 1, char);
+ allocated = len + 1;
+ }
+ memcpy (last, cp + name_offset, len);
+ last[len] = '\0';
+ lastlen = len;
+ }
}
}
free (last);
* was found.
*/
static int
-erlang_func (char *s, char *last, int *name_offset)
-
- /* Name of last clause. */
+erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset)
{
- int pos;
- int len;
char *name = s;
-
- pos = erlang_atom (s);
- if (pos < 1)
+ ptrdiff_t len = erlang_atom (s);
+ if (len == 0)
return 0;
-
- len = pos;
- pos = skip_spaces (s + pos) - s;
+ ptrdiff_t pos = skip_spaces (s + len) - s;
/* If the name is quoted, the quotes are not part of the name. */
- if (len > 2 && name[0] == '\'' && name[len - 1] == '\'')
- {
- *name_offset = 1;
- name++;
- len -= 2;
- }
- else
- *name_offset = 0;
+ bool quoted = 2 < len && name[0] == '\'' && name[len - 1] == '\'';
+ name += quoted;
+ len -= 2 * quoted;
/* Save only the first clause. */
if (s[pos++] == '('
- && (last == NULL
- || len != (int)strlen (last)
- || !strneq (name, last, len)))
- {
- make_tag (name, len, true, s, pos, lineno, linecharno);
- return len;
- }
+ && ! (lastlen == len && memcmp (name, last, len) == 0))
+ {
+ make_tag (s, len, true, s, pos, lineno, linecharno);
+ *name_offset = quoted;
+ return len;
+ }
return 0;
}
single_line = false; /* dot does not match newline */
- if (strlen (regexp_pattern) < 3)
+ if (strnlen (regexp_pattern, 3) < 3)
{
error ("null regexp");
return;
/*
* I really shouldn't use the pop_error variable like this, but....
*/
- if (strlen (username) > ERROR_MAX - 6)
+ if (strnlen (username, ERROR_MAX - 6 + 1) == ERROR_MAX - 6 + 1)
{
pop_close (server);
strcpy (pop_error,
return (0);
}
- if (strlen (password) > ERROR_MAX - 6)
+ if (strnlen (password, ERROR_MAX - 6 + 1) == ERROR_MAX - 6 + 1)
{
pop_close (server);
strcpy (pop_error,
if (! user)
lose_syserr ("Couldn't determine user id");
data = argv[optind + 2];
- if (strlen (data) > MAX_DATA_LEN)
+ if (strnlen (data, MAX_DATA_LEN + 1) == MAX_DATA_LEN + 1)
data[MAX_DATA_LEN] = '\0';
nl = strchr (data, '\n');
if (nl)
# stddef \
# stdio \
# stpcpy \
+# strnlen \
# strtoimax \
# symlink \
# sys_stat \
gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@
gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@
-gl_GNULIB_ENABLED_pathmax = @gl_GNULIB_ENABLED_pathmax@
gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
-runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
endif
## end gnulib module string
+## begin gnulib module strnlen
+ifeq (,$(OMIT_GNULIB_MODULE_strnlen))
+
+
+EXTRA_DIST += strnlen.c
+
+EXTRA_libgnu_a_SOURCES += strnlen.c
+
+endif
+## end gnulib module strnlen
+
## begin gnulib module strtoimax
ifeq (,$(OMIT_GNULIB_MODULE_strtoimax))
--- /dev/null
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ Copyright (C) 2005-2007, 2009-2019 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <string.h>
+
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ If no '\0' terminator is found in that many characters, return MAXLEN. */
+
+size_t
+strnlen (const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
{
int separator_p = 0;
- if (strlen (label) >= 3
- && memcmp (label, "--:", 3) == 0)
+ if (strncmp (label, "--:", 3) == 0)
{
static struct separator_table
{
break;
}
}
- else if (strlen (label) > 3
+ else if (strnlen (label, 4) == 4
&& memcmp (label, "--", 2) == 0
&& label[2] != '-')
{
# Code from module stdlib:
# Code from module stpcpy:
# Code from module string:
+ # Code from module strnlen:
# Code from module strtoimax:
# Code from module strtoll:
# Code from module symlink:
fi
gl_STRING_MODULE_INDICATOR([stpcpy])
gl_HEADER_STRING_H
+ gl_FUNC_STRNLEN
+ if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then
+ AC_LIBOBJ([strnlen])
+ gl_PREREQ_STRNLEN
+ fi
+ gl_STRING_MODULE_INDICATOR([strnlen])
gl_FUNC_STRTOIMAX
if test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
AC_LIBOBJ([strtoimax])
lib/str-two-way.h
lib/strftime.h
lib/string.in.h
+ lib/strnlen.c
lib/strtoimax.c
lib/strtol.c
lib/strtoll.c
m4/stdlib_h.m4
m4/stpcpy.m4
m4/string_h.m4
+ m4/strnlen.m4
m4/strtoimax.m4
m4/strtoll.m4
m4/symlink.m4
--- /dev/null
+# strnlen.m4 serial 13
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2019 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRNLEN],
+[
+ AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+
+ dnl Persuade glibc <string.h> to declare strnlen().
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+ AC_CHECK_DECLS_ONCE([strnlen])
+ if test $ac_cv_have_decl_strnlen = no; then
+ HAVE_DECL_STRNLEN=0
+ else
+ m4_pushdef([AC_LIBOBJ], [:])
+ dnl Note: AC_FUNC_STRNLEN does AC_LIBOBJ([strnlen]).
+ AC_FUNC_STRNLEN
+ m4_popdef([AC_LIBOBJ])
+ if test $ac_cv_func_strnlen_working = no; then
+ REPLACE_STRNLEN=1
+ fi
+ fi
+])
+
+# Prerequisites of lib/strnlen.c.
+AC_DEFUN([gl_PREREQ_STRNLEN], [:])
if (fmtcpy[1] != 's')
minlen = atoi (&fmtcpy[1]);
string = va_arg (ap, char *);
- tem = strlen (string);
- if (STRING_BYTES_BOUND < tem)
+ tem = strnlen (string, STRING_BYTES_BOUND + 1);
+ if (tem == STRING_BYTES_BOUND + 1)
error ("String for %%s or %%S format is too long");
width = strwidth (string, tem);
goto doit1;
}
/* In exec'd: parse special dname into pipe and name info. */
- if (!dname_arg || !strchr (dname_arg, '\n')
- || strlen (dname_arg) < 1 || strlen (dname_arg) > 70)
+ if (!dname_arg || !*dname_arg || strnlen (dname_arg, 71) == 71
+ || !strchr (dname_arg, '\n'))
{
fprintf (stderr, "emacs daemon: daemon name absent or too long\n");
exit (EXIT_CANNOT_INVOKE);
if (ev->len > 0)
{
- size_t const len = strlen (ev->name);
- name = make_unibyte_string (ev->name, min (len, ev->len));
+ name = make_unibyte_string (ev->name, strnlen (ev->name, ev->len));
name = DECODE_FILE (name);
}
else
static bool
json_has_prefix (const char *string, const char *prefix)
{
- size_t string_len = strlen (string);
- size_t prefix_len = strlen (prefix);
- return string_len >= prefix_len && memcmp (string, prefix, prefix_len) == 0;
+ return strncmp (string, prefix, strlen (prefix)) == 0;
}
/* Return whether STRING ends with SUFFIX. */
{
if (!label)
return 0;
- else if (strlen (label) > 3
+ else if (strnlen (label, 4) == 4
&& memcmp (label, "--", 2) == 0
&& label[2] != '-')
{
Lisp_Object tcapt = PROP (TOOL_BAR_ITEM_CAPTION);
const char *label = SYMBOLP (tkey) ? SSDATA (SYMBOL_NAME (tkey)) : "";
const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : "";
- ptrdiff_t max_lbl =
- 2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2));
- char *buf = xmalloc (max_lbl + 1);
+ ptrdiff_t max_lbl_size =
+ 2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2)) + 1;
+ char *buf = xmalloc (max_lbl_size);
Lisp_Object new_lbl;
- ptrdiff_t caption_len = strlen (capt);
+ ptrdiff_t caption_len = strnlen (capt, max_lbl_size);
- if (caption_len <= max_lbl && capt[0] != '\0')
+ if (0 < caption_len && caption_len < max_lbl_size)
{
strcpy (buf, capt);
while (caption_len > 0 && buf[caption_len - 1] == '.')
label = capt = buf;
}
- if (strlen (label) <= max_lbl && label[0] != '\0')
+ ptrdiff_t label_len = strnlen (label, max_lbl_size);
+ if (0 < label_len && label_len < max_lbl_size)
{
ptrdiff_t j;
if (label != buf)
const char *tpos = key;
keyEquivModMask = NSEventModifierFlagCommand;
- if (!key || !strlen (key))
+ if (!key || !*key)
return @"";
while (*tpos == ' ' || *tpos == '(')
sscanf (xlfd, "-%*[^-]-%179[^-]-", name);
/* stopgap for malformed XLFD input */
- if (strlen (name) == 0)
+ if (!*name)
strcpy (name, "Monaco");
/* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
This should work on all systems. KFS. 2003-09-23. */
memset (devname, 0, sizeof devname);
if (STRINGP (val))
- {
- char *arg = SSDATA (val);
- int len = min (strlen (arg), IFNAMSIZ);
- memcpy (devname, arg, len);
- }
+ memcpy (devname, SDATA (val), min (SBYTES (val), IFNAMSIZ));
else if (!NILP (val))
error ("Bad option value for %s", name);
ret = setsockopt (s, sopt->optlevel, sopt->optnum,
pwd = get_current_dir_name ();
if (pwd)
{
- if (strlen (pwd) < dirsize_max)
+ if (strnlen (pwd, dirsize_max) < dirsize_max)
return pwd;
free (pwd);
errno = ERANGE;
sometimes a nicer name, and using it may avoid a fatal error if a
parent directory is searchable but not readable. */
if (pwd
- && (pwdlen = strlen (pwd)) < bufsize_max
+ && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max
&& IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0])
&& stat (pwd, &pwdstat) == 0
&& stat (".", &dotstat) == 0
{
fprintf (stderr, "emacs: ");
vfprintf (stderr, str, ap);
- if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
+ if (! (str[0] && str[strlen (str) - 1] == '\n'))
fprintf (stderr, "\n");
exit (1);
}
if (string != NULL)
{
- len = strlen (string);
- if (precision > 0 && len > precision)
- len = precision;
+ len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
lisp_string = make_string (string, len);
if (NILP (props))
props = mode_line_string_face_prop;