xref: /Universal-ctags/parsers/beta.c (revision 16a2541c0698bd8ee03c1be8172ef3191f6e695a)
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