13ae02089SMasatake YAMATO /*
2e05c2c11SMasatake YAMATO * Copyright (c) 1999-2000, Mjølner Informatics
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * Written by Erik Corry <corry@mjolner.dk>
53ae02089SMasatake YAMATO *
63ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
70ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
83ae02089SMasatake YAMATO *
93ae02089SMasatake YAMATO * This module contains functions for generating tags for BETA language
103ae02089SMasatake YAMATO * files.
113ae02089SMasatake YAMATO */
123ae02089SMasatake YAMATO
133ae02089SMasatake YAMATO /*
143ae02089SMasatake YAMATO * INCLUDE FILES
153ae02089SMasatake YAMATO */
163ae02089SMasatake YAMATO #include "general.h" /* must always come first */
173ae02089SMasatake YAMATO
183ae02089SMasatake YAMATO #include <string.h>
193ae02089SMasatake YAMATO
203ae02089SMasatake YAMATO #include "entry.h"
213ae02089SMasatake YAMATO #include "parse.h"
223ae02089SMasatake YAMATO #include "read.h"
233ae02089SMasatake YAMATO #include "routines.h"
243ae02089SMasatake YAMATO #include "vstring.h"
253ae02089SMasatake YAMATO
263ae02089SMasatake YAMATO /*
273ae02089SMasatake YAMATO * MACROS
283ae02089SMasatake YAMATO */
293ae02089SMasatake YAMATO #define isbident(c) (identarray [(unsigned char) (c)])
303ae02089SMasatake YAMATO
313ae02089SMasatake YAMATO /*
323ae02089SMasatake YAMATO * DATA DEFINITIONS
333ae02089SMasatake YAMATO */
343ae02089SMasatake YAMATO typedef enum {
353ae02089SMasatake YAMATO K_FRAGMENT, K_PATTERN, K_SLOT, K_VIRTUAL
363ae02089SMasatake YAMATO } betaKind;
373ae02089SMasatake YAMATO
38e112e8abSMasatake YAMATO static kindDefinition BetaKinds [] = {
39ce990805SThomas Braun { true, 'f', "fragment", "fragment definitions"},
40ce990805SThomas Braun { false, 'p', "pattern", "all patterns"},
41ce990805SThomas Braun { true, 's', "slot", "slots (fragment uses)"},
42ce990805SThomas Braun { true, 'v', "virtual", "patterns (virtual or rebound)"}
433ae02089SMasatake YAMATO };
443ae02089SMasatake YAMATO
453ae02089SMasatake YAMATO /* [A-Z_a-z0-9] */
463ae02089SMasatake YAMATO static const char identarray [256] = {
473ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
483ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
493ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32-47 !"#$%&'()*+'-./ */
503ae02089SMasatake YAMATO 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 0123456789:;<=>? */
513ae02089SMasatake YAMATO 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 @ABCDEFGHIJKLMNO */
523ae02089SMasatake YAMATO 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 PQRSTUVWXYZ [\]^_ */
533ae02089SMasatake YAMATO 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 `abcdefghijklmno */
543ae02089SMasatake YAMATO 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 pqrstuvwxyz{|}~ */
553ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128- */
563ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
573ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
583ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
593ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
603ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
613ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
623ae02089SMasatake YAMATO 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -255 */
633ae02089SMasatake YAMATO
643ae02089SMasatake YAMATO /*
653ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
663ae02089SMasatake YAMATO */
673ae02089SMasatake YAMATO
makeBetaTag(const char * const name,const betaKind kind)683ae02089SMasatake YAMATO static void makeBetaTag (const char* const name, const betaKind kind)
693ae02089SMasatake YAMATO {
703ae02089SMasatake YAMATO if (BetaKinds [kind].enabled)
713ae02089SMasatake YAMATO {
723ae02089SMasatake YAMATO tagEntryInfo e;
73*16a2541cSMasatake YAMATO initTagEntry (&e, name, kind);
743ae02089SMasatake YAMATO makeTagEntry (&e);
753ae02089SMasatake YAMATO }
763ae02089SMasatake YAMATO }
773ae02089SMasatake YAMATO
findBetaTags(void)783ae02089SMasatake YAMATO static void findBetaTags (void)
793ae02089SMasatake YAMATO {
803ae02089SMasatake YAMATO vString *line = vStringNew ();
81ce990805SThomas Braun bool incomment = false;
82ce990805SThomas Braun bool inquote = false;
83ce990805SThomas Braun bool dovirtuals = BetaKinds [K_VIRTUAL].enabled;
84ce990805SThomas Braun bool dopatterns = BetaKinds [K_PATTERN].enabled;
853ae02089SMasatake YAMATO
86188fd4caSMasatake YAMATO int c;
873ae02089SMasatake YAMATO do
883ae02089SMasatake YAMATO {
89ce990805SThomas Braun bool foundfragmenthere = false;
903ae02089SMasatake YAMATO /* find fragment definition (line that starts and ends with --) */
913ae02089SMasatake YAMATO int last;
923ae02089SMasatake YAMATO int first;
933ae02089SMasatake YAMATO
943ae02089SMasatake YAMATO vStringClear (line);
953ae02089SMasatake YAMATO
96018bce0bSMasatake YAMATO while ((c = getcFromInputFile ()) != EOF && c != '\n' && c != '\r')
973ae02089SMasatake YAMATO vStringPut (line, c);
983ae02089SMasatake YAMATO
993ae02089SMasatake YAMATO last = vStringLength (line) - 1;
1003ae02089SMasatake YAMATO first = 0;
1013ae02089SMasatake YAMATO /* skip white space at start and end of line */
1023ae02089SMasatake YAMATO while (last > 0 && isspace ((int) vStringChar (line, last))) last--;
1033ae02089SMasatake YAMATO while (first < last && isspace ((int) vStringChar (line, first))) first++;
1043ae02089SMasatake YAMATO /* if line still has a reasonable length and ... */
1053ae02089SMasatake YAMATO if (last - first > 4 &&
1063ae02089SMasatake YAMATO (vStringChar (line, first) == '-' &&
1073ae02089SMasatake YAMATO vStringChar (line, first + 1) == '-' &&
1083ae02089SMasatake YAMATO vStringChar (line, last) == '-' &&
1093ae02089SMasatake YAMATO vStringChar (line, last - 1) == '-'))
1103ae02089SMasatake YAMATO {
1113ae02089SMasatake YAMATO if (!incomment && !inquote)
1123ae02089SMasatake YAMATO {
113ce990805SThomas Braun foundfragmenthere = true;
1143ae02089SMasatake YAMATO /* skip past -- and whitespace. Also skip back past 'dopart'
1153ae02089SMasatake YAMATO or 'attributes' to the :. We have to do this because there
1163ae02089SMasatake YAMATO is no sensible way to include whitespace in a ctags token
1173ae02089SMasatake YAMATO so the conventional space after the ':' would mess us up */
1183ae02089SMasatake YAMATO last -= 2;
1193ae02089SMasatake YAMATO first += 2;
1203ae02089SMasatake YAMATO while (last && vStringChar (line, last) != ':') last--;
1213ae02089SMasatake YAMATO while (last && (isspace ((int) vStringChar (line, last-1)))) last--;
1223ae02089SMasatake YAMATO while (first < last &&
1233ae02089SMasatake YAMATO (isspace ((int) vStringChar (line, first)) ||
1243ae02089SMasatake YAMATO vStringChar (line, first) == '-'))
1253ae02089SMasatake YAMATO first++;
1263ae02089SMasatake YAMATO /* If there's anything left it is a fragment title */
1273ae02089SMasatake YAMATO if (first < last - 1)
1283ae02089SMasatake YAMATO {
1293ae02089SMasatake YAMATO vStringChar (line, last) = 0;
1303ae02089SMasatake YAMATO if (strcasecmp ("LIB", vStringValue (line) + first) &&
1313ae02089SMasatake YAMATO strcasecmp ("PROGRAM", vStringValue (line) + first))
1323ae02089SMasatake YAMATO {
1333ae02089SMasatake YAMATO makeBetaTag (vStringValue (line) + first, K_FRAGMENT);
1343ae02089SMasatake YAMATO }
1353ae02089SMasatake YAMATO }
1363ae02089SMasatake YAMATO }
1373ae02089SMasatake YAMATO } else {
1383ae02089SMasatake YAMATO int pos = 0;
1393ae02089SMasatake YAMATO int len = vStringLength (line);
1403ae02089SMasatake YAMATO if (inquote) goto stringtext;
1413ae02089SMasatake YAMATO if (incomment) goto commenttext;
1423ae02089SMasatake YAMATO programtext:
1433ae02089SMasatake YAMATO for ( ; pos < len; pos++)
1443ae02089SMasatake YAMATO {
1453ae02089SMasatake YAMATO if (vStringChar (line, pos) == '\'')
1463ae02089SMasatake YAMATO {
1473ae02089SMasatake YAMATO pos++;
148ce990805SThomas Braun inquote = true;
1493ae02089SMasatake YAMATO goto stringtext;
1503ae02089SMasatake YAMATO }
1513ae02089SMasatake YAMATO if (vStringChar (line, pos) == '{')
1523ae02089SMasatake YAMATO {
1533ae02089SMasatake YAMATO pos++;
154ce990805SThomas Braun incomment = true;
1553ae02089SMasatake YAMATO goto commenttext;
1563ae02089SMasatake YAMATO }
1573ae02089SMasatake YAMATO if (vStringChar (line, pos) == '(' && pos < len - 1 &&
1583ae02089SMasatake YAMATO vStringChar (line, pos+1) == '*')
1593ae02089SMasatake YAMATO {
1603ae02089SMasatake YAMATO pos +=2;
161ce990805SThomas Braun incomment = true;
1623ae02089SMasatake YAMATO goto commenttext;
1633ae02089SMasatake YAMATO }
1643ae02089SMasatake YAMATO /*
1653ae02089SMasatake YAMATO * SLOT definition looks like this:
1663ae02089SMasatake YAMATO * <<SLOT nameofslot: dopart>>
1673ae02089SMasatake YAMATO * or
1683ae02089SMasatake YAMATO * <<SLOT nameofslot: descriptor>>
1693ae02089SMasatake YAMATO */
1703ae02089SMasatake YAMATO if (!foundfragmenthere &&
1713ae02089SMasatake YAMATO vStringChar (line, pos) == '<' &&
1723ae02089SMasatake YAMATO pos+1 < len &&
1733ae02089SMasatake YAMATO vStringChar (line, pos+1) == '<' &&
1743ae02089SMasatake YAMATO strstr (vStringValue (line) + pos, ">>"))
1753ae02089SMasatake YAMATO {
1763ae02089SMasatake YAMATO /* Found slot name, get start and end */
1773ae02089SMasatake YAMATO int eoname;
1783ae02089SMasatake YAMATO char c2;
1793ae02089SMasatake YAMATO pos += 2; /* skip past << */
1803ae02089SMasatake YAMATO /* skip past space before SLOT */
1813ae02089SMasatake YAMATO while (pos < len && isspace ((int) vStringChar (line, pos)))
1823ae02089SMasatake YAMATO pos++;
1833ae02089SMasatake YAMATO /* skip past SLOT */
1843ae02089SMasatake YAMATO if (pos+4 <= len &&
1853ae02089SMasatake YAMATO !strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4))
1863ae02089SMasatake YAMATO pos += 4;
1873ae02089SMasatake YAMATO /* skip past space after SLOT */
1883ae02089SMasatake YAMATO while (pos < len && isspace ((int) vStringChar (line, pos)))
1893ae02089SMasatake YAMATO pos++;
1903ae02089SMasatake YAMATO eoname = pos;
1913ae02089SMasatake YAMATO /* skip to end of name */
1923ae02089SMasatake YAMATO while (eoname < len &&
1933ae02089SMasatake YAMATO (c2 = vStringChar (line, eoname)) != '>' &&
1943ae02089SMasatake YAMATO c2 != ':' &&
1953ae02089SMasatake YAMATO !isspace ((int) c2))
1963ae02089SMasatake YAMATO eoname++;
1973ae02089SMasatake YAMATO if (eoname < len)
1983ae02089SMasatake YAMATO {
1993ae02089SMasatake YAMATO vStringChar (line, eoname) = 0;
2003ae02089SMasatake YAMATO if (strcasecmp ("LIB", vStringValue (line) + pos) &&
2013ae02089SMasatake YAMATO strcasecmp ("PROGRAM", vStringValue (line) + pos) &&
2023ae02089SMasatake YAMATO strcasecmp ("SLOT", vStringValue (line) + pos))
2033ae02089SMasatake YAMATO {
2043ae02089SMasatake YAMATO makeBetaTag (vStringValue (line) + pos, K_SLOT);
2053ae02089SMasatake YAMATO }
2063ae02089SMasatake YAMATO }
2073ae02089SMasatake YAMATO if (eoname+1 < len) {
2083ae02089SMasatake YAMATO pos = eoname + 1;
2093ae02089SMasatake YAMATO } else {
2103ae02089SMasatake YAMATO pos = len;
2113ae02089SMasatake YAMATO continue;
2123ae02089SMasatake YAMATO }
2133ae02089SMasatake YAMATO }
2143ae02089SMasatake YAMATO /* Only patterns that are virtual, extensions of virtuals or
2153ae02089SMasatake YAMATO * final bindings are normally included so as not to overload
2163ae02089SMasatake YAMATO * totally.
2173ae02089SMasatake YAMATO * That means one of the forms name:: name:< or name::<
2183ae02089SMasatake YAMATO */
2193ae02089SMasatake YAMATO if (!foundfragmenthere &&
2203ae02089SMasatake YAMATO vStringChar (line, pos) == ':' &&
2213ae02089SMasatake YAMATO (dopatterns ||
2223ae02089SMasatake YAMATO (dovirtuals &&
2233ae02089SMasatake YAMATO (vStringChar (line, pos+1) == ':' ||
2243ae02089SMasatake YAMATO vStringChar (line, pos+1) == '<')
2253ae02089SMasatake YAMATO )
2263ae02089SMasatake YAMATO )
2273ae02089SMasatake YAMATO )
2283ae02089SMasatake YAMATO {
2293ae02089SMasatake YAMATO /* Found pattern name, get start and end */
2303ae02089SMasatake YAMATO int eoname = pos;
2313ae02089SMasatake YAMATO int soname;
2323ae02089SMasatake YAMATO while (eoname && isspace ((int) vStringChar (line, eoname-1)))
2333ae02089SMasatake YAMATO eoname--;
2343ae02089SMasatake YAMATO foundanothername:
2353ae02089SMasatake YAMATO /* terminate right after name */
2363ae02089SMasatake YAMATO vStringChar (line, eoname) = 0;
2373ae02089SMasatake YAMATO soname = eoname;
2383ae02089SMasatake YAMATO while (soname &&
2393ae02089SMasatake YAMATO isbident (vStringChar (line, soname-1)))
2403ae02089SMasatake YAMATO {
2413ae02089SMasatake YAMATO soname--;
2423ae02089SMasatake YAMATO }
2433ae02089SMasatake YAMATO if (soname != eoname)
2443ae02089SMasatake YAMATO {
2453ae02089SMasatake YAMATO makeBetaTag (vStringValue (line) + soname, K_PATTERN);
2463ae02089SMasatake YAMATO /* scan back past white space */
2473ae02089SMasatake YAMATO while (soname &&
2483ae02089SMasatake YAMATO isspace ((int) vStringChar (line, soname-1)))
2493ae02089SMasatake YAMATO soname--;
2503ae02089SMasatake YAMATO if (soname && vStringChar (line, soname-1) == ',')
2513ae02089SMasatake YAMATO {
2523ae02089SMasatake YAMATO /* we found a new pattern name before comma */
2533ae02089SMasatake YAMATO eoname = soname;
2543ae02089SMasatake YAMATO goto foundanothername;
2553ae02089SMasatake YAMATO }
2563ae02089SMasatake YAMATO }
2573ae02089SMasatake YAMATO }
2583ae02089SMasatake YAMATO }
2593ae02089SMasatake YAMATO goto endofline;
2603ae02089SMasatake YAMATO commenttext:
2613ae02089SMasatake YAMATO for ( ; pos < len; pos++)
2623ae02089SMasatake YAMATO {
2633ae02089SMasatake YAMATO if (vStringChar (line, pos) == '*' && pos < len - 1 &&
2643ae02089SMasatake YAMATO vStringChar (line, pos+1) == ')')
2653ae02089SMasatake YAMATO {
2663ae02089SMasatake YAMATO pos += 2;
267ce990805SThomas Braun incomment = false;
2683ae02089SMasatake YAMATO goto programtext;
2693ae02089SMasatake YAMATO }
2703ae02089SMasatake YAMATO if (vStringChar (line, pos) == '}')
2713ae02089SMasatake YAMATO {
2723ae02089SMasatake YAMATO pos++;
273ce990805SThomas Braun incomment = false;
2743ae02089SMasatake YAMATO goto programtext;
2753ae02089SMasatake YAMATO }
2763ae02089SMasatake YAMATO }
2773ae02089SMasatake YAMATO goto endofline;
2783ae02089SMasatake YAMATO stringtext:
2793ae02089SMasatake YAMATO for ( ; pos < len; pos++)
2803ae02089SMasatake YAMATO {
2813ae02089SMasatake YAMATO if (vStringChar (line, pos) == '\\')
2823ae02089SMasatake YAMATO {
2833ae02089SMasatake YAMATO if (pos < len - 1) pos++;
2843ae02089SMasatake YAMATO }
2853ae02089SMasatake YAMATO else if (vStringChar (line, pos) == '\'')
2863ae02089SMasatake YAMATO {
2873ae02089SMasatake YAMATO pos++;
2883ae02089SMasatake YAMATO /* support obsolete '' syntax */
2893ae02089SMasatake YAMATO if (pos < len && vStringChar (line, pos) == '\'')
2903ae02089SMasatake YAMATO {
2913ae02089SMasatake YAMATO continue;
2923ae02089SMasatake YAMATO }
293ce990805SThomas Braun inquote = false;
2943ae02089SMasatake YAMATO goto programtext;
2953ae02089SMasatake YAMATO }
2963ae02089SMasatake YAMATO }
2973ae02089SMasatake YAMATO }
2983ae02089SMasatake YAMATO endofline:
299ce990805SThomas Braun inquote = false; /* This shouldn't really make a difference */
300188fd4caSMasatake YAMATO } while (c != EOF);
3013ae02089SMasatake YAMATO vStringDelete (line);
3023ae02089SMasatake YAMATO }
3033ae02089SMasatake YAMATO
BetaParser(void)3043ae02089SMasatake YAMATO extern parserDefinition* BetaParser (void)
3053ae02089SMasatake YAMATO {
3063ae02089SMasatake YAMATO static const char *const extensions [] = { "bet", NULL };
3073ae02089SMasatake YAMATO parserDefinition* def = parserNew ("BETA");
30809ae690fSMasatake YAMATO def->kindTable = BetaKinds;
3093db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (BetaKinds);
3103ae02089SMasatake YAMATO def->extensions = extensions;
3113ae02089SMasatake YAMATO def->parser = findBetaTags;
3123ae02089SMasatake YAMATO return def;
3133ae02089SMasatake YAMATO }
314