* autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add memrchr.
* gettext-tools/src/xg-arglist-callshape.h (split_keywordspec_ok,
split_keywordspec_ok2, split_keywordspec_ok_lisp): New declarations.
* gettext-tools/src/xg-arglist-callshape.c (split_keywordspec_ok,
split_keywordspec_ok2, split_keywordspec_ok_lisp): New functions.
* gettext-tools/src/x-awk.c (x_awk_keyword): Call split_keywordspec_ok.
* gettext-tools/src/x-c.c (add_keyword): Likewise.
* gettext-tools/src/x-csharp.c (x_csharp_keyword): Likewise.
* gettext-tools/src/x-d.c (x_d_keyword): Likewise.
* gettext-tools/src/x-elisp.c (x_elisp_keyword): Likewise.
* gettext-tools/src/x-go.c (x_go_keyword): Likewise.
* gettext-tools/src/x-java.c (x_java_keyword): Likewise.
* gettext-tools/src/x-javascript.c (x_javascript_keyword): Likewise.
* gettext-tools/src/x-librep.c (x_librep_keyword): Likewise.
* gettext-tools/src/x-lua.c (x_lua_keyword): Likewise.
* gettext-tools/src/x-modula2.c (x_modula2_keyword): Likewise.
* gettext-tools/src/x-ocaml.c (x_ocaml_keyword): Likewise.
* gettext-tools/src/x-perl.c (x_perl_keyword): Likewise.
* gettext-tools/src/x-php.c (x_php_keyword): Likewise.
* gettext-tools/src/x-python.c (x_python_keyword): Likewise.
* gettext-tools/src/x-rust.c (x_rust_keyword): Likewise.
* gettext-tools/src/x-sh.c (x_sh_keyword): Likewise.
* gettext-tools/src/x-typescript-impl.h (NOTE_OPTION_KEYWORD): Likewise.
* gettext-tools/src/x-vala.c (add_keyword): Likewise.
* gettext-tools/src/x-tcl.c (x_tcl_keyword): Call split_keywordspec_ok2.
* gettext-tools/src/x-lisp.c (x_lisp_keyword): Call split_keywordspec_ok_lisp.
* gettext-tools/src/x-scheme.c (x_scheme_keyword): Likewise.
memchr
memeq
memmove
+ memrchr
memset
minmax
mkdir
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C#
- identifier sequence with dots.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid C#
+ identifier sequence with dots. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid identifier,
- possibly with a trailing '!'.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
{
+ /* The characters between name and end should form a valid identifier,
+ possibly with a trailing '!'. */
if (end > name && end[-1] == '!')
insert_keyword_callshape (&template_keywords, name, end - 1 - name,
&shape);
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Lisp
- symbol. */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid Lisp
+ symbol. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
{
/* The characters between name and end should form
- either a valid Go identifier,
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Java
- identifier sequence with dots.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid Java
+ identifier sequence with dots. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Lisp
- symbol. */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid Lisp
+ symbol. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Lisp symbol.
- Extract the symbol name part. */
- const char *colon = strchr (name, ':');
- if (colon != NULL && colon < end)
+ if (split_keywordspec_ok_lisp (name, end - name))
{
- name = colon + 1;
- if (name < end && *name == ':')
- name++;
- colon = strchr (name, ':');
- if (colon != NULL && colon < end)
- return;
+ /* The characters between name and end should form a valid Lisp
+ symbol. */
+ /* Extract the symbol name part. */
+ const char *colon = memrchr (name, ':', end - name);
+ if (colon != NULL)
+ name = colon + 1;
+
+ /* Uppercase it. */
+ size_t len = end - name;
+ char *symname = XNMALLOC (len, char);
+ for (size_t i = 0; i < len; i++)
+ symname[i] =
+ (name[i] >= 'a' && name[i] <= 'z' ? name[i] - 'a' + 'A' : name[i]);
+
+ insert_keyword_callshape (&keywords, symname, len, &shape);
}
-
- /* Uppercase it. */
- size_t len = end - name;
- char *symname = XNMALLOC (len, char);
- for (size_t i = 0; i < len; i++)
- symname[i] =
- (name[i] >= 'a' && name[i] <= 'z' ? name[i] - 'a' + 'A' : name[i]);
-
- insert_keyword_callshape (&keywords, symname, len, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Modula-2
- identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid Modula-2
+ identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Rust
- identifier, possibly with a trailing '!'.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
{
+ /* The characters between name and end should form a valid Rust
+ identifier, possibly with a trailing '!'. */
if (end > name && end[-1] == '!')
insert_keyword_callshape (¯o_keywords, name, end - 1 - name,
&shape);
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid Lisp symbol.
- Extract the symbol name part. */
- const char *colon = strchr (name, ':');
- if (colon != NULL && colon < end)
+ if (split_keywordspec_ok_lisp (name, end - name))
{
- name = colon + 1;
- if (name < end && *name == ':')
- name++;
- colon = strchr (name, ':');
- if (colon != NULL && colon < end)
- return;
+ /* The characters between name and end should form a valid Lisp
+ symbol. */
+ /* Extract the symbol name part. */
+ const char *colon = memrchr (name, ':', end - name);
+ if (colon != NULL)
+ name = colon + 1;
+
+ insert_keyword_callshape (&keywords, name, end - name, &shape);
}
-
- insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
+ if (split_keywordspec_ok2 (name, end - name))
+ {
+ /* The characters between name and end should form a valid Tcl
+ function name. A leading "::" is redundant. */
+ if (end - name >= 2 && name[0] == ':' && name[1] == ':')
+ name += 2;
- /* The characters between name and end should form a valid Tcl
- function name. A leading "::" is redundant. */
- if (end - name >= 2 && name[0] == ':' && name[1] == ':')
- name += 2;
-
- insert_keyword_callshape (&keywords, name, end - name, &shape);
+ insert_keyword_callshape (&keywords, name, end - name, &shape);
+ }
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ identifier. */
insert_keyword_callshape (&keywords, name, end - name, &shape);
}
}
const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
-
- /* The characters between name and end should form a valid C identifier.
- A colon means an invalid parse in split_keywordspec(). */
- const char *colon = strchr (name, ':');
- if (colon == NULL || colon >= end)
+ if (split_keywordspec_ok (name, end - name))
+ /* The characters between name and end should form a valid
+ C identifier. */
insert_keyword_callshape (keywords, name, end - name, &shape);
}
}
string_list_destroy (&xcomments);
}
+bool
+split_keywordspec_ok (const char *keyword, size_t keyword_len)
+{
+ /* If the keyword contains a colon, it means an invalid parse
+ in split_keywordspec(). */
+ return memchr (keyword, ':', keyword_len) == NULL;
+}
+
+bool
+split_keywordspec_ok2 (const char *keyword, size_t keyword_len)
+{
+ /* If the keyword contains a colon that is not part of a colon pair,
+ it means an invalid parse in split_keywordspec(). */
+ const char *keyword_end = keyword + keyword_len;
+ for (const char *p = keyword; p < keyword_end; )
+ {
+ const char *colon = memchr (p, ':', keyword_end - p);
+ if (colon == NULL)
+ break;
+ if (!(colon + 1 < keyword_end && colon[1] == ':'))
+ /* Found a colon that is not part of a colon pair. */
+ return false;
+ /* Found a colon pair. */
+ p = colon + 2;
+ }
+ return true;
+}
+
+bool
+split_keywordspec_ok_lisp (const char *keyword, size_t keyword_len)
+{
+ /* If the keyword contains more than a single colon or a colon pair,
+ it means an invalid parse in split_keywordspec(). */
+ const char *keyword_end = keyword + keyword_len;
+ const char *colon = memchr (keyword, ':', keyword_end - keyword);
+ if (colon == NULL)
+ return true;
+ if (colon + 1 < keyword_end && colon[1] == ':')
+ colon++;
+ return memchr (colon, ':', keyword_end - colon) == NULL;
+}
+
void
insert_keyword_callshape (hash_table *table,
extern void split_keywordspec (const char *spec, const char **endp,
struct callshape *shapep);
+/* Test whether the preceding split_keywordspec call was successful,
+ assuming a programming language in which a keyword cannot contain
+ colons. */
+extern bool split_keywordspec_ok (const char *keyword, size_t keyword_len);
+
+/* Test whether the preceding split_keywordspec call was successful,
+ assuming a programming language in which a keyword cannot contain colons,
+ except in pairs (such as e.g. in C++). */
+extern bool split_keywordspec_ok2 (const char *keyword, size_t keyword_len);
+
+/* Test whether the preceding split_keywordspec call was successful,
+ assuming a programming language in which a keyword cannot contain colons,
+ except a single colon or a pair of colons (such as e.g. in Common Lisp). */
+extern bool split_keywordspec_ok_lisp (const char *keyword, size_t keyword_len);
+
/* Set of alternative calling conventions for a given keyword. */
struct callshapes
{