diff --git a/Tmain/readtags-formatter-op-tr.d/input.cpp b/Tmain/readtags-formatter-op-tr.d/input.cpp new file mode 100644 index 0000000000..2035077a27 --- /dev/null +++ b/Tmain/readtags-formatter-op-tr.d/input.cpp @@ -0,0 +1,2 @@ +// ctags -o output.tags input.cpp +int __foo(void) { return 0; } diff --git a/Tmain/readtags-formatter-op-tr.d/output.tags b/Tmain/readtags-formatter-op-tr.d/output.tags new file mode 100644 index 0000000000..7fc34103b3 --- /dev/null +++ b/Tmain/readtags-formatter-op-tr.d/output.tags @@ -0,0 +1,40 @@ +!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ +!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ +!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ +!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ +!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ +!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ +!_TAG_FIELD_DESCRIPTION input /input file/ +!_TAG_FIELD_DESCRIPTION name /tag name/ +!_TAG_FIELD_DESCRIPTION pattern /pattern/ +!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ +!_TAG_FIELD_DESCRIPTION!C++ name /aliased names/ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_KIND_DESCRIPTION!C++ c,class /classes/ +!_TAG_KIND_DESCRIPTION!C++ d,macro /macro definitions/ +!_TAG_KIND_DESCRIPTION!C++ e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!C++ f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!C++ g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!C++ h,header /included header files/ +!_TAG_KIND_DESCRIPTION!C++ m,member /class, struct, and union members/ +!_TAG_KIND_DESCRIPTION!C++ n,namespace /namespaces/ +!_TAG_KIND_DESCRIPTION!C++ s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!C++ t,typedef /typedefs/ +!_TAG_KIND_DESCRIPTION!C++ u,union /union names/ +!_TAG_KIND_DESCRIPTION!C++ v,variable /variable definitions/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_OUTPUT_VERSION 0.0 /current.age/ +!_TAG_PARSER_VERSION!C++ 0.0 /current.age/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROC_CWD /home/yamato/var/ctags-github/Tmain/readtags-qualifier-op-tr.d/ // +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 6.0.0 // +!_TAG_ROLE_DESCRIPTION!C++!header local /local header/ +!_TAG_ROLE_DESCRIPTION!C++!header system /system header/ +!_TAG_ROLE_DESCRIPTION!C++!macro undef /undefined/ +__foo input.cpp /^int __foo(void) { return 0; }$/;" f typeref:typename:int diff --git a/Tmain/readtags-formatter-op-tr.d/run.sh b/Tmain/readtags-formatter-op-tr.d/run.sh new file mode 100644 index 0000000000..ce5ecea2a3 --- /dev/null +++ b/Tmain/readtags-formatter-op-tr.d/run.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright: 2024 Masatake YAMATO +# License: GPL-2 + +READTAGS=$3 + +. ../utils.sh + +#V="valgrind --leak-check=full -v" +V= + +skip_if_no_readtags "$READTAGS" + +${V} ${READTAGS} -t output.tags -F '(list (tr $name "_$") #t)' -l + +${V} ${READTAGS} -t output.tags -F '(list (tr $name "_$x") #t)' -l +${V} ${READTAGS} -t output.tags -F '(list (tr $name "_") #t)' -l +${V} ${READTAGS} -t output.tags -F '(list (tr $name "") #t)' -l +${V} ${READTAGS} -t output.tags -F '(list (tr $name 2) #t)' -l diff --git a/Tmain/readtags-formatter-op-tr.d/stderr-expected.txt b/Tmain/readtags-formatter-op-tr.d/stderr-expected.txt new file mode 100644 index 0000000000..b48b8612ce --- /dev/null +++ b/Tmain/readtags-formatter-op-tr.d/stderr-expected.txt @@ -0,0 +1,4 @@ +GOT ERROR in FORMATTING: unexpected-string-length: tr +GOT ERROR in FORMATTING: unexpected-string-length: tr +GOT ERROR in FORMATTING: unexpected-string-length: tr +GOT ERROR in FORMATTING: string-required: tr diff --git a/Tmain/readtags-formatter-op-tr.d/stdout-expected.txt b/Tmain/readtags-formatter-op-tr.d/stdout-expected.txt new file mode 100644 index 0000000000..360bd124d8 --- /dev/null +++ b/Tmain/readtags-formatter-op-tr.d/stdout-expected.txt @@ -0,0 +1 @@ +$$foo diff --git a/dsl/dsl.c b/dsl/dsl.c index 6043d24969..0971a85187 100644 --- a/dsl/dsl.c +++ b/dsl/dsl.c @@ -74,6 +74,7 @@ static EsObject* builtin_substr (EsObject *args, DSLEnv *env); static EsObject* builtin_member (EsObject *args, DSLEnv *env); static EsObject* builtin_downcase (EsObject *args, DSLEnv *env); static EsObject* builtin_upcase (EsObject *args, DSLEnv *env); +static EsObject* builtin_tr (EsObject *args, DSLEnv *env); static EsObject* builtin_length (EsObject *args, DSLEnv *env); static EsObject* bulitin_debug_print (EsObject *args, DSLEnv *env); static EsObject* builtin_entry_ref (EsObject *args, DSLEnv *env); @@ -165,13 +166,15 @@ static DSLProcBind pbinds [] = { { "suffix?", builtin_suffix, NULL, DSL_PATTR_CHECK_ARITY, 2, .helpstr = "(suffix? ) -> " }, { "substr?", builtin_substr, NULL, DSL_PATTR_CHECK_ARITY, 2, - .helpstr = "(substr? string:substr>) -> " }, + .helpstr = "(substr? ) -> " }, { "member", builtin_member, NULL, DSL_PATTR_CHECK_ARITY, 2, .helpstr = "(member ) -> #f|" }, { "downcase", builtin_downcase, NULL, DSL_PATTR_CHECK_ARITY, 1, .helpstr = "(downcase |) -> |" }, { "upcase", builtin_upcase, NULL, DSL_PATTR_CHECK_ARITY, 1, .helpstr = "(upcase |) -> |" }, + { "tr", builtin_tr, NULL, DSL_PATTR_CHECK_ARITY, 2, + .helpstr = "(tr ) -> " }, { "length", builtin_length, NULL, DSL_PATTR_CHECK_ARITY, 1, .helpstr = "(length ) -> " }, { "+", builtin_add, NULL, DSL_PATTR_CHECK_ARITY, 2, @@ -860,6 +863,8 @@ static EsObject* caseop (EsObject *o, int (*op)(int)) { const char *s = es_string_get (o); char *r = strdup (s); + if (r == NULL) + return ES_ERROR_MEMORY; for (char *tmp = r; *tmp != '\0'; tmp++) *tmp = op ((unsigned char) *tmp); @@ -919,6 +924,48 @@ static EsObject* builtin_upcase (EsObject *args, DSLEnv *env) return builtin_caseop0 (o, upcase); } +static EsObject* tr(const char *target, char from, char to) +{ + char *r = strdup(target); + if (r == NULL) + return ES_ERROR_MEMORY; + + for (char *tmp = r; *tmp != '\0'; tmp++) + { + if (*tmp == from) + *tmp = to; + } + + EsObject *q = es_object_autounref (es_string_new (r)); + free (r); + return q; +} + +static EsObject* builtin_tr (EsObject *args, DSLEnv *env) +{ + EsObject *o_target = es_car(args); + EsObject *o_c0c1 = es_car(es_cdr(args)); + + if (!es_string_p (o_target)) + return o_target; + + if (!es_string_p (o_c0c1)) + dsl_throw (STRING_REQUIRED, es_symbol_intern ("tr")); + + const char *cstr_target = es_string_get (o_target); + const char *cstr_c0c1 = es_string_get (o_c0c1); + + if (cstr_target[0] == '\0') + return o_target; + + size_t len_c0c1 = strlen (cstr_c0c1); + if (len_c0c1 != 2) + dsl_throw (UNEXPECTED_STRING_LENGTH, es_symbol_intern ("tr")); + + return tr (cstr_target, cstr_c0c1[0], cstr_c0c1[1]); +} + + static EsObject* builtin_length (EsObject *args, DSLEnv *env) { EsObject *o = es_car(args); diff --git a/dsl/dsl.h b/dsl/dsl.h index 49cba948d6..23320f3380 100644 --- a/dsl/dsl.h +++ b/dsl/dsl.h @@ -72,6 +72,7 @@ typedef struct sDSLCode DSLCode; #define DSL_ERR_WRONG_TYPE_ARGUMENT (es_error_intern("wrong-type-argument")) #define DSL_ERR_NO_ALT_ENTRY (es_error_intern("the-alternative-entry-unavailable")) #define DSL_ERR_WRONG_REGEX_GROUP (es_error_intern("wrong-regex-group")) +#define DSL_ERR_UNEXPECTED_STRING_LENGTH (es_error_intern("unexpected-string-length")) /* * MACROS