Skip to content

Commit

Permalink
main: implement the setter and getter for parser specific fields defi…
Browse files Browse the repository at this point in the history
…ned in an optlib parser

Signed-off-by: Masatake YAMATO <[email protected]>
  • Loading branch information
masatake committed Aug 30, 2024
1 parent 7b991c9 commit 62467ec
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 19 deletions.
6 changes: 3 additions & 3 deletions Tmain/flags-fielddef-datatype.d/stdout-expected.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#LETTER NAME ENABLED LANGUAGE JSTYPE FIXED OP DESCRIPTION
- boolfield no FIELDTEST --b no -- a field having boolean value
- boolfield no FIELDTEST --b no rw a field having boolean value
- deffield no FIELDTEST s-- no -- a field that type is not specified
- intfield no FIELDTEST -i- no -- a field having integer value
- strfield no FIELDTEST s-- no -- a field having string value
- intfield no FIELDTEST -i- no rw a field having integer value
- strfield no FIELDTEST s-- no rw a field having string value
2 changes: 1 addition & 1 deletion Tmain/list-fielddef-flags.d/stdout-expected.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#LETTER NAME DESCRIPTION
- datatype=TYPE acceaptable datatype of the field ([str]|bool|int)
- datatype=TYPE acceaptable datatype of the field (str|bool|int)
1 change: 1 addition & 0 deletions Tmain/parser-own-fields-for-foreign-lang.d/input.unknownx
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ protected func bar(n);
private func baz(n,...);
X:tagme@iamowner
Y:iamowner2=tagme2
Z:tagme-z@iamowner-z
7 changes: 6 additions & 1 deletion Tmain/parser-own-fields-for-foreign-lang.d/knownz.ctags
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
--langdef=knownz
--kinddef-knownz=m,mark,makers

--_fielddef-knownz=owner,the owner of the markers
--_fielddef-knownz=owner,the owner of the markers{datatype=str}

--_fielddef-knownz=len,the length of owner string{datatype=int}
--fields-knownz=+{len}
--_fielddef-knownz=lenplus,the length of owner string + 1{datatype=int}
--fields-knownz=+{lenplus}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ bar input.unknownx /^protected func bar(n);$/;" f language:unknownx protection:p
baz input.unknownx /^private func baz(n,...);$/;" f language:unknownx protection:private signature:(n,...)
foo input.unknownx /^public func foo(n, m);$/;" f language:unknownx protection:public signature:(n, m)
tagme input.unknownx /^X:tagme@iamowner$/;" m language:knownz owner:iamowner
tagme-z input.unknownx /^Z:tagme-z@iamowner-z$/;" m language:knownz owner:iamowner-z len:10 lenplus:11
tagme2 input.unknownx /^Y:iamowner2=tagme2$/;" m language:knownz owner:iamowner2
10 changes: 10 additions & 0 deletions Tmain/parser-own-fields-for-foreign-lang.d/unknownx.ctags
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@
--regex-unknownx=/^((public|protected|private) +)?func ([^\(]+)\((.*)\)/\3/f/{_field=protection:\1}{_field=signature:(\4)}
--regex-unknownx=/^X:([a-z]+)@([a-z]+)/\1/m/{_language=knownz}{_field=owner:\2}
--regex-unknownx=/^Y:([a-z0-9]+)=([a-z0-9]+)/\2/m/{_field=owner:\1}{_language=knownz}
--regex-unknownx=/^Z:([-a-z]+)@([-a-z]+)/\1/m/{_language=knownz}{{
. \2 knownz.owner:
. :knownz.owner {
. exch length knownz.len:
} if
. :knownz.len {
1 add
. exch knownz.lenplus:
} if
}}
59 changes: 59 additions & 0 deletions main/field.c
Original file line number Diff line number Diff line change
Expand Up @@ -1925,3 +1925,62 @@ static EsObject* setFieldValueForInherits (tagEntryInfo *tag, const fieldDefinit

return es_false;
}

extern EsObject* getFieldValueGeneric (const tagEntryInfo *tag, const fieldDefinition *fdef)
{
const char *value = getParserFieldValueForType(tag, fdef->ftype);

if (value == NULL)
return es_nil;

unsigned int dt = fdef->dataType;
if (dt & FIELDTYPE_STRING)
return (dt & FIELDTYPE_BOOL && value[0] == '\0')
? es_false
: opt_string_new_from_cstr (value);
else if (dt & FIELDTYPE_INTEGER)
{
long tmp;
if (strToLong (value, 10, &tmp))
return es_integer_new ((int)tmp); /* TODO: if tmp is not in the range of int, return es_nil */
else
{
AssertNotReached ();
return es_nil;
}
}
else if (dt & FIELDTYPE_BOOL)
return value [0]? es_true: es_false;
else
{
AssertNotReached ();
return es_nil;
}
}

extern EsObject* setFieldValueGeneric (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
{
unsigned int dt = fdef->dataType;
const char * val;
char buf[1 /* [+-] */ + 20 + 1 /* for \0 */];

if (dt & FIELDTYPE_STRING)
val = opt_string_get_cstr (obj);
else if (dt & FIELDTYPE_INTEGER)
{
int tmp = es_integer_get (obj);
/* 2^64 => "18446744073709551616" */
snprintf(buf, 22, "%d", tmp);
val = buf;
}
else if (dt & FIELDTYPE_BOOL)
val = es_boolean_get (obj)? "t": "";
else
{
val = "";
AssertNotReached ();
}

attachParserField (tag, fdef->ftype, val);
return es_false;
}
14 changes: 14 additions & 0 deletions main/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ typedef enum eFieldDataType {

/* used in --list-fields */
FIELDTYPE_END_MARKER = 1 << 3,

/* If you want to allow a parser code written in optscript
* to access the field, append FIELDTYPE_SCRIPTABLE to
* dataType field of your fieldDefinition.
*
* From a optlib parser, pass {datatype=TYPE} flag to
* --_fielddef-<LANV>=... option. Just specifying a
* type is enough; FIELDTYPE_SCRIPTABLE is automatically
* append the filed definition. If you don't pass the
* flag explicitly, FIELDTYPE_SCRIPTABLE is not set. */
FIELDTYPE_SCRIPTABLE = FIELDTYPE_END_MARKER,
} fieldDataType;

typedef const char* (*fieldRenderer)(const tagEntryInfo *const,
Expand Down Expand Up @@ -119,4 +130,7 @@ struct sFieldDefinition {

extern bool isFieldEnabled (fieldType type);

extern struct _EsObject* getFieldValueGeneric (const tagEntryInfo *tag, const fieldDefinition *fdef);
extern struct _EsObject* setFieldValueGeneric (tagEntryInfo *tag, const fieldDefinition *fdef, const struct _EsObject *obj);

#endif /* CTAGS_MAIN_FIELD_H */
28 changes: 17 additions & 11 deletions main/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4018,20 +4018,20 @@ static void field_def_flag_datatype_long (const char *const optflag CTAGS_ATTR_U

if (strncmp (p, "integer", q - p) == 0
|| strncmp (p, "int", q - p) == 0)
fdef->dataType |= FIELDTYPE_INTEGER;
fdef->dataType |= (FIELDTYPE_INTEGER|FIELDTYPE_SCRIPTABLE);
else if (strncmp (p, "string", q - p) == 0
|| strncmp (p, "str", q - p) == 0)
fdef->dataType |= FIELDTYPE_STRING;
fdef->dataType |= (FIELDTYPE_STRING|FIELDTYPE_SCRIPTABLE);
else if (strncmp (p, "boolean", q - p) == 0
|| strncmp (p, "bool", q - p) == 0)
fdef->dataType |= FIELDTYPE_BOOL;
fdef->dataType |= (FIELDTYPE_BOOL|FIELDTYPE_SCRIPTABLE);
p = q;
}
}

static flagDefinition FieldDefFlagDef [] = {
{ '\0', "datatype", NULL, field_def_flag_datatype_long,
"TYPE", "acceaptable datatype of the field ([str]|bool|int)" },
"TYPE", "acceaptable datatype of the field (str|bool|int)" },
};

static bool processLangDefineField (const langType language,
Expand Down Expand Up @@ -4070,21 +4070,27 @@ static bool processLangDefineField (const langType language,
desc = extractDescriptionAndFlags (p, &flags);

fdef = xCalloc (1, fieldDefinition);

fdef->dataType = 0;
if (flags)
flagsEval (flags, FieldDefFlagDef, ARRAY_SIZE (FieldDefFlagDef), fdef);
if (!fdef->dataType)
fdef->dataType = FIELDTYPE_STRING;

fdef->enabled = false;
fdef->letter = NUL_FIELD_LETTER;
fdef->name = eStrndup(parameter, name_end - parameter);
fdef->description = desc;
fdef->isValueAvailable = NULL;
fdef->getValueObject = NULL;
fdef->getValueObject = (fdef->dataType & FIELDTYPE_SCRIPTABLE)
? getFieldValueGeneric
: NULL;
fdef->getterValueType = NULL;
fdef->setValueObject = NULL;
fdef->setValueObject = (fdef->dataType & FIELDTYPE_SCRIPTABLE)
? setFieldValueGeneric
: NULL;
fdef->setterValueType = NULL;
fdef->checkValueForSetter = NULL;
fdef->dataType = 0;
if (flags)
flagsEval (flags, FieldDefFlagDef, sizeof (FieldDefFlagDef), fdef);
if (!fdef->dataType)
fdef->dataType = FIELDTYPE_STRING;
fdef->ftype = FIELD_UNKNOWN;
DEFAULT_TRASH_BOX(fdef, fieldDefinitionDestroy);

Expand Down
45 changes: 42 additions & 3 deletions misc/optlib2c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,32 @@ my $langdef_flags =
} ],
];

my $fielddef_flags =
[
[ qr/\{datatype=([^\}]+)\}/, sub {
my $datatype = "FIELDTYPE_SCRIPTABLE|";

if (($1 eq 'str') || ($1 eq 'string'))
{
$datatype .= "FIELDTYPE_STRING";
}
elsif (($1 eq 'int') || ($1 eq 'integer'))
{
$datatype .= "FIELDTYPE_INTEGER";
}
elsif (($1 eq 'bool') || ($1 eq 'boolean'))
{
$datatype .= "FIELDTYPE_BOOL";
}
else
{
die "Unknown datatype specification: \"{datatype=$1}\" in \"--_fielddef-<LANG>=...\"";
}

$_[0]->{'datatype'} = $datatype;
} ],
];

my $options =
[
[ qr/^--options=(.*)/, sub {
Expand Down Expand Up @@ -88,7 +114,7 @@ my $options =
$_[0]->{'versionCurrent'} = 0;
$_[0]->{'versionAge'} = 0;
$_[0]->{'foreignLanguages'} = [];
parse_flags ($rest, $_[0], $langdef_flags,);
parse_flags ($rest, $_[0], $langdef_flags);

return 1;
} ],
Expand Down Expand Up @@ -135,18 +161,22 @@ my $options =
push @{$_[0]->{'extradefs'}}, { name => $name, desc => $desc };
return 1;
} ],
[ qr/^--_fielddef-(.*)=([^,]+),([^\{]+)/, sub {
[ qr/^--_fielddef-(.*)=([^,]+),([^\{]+)(.*)/, sub {
die "Don't use --_fielddef-<LANG>=+ option before defining the language"
if (! defined $_[0]->{'langdef'});
die "Adding a field is allowed only to the language specified with --langdef: $1"
unless ($_[0]->{'langdef'} eq $1);

my $name = $2;
my $desc = $3;
my $rest = $4;
die "unacceptable character is used for field name: $name"
unless ($name =~ /^[a-zA-Z]+$/);

push @{$_[0]->{'fielddefs'}}, { name => $name, desc => $desc };
my $fdef = { name => $name, desc => $desc };
push @{$_[0]->{'fielddefs'}}, $fdef;
parse_flags ($rest, $fdef, $fielddef_flags);

return 1;
} ],
[ qr/^--_roledef-([^.]*)\.(?:([a-zA-Z])|\{([a-zA-Z][a-zA-Z0-9]*)\})=([a-zA-Z0-9]+),([^\{]+)/, sub {
Expand Down Expand Up @@ -1062,6 +1092,15 @@ EOF
.enabled = $enabled,
.name = "$_->{'name'}",
.description = "$desc",
EOF
if (defined $_->{'datatype'}) {
print <<EOF;
.dataType = $_->{'datatype'},
.getValueObject = getFieldValueGeneric,
.setValueObject = setFieldValueGeneric,
EOF
}
print <<EOF;
},
EOF
}
Expand Down

0 comments on commit 62467ec

Please sign in to comment.