Exemple #1
0
static void findTxt2tagsTags (void)
{
	NestingLevels *nls = nestingLevelsNew();
	vString *name = vStringNew();
	const unsigned char *line;

	while ((line = fileReadLine()) != NULL)
	{
		int depth;

		if (isTxt2tagsLine(line))
			; /* skip not to improperly match titles */
		else if (parseTxt2tagsTitle(line, name, &depth))
		{
			NestingLevel *nl = nestingLevelsGetCurrent(nls);
			while (nl && nl->indentation >= depth)
			{
				nestingLevelsPop(nls);
				nl = nestingLevelsGetCurrent(nls);
			}

			vStringTerminate(name);
			makeTxt2tagsTag(name, nls, K_SECTION);
			nestingLevelsPush(nls, name, K_SECTION);
			nestingLevelsGetCurrent(nls)->indentation = depth;
		}
	}
	vStringDelete (name);
	nestingLevelsFree(nls);
}
Exemple #2
0
/* TODO: parse overlining & underlining as distinct sections. */
static void findRstTags (void)
{
    vString *name = vStringNew ();
    fpos_t filepos;
    const unsigned char *line;

    memset(&filepos, 0, sizeof(fpos_t));
    memset(kindchars, 0, sizeof kindchars);
    nestingLevels = nestingLevelsNew();

    while ((line = readLineFromInputFile ()) != NULL)
    {
        int line_len = strlen((const char*) line);
        int name_len_bytes = vStringLength(name);
        int name_len = utf8_strlen(vStringValue(name), name_len_bytes);

        /* if the name doesn't look like UTF-8, assume one-byte charset */
        if (name_len < 0)
            name_len = name_len_bytes;

        /* underlines must be the same length or more */
        if (line_len >= name_len && name_len > 0 &&
                ispunct(line[0]) && issame((const char*) line))
        {
            char c = line[0];
            int kind = get_kind(c);

            if (kind >= 0)
            {
                makeRstTag(name, kind, filepos);
                continue;
            }
        }
        vStringClear (name);
        if (!isspace(*line))
        {
            vStringCatS(name, (const char*)line);
            filepos = getInputFilePosition();
        }
        vStringTerminate(name);
    }
    vStringDelete (name);
    nestingLevelsFree(nestingLevels);
}
Exemple #3
0
static void findRubyTags (void)
{
	const unsigned char *line;
	boolean inMultiLineComment = FALSE;

	nesting = nestingLevelsNew (0);

	/* FIXME: this whole scheme is wrong, because Ruby isn't line-based.
	* You could perfectly well write:
	*
	*  def
	*  method
	*   puts("hello")
	*  end
	*
	* if you wished, and this function would fail to recognize anything.
	*/
	while ((line = readLineFromInputFile ()) != NULL)
	{
		const unsigned char *cp = line;
		/* if we expect a separator after a while, for, or until statement
		 * separators are "do", ";" or newline */
		boolean expect_separator = FALSE;

		if (canMatch (&cp, "=begin", isWhitespace))
		{
			inMultiLineComment = TRUE;
			continue;
		}
		if (canMatch (&cp, "=end", isWhitespace))
		{
			inMultiLineComment = FALSE;
			continue;
		}
		if (inMultiLineComment)
			continue;

		skipWhitespace (&cp);

		/* Avoid mistakenly starting a scope for modifiers such as
		*
		*   return if <exp>
		*
		* FIXME: this is fooled by code such as
		*
		*   result = if <exp>
		*               <a>
		*            else
		*               <b>
		*            end
		*
		* FIXME: we're also fooled if someone does something heinous such as
		*
		*   puts("hello") \
		*       unless <exp>
		*/
		if (canMatchKeyword (&cp, "for") ||
		    canMatchKeyword (&cp, "until") ||
		    canMatchKeyword (&cp, "while"))
		{
			expect_separator = TRUE;
			enterUnnamedScope ();
		}
		else if (canMatchKeyword (&cp, "case") ||
		         canMatchKeyword (&cp, "if") ||
		         canMatchKeyword (&cp, "unless"))
		{
			enterUnnamedScope ();
		}

		/*
		* "module M", "class C" and "def m" should only be at the beginning
		* of a line.
		*/
		if (canMatchKeyword (&cp, "module"))
		{
			readAndEmitTag (&cp, K_MODULE);
		}
		else if (canMatchKeyword (&cp, "class"))
		{
			readAndEmitTag (&cp, K_CLASS);
		}
		else if (canMatchKeyword (&cp, "def"))
		{
			rubyKind kind = K_METHOD;
			NestingLevel *nl = nestingLevelsGetCurrent (nesting);
			tagEntryInfo *e  = getEntryOfNestingLevel (nl);

			/* if the def is inside an unnamed scope at the class level, assume
			 * it's from a singleton from a construct like this:
			 *
			 * class C
			 *   class << self
			 *     def singleton
			 *       ...
			 *     end
			 *   end
			 * end
			 */
			if (e && (e->kind - RubyKinds) == K_CLASS && strlen (e->name) == 0)
				kind = K_SINGLETON;
			readAndEmitTag (&cp, kind);
		}
		while (*cp != '\0')
		{
			/* FIXME: we don't cope with here documents,
			* or regular expression literals, or ... you get the idea.
			* Hopefully, the restriction above that insists on seeing
			* definitions at the starts of lines should keep us out of
			* mischief.
			*/
			if (inMultiLineComment || isspace (*cp))
			{
				++cp;
			}
			else if (*cp == '#')
			{
				/* FIXME: this is wrong, but there *probably* won't be a
				* definition after an interpolated string (where # doesn't
				* mean 'comment').
				*/
				break;
			}
			else if (canMatchKeyword (&cp, "begin"))
			{
				enterUnnamedScope ();
			}
			else if (canMatchKeyword (&cp, "do"))
			{
				if (! expect_separator)
					enterUnnamedScope ();
				else
					expect_separator = FALSE;
			}
			else if (canMatchKeyword (&cp, "end") && nesting->n > 0)
			{
				/* Leave the most recent scope. */
				nestingLevelsPop (nesting);
			}
			else if (*cp == '"')
			{
				/* Skip string literals.
				 * FIXME: should cope with escapes and interpolation.
				 */
				do {
					++cp;
				} while (*cp != 0 && *cp != '"');
				if (*cp == '"')
					cp++; /* skip the last found '"' */
			}
			else if (*cp == ';')
			{
				++cp;
				expect_separator = FALSE;
			}
			else if (*cp != '\0')
			{
				do
					++cp;
				while (isIdentChar (*cp));
			}
		}
	}
	nestingLevelsFree (nesting);
}
Exemple #4
0
static void findAsciidocTags(void)
{
	vString *name = vStringNew();
	const unsigned char *line;
	unsigned char in_block = '\0';  /* holds the block marking char or \0 if not in block */

	nestingLevels = nestingLevelsNew();

	while ((line = readLineFromInputFile()) != NULL)
	{
		int line_len = strlen((const char*) line);
		int name_len_bytes = vStringLength(name);
		int name_len = utf8_strlen(vStringValue(name), name_len_bytes);

		/* if the name doesn't look like UTF-8, assume one-byte charset */
		if (name_len < 0) name_len = name_len_bytes;
		
		/* if its a title underline, or a delimited block marking character */
		if (line[0] == '=' || line[0] == '-' || line[0] == '~' ||
			line[0] == '^' || line[0] == '+' || line[0] == '.' ||
			line[0] == '*' || line[0] == '_' || line[0] == '/')
		{
			int n_same;
			for (n_same = 1; line[n_same] == line[0]; ++n_same);
			
			/* is it a two line title or a delimited block */
			if (n_same == line_len)
			{
				/* if in a block, can't be block start or title, look for block end */
				if (in_block)
				{
					if (line[0] == in_block) in_block = '\0';
				}
				
				/* if its a =_~^+ and the same length +-2 as the line before then its a title */
				/* (except in the special case its a -- open block start line) */
				else if ((line[0] == '=' || line[0] == '-' || line[0] == '~' ||
							line[0] == '^' || line[0] == '+') &&
						line_len <= name_len + 2 && line_len >= name_len - 2 &&
						!(line_len == 2 && line[0] == '-'))
				{
					int kind = get_kind((char)(line[0]));
					if (kind >= 0)
					{
						makeAsciidocTag(name, kind);
						continue;
					}
				}
				
				/* else if its 4 or more /+-.*_= (plus the -- special case) its a block start */
				else if (((line[0] == '/' || line[0] == '+' || line[0] == '-' ||
						   line[0] == '.' || line[0] == '*' || line[0] == '_' ||
						   line[0] == '=') && line_len >= 4 )
						 || (line[0] == '-' && line_len == 2))
				{
					in_block = line[0];
				}
			}
			
			/* otherwise is it a one line title */
			else if (line[0] == '=' && n_same <= 5 && isspace(line[n_same]) &&
					!in_block)
			{
				int kind = n_same - 1;
				int start = n_same;
				int end = line_len - 1;
				while (line[end] == line[0])--end;
				while (isspace(line[start]))++start;
				while (isspace(line[end]))--end;
				vStringClear(name);
				vStringNCatS(name, (const char*)(&(line[start])), end - start + 1);
				vStringTerminate(name);
				makeAsciidocTag(name, kind);
				continue;
			}
		}
		vStringClear(name);
		if (! isspace(*line))
			vStringCatS(name, (const char*) line);
		vStringTerminate(name);
	}
	vStringDelete(name);
	nestingLevelsFree(nestingLevels);
}