diff --git a/Tmain/list-subparsers-all.d/stdout-expected.txt b/Tmain/list-subparsers-all.d/stdout-expected.txt index 95905bfff5..df2e74a39f 100644 --- a/Tmain/list-subparsers-all.d/stdout-expected.txt +++ b/Tmain/list-subparsers-all.d/stdout-expected.txt @@ -1,30 +1,31 @@ -#NAME BASEPARSER DIRECTIONS -AnsiblePlaybook Yaml base <> sub {bidirectional} -Ant XML base <> sub {bidirectional} -Autoconf M4 base <> sub {bidirectional} -Automake Make base <= sub {dedicated} -Bats Sh base <= sub {dedicated} -DBusIntrospect XML base <> sub {bidirectional} -FunctionParameters Perl base <> sub {bidirectional} -GemSpec Ruby base <= sub {dedicated} -Glade XML base <> sub {bidirectional} -IPythonCell Python base => sub {shared} -ITcl Tcl base <> sub {bidirectional} -Maven2 XML base <> sub {bidirectional} -Moose Perl base <> sub {bidirectional} -OpenAPI Yaml base <> sub {bidirectional} -PlistXML XML base <> sub {bidirectional} -PythonLoggingConfig Iniconf base <> sub {bidirectional} -QtMoc C++ base <> sub {bidirectional} -R6Class R base <> sub {bidirectional} -RMarkdown Markdown base <= sub {dedicated} -RSpec Ruby base => sub {shared} -Rake Ruby base <= sub {dedicated} -RelaxNG XML base <> sub {bidirectional} -S4Class R base <> sub {bidirectional} -SVG XML base <> sub {bidirectional} -SystemdUnit Iniconf base <= sub {dedicated} -TclOO Tcl base <> sub {bidirectional} -TeXBeamer Tex base <> sub {bidirectional} -XSLT XML base <> sub {bidirectional} -YumRepo Iniconf base <= sub {dedicated} +#NAME BASEPARSER DIRECTIONS +AnsiblePlaybook Yaml base <> sub {bidirectional} +Ant XML base <> sub {bidirectional} +Autoconf M4 base <> sub {bidirectional} +Automake Make base <= sub {dedicated} +Bats Sh base <= sub {dedicated} +DBusIntrospect XML base <> sub {bidirectional} +FunctionParameters Perl base <> sub {bidirectional} +GemSpec Ruby base <= sub {dedicated} +Glade XML base <> sub {bidirectional} +IPythonCell Python base => sub {shared} +ITcl Tcl base <> sub {bidirectional} +KernelDoc CPreProcessor base => sub {shared} +Maven2 XML base <> sub {bidirectional} +Moose Perl base <> sub {bidirectional} +OpenAPI Yaml base <> sub {bidirectional} +PlistXML XML base <> sub {bidirectional} +PythonLoggingConfig Iniconf base <> sub {bidirectional} +QtMoc C++ base <> sub {bidirectional} +R6Class R base <> sub {bidirectional} +RMarkdown Markdown base <= sub {dedicated} +RSpec Ruby base => sub {shared} +Rake Ruby base <= sub {dedicated} +RelaxNG XML base <> sub {bidirectional} +S4Class R base <> sub {bidirectional} +SVG XML base <> sub {bidirectional} +SystemdUnit Iniconf base <= sub {dedicated} +TclOO Tcl base <> sub {bidirectional} +TeXBeamer Tex base <> sub {bidirectional} +XSLT XML base <> sub {bidirectional} +YumRepo Iniconf base <= sub {dedicated} diff --git a/Units/parser-kerneldoc.r/dots-in-members.d/args.ctags b/Units/parser-kerneldoc.r/dots-in-members.d/args.ctags new file mode 100644 index 0000000000..7f2bb04f2b --- /dev/null +++ b/Units/parser-kerneldoc.r/dots-in-members.d/args.ctags @@ -0,0 +1,7 @@ +--sort=no +--languages=+KernelDoc +--fields=+Kl +--extras=+g +--kinds-KernelDoc=* +--kinds-C= +--kinds-CPreProcessor= diff --git a/Units/parser-kerneldoc.r/dots-in-members.d/expected.tags b/Units/parser-kerneldoc.r/dots-in-members.d/expected.tags new file mode 100644 index 0000000000..f0b3210829 --- /dev/null +++ b/Units/parser-kerneldoc.r/dots-in-members.d/expected.tags @@ -0,0 +1,13 @@ +dots in members input.c /^ * DOC: dots in members$/;" doc language:KernelDoc +nested_foobar input.c /^ * struct nested_foobar - a struct with nested unions and structs$/;" struct language:KernelDoc doc:dots in members +memb1 input.c /^ * @memb1: first member of anonymous union\/anonymous struct$/;" member language:KernelDoc struct:dots in members""nested_foobar +memb2 input.c /^ * @memb2: second member of anonymous union\/anonymous struct$/;" member language:KernelDoc struct:dots in members""nested_foobar +memb3 input.c /^ * @memb3: third member of anonymous union\/anonymous struct$/;" member language:KernelDoc struct:dots in members""nested_foobar +memb4 input.c /^ * @memb4: fourth member of anonymous union\/anonymous struct$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar input.c /^ * @bar: non-anonymous union$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st1 input.c /^ * @bar.st1: struct st1 inside @bar$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st2 input.c /^ * @bar.st2: struct st2 inside @bar$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st1.memb1 input.c /^ * @bar.st1.memb1: first member of struct st1 on union bar$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st1.memb2 input.c /^ * @bar.st1.memb2: second member of struct st1 on union bar$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st2.memb1 input.c /^ * @bar.st2.memb1: first member of struct st2 on union bar$/;" member language:KernelDoc struct:dots in members""nested_foobar +bar.st2.memb2 input.c /^ * @bar.st2.memb2: second member of struct st2 on union bar$/;" member language:KernelDoc struct:dots in members""nested_foobar diff --git a/Units/parser-kerneldoc.r/dots-in-members.d/input.c b/Units/parser-kerneldoc.r/dots-in-members.d/input.c new file mode 100644 index 0000000000..f6500b4c40 --- /dev/null +++ b/Units/parser-kerneldoc.r/dots-in-members.d/input.c @@ -0,0 +1,42 @@ +/* Taken from linux/Documentation/doc-guide/kernel-doc.rst */ +/** + * DOC: dots in members + */ + +/** + * struct nested_foobar - a struct with nested unions and structs + * @memb1: first member of anonymous union/anonymous struct + * @memb2: second member of anonymous union/anonymous struct + * @memb3: third member of anonymous union/anonymous struct + * @memb4: fourth member of anonymous union/anonymous struct + * @bar: non-anonymous union + * @bar.st1: struct st1 inside @bar + * @bar.st2: struct st2 inside @bar + * @bar.st1.memb1: first member of struct st1 on union bar + * @bar.st1.memb2: second member of struct st1 on union bar + * @bar.st2.memb1: first member of struct st2 on union bar + * @bar.st2.memb2: second member of struct st2 on union bar + */ +struct nested_foobar { + /* Anonymous union/struct*/ + union { + struct { + int memb1; + int memb2; + }; + struct { + void *memb3; + int memb4; + }; + }; + union { + struct { + int memb1; + int memb2; + } st1; + struct { + void *memb1; + int memb2; + } st2; + } bar; +}; diff --git a/Units/parser-kerneldoc.r/inline.d/args.ctags b/Units/parser-kerneldoc.r/inline.d/args.ctags new file mode 100644 index 0000000000..7f2bb04f2b --- /dev/null +++ b/Units/parser-kerneldoc.r/inline.d/args.ctags @@ -0,0 +1,7 @@ +--sort=no +--languages=+KernelDoc +--fields=+Kl +--extras=+g +--kinds-KernelDoc=* +--kinds-C= +--kinds-CPreProcessor= diff --git a/Units/parser-kerneldoc.r/inline.d/expected.tags b/Units/parser-kerneldoc.r/inline.d/expected.tags new file mode 100644 index 0000000000..564ff5073c --- /dev/null +++ b/Units/parser-kerneldoc.r/inline.d/expected.tags @@ -0,0 +1,8 @@ +in-line input.c /^ * DOC: in-line$/;" doc language:KernelDoc +foo input.c /^ * struct foo - Brief description.$/;" struct language:KernelDoc doc:in-line +foo input.c /^ * @foo: The Foo member.$/;" member language:KernelDoc struct:in-line""foo +bar input.c /^ * @bar: The Bar member.$/;" member language:KernelDoc struct:in-line""foo +baz input.c /^ * @baz: The Baz member.$/;" member language:KernelDoc struct:in-line""foo +foobar input.c /^ \/** @foobar: Single line description. *\/$/;" member language:KernelDoc struct:in-line""foo +bar2 input.c /^ \/** @bar2: Description for struct @bar2 inside @foo *\/$/;" member language:KernelDoc struct:in-line""foo +bar2.barbar input.c /^ * @bar2.barbar: Description for @barbar inside @foo.bar2$/;" member language:KernelDoc struct:in-line""foo diff --git a/Units/parser-kerneldoc.r/inline.d/input.c b/Units/parser-kerneldoc.r/inline.d/input.c new file mode 100644 index 0000000000..f6313b80ad --- /dev/null +++ b/Units/parser-kerneldoc.r/inline.d/input.c @@ -0,0 +1,33 @@ +/* Taken from linux/Documentation/doc-guide/kernel-doc.rst */ +/** + * DOC: in-line + */ + +/** + * struct foo - Brief description. + * @foo: The Foo member. + */ +struct foo { + int foo; + /** + * @bar: The Bar member. + */ + int bar; + /** + * @baz: The Baz member. + * + * Here, the member description may contain several paragraphs. + */ + int baz; + union { + /** @foobar: Single line description. */ + int foobar; + }; + /** @bar2: Description for struct @bar2 inside @foo */ + struct { + /** + * @bar2.barbar: Description for @barbar inside @foo.bar2 + */ + int barbar; + } bar2; +}; diff --git a/Units/parser-kerneldoc.r/simple.d/args.ctags b/Units/parser-kerneldoc.r/simple.d/args.ctags new file mode 100644 index 0000000000..7f2bb04f2b --- /dev/null +++ b/Units/parser-kerneldoc.r/simple.d/args.ctags @@ -0,0 +1,7 @@ +--sort=no +--languages=+KernelDoc +--fields=+Kl +--extras=+g +--kinds-KernelDoc=* +--kinds-C= +--kinds-CPreProcessor= diff --git a/Units/parser-kerneldoc.r/simple.d/expected.tags b/Units/parser-kerneldoc.r/simple.d/expected.tags new file mode 100644 index 0000000000..924aa2eb8a --- /dev/null +++ b/Units/parser-kerneldoc.r/simple.d/expected.tags @@ -0,0 +1,21 @@ +simple input.c /^ * DOC: simple$/;" doc language:KernelDoc +cpuhp_invoke_callback input.c /^ * cpuhp_invoke_callback - Invoke the callbacks for a given state$/;" unknown language:KernelDoc doc:simple +cpu input.c /^ * @cpu: The cpu for which the callback should be invoked$/;" parameter language:KernelDoc unknown:simple""cpuhp_invoke_callback +state input.c /^ * @state: The state to do callbacks for$/;" parameter language:KernelDoc unknown:simple""cpuhp_invoke_callback +bringup input.c /^ * @bringup: True if the bringup callback should be invoked$/;" parameter language:KernelDoc unknown:simple""cpuhp_invoke_callback +node input.c /^ * @node: For multi-instance, do a single entry callback for install\/remove$/;" parameter language:KernelDoc unknown:simple""cpuhp_invoke_callback +lastp input.c /^ * @lastp: For multi-instance rollback, remember how far we got$/;" parameter language:KernelDoc unknown:simple""cpuhp_invoke_callback +ACPI_DEVICE_CLASS input.c /^ * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with$/;" unknown language:KernelDoc doc:simple +_cls input.c /^ * @_cls : the class, subclass, prog-if triple for this device$/;" parameter language:KernelDoc unknown:simple""ACPI_DEVICE_CLASS +_msk input.c /^ * @_msk : the class mask for this device$/;" parameter language:KernelDoc unknown:simple""ACPI_DEVICE_CLASS +acpi_dma_spec input.c /^ * struct acpi_dma_spec - slave device DMA resources$/;" struct language:KernelDoc doc:simple +chan_id input.c /^ * @chan_id: channel unique id$/;" member language:KernelDoc struct:simple""acpi_dma_spec +slave_id input.c /^ * @slave_id: request line unique id$/;" member language:KernelDoc struct:simple""acpi_dma_spec +dev input.c /^ * @dev: struct device of the DMA controller to be used in the filter$/;" member language:KernelDoc struct:simple""acpi_dma_spec +dma_cookie_t input.c /^ * typedef dma_cookie_t - an opaque DMA cookie$/;" typedef language:KernelDoc doc:simple +coresight_dev_subtype input.c /^ * union coresight_dev_subtype - further characterisation of a type$/;" union language:KernelDoc doc:simple +sink_subtype input.c /^ * @sink_subtype: type of sink this component is, as defined$/;" member language:KernelDoc union:simple""coresight_dev_subtype +link_subtype input.c /^ * @link_subtype: type of link this component is, as defined$/;" member language:KernelDoc union:simple""coresight_dev_subtype +source_subtype input.c /^ * @source_subtype: type of source this component is, as defined$/;" member language:KernelDoc union:simple""coresight_dev_subtype +helper_subtype input.c /^ * @helper_subtype: type of helper this component is, as defined$/;" member language:KernelDoc union:simple""coresight_dev_subtype +ect_subtype input.c /^ * @ect_subtype: type of cross trigger this component is, as$/;" member language:KernelDoc union:simple""coresight_dev_subtype diff --git a/Units/parser-kerneldoc.r/simple.d/input.c b/Units/parser-kerneldoc.r/simple.d/input.c new file mode 100644 index 0000000000..6c25ab812e --- /dev/null +++ b/Units/parser-kerneldoc.r/simple.d/input.c @@ -0,0 +1,84 @@ +/* Taken from linux/kernel/cpu.c */ +/** + * DOC: simple + */ + +/** + * cpuhp_invoke_callback - Invoke the callbacks for a given state + * @cpu: The cpu for which the callback should be invoked + * @state: The state to do callbacks for + * @bringup: True if the bringup callback should be invoked + * @node: For multi-instance, do a single entry callback for install/remove + * @lastp: For multi-instance rollback, remember how far we got + * + * Called from cpu hotplug and from the state register machinery. + * + * Return: %0 on success or a negative errno code + */ +static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state, + bool bringup, struct hlist_node *node, + struct hlist_node **lastp) +{ + return 0; +} + +/* Taken from linux/include/linux/acpi.h */ +/** + * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with + * the PCI-defined class-code information + * + * @_cls : the class, subclass, prog-if triple for this device + * @_msk : the class mask for this device + * + * This macro is used to create a struct acpi_device_id that matches a + * specific PCI class. The .id and .driver_data fields will be left + * initialized with the default value. + */ +#define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (_cls), .cls_msk = (_msk), + +/* Taken from linux/include/linux/acpi_dma.h */ +/** + * struct acpi_dma_spec - slave device DMA resources + * @chan_id: channel unique id + * @slave_id: request line unique id + * @dev: struct device of the DMA controller to be used in the filter + * function + */ +struct acpi_dma_spec { + int chan_id; + int slave_id; + struct device *dev; +}; + +/* Taken from linux/include/linux/dmaengine.h */ +/** + * typedef dma_cookie_t - an opaque DMA cookie + * + * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code + */ +typedef s32 dma_cookie_t; + +/* Taken from linux/include/linux/coresight.h */ +/** + * union coresight_dev_subtype - further characterisation of a type + * @sink_subtype: type of sink this component is, as defined + * by @coresight_dev_subtype_sink. + * @link_subtype: type of link this component is, as defined + * by @coresight_dev_subtype_link. + * @source_subtype: type of source this component is, as defined + * by @coresight_dev_subtype_source. + * @helper_subtype: type of helper this component is, as defined + * by @coresight_dev_subtype_helper. + * @ect_subtype: type of cross trigger this component is, as + * defined by @coresight_dev_subtype_ect + */ +union coresight_dev_subtype { + /* We have some devices which acts as LINK and SINK */ + struct { + enum coresight_dev_subtype_sink sink_subtype; + enum coresight_dev_subtype_link link_subtype; + }; + enum coresight_dev_subtype_source source_subtype; + enum coresight_dev_subtype_helper helper_subtype; + enum coresight_dev_subtype_ect ect_subtype; +}; diff --git a/Units/parser-kerneldoc.r/typedef-with-prototype.d/args.ctags b/Units/parser-kerneldoc.r/typedef-with-prototype.d/args.ctags new file mode 100644 index 0000000000..7f2bb04f2b --- /dev/null +++ b/Units/parser-kerneldoc.r/typedef-with-prototype.d/args.ctags @@ -0,0 +1,7 @@ +--sort=no +--languages=+KernelDoc +--fields=+Kl +--extras=+g +--kinds-KernelDoc=* +--kinds-C= +--kinds-CPreProcessor= diff --git a/Units/parser-kerneldoc.r/typedef-with-prototype.d/expected.tags b/Units/parser-kerneldoc.r/typedef-with-prototype.d/expected.tags new file mode 100644 index 0000000000..728b4f9df0 --- /dev/null +++ b/Units/parser-kerneldoc.r/typedef-with-prototype.d/expected.tags @@ -0,0 +1,4 @@ +Typedefs with function prototypes input.c /^ * DOC: Typedefs with function prototypes$/;" doc language:KernelDoc +type_name input.c /^ * typedef type_name - Brief description.$/;" typedef language:KernelDoc doc:Typedefs with function prototypes +arg1 input.c /^ * @arg1: description of arg1$/;" parameter language:KernelDoc typedef:Typedefs with function prototypes""type_name +arg2 input.c /^ * @arg2: description of arg2$/;" parameter language:KernelDoc typedef:Typedefs with function prototypes""type_name diff --git a/Units/parser-kerneldoc.r/typedef-with-prototype.d/input.c b/Units/parser-kerneldoc.r/typedef-with-prototype.d/input.c new file mode 100644 index 0000000000..e5184e62a1 --- /dev/null +++ b/Units/parser-kerneldoc.r/typedef-with-prototype.d/input.c @@ -0,0 +1,16 @@ +/* Taken from linux/Documentation/doc-guide/kernel-doc.rst */ +/** + * DOC: Typedefs with function prototypes + */ + +/** + * typedef type_name - Brief description. + * @arg1: description of arg1 + * @arg2: description of arg2 + * + * Description of the type. + * + * Context: Locking context. + * Return: Meaning of the return value. + */ + typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2); diff --git a/docs/news.rst b/docs/news.rst index 464ed4b77c..1ee18793ef 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -429,6 +429,7 @@ The following parsers have been added: * JSON * Julia * Kconfig *optlib* +* KernelDoc *CPreProcessor based subparser" * Kotlin *peg/packcc* * GNU linker script(LdScript) * LEX *optlib* diff --git a/main/parsers_p.h b/main/parsers_p.h index faba51fb11..dcb7c4b9e1 100644 --- a/main/parsers_p.h +++ b/main/parsers_p.h @@ -115,6 +115,7 @@ JsonParser, \ JuliaParser, \ KconfigParser, \ + KernelDocParser, \ LdScriptParser, \ LEXParser, \ LispParser, \ diff --git a/parsers/kerneldoc.c b/parsers/kerneldoc.c new file mode 100644 index 0000000000..4ace3ceeaa --- /dev/null +++ b/parsers/kerneldoc.c @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2023, Masatake YAMATO + * Copyright (c) 2023, Red Hat, Inc. + * + * This source code is released for free distribution under the terms of the + * GNU General Public License version 2 or (at your option) any later version. + * + * This module contains functions for generating tags for kerledoc used in + * linux kernel. + * + * References: + * - https://www.kernel.org/doc/html/v4.9/kernel-documentation.html#writing-kernel-doc-comments + * - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/doc-guide/kernel-doc.rst + * - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/kernel-doc + */ + +#include "general.h" /* must always come first */ +#include "cpreprocessor.h" + +#include "entry.h" +#include "keyword.h" +#include "kind.h" +#include "parse.h" +#include "read.h" +#include "vstring.h" + +#include +#include + +static langType Lang_kerneldoc; + +typedef enum { + K_UNKNOWN, + K_STRUCT, + K_UNION, + K_ENUM, + K_TYPEDEF, + K_PARAM, + K_FUNCTION, + K_MEMBER, + K_ENUMERATOR, + K_DOC, +} kernelDocKind; + +static scopeSeparator KernelDocRootSeparators [] = { + { K_DOC, "\"\"" }, +}; + +static kindDefinition KernelDocKinds [] = { + { true, 'Y', "unknown", "unknown items", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 's', "struct", "struct names", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 'u', "union", "union names", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 'g', "enum", "enumeration names", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 't', "typedef", "typedefs", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 'z', "parameter", "parameters" }, + { true, 'f', "function", "functions and macros", + ATTACH_SEPARATORS(KernelDocRootSeparators) }, + { true, 'm', "member", "struct, and union members" }, + { true, 'e', "enumerator", "enumerators (values inside an enumeration)" }, + { true, 'd', "doc", "overviews marked with \"DOC:\"" }, +}; + +struct sKernelDocSubparser { + cPreProcessorSubparser cpp; + int doc; + int current; /* cork index */ +}; + +enum { + KEYWORD_struct, + KEYWORD_typedef, + KEYWORD_union, + KEYWORD_enum, +}; + +static const keywordTable KernelDocKeywordTable[] = { + { "struct", KEYWORD_struct }, + { "typedef", KEYWORD_typedef }, + { "union", KEYWORD_union }, + { "enum", KEYWORD_enum }, +}; + +static void findKernelDocTags (void) +{ + scheduleRunningBaseparser (0); +} + +static int parseFollowingAtmark (cPreProcessorSubparser *s, const char *c) +{ + int r = CORK_NIL; + vString *obj = vStringNew (); + + while (*c && *c != ':') + vStringPut (obj, *c++); + if (*c == ':' && !vStringIsEmpty (obj)) + { + tagEntryInfo e; + int kindex = K_PARAM; + int current = ((struct sKernelDocSubparser *)s)->current; + tagEntryInfo *parent = getEntryInCorkQueue (current); + + if (parent) + { + switch (parent->kindIndex) + { + case K_TYPEDEF: + case K_FUNCTION: + break; + case K_UNION: + case K_STRUCT: + kindex = K_MEMBER; + break; + case K_ENUM: + kindex = K_ENUMERATOR; + break; + } + } + initTagEntry (&e, vStringValue (obj), kindex); + e.extensionFields.scopeIndex = current; + r = makeTagEntry(&e); + } + vStringDelete (obj); + return r; +} + +static bool firstLineNotify (cPreProcessorSubparser *s, char firstchar, const char *line) +{ + int kind = K_UNKNOWN; + int r = CORK_NIL; + const char *c = line; + vString *obj = NULL; + + while (isspace((unsigned char)*c) || *c == '*') + c++; + + /* Handling in-line documentation. */ + if (((struct sKernelDocSubparser *)s)->current != CORK_NIL + && *c == '@') + { + c++; + if (parseFollowingAtmark (s, c) != CORK_NIL) + return true; + } + + obj = vStringNew (); + while (*c) + { + if (isspace((unsigned char)*c)) + { + int k = lookupKeyword (vStringValue (obj), Lang_kerneldoc); + if (k == KEYWORD_struct) + { + vStringClear(obj); + kind = K_STRUCT; + c++; + continue; + } + else if (k == KEYWORD_union) + { + vStringClear(obj); + kind = K_UNION; + c++; + continue; + + } + else if (k == KEYWORD_enum) + { + vStringClear(obj); + kind = K_ENUMERATOR; + c++; + continue; + + } + else if (k == KEYWORD_typedef) + { + vStringClear(obj); + kind = K_TYPEDEF; + c++; + continue; + } + else + { + c++; + break; + } + } + else if (*c == ':' && strcmp (vStringValue(obj), "DOC") == 0) + { + vStringClear(obj); + kind = K_DOC; + c++; + break; + } + vStringPut(obj, *c++); + } + + while (isspace((unsigned char)*c)) + c++; + + if (kind == K_DOC) + { + vStringCopyS(obj, c); + vStringStripTrailing(obj); + if (vStringLength(obj) > 0) + { + r = makeSimpleTag(obj, kind); + ((struct sKernelDocSubparser *)s)->doc = r; + goto out; + } + } + + size_t len = vStringLength(obj); + if (len > 2 + && (vStringChar(obj, len - 1) == ')') && (vStringChar(obj, len - 2) == '(')) + { + kind = K_FUNCTION; + vStringTruncate (obj, len - 2); + len -= 2; + } + + if (*c == '-' && isspace((unsigned char)*(c + 1)) && len > 0) + { + r = makeSimpleTag(obj, kind); + if (((struct sKernelDocSubparser *)s)->doc != CORK_NIL) + { + tagEntryInfo *e = getEntryInCorkQueue (r); + if (e) + e->extensionFields.scopeIndex = ((struct sKernelDocSubparser *)s)->doc; + } + ((struct sKernelDocSubparser *)s)->current = r; + } + + out: + vStringDelete(obj); + + return r != CORK_NIL; +} + +static void restLineNotify (cPreProcessorSubparser *s, const char *line) +{ + const char *c = line; + + while (isspace((unsigned char)*c) || *c == '*') + c++; + + if (*c == '@') + { + c++; + parseFollowingAtmark(s, c); + } +} + +static void endOfCommentNotify(cPreProcessorSubparser *s) +{ + int r = ((struct sKernelDocSubparser *)s)->current; + tagEntryInfo *e = getEntryInCorkQueue (r); + if (e) + e->extensionFields.endLine = getInputLineNumber (); +} + +static void initialize (const langType language) +{ + Lang_kerneldoc = language; +} + +static void inputStart (subparser *s) +{ + struct sKernelDocSubparser *kerneldoc = (struct sKernelDocSubparser*)s; + + kerneldoc->doc = CORK_NIL; + kerneldoc->current = CORK_NIL; +} + +extern parserDefinition* KernelDocParser (void) +{ + static struct sKernelDocSubparser kernelDocSubparser = { + .cpp = { + .subparser = { + .direction = SUBPARSER_BASE_RUNS_SUB, + .inputStart = inputStart, + .inputEnd = NULL, + }, + .firstLineNotify = firstLineNotify, + .restLineNotify = restLineNotify, + .endOfCommentNotify = endOfCommentNotify, + }, + }; + static parserDependency dependencies [] = { + { DEPTYPE_SUBPARSER, "CPreProcessor", &kernelDocSubparser }, + }; + + parserDefinition* def = parserNew ("KernelDoc"); + def->enabled = false; + + def->kindTable = KernelDocKinds; + def->kindCount = ARRAY_SIZE (KernelDocKinds); + + def->parser = findKernelDocTags; + def->initialize = initialize; + + def->dependencies = dependencies; + def->dependencyCount = ARRAY_SIZE (dependencies); + + def->keywordTable = KernelDocKeywordTable; + def->keywordCount = ARRAY_SIZE (KernelDocKeywordTable); + + def->useCork = CORK_QUEUE; + return def; +} diff --git a/source.mak b/source.mak index 9d54ca38fe..a83505f5b3 100644 --- a/source.mak +++ b/source.mak @@ -361,6 +361,7 @@ PARSER_SRCS = \ parsers/jscript.c \ parsers/json.c \ parsers/julia.c \ + parsers/kerneldoc.c \ parsers/ldscript.c \ parsers/lisp.c \ parsers/lua.c \ diff --git a/win32/ctags_vs2013.vcxproj b/win32/ctags_vs2013.vcxproj index 3327af28d0..42b018ea76 100644 --- a/win32/ctags_vs2013.vcxproj +++ b/win32/ctags_vs2013.vcxproj @@ -316,6 +316,7 @@ + diff --git a/win32/ctags_vs2013.vcxproj.filters b/win32/ctags_vs2013.vcxproj.filters index 4d552b9498..0685616d47 100644 --- a/win32/ctags_vs2013.vcxproj.filters +++ b/win32/ctags_vs2013.vcxproj.filters @@ -471,6 +471,9 @@ Source Files\parsers + + Source Files\parsers + Source Files\parsers