xref: /Universal-ctags/old-docs/EXTENDING.html (revision cfc45e3bd9000e8ce193399c7e0ecf2bbeb57977)
194eb5533SMasatake YAMATO<html>
294eb5533SMasatake YAMATO<head>
394eb5533SMasatake YAMATO<title>Exuberant Ctags: Adding support for a new language</title>
494eb5533SMasatake YAMATO</head>
594eb5533SMasatake YAMATO<body>
694eb5533SMasatake YAMATO
794eb5533SMasatake YAMATO<h1>How to Add Support for a New Language to Exuberant Ctags</h1>
894eb5533SMasatake YAMATO
994eb5533SMasatake YAMATO<p>
1094eb5533SMasatake YAMATO<b>Exuberant Ctags</b> has been designed to make it very easy to add your own
1194eb5533SMasatake YAMATOcustom language parser. As an exercise, let us assume that I want to add
1294eb5533SMasatake YAMATOsupport for my new language, <em>Swine</em>, the successor to Perl (i.e. Perl
1394eb5533SMasatake YAMATObefore Swine &lt;wince&gt;). This language consists of simple definitions of
1494eb5533SMasatake YAMATOlabels in the form "<code>def my_label</code>". Let us now examine the various
1594eb5533SMasatake YAMATOways to do this.
1694eb5533SMasatake YAMATO</p>
1794eb5533SMasatake YAMATO
1894eb5533SMasatake YAMATO<h2>Operational background</h2>
1994eb5533SMasatake YAMATO
2094eb5533SMasatake YAMATO<p>
2194eb5533SMasatake YAMATOAs ctags considers each file name, it tries to determine the language of the
2294eb5533SMasatake YAMATOfile by applying the following three tests in order: if the file extension has
2394eb5533SMasatake YAMATObeen mapped to a language, if the file name matches a shell pattern mapped to
2494eb5533SMasatake YAMATOa language, and finally if the file is executable and its first line specifies
2594eb5533SMasatake YAMATOan interpreter using the Unix-style "#!" specification (if supported on the
2694eb5533SMasatake YAMATOplatform). If a language was identified, the file is opened and then the
2794eb5533SMasatake YAMATOappropriate language parser is called to operate on the currently open file.
2894eb5533SMasatake YAMATOThe parser parses through the file and whenever it finds some interesting
2994eb5533SMasatake YAMATOtoken, calls a function to define a tag entry.
3094eb5533SMasatake YAMATO</p>
3194eb5533SMasatake YAMATO
3294eb5533SMasatake YAMATO<h2>Creating a user-defined language</h2>
3394eb5533SMasatake YAMATO
3494eb5533SMasatake YAMATO<p>
3594eb5533SMasatake YAMATOThe quickest and easiest way to do this is by defining a new language using
3694eb5533SMasatake YAMATOthe program options. In order to have Swine support available every time I
3794eb5533SMasatake YAMATOstart ctags, I will place the following lines into the file
3894eb5533SMasatake YAMATO<code>$HOME/.ctags</code>, which is read in every time ctags starts:
3994eb5533SMasatake YAMATO
4094eb5533SMasatake YAMATO<code>
4194eb5533SMasatake YAMATO<pre>
4294eb5533SMasatake YAMATO  --langdef=swine
4394eb5533SMasatake YAMATO  --langmap=swine:.swn
4494eb5533SMasatake YAMATO  --regex-swine=/^def[ \t]*([a-zA-Z0-9_]+)/\1/d,definition/
4594eb5533SMasatake YAMATO</pre>
4694eb5533SMasatake YAMATO</code>
4794eb5533SMasatake YAMATOThe first line defines the new language, the second maps a file extension to
4894eb5533SMasatake YAMATOit, and the third defines a regular expression to identify a language
4994eb5533SMasatake YAMATOdefinition and generate a tag file entry for it.
5094eb5533SMasatake YAMATO</p>
5194eb5533SMasatake YAMATO
5294eb5533SMasatake YAMATO<h2>Integrating a new language parser</h2>
5394eb5533SMasatake YAMATO
5494eb5533SMasatake YAMATO<p>
5594eb5533SMasatake YAMATONow suppose that I want to truly integrate compiled-in support for Swine into
5694eb5533SMasatake YAMATOctags. First, I create a new module, <code>swine.c</code>, and add one
5794eb5533SMasatake YAMATOexternally visible function to it, <code>extern parserDefinition
5894eb5533SMasatake YAMATO*SwineParser(void)</code>, and add its name to the table in
5994eb5533SMasatake YAMATO<code>parsers.h</code>. The job of this parser definition function is to
6094eb5533SMasatake YAMATOcreate an instance of the <code>parserDefinition</code> structure (using
6194eb5533SMasatake YAMATO<code>parserNew()</code>) and populate it with information defining how files
6294eb5533SMasatake YAMATOof this language are recognized, what kinds of tags it can locate, and the
6394eb5533SMasatake YAMATOfunction used to invoke the parser on the currently open file.
6494eb5533SMasatake YAMATO</p>
6594eb5533SMasatake YAMATO
6694eb5533SMasatake YAMATO<p>
6794eb5533SMasatake YAMATOThe structure <code>parserDefinition</code> allows assignment of the following
6894eb5533SMasatake YAMATOfields:
6994eb5533SMasatake YAMATO
7094eb5533SMasatake YAMATO<code>
7194eb5533SMasatake YAMATO<pre>
7294eb5533SMasatake YAMATO  const char *name;               /* name of language */
7394eb5533SMasatake YAMATO  kindOption *kinds;              /* tag kinds handled by parser */
7494eb5533SMasatake YAMATO  unsigned int kindCount;         /* size of `kinds' list */
7594eb5533SMasatake YAMATO  const char *const *extensions;  /* list of default extensions */
7694eb5533SMasatake YAMATO  const char *const *patterns;    /* list of default file name patterns */
7794eb5533SMasatake YAMATO  parserInitialize initialize;    /* initialization routine, if needed */
7894eb5533SMasatake YAMATO  simpleParser parser;            /* simple parser (common case) */
7994eb5533SMasatake YAMATO  rescanParser parser2;           /* rescanning parser (unusual case) */
8094eb5533SMasatake YAMATO  boolean regex;                  /* is this a regex parser? */
8194eb5533SMasatake YAMATO</pre>
8294eb5533SMasatake YAMATO</code>
8394eb5533SMasatake YAMATO</p>
8494eb5533SMasatake YAMATO
8594eb5533SMasatake YAMATO<p>
8694eb5533SMasatake YAMATOThe <code>name</code> field must be set to a non-empty string. Also, unless
8794eb5533SMasatake YAMATO<code>regex</code> is set true (see below), either <code>parser</code> or
8894eb5533SMasatake YAMATO<code>parser2</code> must set to point to a parsing routine which will
8994eb5533SMasatake YAMATOgenerate the tag entries. All other fields are optional.
9094eb5533SMasatake YAMATO
9194eb5533SMasatake YAMATO<p>
9294eb5533SMasatake YAMATONow all that is left is to implement the parser. In order to do its job, the
9394eb5533SMasatake YAMATOparser should read the file stream using using one of the two I/O interfaces:
9494eb5533SMasatake YAMATOeither the character-oriented <code>fileGetc()</code>, or the line-oriented
9594eb5533SMasatake YAMATO<code>fileReadLine()</code>. When using <code>fileGetc()</code>, the parser
9694eb5533SMasatake YAMATOcan put back a character using <code>fileUngetc()</code>. How our Swine parser
9794eb5533SMasatake YAMATOactually parses the contents of the file is entirely up to the writer of the
9894eb5533SMasatake YAMATOparser--it can be as crude or elegant as desired. You will note a variety of
9994eb5533SMasatake YAMATOexamples from the most complex (c.c) to the simplest (make.c).
10094eb5533SMasatake YAMATO</p>
10194eb5533SMasatake YAMATO
10294eb5533SMasatake YAMATO<p>
10394eb5533SMasatake YAMATOWhen the Swine parser identifies an interesting token for which it wants to
10494eb5533SMasatake YAMATOadd a tag to the tag file, it should create a <code>tagEntryInfo</code>
10594eb5533SMasatake YAMATOstructure and initialize it by calling <code>initTagEntry()</code>, which
10694eb5533SMasatake YAMATOinitializes defaults and fills information about the current line number and
10794eb5533SMasatake YAMATOthe file position of the beginning of the line. After filling in information
10894eb5533SMasatake YAMATOdefining the current entry (and possibly overriding the file position or other
10994eb5533SMasatake YAMATOdefaults), the parser passes this structure to <code>makeTagEntry()</code>.
11094eb5533SMasatake YAMATO</p>
11194eb5533SMasatake YAMATO
11294eb5533SMasatake YAMATO<p>
11394eb5533SMasatake YAMATOInstead of writing a character-oriented parser, it may be possible to specify
11494eb5533SMasatake YAMATOregular expressions which define the tags. In this case, instead of defining a
11594eb5533SMasatake YAMATOparsing function, <code>SwineParser()</code>, sets <code>regex</code> to true,
11694eb5533SMasatake YAMATOand points <code>initialize</code> to a function which calls
11794eb5533SMasatake YAMATO<code>addTagRegex()</code> to install the regular expressions which define its
11894eb5533SMasatake YAMATOtags. The regular expressions thus installed are compared against each line
11994eb5533SMasatake YAMATOof the input file and generate a specified tag when matched. It is usually
12094eb5533SMasatake YAMATOmuch easier to write a regex-based parser, although they can be slower (one
12194eb5533SMasatake YAMATOparser example was 4 times slower). Whether the speed difference matters to
12294eb5533SMasatake YAMATOyou depends upon how much code you have to parse. It is probably a good
12394eb5533SMasatake YAMATOstrategy to implement a regex-based parser first, and if it is too slow for
12494eb5533SMasatake YAMATOyou, then invest the time and effort to write a character-based parser.
12594eb5533SMasatake YAMATO</p>
12694eb5533SMasatake YAMATO
12794eb5533SMasatake YAMATO<p>
12894eb5533SMasatake YAMATOA regex-based parser is inherently line-oriented (i.e. the entire tag must be
12994eb5533SMasatake YAMATOrecognizable from looking at a single line) and context-insensitive (i.e the
13094eb5533SMasatake YAMATOgeneration of the tag is entirely based upon when the regular expression
13194eb5533SMasatake YAMATOmatches a single line). However, a regex-based callback mechanism is also
13294eb5533SMasatake YAMATOavailable, installed via the function <code>addCallbackRegex()</code>. This
13394eb5533SMasatake YAMATOallows a specified function to be invoked whenever a specific regular
13494eb5533SMasatake YAMATOexpression is matched. This allows a character-oriented parser to operate
13594eb5533SMasatake YAMATObased upon context of what happened on a previous line (e.g. the start or end
13694eb5533SMasatake YAMATOof a multi-line comment). Note that regex callbacks are called just before the
13794eb5533SMasatake YAMATOfirst character of that line can is read via either <code>fileGetc()</code> or
13894eb5533SMasatake YAMATOusing <code>fileGetc()</code>. The effect of this is that before either of
13994eb5533SMasatake YAMATOthese routines return, a callback routine may be invoked because the line
14094eb5533SMasatake YAMATOmatched a regex callback. A callback function to be installed is defined by
14194eb5533SMasatake YAMATOthese types:
14294eb5533SMasatake YAMATO
14394eb5533SMasatake YAMATO<code>
14494eb5533SMasatake YAMATO<pre>
14594eb5533SMasatake YAMATO  typedef void (*regexCallback) (const char *line, const regexMatch *matches, unsigned int count);
14694eb5533SMasatake YAMATO
14794eb5533SMasatake YAMATO  typedef struct {
14894eb5533SMasatake YAMATO      size_t start;   /* character index in line where match starts */
14994eb5533SMasatake YAMATO      size_t length;  /* length of match */
15094eb5533SMasatake YAMATO  } regexMatch;
15194eb5533SMasatake YAMATO</pre>
15294eb5533SMasatake YAMATO</code>
15394eb5533SMasatake YAMATO</p>
15494eb5533SMasatake YAMATO
15594eb5533SMasatake YAMATO<p>
15694eb5533SMasatake YAMATOThe callback function is passed the line matching the regular expression and
15794eb5533SMasatake YAMATOan array of <code>count</code> structures defining the subexpression matches
15894eb5533SMasatake YAMATOof the regular expression, starting from \0 (the entire line).
15994eb5533SMasatake YAMATO</p>
16094eb5533SMasatake YAMATO
16194eb5533SMasatake YAMATO<p>
16294eb5533SMasatake YAMATOLastly, be sure to add your the name of the file containing your parser (e.g.
16394eb5533SMasatake YAMATOswine.c) to the macro <code>SOURCES</code> in the file <code>source.mak</code>
16494eb5533SMasatake YAMATOand an entry for the object file to the macro <code>OBJECTS</code> in the same
16594eb5533SMasatake YAMATOfile, so that your new module will be compiled into the program.
16694eb5533SMasatake YAMATO</p>
16794eb5533SMasatake YAMATO
16894eb5533SMasatake YAMATO<p>
16994eb5533SMasatake YAMATOIn case you have some problems run <code>ctags --verbose</code> to see if the
17094eb5533SMasatake YAMATOextensions or patterns you defined for your language conflict with other
17194eb5533SMasatake YAMATOlanguages.
17294eb5533SMasatake YAMATO</p>
17394eb5533SMasatake YAMATO
17494eb5533SMasatake YAMATO<p>
17594eb5533SMasatake YAMATOThis is all there is to it. All other details are specific to the parser and
17694eb5533SMasatake YAMATOhow it wants to do its job. There are some support functions which can take
17794eb5533SMasatake YAMATOcare of some commonly needed parsing tasks, such as keyword table lookups (see
17894eb5533SMasatake YAMATOkeyword.c), which you can make use of if desired (examples of its use can be
17994eb5533SMasatake YAMATOfound in c.c, eiffel.c, and fortran.c). Almost everything is already taken care
18094eb5533SMasatake YAMATOof automatically for you by the infrastructure.  Writing the actual parsing
18194eb5533SMasatake YAMATOalgorithm is the hardest part, but is not constrained by any need to conform
18294eb5533SMasatake YAMATOto anything in ctags other than that mentioned above.
18394eb5533SMasatake YAMATO</p>
18494eb5533SMasatake YAMATO
18594eb5533SMasatake YAMATO<p>
18694eb5533SMasatake YAMATOThere are several different approaches used in the parsers inside <b>Exuberant
18794eb5533SMasatake YAMATOCtags</b> and you can browse through these as examples of how to go about
18894eb5533SMasatake YAMATOcreating your own.
18994eb5533SMasatake YAMATO</p>
19094eb5533SMasatake YAMATO
19194eb5533SMasatake YAMATO<h2>Examples</h2>
19294eb5533SMasatake YAMATO
19394eb5533SMasatake YAMATO<p>
19494eb5533SMasatake YAMATOBelow you will find several example parsers demonstrating most of the
19594eb5533SMasatake YAMATOfacilities available. These include three alternative implementations
19694eb5533SMasatake YAMATOof a Swine parser, which generate tags for lines beginning with
19794eb5533SMasatake YAMATO"<code>def</code>" followed by some name.
19894eb5533SMasatake YAMATO</p>
19994eb5533SMasatake YAMATO
20094eb5533SMasatake YAMATO<code>
20194eb5533SMasatake YAMATO<pre>
20294eb5533SMasatake YAMATO/***************************************************************************
20394eb5533SMasatake YAMATO * swine.c
20494eb5533SMasatake YAMATO * Character-based parser for Swine definitions
20594eb5533SMasatake YAMATO **************************************************************************/
20694eb5533SMasatake YAMATO/* INCLUDE FILES */
20794eb5533SMasatake YAMATO#include "general.h"    /* always include first */
20894eb5533SMasatake YAMATO
20994eb5533SMasatake YAMATO#include &lt;string.h&gt;     /* to declare strxxx() functions */
21094eb5533SMasatake YAMATO#include &lt;ctype.h&gt;      /* to define isxxx() macros */
21194eb5533SMasatake YAMATO
21294eb5533SMasatake YAMATO#include "parse.h"      /* always include */
21394eb5533SMasatake YAMATO#include "read.h"       /* to define file fileReadLine() */
21494eb5533SMasatake YAMATO
21594eb5533SMasatake YAMATO/* DATA DEFINITIONS */
21694eb5533SMasatake YAMATOtypedef enum eSwineKinds {
21794eb5533SMasatake YAMATO    K_DEFINE
21894eb5533SMasatake YAMATO} swineKind;
21994eb5533SMasatake YAMATO
22094eb5533SMasatake YAMATOstatic kindOption SwineKinds [] = {
22194eb5533SMasatake YAMATO    { TRUE, 'd', "definition", "pig definition" }
22294eb5533SMasatake YAMATO};
22394eb5533SMasatake YAMATO
22494eb5533SMasatake YAMATO/* FUNCTION DEFINITIONS */
22594eb5533SMasatake YAMATO
22694eb5533SMasatake YAMATOstatic void findSwineTags (void)
22794eb5533SMasatake YAMATO{
22894eb5533SMasatake YAMATO    vString *name = vStringNew ();
22994eb5533SMasatake YAMATO    const unsigned char *line;
23094eb5533SMasatake YAMATO
23194eb5533SMasatake YAMATO    while ((line = fileReadLine ()) != NULL)
23294eb5533SMasatake YAMATO    {
23394eb5533SMasatake YAMATO        /* Look for a line beginning with "def" followed by name */
23494eb5533SMasatake YAMATO        if (strncmp ((const char*) line, "def", (size_t) 3) == 0  &amp;&amp;
23594eb5533SMasatake YAMATO            isspace ((int) line [3]))
23694eb5533SMasatake YAMATO        {
23794eb5533SMasatake YAMATO            const unsigned char *cp = line + 4;
23894eb5533SMasatake YAMATO            while (isspace ((int) *cp))
23994eb5533SMasatake YAMATO                ++cp;
24094eb5533SMasatake YAMATO            while (isalnum ((int) *cp)  ||  *cp == '_')
24194eb5533SMasatake YAMATO            {
24294eb5533SMasatake YAMATO                vStringPut (name, (int) *cp);
24394eb5533SMasatake YAMATO                ++cp;
24494eb5533SMasatake YAMATO            }
24594eb5533SMasatake YAMATO            makeSimpleTag (name, SwineKinds, K_DEFINE);
24694eb5533SMasatake YAMATO            vStringClear (name);
24794eb5533SMasatake YAMATO        }
24894eb5533SMasatake YAMATO    }
24994eb5533SMasatake YAMATO    vStringDelete (name);
25094eb5533SMasatake YAMATO}
25194eb5533SMasatake YAMATO
25294eb5533SMasatake YAMATO/* Create parser definition stucture */
25394eb5533SMasatake YAMATOextern parserDefinition* SwineParser (void)
25494eb5533SMasatake YAMATO{
25594eb5533SMasatake YAMATO    static const char *const extensions [] = { "swn", NULL };
25694eb5533SMasatake YAMATO    parserDefinition* def = parserNew ("Swine");
25794eb5533SMasatake YAMATO    def-&gt;kinds      = SwineKinds;
25894eb5533SMasatake YAMATO    def-&gt;kindCount  = KIND_COUNT (SwineKinds);
25994eb5533SMasatake YAMATO    def-&gt;extensions = extensions;
26094eb5533SMasatake YAMATO    def-&gt;parser     = findSwineTags;
26194eb5533SMasatake YAMATO    return def;
26294eb5533SMasatake YAMATO}
26394eb5533SMasatake YAMATO</pre>
26494eb5533SMasatake YAMATO</code>
26594eb5533SMasatake YAMATO
26694eb5533SMasatake YAMATO<p>
26794eb5533SMasatake YAMATO<pre>
26894eb5533SMasatake YAMATO<code>
26994eb5533SMasatake YAMATO/***************************************************************************
27094eb5533SMasatake YAMATO * swine.c
27194eb5533SMasatake YAMATO * Regex-based parser for Swine
27294eb5533SMasatake YAMATO **************************************************************************/
27394eb5533SMasatake YAMATO/* INCLUDE FILES */
27494eb5533SMasatake YAMATO#include "general.h"    /* always include first */
27594eb5533SMasatake YAMATO#include "parse.h"      /* always include */
27694eb5533SMasatake YAMATO
27794eb5533SMasatake YAMATO/* FUNCTION DEFINITIONS */
27894eb5533SMasatake YAMATO
27994eb5533SMasatake YAMATOstatic void installSwineRegex (const langType language)
28094eb5533SMasatake YAMATO{
28194eb5533SMasatake YAMATO    addTagRegex (language, "^def[ \t]*([a-zA-Z0-9_]+)", "\\1", "d,definition", NULL);
28294eb5533SMasatake YAMATO}
28394eb5533SMasatake YAMATO
28494eb5533SMasatake YAMATO/* Create parser definition stucture */
28594eb5533SMasatake YAMATOextern parserDefinition* SwineParser (void)
28694eb5533SMasatake YAMATO{
28794eb5533SMasatake YAMATO    static const char *const extensions [] = { "swn", NULL };
28894eb5533SMasatake YAMATO    parserDefinition* def = parserNew ("Swine");
28994eb5533SMasatake YAMATO    def-&gt;patterns   = patterns;
29094eb5533SMasatake YAMATO    def-&gt;extensions = extensions;
29194eb5533SMasatake YAMATO    def-&gt;initialize = installSwineRegex;
29294eb5533SMasatake YAMATO    def-&gt;regex      = TRUE;
29394eb5533SMasatake YAMATO    return def;
29494eb5533SMasatake YAMATO}
29594eb5533SMasatake YAMATO</code>
29694eb5533SMasatake YAMATO</pre>
29794eb5533SMasatake YAMATO
29894eb5533SMasatake YAMATO<p>
29994eb5533SMasatake YAMATO<pre>
30094eb5533SMasatake YAMATO/***************************************************************************
30194eb5533SMasatake YAMATO * swine.c
30294eb5533SMasatake YAMATO * Regex callback-based parser for Swine definitions
30394eb5533SMasatake YAMATO **************************************************************************/
30494eb5533SMasatake YAMATO/* INCLUDE FILES */
30594eb5533SMasatake YAMATO#include "general.h"    /* always include first */
30694eb5533SMasatake YAMATO
30794eb5533SMasatake YAMATO#include "parse.h"      /* always include */
30894eb5533SMasatake YAMATO#include "read.h"       /* to define file fileReadLine() */
30994eb5533SMasatake YAMATO
31094eb5533SMasatake YAMATO/* DATA DEFINITIONS */
31194eb5533SMasatake YAMATOtypedef enum eSwineKinds {
31294eb5533SMasatake YAMATO    K_DEFINE
31394eb5533SMasatake YAMATO} swineKind;
31494eb5533SMasatake YAMATO
31594eb5533SMasatake YAMATOstatic kindOption SwineKinds [] = {
31694eb5533SMasatake YAMATO    { TRUE, 'd', "definition", "pig definition" }
31794eb5533SMasatake YAMATO};
31894eb5533SMasatake YAMATO
31994eb5533SMasatake YAMATO/* FUNCTION DEFINITIONS */
32094eb5533SMasatake YAMATO
32194eb5533SMasatake YAMATOstatic void definition (const char *const line, const regexMatch *const matches,
32294eb5533SMasatake YAMATO                       const unsigned int count)
32394eb5533SMasatake YAMATO{
32494eb5533SMasatake YAMATO    if (count &gt; 1)    /* should always be true per regex */
32594eb5533SMasatake YAMATO    {
32694eb5533SMasatake YAMATO        vString *const name = vStringNew ();
32794eb5533SMasatake YAMATO        vStringNCopyS (name, line + matches [1].start, matches [1].length);
32894eb5533SMasatake YAMATO        makeSimpleTag (name, SwineKinds, K_DEFINE);
32994eb5533SMasatake YAMATO    }
33094eb5533SMasatake YAMATO}
33194eb5533SMasatake YAMATO
33294eb5533SMasatake YAMATOstatic void findSwineTags (void)
33394eb5533SMasatake YAMATO{
33494eb5533SMasatake YAMATO    while (fileReadLine () != NULL)
33594eb5533SMasatake YAMATO        ;  /* don't need to do anything here since callback is sufficient */
33694eb5533SMasatake YAMATO}
33794eb5533SMasatake YAMATO
33894eb5533SMasatake YAMATOstatic void installSwine (const langType language)
33994eb5533SMasatake YAMATO{
34094eb5533SMasatake YAMATO    addCallbackRegex (language, "^def[ \t]+([a-zA-Z0-9_]+)", NULL, definition);
34194eb5533SMasatake YAMATO}
34294eb5533SMasatake YAMATO
34394eb5533SMasatake YAMATO/* Create parser definition stucture */
34494eb5533SMasatake YAMATOextern parserDefinition* SwineParser (void)
34594eb5533SMasatake YAMATO{
34694eb5533SMasatake YAMATO    static const char *const extensions [] = { "swn", NULL };
34794eb5533SMasatake YAMATO    parserDefinition* def = parserNew ("Swine");
34894eb5533SMasatake YAMATO    def-&gt;kinds      = SwineKinds;
349*a9bab3f0SMasatake YAMATO    def-&gt;kindCount  = COUNT_ARRAY (SwineKinds);
35094eb5533SMasatake YAMATO    def-&gt;extensions = extensions;
35194eb5533SMasatake YAMATO    def-&gt;parser     = findSwineTags;
35294eb5533SMasatake YAMATO    def-&gt;initialize = installSwine;
35394eb5533SMasatake YAMATO    return def;
35494eb5533SMasatake YAMATO}
35594eb5533SMasatake YAMATO</pre>
35694eb5533SMasatake YAMATO
35794eb5533SMasatake YAMATO<p>
35894eb5533SMasatake YAMATO<pre>
35994eb5533SMasatake YAMATO/***************************************************************************
36094eb5533SMasatake YAMATO * make.c
36194eb5533SMasatake YAMATO * Regex-based parser for makefile macros
36294eb5533SMasatake YAMATO **************************************************************************/
36394eb5533SMasatake YAMATO/* INCLUDE FILES */
36494eb5533SMasatake YAMATO#include "general.h"    /* always include first */
36594eb5533SMasatake YAMATO#include "parse.h"      /* always include */
36694eb5533SMasatake YAMATO
36794eb5533SMasatake YAMATO/* FUNCTION DEFINITIONS */
36894eb5533SMasatake YAMATO
36994eb5533SMasatake YAMATOstatic void installMakefileRegex (const langType language)
37094eb5533SMasatake YAMATO{
37194eb5533SMasatake YAMATO    addTagRegex (language, "(^|[ \t])([A-Z0-9_]+)[ \t]*:?=", "\\2", "m,macro", "i");
37294eb5533SMasatake YAMATO}
37394eb5533SMasatake YAMATO
37494eb5533SMasatake YAMATO/* Create parser definition stucture */
37594eb5533SMasatake YAMATOextern parserDefinition* MakefileParser (void)
37694eb5533SMasatake YAMATO{
37794eb5533SMasatake YAMATO    static const char *const patterns [] = { "[Mm]akefile", NULL };
37894eb5533SMasatake YAMATO    static const char *const extensions [] = { "mak", NULL };
37994eb5533SMasatake YAMATO    parserDefinition* const def = parserNew ("Makefile");
38094eb5533SMasatake YAMATO    def-&gt;patterns   = patterns;
38194eb5533SMasatake YAMATO    def-&gt;extensions = extensions;
38294eb5533SMasatake YAMATO    def-&gt;initialize = installMakefileRegex;
38394eb5533SMasatake YAMATO    def-&gt;regex      = TRUE;
38494eb5533SMasatake YAMATO    return def;
38594eb5533SMasatake YAMATO}
38694eb5533SMasatake YAMATO</pre>
38794eb5533SMasatake YAMATO
38894eb5533SMasatake YAMATO</body>
38994eb5533SMasatake YAMATO</html>
390