13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2000-2001, Max Ischenko <mfi@ukr.net>.
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 Lua language.
83ae02089SMasatake YAMATO */
93ae02089SMasatake YAMATO
103ae02089SMasatake YAMATO /*
113ae02089SMasatake YAMATO * INCLUDE FILES
123ae02089SMasatake YAMATO */
133ae02089SMasatake YAMATO #include "general.h" /* must always come first */
143ae02089SMasatake YAMATO
153ae02089SMasatake YAMATO #include <string.h>
163ae02089SMasatake YAMATO
171df886f0SMasatake YAMATO #include "debug.h"
189f9a097cSMasatake YAMATO #include "entry.h"
193ae02089SMasatake YAMATO #include "parse.h"
203ae02089SMasatake YAMATO #include "read.h"
213db72c21SMasatake YAMATO #include "routines.h"
223ae02089SMasatake YAMATO #include "vstring.h"
233ae02089SMasatake YAMATO
243ae02089SMasatake YAMATO /*
253ae02089SMasatake YAMATO * DATA DEFINITIONS
263ae02089SMasatake YAMATO */
273ae02089SMasatake YAMATO typedef enum {
289f9a097cSMasatake YAMATO K_FUNCTION,
299f9a097cSMasatake YAMATO K_UNKNOWN,
303ae02089SMasatake YAMATO } luaKind;
313ae02089SMasatake YAMATO
329f9a097cSMasatake YAMATO typedef enum {
339f9a097cSMasatake YAMATO LUA_UNKNOWN_REFERENCED,
349f9a097cSMasatake YAMATO } luaUnknownRole;
359f9a097cSMasatake YAMATO
369f9a097cSMasatake YAMATO static roleDefinition LuaUnknownRoles [] = {
379f9a097cSMasatake YAMATO { false, "referenced", "referenced somehow" },
389f9a097cSMasatake YAMATO };
399f9a097cSMasatake YAMATO
40e112e8abSMasatake YAMATO static kindDefinition LuaKinds [] = {
419f9a097cSMasatake YAMATO { true, 'f', "function", "functions" },
429f9a097cSMasatake YAMATO
439f9a097cSMasatake YAMATO /* `unknown' is a kind just for making FQ tag for functions. */
449f9a097cSMasatake YAMATO { false, 'X', "unknown", "unknown language object",
459f9a097cSMasatake YAMATO .referenceOnly = true, ATTACH_ROLES(LuaUnknownRoles) },
463ae02089SMasatake YAMATO };
473ae02089SMasatake YAMATO
483ae02089SMasatake YAMATO /*
493ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
503ae02089SMasatake YAMATO */
513ae02089SMasatake YAMATO
523ae02089SMasatake YAMATO /*
533ae02089SMasatake YAMATO * Helper function.
543ae02089SMasatake YAMATO * Returns 1 if line looks like a line of Lua code.
553ae02089SMasatake YAMATO *
563ae02089SMasatake YAMATO * TODO: Recognize UNIX bang notation.
573ae02089SMasatake YAMATO * (Lua treat first line as a comment if it starts with #!)
583ae02089SMasatake YAMATO *
593ae02089SMasatake YAMATO */
is_a_code_line(const unsigned char * line)60ce990805SThomas Braun static bool is_a_code_line (const unsigned char *line)
613ae02089SMasatake YAMATO {
62ce990805SThomas Braun bool result;
633ae02089SMasatake YAMATO const unsigned char *p = line;
643ae02089SMasatake YAMATO while (isspace ((int) *p))
653ae02089SMasatake YAMATO p++;
663ae02089SMasatake YAMATO if (p [0] == '\0')
67ce990805SThomas Braun result = false;
683ae02089SMasatake YAMATO else if (p [0] == '-' && p [1] == '-')
69ce990805SThomas Braun result = false;
703ae02089SMasatake YAMATO else
71ce990805SThomas Braun result = true;
723ae02089SMasatake YAMATO return result;
733ae02089SMasatake YAMATO }
743ae02089SMasatake YAMATO
isLuaIdentifier(char c)75ce990805SThomas Braun static bool isLuaIdentifier (char c)
763ae02089SMasatake YAMATO {
77*93b3d55cSMasatake YAMATO return (bool) !(isspace(c) || c == '(' || c == ')' || c == '=' || c == '.' || c == ':'
78*93b3d55cSMasatake YAMATO || c == '{' || c == '}');
79d88f3cdeSMasatake YAMATO }
80d88f3cdeSMasatake YAMATO
set_scope(int child,int parent)819f9a097cSMasatake YAMATO static void set_scope (int child, int parent)
829f9a097cSMasatake YAMATO {
839f9a097cSMasatake YAMATO if (parent == CORK_NIL || child == CORK_NIL)
849f9a097cSMasatake YAMATO return;
859f9a097cSMasatake YAMATO
869f9a097cSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (child);
879f9a097cSMasatake YAMATO if (!e)
889f9a097cSMasatake YAMATO return;
899f9a097cSMasatake YAMATO
909f9a097cSMasatake YAMATO e->extensionFields.scopeIndex = parent;
919f9a097cSMasatake YAMATO }
929f9a097cSMasatake YAMATO
extract_next_token(const char * begin,const char * end_sentinel,vString * name)93d88f3cdeSMasatake YAMATO static void extract_next_token (const char *begin, const char *end_sentinel, vString *name)
943ae02089SMasatake YAMATO {
95d88f3cdeSMasatake YAMATO if (begin == NULL || end_sentinel == NULL)
96d88f3cdeSMasatake YAMATO return;
97d88f3cdeSMasatake YAMATO
981df886f0SMasatake YAMATO Assert (begin <= end_sentinel);
991df886f0SMasatake YAMATO
1001df886f0SMasatake YAMATO /* Both on '(' */
1011df886f0SMasatake YAMATO if (begin == end_sentinel)
102d88f3cdeSMasatake YAMATO return;
1033ae02089SMasatake YAMATO
1041df886f0SMasatake YAMATO /* Trim prefixed white spaces */
1053ae02089SMasatake YAMATO while (isspace ((int) *begin))
106d88f3cdeSMasatake YAMATO begin++;
1071df886f0SMasatake YAMATO
1081df886f0SMasatake YAMATO /* Both on '(' */
1091df886f0SMasatake YAMATO if (begin == end_sentinel)
1101df886f0SMasatake YAMATO return;
1111df886f0SMasatake YAMATO
1121df886f0SMasatake YAMATO const char *end = end_sentinel - 1;
1131df886f0SMasatake YAMATO
1141df886f0SMasatake YAMATO /* Trim suffixed white spaces */
1151df886f0SMasatake YAMATO while (isspace ((int) *end))
1161df886f0SMasatake YAMATO end--;
1171df886f0SMasatake YAMATO
1181df886f0SMasatake YAMATO Assert (begin <= end);
1191df886f0SMasatake YAMATO
1209f9a097cSMasatake YAMATO int lastCorkIndx = CORK_NIL;
1211df886f0SMasatake YAMATO for (const char *c = begin; c <= end; ++c)
1221df886f0SMasatake YAMATO {
123bf8189b4SGregory Anders if (*c == '.' || *c == ':')
124bf8189b4SGregory Anders {
1259f9a097cSMasatake YAMATO int r = makeSimpleRefTag(name,
1269f9a097cSMasatake YAMATO K_UNKNOWN, LUA_UNKNOWN_REFERENCED);
1279f9a097cSMasatake YAMATO set_scope(r, lastCorkIndx);
1289f9a097cSMasatake YAMATO lastCorkIndx = r;
1299f9a097cSMasatake YAMATO
130bf8189b4SGregory Anders /* Do not include module names in function name */
131bf8189b4SGregory Anders vStringClear (name);
132bf8189b4SGregory Anders }
133bf8189b4SGregory Anders else if (isLuaIdentifier (*c))
1341df886f0SMasatake YAMATO vStringPut (name, (int) *c);
1351df886f0SMasatake YAMATO else
1361df886f0SMasatake YAMATO {
1371df886f0SMasatake YAMATO /* An unexpected character is found
1381df886f0SMasatake YAMATO * between "function" and "(" */
1391df886f0SMasatake YAMATO vStringClear (name);
140d88f3cdeSMasatake YAMATO return;
141d88f3cdeSMasatake YAMATO }
142d88f3cdeSMasatake YAMATO }
143d88f3cdeSMasatake YAMATO
1449f9a097cSMasatake YAMATO int d = makeSimpleTag (name, K_FUNCTION);
1459f9a097cSMasatake YAMATO set_scope(d, lastCorkIndx);
1463ae02089SMasatake YAMATO vStringClear (name);
1473ae02089SMasatake YAMATO }
148d88f3cdeSMasatake YAMATO
extract_prev_token(const char * end,const char * begin_sentinel,vString * name)149d88f3cdeSMasatake YAMATO static void extract_prev_token (const char *end, const char *begin_sentinel, vString *name)
150d88f3cdeSMasatake YAMATO {
151d88f3cdeSMasatake YAMATO const char *begin;
152d88f3cdeSMasatake YAMATO
153d88f3cdeSMasatake YAMATO if (end == NULL || begin_sentinel == NULL)
154d88f3cdeSMasatake YAMATO return;
155d88f3cdeSMasatake YAMATO
156d88f3cdeSMasatake YAMATO if (! (begin_sentinel <= end))
157d88f3cdeSMasatake YAMATO return;
158d88f3cdeSMasatake YAMATO
159d88f3cdeSMasatake YAMATO while (isspace ((int) *end))
160d88f3cdeSMasatake YAMATO {
161d88f3cdeSMasatake YAMATO end--;
162d88f3cdeSMasatake YAMATO if (! (begin_sentinel <= end))
163d88f3cdeSMasatake YAMATO return;
164d88f3cdeSMasatake YAMATO }
165d88f3cdeSMasatake YAMATO
166d88f3cdeSMasatake YAMATO begin = end;
167d88f3cdeSMasatake YAMATO while (begin_sentinel <= begin && isLuaIdentifier (*begin))
168d88f3cdeSMasatake YAMATO begin--;
169d88f3cdeSMasatake YAMATO
1709f9a097cSMasatake YAMATO int targetCorkIndex = CORK_NIL;
171d88f3cdeSMasatake YAMATO if (end - begin)
172d88f3cdeSMasatake YAMATO {
173d88f3cdeSMasatake YAMATO vStringNCatS (name, begin + 1, end - begin);
1749f9a097cSMasatake YAMATO targetCorkIndex = makeSimpleTag (name, K_FUNCTION);
175d88f3cdeSMasatake YAMATO vStringClear (name);
1763ae02089SMasatake YAMATO }
1779f9a097cSMasatake YAMATO
1789f9a097cSMasatake YAMATO if (targetCorkIndex == CORK_NIL || begin_sentinel == begin)
1799f9a097cSMasatake YAMATO return;
1809f9a097cSMasatake YAMATO
1819f9a097cSMasatake YAMATO /* Fill the scope field of the function. */
1829f9a097cSMasatake YAMATO end = begin;
1839f9a097cSMasatake YAMATO while (begin_sentinel <= (begin + 1))
1849f9a097cSMasatake YAMATO {
1859f9a097cSMasatake YAMATO bool on_boundary = false;
1869f9a097cSMasatake YAMATO if (begin < begin_sentinel || !isLuaIdentifier (*begin))
1879f9a097cSMasatake YAMATO {
1889f9a097cSMasatake YAMATO if (end - begin)
1899f9a097cSMasatake YAMATO {
1909f9a097cSMasatake YAMATO vStringNCatS (name, begin + 1, end - begin);
1919f9a097cSMasatake YAMATO int r = makeSimpleRefTag (name,
1929f9a097cSMasatake YAMATO K_UNKNOWN, LUA_UNKNOWN_REFERENCED);
1939f9a097cSMasatake YAMATO set_scope (targetCorkIndex, r);
1949f9a097cSMasatake YAMATO targetCorkIndex = r;
1959f9a097cSMasatake YAMATO vStringClear (name);
1969f9a097cSMasatake YAMATO }
1979f9a097cSMasatake YAMATO if (begin_sentinel <= begin && ! (*begin == ':' || *begin == '.'))
1989f9a097cSMasatake YAMATO break;
1999f9a097cSMasatake YAMATO on_boundary = true;
2009f9a097cSMasatake YAMATO }
2019f9a097cSMasatake YAMATO begin--;
2029f9a097cSMasatake YAMATO
2039f9a097cSMasatake YAMATO if(on_boundary)
2049f9a097cSMasatake YAMATO end = begin;
2059f9a097cSMasatake YAMATO }
2063ae02089SMasatake YAMATO }
2073ae02089SMasatake YAMATO
findLuaTags(void)2083ae02089SMasatake YAMATO static void findLuaTags (void)
2093ae02089SMasatake YAMATO {
2103ae02089SMasatake YAMATO vString *name = vStringNew ();
2113ae02089SMasatake YAMATO const unsigned char *line;
2123ae02089SMasatake YAMATO
2131b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
2143ae02089SMasatake YAMATO {
2153ae02089SMasatake YAMATO const char *p, *q;
2163ae02089SMasatake YAMATO
2173ae02089SMasatake YAMATO if (! is_a_code_line (line))
2183ae02089SMasatake YAMATO continue;
2193ae02089SMasatake YAMATO
2203ae02089SMasatake YAMATO p = (const char*) strstr ((const char*) line, "function");
2213ae02089SMasatake YAMATO if (p == NULL)
2223ae02089SMasatake YAMATO continue;
2233ae02089SMasatake YAMATO
2243ae02089SMasatake YAMATO q = strchr ((const char*) line, '=');
2253ae02089SMasatake YAMATO
2263ae02089SMasatake YAMATO if (q == NULL) {
2271df886f0SMasatake YAMATO p = p + 8; /* skip the `function' word */
2281df886f0SMasatake YAMATO
2291df886f0SMasatake YAMATO /* We expect [ \t(] */
2301df886f0SMasatake YAMATO if (! (*p == '(' || isspace ((int)*p)))
2311df886f0SMasatake YAMATO continue;
2323ae02089SMasatake YAMATO q = strchr ((const char*) p, '(');
233d88f3cdeSMasatake YAMATO if (q)
234d88f3cdeSMasatake YAMATO extract_next_token (p, q, name);
2352fb42ce6SMasatake YAMATO } else if (
2362fb42ce6SMasatake YAMATO (*(q+1) != '=') /* ignore `if type(v) == "function" then ...' */
2372fb42ce6SMasatake YAMATO && (q < p) /* ignore "function" ~= */
2382fb42ce6SMasatake YAMATO ) {
2393ae02089SMasatake YAMATO p = (const char*) &line[0];
240d88f3cdeSMasatake YAMATO if (p < q)
241d88f3cdeSMasatake YAMATO extract_prev_token (q - 1, p, name);
2423ae02089SMasatake YAMATO }
2433ae02089SMasatake YAMATO }
2443ae02089SMasatake YAMATO vStringDelete (name);
2453ae02089SMasatake YAMATO }
2463ae02089SMasatake YAMATO
LuaParser(void)2473ae02089SMasatake YAMATO extern parserDefinition* LuaParser (void)
2483ae02089SMasatake YAMATO {
2493ae02089SMasatake YAMATO static const char* const extensions [] = { "lua", NULL };
2503ae02089SMasatake YAMATO parserDefinition* def = parserNew ("Lua");
25109ae690fSMasatake YAMATO def->kindTable = LuaKinds;
2523db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (LuaKinds);
2533ae02089SMasatake YAMATO def->extensions = extensions;
2543ae02089SMasatake YAMATO def->parser = findLuaTags;
2559f9a097cSMasatake YAMATO def->useCork = CORK_QUEUE;
2569f9a097cSMasatake YAMATO def->requestAutomaticFQTag = true;
2573ae02089SMasatake YAMATO return def;
2583ae02089SMasatake YAMATO }
259