13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2003, Brent Fulgham <bfulgham@debian.org>
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO * This module contains functions for generating tags for Erlang language
83ae02089SMasatake YAMATO * files. Some of the parsing constructs are based on the Emacs 'etags'
93ae02089SMasatake YAMATO * program by Francesco Potori <pot@gnu.org>
103ae02089SMasatake YAMATO */
113ae02089SMasatake YAMATO /*
123ae02089SMasatake YAMATO * INCLUDE FILES
133ae02089SMasatake YAMATO */
143ae02089SMasatake YAMATO #include "general.h" /* must always come first */
153ae02089SMasatake YAMATO
163ae02089SMasatake YAMATO #include <string.h>
173ae02089SMasatake YAMATO
183ae02089SMasatake YAMATO #include "entry.h"
193ae02089SMasatake YAMATO #include "read.h"
20*0d502ef0SMasatake YAMATO #include "parse.h"
213ae02089SMasatake YAMATO #include "routines.h"
223ae02089SMasatake YAMATO #include "vstring.h"
233ae02089SMasatake YAMATO
243ae02089SMasatake YAMATO /*
253ae02089SMasatake YAMATO * DATA DEFINITIONS
263ae02089SMasatake YAMATO */
273ae02089SMasatake YAMATO typedef enum {
283ae02089SMasatake YAMATO K_MACRO, K_FUNCTION, K_MODULE, K_RECORD, K_TYPE
293ae02089SMasatake YAMATO } erlangKind;
303ae02089SMasatake YAMATO
31e112e8abSMasatake YAMATO static kindDefinition ErlangKinds[] = {
32ce990805SThomas Braun {true, 'd', "macro", "macro definitions"},
33ce990805SThomas Braun {true, 'f', "function", "functions"},
34ce990805SThomas Braun {true, 'm', "module", "modules"},
35ce990805SThomas Braun {true, 'r', "record", "record definitions"},
36ce990805SThomas Braun {true, 't', "type", "type definitions"},
373ae02089SMasatake YAMATO };
383ae02089SMasatake YAMATO
393ae02089SMasatake YAMATO /*
403ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
413ae02089SMasatake YAMATO */
423ae02089SMasatake YAMATO /* tagEntryInfo and vString should be preinitialized/preallocated but not
433ae02089SMasatake YAMATO * necessary. If successful you will find class name in vString
443ae02089SMasatake YAMATO */
453ae02089SMasatake YAMATO
isIdentifierFirstCharacter(int c)46ce990805SThomas Braun static bool isIdentifierFirstCharacter (int c)
473ae02089SMasatake YAMATO {
48ce990805SThomas Braun return (bool) (isalpha (c));
493ae02089SMasatake YAMATO }
503ae02089SMasatake YAMATO
isIdentifierCharacter(int c)51ce990805SThomas Braun static bool isIdentifierCharacter (int c)
523ae02089SMasatake YAMATO {
53ce990805SThomas Braun return (bool) (isalnum (c) || c == '_' || c == ':');
543ae02089SMasatake YAMATO }
553ae02089SMasatake YAMATO
skipSpace(const unsigned char * cp)563ae02089SMasatake YAMATO static const unsigned char *skipSpace (const unsigned char *cp)
573ae02089SMasatake YAMATO {
583ae02089SMasatake YAMATO while (isspace ((int) *cp))
593ae02089SMasatake YAMATO ++cp;
603ae02089SMasatake YAMATO return cp;
613ae02089SMasatake YAMATO }
623ae02089SMasatake YAMATO
parseIdentifier(const unsigned char * cp,vString * const identifier)633ae02089SMasatake YAMATO static const unsigned char *parseIdentifier (
643ae02089SMasatake YAMATO const unsigned char *cp, vString *const identifier)
653ae02089SMasatake YAMATO {
663ae02089SMasatake YAMATO vStringClear (identifier);
673ae02089SMasatake YAMATO while (isIdentifierCharacter ((int) *cp))
683ae02089SMasatake YAMATO {
693ae02089SMasatake YAMATO vStringPut (identifier, (int) *cp);
703ae02089SMasatake YAMATO ++cp;
713ae02089SMasatake YAMATO }
723ae02089SMasatake YAMATO return cp;
733ae02089SMasatake YAMATO }
743ae02089SMasatake YAMATO
makeMemberTag(vString * const identifier,erlangKind kind,vString * const module)753ae02089SMasatake YAMATO static void makeMemberTag (
763ae02089SMasatake YAMATO vString *const identifier, erlangKind kind, vString *const module)
773ae02089SMasatake YAMATO {
783ae02089SMasatake YAMATO if (ErlangKinds [kind].enabled && vStringLength (identifier) > 0)
793ae02089SMasatake YAMATO {
803ae02089SMasatake YAMATO tagEntryInfo tag;
8116a2541cSMasatake YAMATO initTagEntry (&tag, vStringValue (identifier), kind);
823ae02089SMasatake YAMATO
833ae02089SMasatake YAMATO if (module != NULL && vStringLength (module) > 0)
843ae02089SMasatake YAMATO {
85f92e6bf2SMasatake YAMATO tag.extensionFields.scopeKindIndex = K_MODULE;
86015ab54cSMasatake YAMATO tag.extensionFields.scopeName = vStringValue (module);
873ae02089SMasatake YAMATO }
883ae02089SMasatake YAMATO makeTagEntry (&tag);
893ae02089SMasatake YAMATO }
903ae02089SMasatake YAMATO }
913ae02089SMasatake YAMATO
parseModuleTag(const unsigned char * cp,vString * const module)923ae02089SMasatake YAMATO static void parseModuleTag (const unsigned char *cp, vString *const module)
933ae02089SMasatake YAMATO {
943ae02089SMasatake YAMATO vString *const identifier = vStringNew ();
953ae02089SMasatake YAMATO parseIdentifier (cp, identifier);
9616a2541cSMasatake YAMATO makeSimpleTag (identifier, K_MODULE);
973ae02089SMasatake YAMATO
983ae02089SMasatake YAMATO /* All further entries go in the new module */
993ae02089SMasatake YAMATO vStringCopy (module, identifier);
1003ae02089SMasatake YAMATO vStringDelete (identifier);
1013ae02089SMasatake YAMATO }
1023ae02089SMasatake YAMATO
parseSimpleTag(const unsigned char * cp,erlangKind kind)1033ae02089SMasatake YAMATO static void parseSimpleTag (const unsigned char *cp, erlangKind kind)
1043ae02089SMasatake YAMATO {
1053ae02089SMasatake YAMATO vString *const identifier = vStringNew ();
1063ae02089SMasatake YAMATO parseIdentifier (cp, identifier);
10716a2541cSMasatake YAMATO makeSimpleTag (identifier, kind);
1083ae02089SMasatake YAMATO vStringDelete (identifier);
1093ae02089SMasatake YAMATO }
1103ae02089SMasatake YAMATO
parseFunctionTag(const unsigned char * cp,vString * const module)1113ae02089SMasatake YAMATO static void parseFunctionTag (const unsigned char *cp, vString *const module)
1123ae02089SMasatake YAMATO {
1133ae02089SMasatake YAMATO vString *const identifier = vStringNew ();
1143ae02089SMasatake YAMATO parseIdentifier (cp, identifier);
1153ae02089SMasatake YAMATO makeMemberTag (identifier, K_FUNCTION, module);
1163ae02089SMasatake YAMATO vStringDelete (identifier);
1173ae02089SMasatake YAMATO }
1183ae02089SMasatake YAMATO
1193ae02089SMasatake YAMATO /*
1203ae02089SMasatake YAMATO * Directives are of the form:
1213ae02089SMasatake YAMATO * -module(foo)
1223ae02089SMasatake YAMATO * -define(foo, bar)
1233ae02089SMasatake YAMATO * -record(graph, {vtab = notable, cyclic = true}).
1243ae02089SMasatake YAMATO * -type some_type() :: any().
1253ae02089SMasatake YAMATO * -opaque some_opaque_type() :: any().
1263ae02089SMasatake YAMATO */
parseDirective(const unsigned char * cp,vString * const module)1273ae02089SMasatake YAMATO static void parseDirective (const unsigned char *cp, vString *const module)
1283ae02089SMasatake YAMATO {
1293ae02089SMasatake YAMATO /*
1303ae02089SMasatake YAMATO * A directive will be either a record definition or a directive.
1313ae02089SMasatake YAMATO * Record definitions are handled separately
1323ae02089SMasatake YAMATO */
1333ae02089SMasatake YAMATO vString *const directive = vStringNew ();
1343ae02089SMasatake YAMATO const char *const drtv = vStringValue (directive);
1353ae02089SMasatake YAMATO cp = parseIdentifier (cp, directive);
1363ae02089SMasatake YAMATO cp = skipSpace (cp);
1373ae02089SMasatake YAMATO if (*cp == '(')
1383ae02089SMasatake YAMATO ++cp;
1393ae02089SMasatake YAMATO
1403ae02089SMasatake YAMATO if (strcmp (drtv, "record") == 0)
1413ae02089SMasatake YAMATO parseSimpleTag (cp, K_RECORD);
1423ae02089SMasatake YAMATO else if (strcmp (drtv, "define") == 0)
1433ae02089SMasatake YAMATO parseSimpleTag (cp, K_MACRO);
1443ae02089SMasatake YAMATO else if (strcmp (drtv, "type") == 0)
1453ae02089SMasatake YAMATO parseSimpleTag (cp, K_TYPE);
1463ae02089SMasatake YAMATO else if (strcmp (drtv, "opaque") == 0)
1473ae02089SMasatake YAMATO parseSimpleTag (cp, K_TYPE);
1483ae02089SMasatake YAMATO else if (strcmp (drtv, "module") == 0)
1493ae02089SMasatake YAMATO parseModuleTag (cp, module);
1503ae02089SMasatake YAMATO /* Otherwise, it was an import, export, etc. */
1513ae02089SMasatake YAMATO
1523ae02089SMasatake YAMATO vStringDelete (directive);
1533ae02089SMasatake YAMATO }
1543ae02089SMasatake YAMATO
findErlangTags(void)1553ae02089SMasatake YAMATO static void findErlangTags (void)
1563ae02089SMasatake YAMATO {
1573ae02089SMasatake YAMATO vString *const module = vStringNew ();
1583ae02089SMasatake YAMATO const unsigned char *line;
1593ae02089SMasatake YAMATO
1601b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
1613ae02089SMasatake YAMATO {
1623ae02089SMasatake YAMATO const unsigned char *cp = line;
1633ae02089SMasatake YAMATO
1643ae02089SMasatake YAMATO if (*cp == '%') /* skip initial comment */
1653ae02089SMasatake YAMATO continue;
1663ae02089SMasatake YAMATO if (*cp == '"') /* strings sometimes start in column one */
1673ae02089SMasatake YAMATO continue;
1683ae02089SMasatake YAMATO
1693ae02089SMasatake YAMATO if ( *cp == '-')
1703ae02089SMasatake YAMATO {
1713ae02089SMasatake YAMATO ++cp; /* Move off of the '-' */
1723ae02089SMasatake YAMATO parseDirective(cp, module);
1733ae02089SMasatake YAMATO }
1743ae02089SMasatake YAMATO else if (isIdentifierFirstCharacter ((int) *cp))
1753ae02089SMasatake YAMATO parseFunctionTag (cp, module);
1763ae02089SMasatake YAMATO }
1773ae02089SMasatake YAMATO vStringDelete (module);
1783ae02089SMasatake YAMATO }
1793ae02089SMasatake YAMATO
ErlangParser(void)1803ae02089SMasatake YAMATO extern parserDefinition *ErlangParser (void)
1813ae02089SMasatake YAMATO {
1823ae02089SMasatake YAMATO static const char *const extensions[] = { "erl", "ERL", "hrl", "HRL", NULL };
1833ae02089SMasatake YAMATO parserDefinition *def = parserNew ("Erlang");
18409ae690fSMasatake YAMATO def->kindTable = ErlangKinds;
1853db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (ErlangKinds);
1863ae02089SMasatake YAMATO def->extensions = extensions;
1873ae02089SMasatake YAMATO def->parser = findErlangTags;
1883ae02089SMasatake YAMATO return def;
1893ae02089SMasatake YAMATO }
190