Esempio n. 1
0
static void findVimTags (void)
{
	vString *name = vStringNew ();
	const unsigned char *line;
	boolean inFunction = FALSE;
	int scope;

	while ((line = fileReadLine ()) != NULL)
	{
		while (isspace ((int) *line))
			++line;
		if ((int) *line == '"')
			continue;  /* skip comment */
		if (strncmp ((const char*) line, "fu", (size_t) 2) == 0)
		{
			const unsigned char *cp = line + 1;
			inFunction = TRUE;

			if ((int) *++cp == 'n'  &&  (int) *++cp == 'c'  &&
				(int) *++cp == 't'  &&  (int) *++cp == 'i'  &&
				(int) *++cp == 'o'  &&  (int) *++cp == 'n')
					++cp;
			if ((int) *cp == '!')
				++cp;
			if (isspace ((int) *cp))
			{
				while (isspace ((int) *cp))
					++cp;
				cp = skipPrefix (cp, &scope);
				if (isupper ((int) *cp)  ||  scope == 's'  ||  scope == '<')
				{
					do
					{
						vStringPut (name, (int) *cp);
						++cp;
					} while (isalnum ((int) *cp)  ||  *cp == '_');
					vStringTerminate (name);
					makeSimpleTag (name, VimKinds, K_FUNCTION);
					vStringClear (name);
				}
			}
		}

	    if  (strncmp ((const char*) line, "aug", (size_t) 3) == 0)
		{
			/* Found Autocommand Group (augroup) */
			const unsigned char *cp = line + 2;
			if ((int) *++cp == 'r' && (int) *++cp == 'o' &&
				(int) *++cp == 'u' && (int) *++cp == 'p')
					++cp;
			if (isspace ((int) *cp))
			{
				while (isspace ((int) *cp))
					++cp; 
				if (strncasecmp ((const char*) cp, "end", (size_t) 3) != 0)
				{    
					do
					{
						vStringPut (name, (int) *cp);
						++cp;
					} while (isalnum ((int) *cp)  ||  *cp == '_');
					vStringTerminate (name);
					makeSimpleTag (name, VimKinds, K_AUGROUP);
					vStringClear (name);
				}
			}
		}

		if (strncmp ((const char*) line, "endf", (size_t) 4) == 0)
			inFunction = FALSE;

		if (!inFunction  &&
				strncmp ((const char*) line, "let", (size_t) 3) == 0)
		{
			/* we've found a variable declared outside of a function!! */
			const unsigned char *cp = line + 3;
			/* get the name */
			if (isspace ((int) *cp))
			{
				/* deal with spaces, $, @ and & */
				while (!isalnum ((int) *cp))
					++cp;
				cp = skipPrefix (cp, &scope);
				do
				{
					vStringPut (name, (int) *cp);
					++cp;
				} while (isalnum ((int) *cp)  ||  *cp == '_');
				vStringTerminate (name);
				makeSimpleTag (name, VimKinds, K_VARIABLE);
				vStringClear (name);
			}
		}
	}
	vStringDelete (name);
}
Esempio n. 2
0
/* Algorithm adapted from from GNU etags.
 * Perl support by Bart Robinson <*****@*****.**>
 * Perl sub names: look for /^ [ \t\n]sub [ \t\n]+ [^ \t\n{ (]+/
 */
static void findPerlTags (void)
{
	vString *name = vStringNew ();
	vString *package = NULL;
	boolean skipPodDoc = FALSE;
	const unsigned char *line;

	/* Core modules AutoLoader and SelfLoader support delayed compilation
	 * by allowing Perl code that follows __END__ and __DATA__ tokens,
	 * respectively.  When we detect that one of these modules is used
	 * in the file, we continue processing even after we see the
	 * corresponding token that would usually terminate parsing of the
	 * file.
	 */
	enum {
		RESPECT_END		= (1 << 0),
		RESPECT_DATA	= (1 << 1),
	} respect_token = RESPECT_END | RESPECT_DATA;

	while ((line = fileReadLine ()) != NULL)
	{
		boolean spaceRequired = FALSE;
		boolean qualified = FALSE;
		const unsigned char *cp = line;
		perlKind kind = K_NONE;
		tagEntryInfo e;

		if (skipPodDoc)
		{
			if (strncmp ((const char*) line, "=cut", (size_t) 4) == 0)
				skipPodDoc = FALSE;
			continue;
		}
		else if (line [0] == '=')
		{
			skipPodDoc = isPodWord ((const char*)line + 1);
			continue;
		}
		else if (strcmp ((const char*) line, "__DATA__") == 0)
		{
			if (respect_token & RESPECT_DATA)
				break;
			else
				continue;
		}
		else if (strcmp ((const char*) line, "__END__") == 0)
		{
			if (respect_token & RESPECT_END)
				break;
			else
				continue;
		}
		else if (line [0] == '#')
			continue;

		while (isspace (*cp))
			cp++;

		if (strncmp((const char*) cp, "sub", (size_t) 3) == 0)
		{
			TRACE("this looks like a sub\n");
			cp += 3;
			kind = K_SUBROUTINE;
			spaceRequired = TRUE;
			qualified = TRUE;
		}
		else if (strncmp((const char*) cp, "use", (size_t) 3) == 0)
		{
			cp += 3;
			if (!isspace(*cp))
				continue;
			while (*cp && isspace (*cp))
				++cp;
			if (strncmp((const char*) cp, "AutoLoader", (size_t) 10) == 0) {
				respect_token &= ~RESPECT_END;
				continue;
			}
			if (strncmp((const char*) cp, "SelfLoader", (size_t) 10) == 0) {
				respect_token &= ~RESPECT_DATA;
				continue;
			}
			if (strncmp((const char*) cp, "constant", (size_t) 8) != 0)
				continue;
			cp += 8;
			/* Skip up to the first non-space character, skipping empty
			 * and comment lines.
			 */
			while (isspace(*cp))
				cp++;
			while (!*cp || '#' == *cp) {
				cp = fileReadLine ();
				if (!cp)
					goto END_MAIN_WHILE;
				while (isspace (*cp))
					cp++;
			}
			if ('{' == *cp) {
				++cp;
				if (0 == parseConstantsFromHashRef(cp, name, package)) {
					vStringClear(name);
					continue;
				} else
					goto END_MAIN_WHILE;
			}
			kind = K_CONSTANT;
			spaceRequired = FALSE;
			qualified = TRUE;
		}
		else if (strncmp((const char*) cp, "package", (size_t) 7) == 0 &&
				 ('\0' == cp[7] || isspace(cp[7])))
		{
			cp += 7;
			while (isspace (*cp))
				cp++;
			while (!*cp || '#' == *cp) {
				cp = fileReadLine ();
				if (!cp)
					goto END_MAIN_WHILE;
				while (isspace (*cp))
					cp++;
			}
			if (package == NULL)
				package = vStringNew ();
			else
				vStringClear (package);
			const unsigned char *const first = cp;
			while (*cp && (int) *cp != ';'  &&  !isspace ((int) *cp))
			{
				vStringPut (package, (int) *cp);
				cp++;
			}
			vStringCatS (package, "::");

			cp = first;	 /* Rewind */
			kind = K_PACKAGE;
			spaceRequired = FALSE;
			qualified = TRUE;
		}
		else if (strncmp((const char*) cp, "format", (size_t) 6) == 0)
		{
			cp += 6;
			kind = K_FORMAT;
			spaceRequired = TRUE;
			qualified = TRUE;
		}
		else
		{
			if (isIdentifier1 (*cp))
			{
				const unsigned char *p = cp;
				while (isIdentifier (*p))
					++p;
				while (isspace (*p))
					++p;
				if ((int) *p == ':' && (int) *(p + 1) != ':')
					kind = K_LABEL;
			}
		}
		if (kind != K_NONE)
		{
			TRACE("cp0: %s\n", (const char *) cp);
			if (spaceRequired && *cp && !isspace (*cp))
				continue;

			TRACE("cp1: %s\n", (const char *) cp);
			while (isspace (*cp))
				cp++;

			while (!*cp || '#' == *cp) { /* Gobble up empty lines
				                            and comments */
				cp = fileReadLine ();
				if (!cp)
					goto END_MAIN_WHILE;
				while (isspace (*cp))
					cp++;
			}

			while (isIdentifier (*cp) || (K_PACKAGE == kind && ':' == *cp))
			{
				vStringPut (name, (int) *cp);
				cp++;
			}

			if (K_FORMAT == kind &&
				vStringLength (name) == 0 && /* cp did not advance */
				'=' == *cp)
			{
				/* format's name is optional.  If it's omitted, 'STDOUT'
				   is assumed. */
				vStringCatS (name, "STDOUT");
			}

			vStringTerminate (name);
			TRACE("name: %s\n", name->buffer);

			if (0 == vStringLength(name)) {
				vStringClear(name);
				continue;
			}

			if (K_SUBROUTINE == kind)
			{
				/*
				 * isSubroutineDeclaration() may consume several lines.  So
				 * we record line positions.
				 */
				initTagEntry(&e, vStringValue(name), NULL);

				if (TRUE == isSubroutineDeclaration(cp)) {
					if (TRUE == PerlKinds[K_SUBROUTINE_DECLARATION].enabled) {
						kind = K_SUBROUTINE_DECLARATION;
					} else {
						vStringClear (name);
						continue;
					}
				} else if (! PerlKinds[kind].enabled) {
					continue;
				}

				e.kind     = &(PerlKinds[kind]);

				makeTagEntry(&e);

				if (Option.include.qualifiedTags && qualified &&
					package != NULL  && vStringLength (package) > 0)
				{
					vString *const qualifiedName = vStringNew ();
					vStringCopy (qualifiedName, package);
					vStringCat (qualifiedName, name);
					e.name = vStringValue(qualifiedName);
					makeTagEntry(&e);
					vStringDelete (qualifiedName);
				}
			} else if (vStringLength (name) > 0)
			{
				makeSimpleTag (name, PerlKinds, kind);
				if (Option.include.qualifiedTags && qualified &&
					K_PACKAGE != kind &&
					package != NULL  && vStringLength (package) > 0)
				{
					vString *const qualifiedName = vStringNew ();
					vStringCopy (qualifiedName, package);
					vStringCat (qualifiedName, name);
					makeSimpleTag (qualifiedName, PerlKinds, kind);
					vStringDelete (qualifiedName);
				}
			}
			vStringClear (name);
		}
	}

END_MAIN_WHILE:
	vStringDelete (name);
	if (package != NULL)
		vStringDelete (package);
}
Esempio n. 3
0
File: asp.c Progetto: ajitvin/v
static void findAspTags (void)
{
	vString *name = vStringNew ();
	const unsigned char *line;

	while ((line = fileReadLine ()) != NULL)
	{
		const unsigned char *cp = line;

		while (*cp != '\0')
		{
			/* jump over whitespace */
			while (isspace ((int)*cp))
				cp++;

			/* jump over strings */
			if (*cp == '"')
			{
				cp++;
				while (*cp!='"' && *cp!='\0')
					cp++;
			}

			/* jump over comments */ 
			else if (*cp == '\'')
				break;
			
			/* jump over end function/sub lines */
			else if (strncasecmp ((const char*) cp, "end", (size_t) 3)== 0)
			{
				cp += 3;
				if (isspace ((int)*cp))
				{
					while (isspace ((int)*cp))
						++cp;

					if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
					{
						cp+=8;
						break;
					}

					else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
					{
						cp+=3;
						break;
					}
				}
			}

			/* jump over exit function/sub lines */
			else if (strncasecmp ((const char*) cp, "exit", (size_t) 4)==0)
			{
				cp += 4;
				if (isspace ((int) *cp))
				{
					while (isspace ((int) *cp))
						++cp;

					if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
					{
						cp+=8;
						break;
					}

					else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
					{
						cp+=3;
						break;
					}
				}
			}

			/* function? */
			else if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
			{
				cp += 8;

				if (isspace ((int) *cp))
				{
					while (isspace ((int) *cp))
						++cp;
					while (isalnum ((int) *cp)  ||  *cp == '_')
					{
						vStringPut (name, (int) *cp);
						++cp;
					}
					vStringTerminate (name);
					makeSimpleTag (name, AspKinds, K_FUNCTION);
					vStringClear (name);
				}
			}

			/* sub? */
			else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
			{
				cp += 3;
				if (isspace ((int) *cp))
				{
					while (isspace ((int) *cp))
						++cp;
					while (isalnum ((int) *cp)  ||  *cp == '_')
					{
						vStringPut (name, (int) *cp);
						++cp;
					}
					vStringTerminate (name);
					makeSimpleTag (name, AspKinds, K_SUB);
					vStringClear (name);
				}
			}

			/* dim variable? */
			else if (strncasecmp ((const char*) cp, "dim", (size_t) 3) == 0)
			{
				cp += 3;
				if (isspace ((int) *cp))
				{
					while (isspace ((int) *cp))
						++cp;
					while (isalnum ((int) *cp)  ||  *cp == '_')
					{
						vStringPut (name, (int) *cp);
						++cp;
					}
					vStringTerminate (name);
					makeSimpleTag (name, AspKinds, K_DIM);
					vStringClear (name);
				}
			}

			/* const declaration? */
			else if (strncasecmp ((const char*) cp, "const", (size_t) 5) == 0)
			{
				cp += 5;
				if (isspace ((int) *cp))
				{
					while (isspace ((int) *cp))
						++cp;
					while (isalnum ((int) *cp)  ||  *cp == '_')
					{
						vStringPut (name, (int) *cp);
						++cp;
					}
					vStringTerminate (name);
					makeSimpleTag (name, AspKinds, K_CONST);
					vStringClear (name);
				}
			}

			/* nothing relevant */
			else if (*cp != '\0')
				cp++;
		}
	}
	vStringDelete (name);
}
Esempio n. 4
0
static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
{
	boolean is_class = FALSE;
	boolean read_next_token = TRUE;
	vString * saveScope = vStringNew ();

	token->nestLevel++;
	/*
	 * Make this routine a bit more forgiving.
	 * If called on an open_curly advance it
	 */
	if ( isType (token, TOKEN_OPEN_CURLY) &&
			isKeyword(token, KEYWORD_NONE) )
		readToken(token);

	if (! isType (token, TOKEN_CLOSE_CURLY))
	{
		/*
		 * Read until we find the closing brace,
		 * any nested braces will be handled within
		 */
		do
		{
			read_next_token = TRUE;
			if (isKeyword (token, KEYWORD_this))
			{
				/*
				 * Means we are inside a class and have found
				 * a class, not a function
				 */
				is_class = TRUE;
				vStringCopy(saveScope, token->scope);
				addToScope (token, parent->string);

				/*
				 * Ignore the remainder of the line
				 * findCmdTerm(token);
				 */
				parseLine (token, is_class);

				vStringCopy(token->scope, saveScope);
			}
			else if (isKeyword (token, KEYWORD_var))
			{
				/*
				 * Potentially we have found an inner function.
				 * Set something to indicate the scope
				 */
				vStringCopy(saveScope, token->scope);
				addToScope (token, parent->string);
				parseLine (token, is_class);
				vStringCopy(token->scope, saveScope);
			}
			else if (isKeyword (token, KEYWORD_function))
			{
				vStringCopy(saveScope, token->scope);
				addToScope (token, parent->string);
				parseFunction (token);
				vStringCopy(token->scope, saveScope);
			}
			else if (isType (token, TOKEN_OPEN_CURLY))
			{
				/* Handle nested blocks */
				parseBlock (token, parent);
			}
			else
			{
				/*
				 * It is possible for a line to have no terminator
				 * if the following line is a closing brace.
				 * parseLine will detect this case and indicate
				 * whether we should read an additional token.
				 */
				read_next_token = parseLine (token, is_class);
			}

			/*
			 * Always read a new token unless we find a statement without
			 * a ending terminator
			 */
			if( read_next_token )
				readToken(token);

			/*
			 * If we find a statement without a terminator consider the
			 * block finished, otherwise the stack will be off by one.
			 */
		} while (! isType (token, TOKEN_CLOSE_CURLY) && read_next_token );
	}

	vStringDelete(saveScope);
	token->nestLevel--;

	return is_class;
}
Esempio n. 5
0
extern void createRTags(void)
{
  vString *vLine = vStringNew();
  vString *name = vStringNew();
  int ikind;
  const unsigned char *line;

  while ((line = fileReadLine()) != NULL)
  {
    const unsigned char *cp = (const unsigned char*)line;

    vStringClear(name);
    while ((*cp != '\0') && (*cp != '#')) {
      /* iterate to the end of line or to a comment */
      ikind = -1;
      switch (*cp) {
        case 'l':
        case 's':
          if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
            /* load a library: library(tools) */
            cp += 7;
            SKIPSPACE(cp);
            if (*cp == '(')
              ikind = 1;
            else
              cp -= 7;
          } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
            /* load a source file: source("myfile.r") */
            cp += 6;
            SKIPSPACE(cp);
            if (*cp == '(')
              ikind = 2;
            else
              cp -= 6;
          }
          if (ikind != -1) {
            cp++;

            vStringClear(name);
            while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
              vStringPut(name, (int)*cp);
              cp++;
            }
            vStringTerminate(name);

            /* if the string really exists, make a tag of it */
            if (vStringLength(name) > 0)
              makeRTag(name, ikind);

            /* prepare for the next iteration */
            vStringClear(name);
          } else {
            vStringPut(name, (int)*cp);
            cp++;
          }
          break;
        case '<':
          cp++;
          if (*cp == '-') {
            /* assignment: ident <- someval */
            cp++;
            SKIPSPACE(cp);

            if (*cp == '\0') {
              /* not in this line, read next */
              /* sometimes functions are declared this way:
                ident <-
                function(...)
                {
                  ...
                }
                I don't know if there is a reason to write the function keyword
                in a new line
              */
              if ((line = fileReadLine()) != NULL) {
                cp = (const unsigned char*)line;
                SKIPSPACE(cp);
              }
            }

            if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
              /* it's a function: ident <- function(args) */
              cp += 8;
              vStringTerminate(name);
              /* if the string really exists, make a tag of it */
              if (vStringLength(name) > 0)
                makeRTag(name, 0);

              /* prepare for the next iteration */
              vStringClear(name);
              break;
            }
          }
        case ' ':
        case '\x009':
          /* skip whitespace */
          cp++;
          break;
        default:
          /* collect all characters that could be a part of an identifier */
          vStringPut(name, (int)*cp);
          cp++;
          break;
      }
    }
  }

  vStringDelete(name);
  vStringDelete(vLine);
}
Esempio n. 6
0
/* Structs and enums are very similar syntax-wise.
 * It is possible to parse variants a bit more cleverly (e.g. make tuple variants functions and
 * struct variants structs) but it'd be too clever and the signature wouldn't make too much sense without
 * the enum's definition (e.g. for the type bounds)
 *
 * Struct/Enum format:
 * "struct/enum" <ident>[<type_bounds>] "{" [<ident>,]+ "}"
 * "struct/enum" <ident>[<type_bounds>] ";"
 * */
static void parseStructOrEnum (lexerState *lexer, vString *scope, int parent_kind, boolean is_struct)
{
	int kind = is_struct ? K_STRUCT : K_ENUM;
	int field_kind = is_struct ? K_FIELD : K_VARIANT;
	int goal_tokens1[] = {';', '{'};

	advanceToken(lexer, TRUE);
	if (lexer->cur_token != TOKEN_IDENT)
		return;

	addTag(lexer->token_str, NULL, kind, lexer->line, lexer->pos, scope, parent_kind);
	addToScope(scope, lexer->token_str);

	skipUntil(lexer, goal_tokens1, 2);

	if (lexer->cur_token == '{')
	{
		vString *field_name = vStringNew();
		while (lexer->cur_token != TOKEN_EOF)
		{
			int goal_tokens2[] = {'}', ','};
			/* Skip attributes. Format:
			 * #[..] or #![..]
			 * */
			if (lexer->cur_token == '#')
			{
				advanceToken(lexer, TRUE);
				if (lexer->cur_token == '!')
					advanceToken(lexer, TRUE);
				if (lexer->cur_token == '[')
				{
					/* It's an attribute, skip it. */
					skipUntil(lexer, NULL, 0);
				}
				else
				{
					/* Something's up with this field, skip to the next one */
					skipUntil(lexer, goal_tokens2, 2);
					continue;
				}
			}
			if (lexer->cur_token == TOKEN_IDENT)
			{
				if (strcmp(lexer->token_str->buffer, "priv") == 0
				    || strcmp(lexer->token_str->buffer, "pub") == 0)
				{
					advanceToken(lexer, TRUE);
					if (lexer->cur_token != TOKEN_IDENT)
					{
						/* Something's up with this field, skip to the next one */
						skipUntil(lexer, goal_tokens2, 2);
						continue;
					}
				}

				vStringClear(field_name);
				vStringCat(field_name, lexer->token_str);
				addTag(field_name, NULL, field_kind, lexer->line, lexer->pos, scope, kind);
				skipUntil(lexer, goal_tokens2, 2);
			}
			if (lexer->cur_token == '}')
			{
				advanceToken(lexer, TRUE);
				break;
			}
			advanceToken(lexer, TRUE);
		}
		vStringDelete(field_name);
	}
}
Esempio n. 7
0
File: sh.c Progetto: shunlir/ctags
static void findShTags (void)
{
    vString *name = vStringNew ();
    const unsigned char *line;
    vString *hereDocDelimiter = NULL;
    boolean hereDocIndented = FALSE;
    boolean (* check_char)(int);

    while ((line = fileReadLine ()) != NULL)
    {
        const unsigned char* cp = line;
        shKind found_kind = K_NOTHING;

        if (hereDocDelimiter)
        {
            if (hereDocIndented)
            {
                while (*cp == '\t')
                    cp++;
            }
            if (strcmp ((const char *) cp, vStringValue (hereDocDelimiter)) == 0)
            {
                vStringDelete (hereDocDelimiter);
                hereDocDelimiter = NULL;
            }
            continue;
        }

        while (*cp != '\0')
        {
            /* jump over whitespace */
            while (isspace ((int)*cp))
                cp++;

            /* jump over strings */
            if (*cp == '"')
                cp = skipDoubleString (cp);
            else if (*cp == '\'')
                cp = skipSingleString (cp);
            /* jump over comments */
            else if (*cp == '#')
                break;
            /* jump over here-documents */
            else if (cp[0] == '<' && cp[1] == '<')
            {
                const unsigned char *start, *end;
                boolean trimEscapeSequences = FALSE;
                boolean quoted = FALSE;
                cp += 2;
                /* an optional "-" strips leading tabulations from the heredoc lines */
                if (*cp != '-')
                    hereDocIndented = FALSE;
                else
                {
                    hereDocIndented = TRUE;
                    cp++;
                }
                while (isspace (*cp))
                    cp++;
                start = end = cp;
                /* the delimiter can be surrounded by quotes */
                if (*cp == '"')
                {
                    start++;
                    end = cp = skipDoubleString (cp);
                    /* we need not to worry about variable substitution, they
                     * don't happen in heredoc delimiter definition */
                    trimEscapeSequences = TRUE;
                    quoted = TRUE;
                }
                else if (*cp == '\'')
                {
                    start++;
                    end = cp = skipSingleString (cp);
                    quoted = TRUE;
                }
                else
                {
                    while (isIdentChar ((int) *cp))
                        cp++;
                    end = cp;
                }
                if (end > start || quoted)
                {
                    /* The input may be broken as a shell script but we need to avoid
                       memory leaking. */
                    if (hereDocDelimiter)
                        vStringClear(hereDocDelimiter);
                    else
                        hereDocDelimiter = vStringNew ();
                    for (; end > start; start++)
                    {
                        if (trimEscapeSequences && *start == '\\')
                            start++;
                        vStringPut (hereDocDelimiter, *start);
                    }
                }
            }

            if (strncmp ((const char*) cp, "function", (size_t) 8) == 0  &&
                    isspace ((int) cp [8]))
            {
                found_kind = K_FUNCTION;
                cp += 8;
            }

            else if (strncmp ((const char*) cp, "alias", (size_t) 5) == 0  &&
                     isspace ((int) cp [5]))
            {
                found_kind = K_ALIAS;
                cp += 5;
            }

            else if (cp [0] == '.'
                     && isspace((int) cp [1]))
            {
                found_kind = K_SOURCE;
                ++cp;
            }
            else if (strncmp ((const char*) cp, "source", (size_t) 6) == 0
                     && isspace((int) cp [6]))
            {
                found_kind = K_SOURCE;
                cp += 6;
            }

            if (found_kind != K_NOTHING)
                while (isspace ((int) *cp))
                    ++cp;

            // Get the name of the function, alias or file to be read by source
            check_char = isIdentChar;
            if (found_kind == K_SOURCE)
                check_char = isFileChar;

            if (! check_char ((int) *cp))
            {
                found_kind = K_NOTHING;
                if (*cp != '\0')
                    ++cp;
                continue;
            }
            while (check_char ((int) *cp))
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }
            vStringTerminate (name);

            while (isspace ((int) *cp))
                ++cp;

            if ((found_kind != K_SOURCE)
                    && *cp == '(')
            {
                ++cp;
                while (isspace ((int) *cp))
                    ++cp;
                if (*cp == ')')
                {
                    found_kind = K_FUNCTION;
                    ++cp;
                }
            }
            if (found_kind != K_NOTHING)
            {
                makeSimpleTag (name, ShKinds, found_kind);
                found_kind = K_NOTHING;
            }
            vStringClear (name);
        }
    }
    vStringDelete (name);
    if (hereDocDelimiter)
        vStringDelete (hereDocDelimiter);
}
Esempio n. 8
0
/* parse a function
 *
 * if @name is NULL, parses a normal function
 * 	function myfunc($foo, $bar) {}
 * 	function &myfunc($foo, $bar) {}
 * 	function myfunc($foo, $bar) : type {}
 *
 * if @name is not NULL, parses an anonymous function with name @name
 * 	$foo = function($foo, $bar) {}
 * 	$foo = function&($foo, $bar) {}
 * 	$foo = function($foo, $bar) use ($x, &$y) {}
 * 	$foo = function($foo, $bar) use ($x, &$y) : type {} */
static boolean parseFunction (tokenInfo *const token, const tokenInfo *name)
{
	boolean readNext = TRUE;
	accessType access = CurrentStatement.access;
	implType impl = CurrentStatement.impl;
	tokenInfo *nameFree = NULL;

	readToken (token);
	/* skip a possible leading ampersand (return by reference) */
	if (token->type == TOKEN_AMPERSAND)
		readToken (token);

	if (! name)
	{
		if (token->type != TOKEN_IDENTIFIER && token->type != TOKEN_KEYWORD)
			return FALSE;

		name = nameFree = newToken ();
		copyToken (nameFree, token, TRUE);
		readToken (token);
	}

	if (token->type == TOKEN_OPEN_PAREN)
	{
		vString *arglist = vStringNew ();
		int depth = 1;

		vStringPut (arglist, '(');
		do
		{
			readToken (token);

			switch (token->type)
			{
				case TOKEN_OPEN_PAREN:  depth++; break;
				case TOKEN_CLOSE_PAREN: depth--; break;
				default: break;
			}
			/* display part */
			switch (token->type)
			{
				case TOKEN_AMPERSAND:		vStringPut (arglist, '&');		break;
				case TOKEN_CLOSE_CURLY:		vStringPut (arglist, '}');		break;
				case TOKEN_CLOSE_PAREN:		vStringPut (arglist, ')');		break;
				case TOKEN_CLOSE_SQUARE:	vStringPut (arglist, ']');		break;
				case TOKEN_COLON:			vStringPut (arglist, ':');		break;
				case TOKEN_COMMA:			vStringCatS (arglist, ", ");	break;
				case TOKEN_EQUAL_SIGN:		vStringCatS (arglist, " = ");	break;
				case TOKEN_OPEN_CURLY:		vStringPut (arglist, '{');		break;
				case TOKEN_OPEN_PAREN:		vStringPut (arglist, '(');		break;
				case TOKEN_OPEN_SQUARE:		vStringPut (arglist, '[');		break;
				case TOKEN_PERIOD:			vStringPut (arglist, '.');		break;
				case TOKEN_SEMICOLON:		vStringPut (arglist, ';');		break;
				case TOKEN_BACKSLASH:		vStringPut (arglist, '\\');		break;
				case TOKEN_STRING:
				{
					vStringCatS (arglist, "'");	
					vStringCat  (arglist, token->string);
					vStringCatS (arglist, "'");
					break;
				}

				case TOKEN_IDENTIFIER:
				case TOKEN_KEYWORD:
				case TOKEN_VARIABLE:
				{
					switch (vStringLast (arglist))
					{
						case 0:
						case ' ':
						case '{':
						case '(':
						case '[':
						case '.':
						case '\\':
							/* no need for a space between those and the identifier */
							break;

						default:
							vStringPut (arglist, ' ');
							break;
					}
					if (token->type == TOKEN_VARIABLE)
						vStringPut (arglist, '$');
					vStringCat (arglist, token->string);
					break;
				}

				default: break;
			}
		}
		while (token->type != TOKEN_EOF && depth > 0);

		vStringTerminate (arglist);

		makeFunctionTag (name, arglist, access, impl);
		vStringDelete (arglist);

		readToken (token); /* normally it's an open brace or "use" keyword */
	}

	/* skip use(...) */
	if (token->type == TOKEN_KEYWORD && token->keyword == KEYWORD_use)
	{
		readToken (token);
		skipOverParens (token);
	}

	/* PHP7 return type declaration or if parsing Zephir, skip function return
	 * type hint */
	if ((getInputLanguage () == Lang_php && token->type == TOKEN_COLON) ||
	    (getInputLanguage () == Lang_zephir && token->type == TOKEN_OPERATOR))
	{
		do
			readToken (token);
		while (token->type == TOKEN_IDENTIFIER ||
		       token->type == TOKEN_BACKSLASH);
	}

	if (token->type == TOKEN_OPEN_CURLY)
		enterScope (token, name->string, K_FUNCTION);
	else
		readNext = FALSE;

	if (nameFree)
		deleteToken (nameFree);

	return readNext;
}
Esempio n. 9
0
static void findBetaTags (void)
{
	vString *line = vStringNew ();
	boolean incomment = FALSE;
	boolean inquote = FALSE;
	boolean dovirtuals = BetaKinds [K_VIRTUAL].enabled;
	boolean dopatterns = BetaKinds [K_PATTERN].enabled;

	do
	{
		boolean foundfragmenthere = FALSE;
		/* find fragment definition (line that starts and ends with --) */
		int last;
		int first;
		int c;

		vStringClear (line);

		while ((c = fileGetc ()) != EOF && c != '\n' && c != '\r')
			vStringPut (line, c);

		vStringTerminate (line);

		last = vStringLength (line) - 1;
		first = 0;
		/* skip white space at start and end of line */
		while (last && isspace ((int) vStringChar (line, last))) last--;
		while (first < last && isspace ((int) vStringChar (line, first))) first++;
		/* if line still has a reasonable length and ... */
		if (last - first > 4 &&
			(vStringChar (line, first)     == '-' && 
			 vStringChar (line, first + 1) == '-' && 
			 vStringChar (line, last)      == '-' && 
			 vStringChar (line, last - 1)  == '-'))
		{
			if (!incomment && !inquote)
			{
				foundfragmenthere = TRUE;
				/* skip past -- and whitespace.  Also skip back past 'dopart'
				   or 'attributes' to the :.  We have to do this because there
				   is no sensible way to include whitespace in a ctags token
				   so the conventional space after the ':' would mess us up */
				last -= 2;
				first += 2;
				while (last && vStringChar (line, last) != ':') last--;
				while (last && (isspace ((int) vStringChar (line, last-1)))) last--;
				while (first < last &&
					   (isspace ((int) vStringChar (line, first)) ||
						vStringChar (line, first) == '-'))
					first++;
				/* If there's anything left it is a fragment title */
				if (first < last - 1)
				{
					vStringChar (line, last) = 0;
					if (strcasecmp ("LIB", vStringValue (line) + first) &&
						strcasecmp ("PROGRAM", vStringValue (line) + first))
					{
						makeBetaTag (vStringValue (line) + first, K_FRAGMENT);
					}
				}
			}
		} else {
			int pos = 0;
			int len = vStringLength (line);
			if (inquote) goto stringtext;
			if (incomment) goto commenttext;
		programtext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '\'')
				{
					pos++;
					inquote = TRUE;
					goto stringtext;
				}
				if (vStringChar (line, pos) == '{')
				{
					pos++;
					incomment = TRUE;
					goto commenttext;
				}
				if (vStringChar (line, pos) == '(' && pos < len - 1 &&
					vStringChar (line, pos+1) == '*')
				{
					pos +=2;
					incomment = TRUE;
					goto commenttext;
				}
				/*
				 * SLOT definition looks like this: 
				 * <<SLOT nameofslot: dopart>> 
				 * or
				 * <<SLOT nameofslot: descriptor>> 
				 */
				if (!foundfragmenthere &&
					vStringChar (line, pos) == '<' &&
					pos+1 < len &&
					vStringChar (line, pos+1) == '<' &&
					strstr (vStringValue (line) + pos, ">>"))
				{
					/* Found slot name, get start and end */
					int eoname;
					char c2;
					pos += 2; /* skip past << */
					/* skip past space before SLOT */
					while (pos < len && isspace ((int) vStringChar (line, pos)))
						pos++;
					/* skip past SLOT */
					if (pos+4 <= len &&
						!strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4))
						pos += 4;
					/* skip past space after SLOT */
					while (pos < len && isspace ((int) vStringChar (line, pos)))
						pos++;
					eoname = pos;
					/* skip to end of name */
					while (eoname < len &&
							(c2 = vStringChar (line, eoname)) != '>' &&
							c2 != ':' &&
							!isspace ((int) c2))
						eoname++;
					if (eoname < len)
					{
						vStringChar (line, eoname) = 0;
						if (strcasecmp ("LIB", vStringValue (line) + pos) &&
							strcasecmp ("PROGRAM", vStringValue (line) + pos) &&
							strcasecmp ("SLOT", vStringValue (line) + pos))
						{
							makeBetaTag (vStringValue (line) + pos, K_SLOT);
						}
					}
					if (eoname+1 < len) {
						pos = eoname + 1;
					} else {
						pos = len;
						continue;
					}
				}
				/* Only patterns that are virtual, extensions of virtuals or
				 * final bindings are normally included so as not to overload
	             * totally.
				 * That means one of the forms name:: name:< or name::<
				 */
				if (!foundfragmenthere &&
					vStringChar (line, pos) == ':' &&
	                (dopatterns ||
					 (dovirtuals &&
					  (vStringChar (line, pos+1) == ':' ||
					   vStringChar (line, pos+1) == '<')
					 )
					)
	               )
				{
					/* Found pattern name, get start and end */
					int eoname = pos;
					int soname;
					while (eoname && isspace ((int) vStringChar (line, eoname-1)))
						eoname--;
				foundanothername:
					/* terminate right after name */
					vStringChar (line, eoname) = 0;
					soname = eoname;
					while (soname &&
						isbident (vStringChar (line, soname-1)))
					{
						soname--;
					}
					if (soname != eoname)
					{
						makeBetaTag (vStringValue (line) + soname, K_PATTERN);
						/* scan back past white space */
						while (soname &&
								isspace ((int) vStringChar (line, soname-1)))
							soname--;
						if (soname && vStringChar (line, soname-1) == ',')
						{
							/* we found a new pattern name before comma */
							eoname = soname;
							goto foundanothername;
						}
					}
				}
			}
			goto endofline;
		commenttext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '*' && pos < len - 1 &&
					vStringChar (line, pos+1) == ')')
				{
					pos += 2;
					incomment = FALSE;
					goto programtext;
				}
				if (vStringChar (line, pos) == '}')
				{
					pos++;
					incomment = FALSE;
					goto programtext;
				}
			}
			goto endofline;
		stringtext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '\\')
				{
					if (pos < len - 1) pos++;
				}
				else if (vStringChar (line, pos) == '\'')
				{
					pos++;
					/* support obsolete '' syntax */
					if (pos < len && vStringChar (line, pos) == '\'')
					{
						continue;
					}
					inquote = FALSE;
					goto programtext;
				}
			}
		}
		endofline:
		inquote = FALSE;  /* This shouldn't really make a difference */
	} while (!feof (File.fp));
}
Esempio n. 10
0
File: nsis.c Progetto: 15ramky/geany
static void findNsisTags (void)
{
	vString *name = vStringNew ();
	const unsigned char *line;

	while ((line = fileReadLine ()) != NULL)
	{
		const unsigned char* cp = line;

		while (isspace (*cp))
			cp++;

		if (*cp == '#' || *cp == ';')
			continue;

		/* functions */
		if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0 &&
			isspace ((int) cp [8]))
		{
			cp += 8;
			/* skip all whitespace */
			while (isspace ((int) *cp))
				++cp;
			while (isalnum ((int) *cp) || *cp == '_' || *cp == '-' || *cp == '.' || *cp == '!')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, NsisKinds, K_FUNCTION);
			vStringClear (name);
		}
		/* variables */
		else if (strncasecmp ((const char*) cp, "var", (size_t) 3) == 0 &&
			isspace ((int) cp [3]))
		{
			cp += 3;
			/* skip all whitespace */
			while (isspace ((int) *cp))
				++cp;
			/* skip any flags */
			while (*cp == '/')
			{
				++cp;
				while (! isspace ((int) *cp))
					++cp;
				while (isspace ((int) *cp))
					++cp;
			}
			while (isalnum ((int) *cp) || *cp == '_')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, NsisKinds, K_VARIABLE);
			vStringClear (name);
		}
		/* sections */
		else if (strncasecmp ((const char*) cp, "section", (size_t) 7) == 0  &&
				 isspace ((int) cp [7]))
		{
			boolean in_quotes = FALSE;
			cp += 7;
			/* skip all whitespace */
			while (isspace ((int) *cp))
			++cp;
			while (isalnum ((int) *cp) || isspace ((int) *cp) ||
				   *cp == '_' || *cp == '-' || *cp == '.' || *cp == '!' || *cp == '"')
			{
				if (*cp == '"')
				{
					if (in_quotes)
						break;
					else
					{
						in_quotes = TRUE;
						++cp;
						continue;
					}
				}
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, NsisKinds, K_SECTION);
			vStringClear (name);
		}
	}
	vStringDelete (name);
}
Esempio n. 11
0
static void findMakeTagsCommon (void *data)
{
	stringList *identifiers = stringListNew ();
	boolean newline = TRUE;
	boolean in_define = FALSE;
	boolean in_value  = FALSE;
	boolean in_rule = FALSE;
	boolean variable_possible = TRUE;
	boolean appending = FALSE;
	int c;

	while ((c = nextChar ()) != EOF)
	{
		if (newline)
		{
			if (in_rule)
			{
				if (c == '\t' || (c = skipToNonWhite (c)) == '#')
				{
					skipLine ();  /* skip rule or comment */
					c = nextChar ();
				}
				else if (c != '\n')
					in_rule = FALSE;
			}
			else if (in_value)
				in_value = FALSE;

			stringListClear (identifiers);
			variable_possible = (boolean)(!in_rule);
			newline = FALSE;
		}
		if (c == '\n')
			newline = TRUE;
		else if (isspace (c))
			continue;
		else if (c == '#')
			skipLine ();
		else if (variable_possible && c == '?')
		{
			c = nextChar ();
			ungetcToInputFile (c);
			variable_possible = (c == '=');
		}
		else if (variable_possible && c == '+')
		{
			c = nextChar ();
			ungetcToInputFile (c);
			variable_possible = (c == '=');
			appending = TRUE;
		}
		else if (variable_possible && c == ':' &&
				 stringListCount (identifiers) > 0)
		{
			c = nextChar ();
			ungetcToInputFile (c);
			if (c != '=')
			{
				unsigned int i;
				for (i = 0; i < stringListCount (identifiers); i++)
					newTarget (stringListItem (identifiers, i));
				stringListClear (identifiers);
				in_rule = TRUE;
			}
		}
		else if (variable_possible && c == '=' &&
				 stringListCount (identifiers) == 1)
		{
			newMacro (stringListItem (identifiers, 0), FALSE, appending, data);
			in_value = TRUE;
			in_rule = FALSE;
			appending = FALSE;
		}
		else if (variable_possible && isIdentifier (c))
		{
			vString *name = vStringNew ();
			readIdentifier (c, name);
			stringListAdd (identifiers, name);

			if (in_value && valuesFoundCB)
				valuesFoundCB (name, data);

			if (stringListCount (identifiers) == 1)
			{
				if (in_define && ! strcmp (vStringValue (name), "endef"))
					in_define = FALSE;
				else if (in_define)
					skipLine ();
				else if (! strcmp (vStringValue (name), "define"))
				{
					in_define = TRUE;
					c = skipToNonWhite (nextChar ());
					vStringClear (name);
					/* all remaining characters on the line are the name -- even spaces */
					while (c != EOF && c != '\n')
					{
						vStringPut (name, c);
						c = nextChar ();
					}
					if (c == '\n')
						ungetcToInputFile (c);
					vStringTerminate (name);
					vStringStripTrailing (name);
					newMacro (name, TRUE, FALSE, data);
				}
				else if (! strcmp (vStringValue (name), "export"))
					stringListClear (identifiers);
				else if (! strcmp (vStringValue (name), "include")
					 || ! strcmp (vStringValue (name), "sinclude")
					 || ! strcmp (vStringValue (name), "-include"))
				{
					boolean optional = (vStringValue (name)[0] == 'i')? FALSE: TRUE;
					while (1)
					{
						c = skipToNonWhite (nextChar ());
						readIdentifier (c, name);
						vStringStripTrailing (name);
						if (isAcceptableAsInclude(name))
							newInclude (name, optional);

						/* non-space characters after readIdentifier() may
						 * be rejected by the function:
						 * e.g.
						 * include $*
						 *
						 * Here, remove such characters from input stream.
						 */
						do
							c = nextChar ();
						while (c != EOF && c != '\n' && (!isspace (c)));
						if (c == '\n')
							ungetcToInputFile (c);

						if (c == EOF || c == '\n')
							break;
					}
				}
			}
		}
		else
			variable_possible = FALSE;
	}
	stringListDelete (identifiers);
}
Esempio n. 12
0
static void parseString (vString *const string)
{
	boolean verbatim = FALSE;
	boolean align = FALSE;
	boolean end = FALSE;
	vString *verbatimCloser = vStringNew ();
	vString *lastLine = vStringNew ();
	int prev = '\0';
	int c;

	while (! end)
	{
		c = getcFromInputFile ();
		if (c == EOF)
			end = TRUE;
		else if (c == '"')
		{
			if (! verbatim)
				end = TRUE;
			else
				end = (boolean) (strcmp (vStringValue (lastLine),
				                         vStringValue (verbatimCloser)) == 0);
		}
		else if (c == '\n')
		{
			if (verbatim)
				vStringClear (lastLine);
			if (prev == '[' /* ||  prev == '{' */)
			{
				verbatim = TRUE;
				vStringClear (verbatimCloser);
				vStringClear (lastLine);
				if (prev == '{')
					vStringPut (verbatimCloser, '}');
				else
				{
					vStringPut (verbatimCloser, ']');
					align = TRUE;
				}
				vStringNCat (verbatimCloser, string, vStringLength (string) - 1);
				vStringClear (string);
			}
			if (verbatim && align)
			{
				do
					c = getcFromInputFile ();
				while (isspace (c));
			}
		}
		else if (c == '%')
			c = parseEscapedCharacter ();
		if (! end)
		{
			vStringPut (string, c);
			if (verbatim)
			{
				vStringPut (lastLine, c);
				vStringTerminate (lastLine);
			}
			prev = c;
		}
	}
	vStringTerminate (string);
	vStringDelete (lastLine);
	vStringDelete (verbatimCloser);
}
Esempio n. 13
0
static boolean parseTag (tokenInfo *const token, texKind kind)
{
    tokenInfo *const name = newToken ();
    vString *   fullname;
    boolean     useLongName = TRUE;

    fullname = vStringNew ();
    vStringClear (fullname);

    /*
     * Tex tags are of these formats:
     *   \keyword{any number of words}
     *   \keyword[short desc]{any number of words}
     *   \keyword*[short desc]{any number of words}
     *
     * When a keyword is found, loop through all words within
     * the curly braces for the tag name.
     */

    if (isType (token, TOKEN_KEYWORD))
    {
        copyToken (name, token);
        readToken (token);
    }

    if (isType (token, TOKEN_OPEN_SQUARE))
    {
        useLongName = FALSE;

        readToken (token);
        while (! isType (token, TOKEN_CLOSE_SQUARE) )
        {
            if (isType (token, TOKEN_IDENTIFIER))
            {
                if (fullname->length > 0)
                    vStringCatS (fullname, " ");
                vStringCatS (fullname, vStringValue (token->string));
            }
            readToken (token);
        }
        vStringTerminate (fullname);
        vStringCopy (name->string, fullname);
        makeTexTag (name, kind);
    }

    if (isType (token, TOKEN_STAR))
    {
        readToken (token);
    }

    if (isType (token, TOKEN_OPEN_CURLY))
    {
        readToken (token);
        while (! isType (token, TOKEN_CLOSE_CURLY) )
        {
            if (isType (token, TOKEN_IDENTIFIER) && useLongName)
            {
                if (fullname->length > 0)
                    vStringCatS (fullname, " ");
                vStringCatS (fullname, vStringValue (token->string));
            }
            readToken (token);
        }
        if (useLongName) 
        {
            vStringTerminate (fullname);
            vStringCopy (name->string, fullname);
            makeTexTag (name, kind);
        }
    }

    deleteToken (name);
    vStringDelete (fullname);
    return TRUE;
}
Esempio n. 14
0
File: lxcmd.c Progetto: simlrh/ctags
static boolean loadPathKinds  (xcmdPath *const path, const langType language)
{
	enum pcoprocError r;
	FILE* pp = NULL;
	char * argv[3];
	int status;
	vString * opt;
	char file_kind = getLanguageFileKind (language)->letter;

	opt = vStringNewInit(XCMD_LIST_KIND_OPTION);
	vStringCatS (opt, "=");
	vStringCatS (opt, getLanguageName(language));

	argv[2] = NULL;
	argv[1] = vStringValue (opt);
	argv[0] = vStringValue (path->path);

	errno = 0;

	if (getuid() == 0 || geteuid() == 0)
	{
		verbose ("all xcmd feature is disabled when running ctags in root privilege\n");
		vStringDelete (opt);
		return FALSE;
	}

	if (! isSafeExecutable (argv [0]))
	{
		vStringDelete (opt);
		return FALSE;
	}
	verbose ("loading path kinds of %s from [%s %s]\n", getLanguageName(language), argv[0], argv[1]);
	r = pcoprocOpen (vStringValue (path->path), argv, &pp, NULL);
	switch (r) {
	case PCOPROC_ERROR_WPIPE:
		error (WARNING | PERROR, "failed to make pipe to write to command: [%s %s]",
		       argv[0], argv[1]);
		break;
	case PCOPROC_ERROR_RPIPE:
		error (WARNING | PERROR, "failed to make pipe to read from command: [%s %s]",
		       argv[0], argv[1]);
		break;
	case PCOPROC_ERROR_FORK:
		error (WARNING | PERROR, "failed to do fork: [%s %s]",
		       argv[0], argv[1]);
		break;
	case PCOPROC_SUCCESSFUL:
		break;
	}

	if (pp)
	{
		vString* vline = vStringNew();

		while (readLineWithNoSeek (vline, pp))
		{
			char* line;
			char  kind_letter;

			vStringStripNewline (vline);
			line = vStringValue (vline);
			if (!loadPathKind (path, line, argv))
				break;

			kind_letter = path->kinds [path->n_kinds - 1].letter;
			if (kind_letter == file_kind)
				error (FATAL,
				       "Kind letter \'%c\' returned from xcmd %s of %s language is reserved in ctags main",
				       kind_letter,
				       vStringValue (path->path),
				       getLanguageName (language));
		}

		vStringDelete (vline);


		status = pcoprocClose (pp);

		/* TODO: Decode status */
		verbose("	status: %d\n", status);
		if (status != 0)
		{
			if (status > 0
			    && WIFEXITED (status)
			    && (WEXITSTATUS (status) == path->not_available_status))
				verbose ("xcmd: the %s backend is not available\n", argv[0]);
			else
				error (WARNING, "xcmd exits abnormally status(%d): [%s %s]",
				       status, argv[0], argv[1]);
			vStringDelete (opt);
			return FALSE;
		}
	}
	else
	{
		error (WARNING | PERROR, "cannot make pipe to xcmd: [%s %s]",
		       argv[0], argv[1]);
	}

	vStringDelete (opt);
	return path->kinds == NULL? FALSE: TRUE;
}
Esempio n. 15
0
File: php.c Progetto: qzhuyan/ctags
		initPhpEntry (&e, token, K_FUNCTION, access);

		if (impl != IMPL_UNDEFINED)
			e.extensionFields.implementation = implToString (impl);
		if (arglist)
			e.extensionFields.signature = vStringValue (arglist);

		makePhpTagEntry (&e);
	}
}

static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
{
	tokenInfo *token = xMalloc (1, tokenInfo);

	token->string = vStringNew ();
	token->scope  = vStringNew ();
	return token;
}

static void clearPoolToken (void *data)
{
	tokenInfo *token = data;

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	token->lineNumber   = getInputLineNumber ();
	token->filePosition = getInputFilePosition ();
	token->parentKind	= -1;
	vStringClear (token->string);
	vStringClear (token->scope);
Esempio n. 16
0
static boolean parseCommand (const unsigned char *line)
{
	vString *name = vStringNew ();
	boolean cmdProcessed = TRUE;

	/* 
	 * Found a user-defined command 
	 *
	 * They can have many options preceeded by a dash
	 * command! -nargs=+ -complete Select  :call s:DB_execSql("select " . <q-args>)
	 * The name of the command should be the first word not preceeded by a dash
	 *
	 */
	const unsigned char *cp = line;

	if ( (int) *cp == '\\' ) 
	{
		/*
		 * We are recursively calling this function is the command
		 * has been continued on to the next line
		 *
		 * Vim statements can be continued onto a newline using a \
		 * to indicate the previous line is continuing.
		 *
		 * com -nargs=1 -bang -complete=customlist,EditFileComplete
		 * 			\ EditFile edit<bang> <args>
		 *
		 * If the following lines do not have a line continuation
		 * the command must not be spanning multiple lines and should
		 * be synatically incorrect.
		 */
		if ((int) *cp == '\\')
			++cp;

		while (*cp && isspace ((int) *cp))
			++cp; 
	}
	else if ( (!strncmp ((const char*) line, "comp", (size_t) 4) == 0) && 
		     (!strncmp ((const char*) line, "comc", (size_t) 4) == 0) && 
				(strncmp ((const char*) line, "com", (size_t) 3) == 0) )
	{
		cp += 2;
		if ((int) *++cp == 'm' && (int) *++cp == 'a' &&
				(int) *++cp == 'n' && (int) *++cp == 'd')
			++cp;

		if ((int) *cp == '!')
			++cp;

		if ((int) *cp != ' ')
		{
			/*
			 * :command must be followed by a space.  If it is not, it is 
			 * not a valid command.
			 * Treat the line as processed and continue.
			 */
			cmdProcessed = TRUE;
			goto cleanUp;
		}

		while (*cp && isspace ((int) *cp))
			++cp; 
	} 
	else 
	{
		/*
		 * We are recursively calling this function.  If it does not start
		 * with "com" or a line continuation character, we have moved off
		 * the command line and should let the other routines parse this file.
		 */
		cmdProcessed = FALSE;
		goto cleanUp;
	}

	/*
	 * Strip off any spaces and options which are part of the command.
	 * These should preceed the command name.
	 */
	do
	{
		if (isspace ((int) *cp))
		{
			++cp;
		}
		else if (*cp == '-')
		{
			/* 
			 * Read until the next space which separates options or the name
			 */
			while (*cp && !isspace ((int) *cp))
				++cp; 
		}
	} while ( *cp &&  !isalnum ((int) *cp) );

	if ( ! *cp )
	{
		/*
		 * We have reached the end of the line without finding the command name.
		 * Read the next line and continue processing it as a command.
		 */
		line = readVimLine();
		parseCommand(line);
		goto cleanUp;
	}

	do
	{
		vStringPut (name, (int) *cp);
		++cp;
	} while (isalnum ((int) *cp)  ||  *cp == '_');

	vStringTerminate (name);
	makeSimpleTag (name, VimKinds, K_COMMAND);
	vStringClear (name);

cleanUp:
	vStringDelete (name);

	return cmdProcessed;
}
Esempio n. 17
0
/* Function format:
 * "fn" <ident>[<type_bounds>] "(" [<args>] ")" ["->" <ret_type>] "{" [<body>] "}"*/
static void parseFn (lexerState *lexer, vString *scope, int parent_kind)
{
	int kind = (parent_kind == K_TRAIT || parent_kind == K_IMPL) ? K_METHOD : K_FN;
	vString *name;
	vString *arg_list;
	unsigned long line;
	fpos_t pos;
	int paren_level = 0;
	boolean found_paren = FALSE;
	boolean valid_signature = TRUE;

	advanceToken(lexer, TRUE);
	if (lexer->cur_token != TOKEN_IDENT)
		return;

	name = vStringNewCopy(lexer->token_str);
	arg_list = vStringNew();

	line = lexer->line;
	pos = lexer->pos;

	advanceToken(lexer, TRUE);

	/* HACK: This is a bit coarse as far as what tag entry means by
	 * 'arglist'... */
	while (lexer->cur_token != '{' && lexer->cur_token != ';')
	{
		if (lexer->cur_token == '}')
		{
			valid_signature = FALSE;
			break;
		}
		else if (lexer->cur_token == '(')
		{
			found_paren = TRUE;
			paren_level++;
		}
		else if (lexer->cur_token == ')')
		{
			paren_level--;
			if (paren_level < 0)
			{
				valid_signature = FALSE;
				break;
			}
		}
		else if (lexer->cur_token == TOKEN_EOF)
		{
			valid_signature = FALSE;
			break;
		}
		writeCurTokenToStr(lexer, arg_list);
		advanceToken(lexer, FALSE);
	}
	if (!found_paren || paren_level != 0)
		valid_signature = FALSE;

	if (valid_signature)
	{
		vStringStripTrailing(arg_list);
		addTag(name, arg_list->buffer, kind, line, pos, scope, parent_kind);
		addToScope(scope, name);
		parseBlock(lexer, TRUE, kind, scope);
	}

	vStringDelete(name);
	vStringDelete(arg_list);
}
Esempio n. 18
0
static boolean parseMap (const unsigned char *line)
{
	vString *name = vStringNew ();

	const unsigned char *cp = line;

	/* Remove map */
	while (*cp && isalnum ((int) *cp))
		++cp;

	if ((int) *cp == '!')
		++cp;

	/*
	 * Maps follow this basic format
	 *     map 
     *    nnoremap <silent> <F8> :Tlist<CR>
     *    map <unique> <Leader>scdt <Plug>GetColumnDataType
     *    inoremap ,,, <esc>diwi<<esc>pa><cr></<esc>pa><esc>kA
     *    inoremap <buffer> ( <C-R>=PreviewFunctionSignature()<LF> 
	 *
	 * The Vim help shows the various special arguments available to a map:
	 * 1.2 SPECIAL ARGUMENTS					*:map-arguments*
     *    <buffer>
	 *    <silent>
	 *    <script>
	 *    <unique>
	 *    <special>
	 *    <expr>
	 *
	 * Strip the special arguments from the map command, this should leave
	 * the map name which we will use as the "name".
	 */
	
	do
	{
		while (*cp && isspace ((int) *cp))
			++cp; 

		if (strncmp ((const char*) cp, "<Leader>", (size_t) 8) == 0)
			break;
	
		if (
				strncmp ((const char*) cp, "<buffer>", (size_t) 8) == 0 ||
				strncmp ((const char*) cp, "<silent>", (size_t) 8) == 0 ||
				strncmp ((const char*) cp, "<script>", (size_t) 8) == 0 ||
				strncmp ((const char*) cp, "<unique>", (size_t) 8) == 0
		   )
		{
			cp += 8;
			continue;
		}
	
		if (strncmp ((const char*) cp, "<expr>", (size_t) 6) == 0)
		{
			cp += 6;
			continue;
		}
	
		if (strncmp ((const char*) cp, "<special>", (size_t) 9) == 0)
		{
			cp += 9;
			continue;
		}
	
		break;
	} while (*cp);

	do
	{
		vStringPut (name, (int) *cp);
		++cp;
	} while (*cp && *cp != ' ');

	vStringTerminate (name);
	makeSimpleTag (name, VimKinds, K_MAP);
	vStringClear (name);

	vStringDelete (name);

	return TRUE;
}
Esempio n. 19
0
File: make.c Progetto: Monits/ctags
static void findMakeTags (void)
{
	stringList *identifiers = stringListNew ();
	boolean newline = TRUE;
	boolean in_define = FALSE;
	boolean in_rule = FALSE;
	boolean variable_possible = TRUE;
	int c;

	while ((c = nextChar ()) != EOF)
	{
		if (newline)
		{
			if (in_rule)
			{
				if (c == '\t' || (c = skipToNonWhite (c)) == '#')
				{
					skipLine ();  /* skip rule or comment */
					c = nextChar ();
				}
				else if (c != '\n')
					in_rule = FALSE;
			}
			stringListClear (identifiers);
			variable_possible = (boolean)(!in_rule);
			newline = FALSE;
		}
		if (c == '\n')
			newline = TRUE;
		else if (isspace (c))
			continue;
		else if (c == '#')
			skipLine ();
		else if (variable_possible && c == '?')
		{
			c = nextChar ();
			fileUngetc (c);
			variable_possible = (c == '=');
		}
		else if (variable_possible && c == ':' &&
				 stringListCount (identifiers) > 0)
		{
			c = nextChar ();
			fileUngetc (c);
			if (c != '=')
			{
				unsigned int i;
				for (i = 0; i < stringListCount (identifiers); i++)
					newTarget (stringListItem (identifiers, i));
				stringListClear (identifiers);
				in_rule = TRUE;
			}
		}
		else if (variable_possible && c == '=' &&
				 stringListCount (identifiers) == 1)
		{
			newMacro (stringListItem (identifiers, 0));
			skipLine ();
			in_rule = FALSE;
		}
		else if (variable_possible && isIdentifier (c))
		{
			vString *name = vStringNew ();
			readIdentifier (c, name);
			stringListAdd (identifiers, name);

			if (stringListCount (identifiers) == 1)
			{
				if (in_define && ! strcmp (vStringValue (name), "endef"))
					in_define = FALSE;
				else if (in_define)
					skipLine ();
				else if (! strcmp (vStringValue (name), "define"))
				{
					in_define = TRUE;
					c = skipToNonWhite (nextChar ());
					vStringClear (name);
					/* all remaining characters on the line are the name -- even spaces */
					while (c != EOF && c != '\n')
					{
						vStringPut (name, c);
						c = nextChar ();
					}
					if (c == '\n')
						fileUngetc (c);
					vStringTerminate (name);
					vStringStripTrailing (name);
					newMacro (name);
				}
				else if (! strcmp (vStringValue (name), "export"))
					stringListClear (identifiers);
			}
		}
		else
			variable_possible = FALSE;
	}
	stringListDelete (identifiers);
}
Esempio n. 20
0
static void parseVimBallFile (const unsigned char *line)
{
	vString *fname = vStringNew ();
	const unsigned char *cp;
	int file_line_count;
	int i;

	/*
	 * Vimball Archives follow this format
	 *    " Vimball Archiver comment
	 *    UseVimball
	 *    finish
	 *    filename
	 *    line count (n) for filename
	 *    (n) lines
	 *    filename
	 *    line count (n) for filename
	 *    (n) lines
	 *    ...
	 */

	/* Next line should be "finish" */
	line = readVimLine();
	if (line == NULL)
	{
		return;
	}
	while (line != NULL)
	{
		/* Next line should be a filename */
		line = readVimLine();
		if (line == NULL)
		{
			return;
		}
		else
		{
			cp = line;
			do
			{
				vStringPut (fname, (int) *cp);
				++cp;
			} while (isalnum ((int) *cp) ||  *cp == '.' ||  *cp == '/' ||	*cp == '\\');
			vStringTerminate (fname);
			makeSimpleTag (fname, VimKinds, K_FILENAME);
			vStringClear (fname);
		}

		file_line_count = 0;
		/* Next line should be the line count of the file */
		line = readVimLine();
		if (line == NULL)
		{
			return;
		}
		else
		{
			file_line_count = atoi( (const char *) line );
		}

		/* Read all lines of the file */
		for ( i=0; i<file_line_count; i++ )
		{
			line = readVimballLine();
			if (line == NULL)
			{
				return;
			}
		}
	}

	vStringDelete (fname);
}
Esempio n. 21
0
extern void openTagFile (void)
{
        setDefaultTagFileName ();
        TagsToStdout = isDestinationStdout ();

        if (TagFile.vLine == NULL)
                TagFile.vLine = vStringNew ();

        /*  Open the tags file.
         */
        if (TagsToStdout)
                TagFile.fp = tempFile ("w", &TagFile.name);
        else
        {
                boolean fileExists;

                setDefaultTagFileName ();
                TagFile.name = eStrdup (Option.tagFileName);
                fileExists = doesFileExist (TagFile.name);
                if (fileExists  &&  ! isTagFile (TagFile.name))
                        error (FATAL,
                          "\"%s\" doesn't look like a tag file; I refuse to overwrite it.",
                                  TagFile.name);

                if (Option.etags)
                {
                        if (Option.append  &&  fileExists)
                                TagFile.fp = fopen (TagFile.name, "a+b");
                        else
                                TagFile.fp = fopen (TagFile.name, "w+b");
                }
                else
                {
                        if (Option.append  &&  fileExists)
                        {
                                TagFile.fp = fopen (TagFile.name, "r+");
                                if (TagFile.fp != NULL)
                                {
                                        TagFile.numTags.prev = updatePseudoTags (TagFile.fp);
                                        fclose (TagFile.fp);
                                        TagFile.fp = fopen (TagFile.name, "a+");
                                }
                        }
                        else
                        {
                                TagFile.fp = fopen (TagFile.name, "w");
                                if (TagFile.fp != NULL)
                                        addPseudoTags ();
                        }
                }
                if (TagFile.fp == NULL)
                {
                        error (FATAL | PERROR, "cannot open tag file");
                        exit (1);
                }
        }
        if (TagsToStdout)
                TagFile.directory = eStrdup (CurrentDirectory);
        else
                TagFile.directory = absoluteDirname (TagFile.name);
}
Esempio n. 22
0
static void findHxTags (void)
{
	vString *name = vStringNew ();
	vString *clsName = vStringNew();
	vString *scope2 = vStringNew();
	vString *laccess = vStringNew();
	const char *const priv = "private";
	const char *const pub = "public";

	const unsigned char *line;

	while ((line = readLineFromInputFile ()) != NULL)
	{
		const unsigned char *cp = line;
another:
		while (isspace (*cp))
			cp++;

		vStringCopyS(laccess,priv);

		if (strncmp ((const char*) cp, "var", (size_t) 3) == 0  &&
			isspace ((int) cp [3]))
		{
			cp += 3;

			while (isspace ((int) *cp))
				++cp;

			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_VARIABLE);

			vStringClear (name);
		}
		else if (strncmp ((const char*) cp, "function", (size_t) 8) == 0  &&
			isspace ((int) cp [8]))
		{
			cp += 8;

			while (isspace ((int) *cp))
				++cp;

			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_METHODS);

			vStringClear (name);
		}
		else if (strncmp ((const char*) cp, "class", (size_t) 5) == 0 &&
				 isspace ((int) cp [5]))
		{
			cp += 5;

			while (isspace ((int) *cp))
				++cp;
			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_CLASS);
			vStringCopy(clsName,name);
			vStringClear (name);
		}
		else if (strncmp ((const char*) cp, "enum", (size_t) 4) == 0 &&
				  isspace ((int) cp [4]))
		{
			cp += 4;

			while (isspace ((int) *cp))
				++cp;
			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_')
			{
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_ENUM);
			vStringClear (name);
		} else if (strncmp ((const char*) cp, "public", (size_t) 6) == 0 &&
				 isspace((int) cp [6]))
		{
			cp += 6;
			while (isspace ((int) *cp))
				++cp;
			vStringCopyS(laccess,pub);
			goto another;
		} else if (strncmp ((const char*) cp, "static", (size_t) 6) == 0 &&
				 isspace((int) cp [6]))
		{
			cp += 6;
			while (isspace ((int) *cp))
				++cp;
			goto another;
		} else if (strncmp ((const char*) cp, "interface", (size_t) 9) == 0 &&
			isspace((int) cp [9]))
		{
			cp += 9;

			while (isspace ((int) *cp))
				++cp;
			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_') {
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_INTERFACE);
			vStringClear (name);
		} else if (strncmp ((const char *) cp,"typedef",(size_t) 7) == 0 && isspace(((int) cp[7]))) {
			cp += 7;

			while (isspace ((int) *cp))
				++cp;
			vStringClear (name);
			while (isalnum ((int) *cp)  ||  *cp == '_') {
				vStringPut (name, (int) *cp);
				++cp;
			}
			vStringTerminate (name);
			makeSimpleTag (name, HxKinds, HXTAG_TYPEDEF);
			vStringClear (name);
		}


	}

	vStringDelete(name);
	vStringDelete(clsName);
	vStringDelete(scope2);
	vStringDelete(laccess);
}
Esempio n. 23
0
		e.lineNumber	= token->lineNumber;
		e.filePosition	= token->filePosition;

		if (xtag != XTAG_UNKNOWN)
			markTagExtraBit (&e, xtag);

		return makeTagEntry (&e);
	}

	return CORK_NIL;
}

static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
{
	tokenInfo *token = xMalloc (1, tokenInfo);
	token->string = vStringNew ();
	return token;
}

static void deletePoolToken (void *data)
{
	tokenInfo *token = data;
	vStringDelete (token->string);
	eFree (token);
}

static void clearPoolToken (void *data)
{
	tokenInfo *token = data;

	token->type			= TOKEN_UNDEFINED;
Esempio n. 24
0
static void findSdlTags (void)
{
    vString *name = vStringNew() ;
	const unsigned char *line;

	sdlKind kindNow = K_UNDEFINED ;

	while ((line = fileReadLine ()) != NULL)
	{
		const unsigned char *cp = line;

		skipWhitespace (&cp);

		if (canMatch (&cp, "TOKEN"))
		{
		    kindNow = K_TOKEN ;
            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (isspace ((int) *cp)) ++cp;
            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }
		}
		else if (canMatch (&cp, "ELINK"))
		{
		    kindNow = K_ELINK ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }
		}
		else if (canMatch (&cp, "PATH"))
		{
		    kindNow = K_PATH ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }

		}
		else if (canMatch (&cp, "MODULE"))
		{
		    kindNow = K_MODULE ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }

		}
		else if (canMatch (&cp, "IRQLINK"))
		{
		    kindNow = K_IRQLINK ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }

		}
		else if (canMatch (&cp, "IODEVICE"))
		{
		    kindNow = K_IODEVICE ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Name")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }

		}
		else if (canMatch (&cp, "PCIDEVICE"))
		{
		    kindNow = K_PCIDEVICE ;

            do{
                cp = fileReadLine() ;
                while (isspace ((int) *cp)) ++cp;
            
            }while(!canMatch(&cp,"Title")) ;

            cp+=4 ;

            while (*cp != '\0')
            {
                vStringPut (name, (int) *cp);
                ++cp;
            }

		}

        vStringTerminate (name);
        makeSimpleTag (name, sdlKinds, kindNow);
        vStringClear (name);

		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 (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 (*cp == '"')
			{
				/* Skip string literals.
				 * FIXME: should cope with escapes and interpolation.
				 */
				do {
					++cp;
				} while (*cp != 0 && *cp != '"');
			}
			else if (*cp != '\0')
			{
				do
					++cp;
				while (isalnum (*cp) || *cp == '_');
			}
		}
	}
}
Esempio n. 25
0
/* Algorithm adapted from from GNU etags.
 * Locates tags for procedures & functions.  Doesn't do any type- or
 * var-definitions.  It does look for the keyword "extern" or "forward"
 * immediately following the procedure statement; if found, the tag is
 * skipped.
 */
static void findPascalTags (void)
{
    vString *name = vStringNew ();
    tagEntryInfo tag;
    char *arglist = NULL;
    char *vartype = NULL;
    pascalKind kind = K_FUNCTION;
				/* each of these flags is TRUE iff: */
    boolean incomment = FALSE;	/* point is inside a comment */
    int comment_char = '\0';    /* type of current comment */
    boolean inquote = FALSE;	/* point is inside '..' string */
    boolean get_tagname = FALSE;/* point is after PROCEDURE/FUNCTION
				    keyword, so next item = potential tag */
    boolean found_tag = FALSE;	/* point is after a potential tag */
    boolean inparms = FALSE;	/* point is within parameter-list */
    boolean verify_tag = FALSE;	/* point has passed the parm-list, so the
				   next token will determine whether this
				   is a FORWARD/EXTERN to be ignored, or
				   whether it is a real tag */

    dbp = fileReadLine ();
    while (dbp != NULL)
    {
	int c = *dbp++;

	if (c == '\0')		/* if end of line */
	{
	    dbp = fileReadLine ();
	    if (dbp == NULL  ||  *dbp == '\0')
		continue;
	    if (!((found_tag && verify_tag) || get_tagname))
		c = *dbp++;		/* only if don't need *dbp pointing
				    to the beginning of the name of
				    the procedure or function */
	}
	if (incomment)
	{
	    if (comment_char == '{' && c == '}')
		incomment = FALSE;
	    else if (comment_char == '(' && c == '*' && *dbp == ')')
	    {
		dbp++;
		incomment = FALSE;
	    }
	    continue;
	}
	else if (inquote)
	{
	    if (c == '\'')
		inquote = FALSE;
	    continue;
	}
	else switch (c)
	{
	    case '\'':
		inquote = TRUE;	/* found first quote */
		continue;
	    case '{':		/* found open { comment */
		incomment = TRUE;
		comment_char = c;
		continue;
	    case '(':
		if (*dbp == '*')	/* found open (* comment */
		{
		    incomment = TRUE;
		    comment_char = c;
		    dbp++;
		}
		else if (found_tag)  /* found '(' after tag, i.e., parm-list */
		    inparms = TRUE;
		continue;
	    case ')':		/* end of parms list */
		if (inparms)
		    inparms = FALSE;
		continue;
	    case ';':
		if (found_tag && !inparms) /* end of proc or fn stmt */
		{
		    verify_tag = TRUE;
		    break;
		}
		continue;
	}
	if (found_tag && verify_tag && *dbp != ' ')
	{
	    /* check if this is an "extern" declaration */
	    if (*dbp == '\0')
		continue;
	    if (tolower ((int) *dbp == 'e'))
	    {
		if (tail ("extern"))	/* superfluous, really! */
		{
		    found_tag = FALSE;
		    verify_tag = FALSE;
		}
	    }
	    else if (tolower ((int) *dbp) == 'f')
	    {
		if (tail ("forward"))	/*  check for forward reference */
		{
		    found_tag = FALSE;
		    verify_tag = FALSE;
		}
	    }
	    else if (tolower ((int) *dbp) == 't')
	    {
		if (tail ("type"))	/*  check for forward reference */
		{
		    found_tag = FALSE;
		    verify_tag = FALSE;
		}
	    }
	    if (found_tag && verify_tag) /* not external proc, so make tag */
	    {
		found_tag = FALSE;
		verify_tag = FALSE;
		makePascalTag (&tag);
		continue;
	    }
	}
	if (get_tagname)		/* grab name of proc or fn */
	{
	    const unsigned char *cp;

	    if (*dbp == '\0')
		continue;

	    /* grab block name */
	    while (isspace ((int) *dbp))
		++dbp;
	    for (cp = dbp  ;  *cp != '\0' && !endtoken (*cp)  ;  cp++)
		continue;
	    vStringNCopyS (name, (const char*) dbp,  cp - dbp);
	    if (arglist != NULL)
		eFree(arglist);
	    if (kind == K_FUNCTION && vartype != NULL)
		eFree(vartype);
	    parseArglist((const char*) cp, &arglist, (kind == K_FUNCTION) ? &vartype : NULL);
	    createPascalTag (&tag, name, kind, arglist, (kind == K_FUNCTION) ? vartype : NULL);
	    dbp = cp;		/* set dbp to e-o-token */
	    get_tagname = FALSE;
	    found_tag = TRUE;
	    /* and proceed to check for "extern" */
	}
	else if (!incomment && !inquote && !found_tag)
	{
	    switch (tolower ((int) c))
	    {
		case 'c':
		    if (tail ("onstructor"))
		    {
			get_tagname = TRUE;
			kind = K_PROCEDURE;
		    }
		    break;
		case 'd':
		    if (tail ("estructor"))
		    {
			get_tagname = TRUE;
			kind = K_PROCEDURE;
		    }
		    break;
		case 'p':
		    if (tail ("rocedure"))
		    {
			get_tagname = TRUE;
			kind = K_PROCEDURE;
		    }
		    break;
		case 'f':
		    if (tail ("unction"))
		    {
			get_tagname = TRUE;
			kind = K_FUNCTION;
		    }
		    break;
		case 't':
		    if (tail ("ype"))
		    {
			get_tagname = TRUE;
			kind = K_FUNCTION;
		    }
		    break;
	    }
	}  /* while not eof */
    }
    if (arglist != NULL)
	eFree(arglist);
    if (vartype != NULL)
	eFree(vartype);
    vStringDelete(name);
}
Esempio n. 26
0
static vString* extractVimFileType(FILE* input)
{
	/* http://vimdoc.sourceforge.net/htmldoc/options.html#modeline

	   [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
	   options=> filetype=TYPE or ft=TYPE

	   'modelines' 'mls'	number	(default 5)
			global
			{not in Vi}
	    If 'modeline' is on 'modelines' gives the number of lines that is
	    checked for set commands. */

	vString* filetype = NULL;
#define RING_SIZE 5
	vString* ring[RING_SIZE];
	int i, j;
	unsigned int k;
	const char* const prefix[] = {
		"vim:", "vi:", "ex:"
	};

	for (i = 0; i < RING_SIZE; i++)
		ring[i] = vStringNew ();

	i = 0;
	while ((readLine (ring[i++], input)) != NULL)
		if (i == RING_SIZE)
			i = 0;

	j = i;
	do
	{
		const char* p;

		j--;
		if (j < 0)
			j = RING_SIZE - 1;

		for (k = 0; k < ARRAY_SIZE(prefix); k++)
			if ((p = strstr (vStringValue (ring[j]), prefix[k])) != NULL)
			{
				p += strlen(prefix[k]);
				for ( ;  isspace ((int) *p)  ;  ++p)
					;  /* no-op */
				filetype = determineVimFileType(p);
				break;
			}
	} while (((i == RING_SIZE)? (j != RING_SIZE - 1): (j != i)) && (!filetype));

	for (i = RING_SIZE - 1; i >= 0; i--)
		vStringDelete (ring[i]);
#undef RING_SIZE

	if (filetype && (vStringLength (filetype) == 0))
	{
		vStringDelete (filetype);
		filetype = NULL;
	}
	return filetype;

	/* TODO:
	   [text]{white}{vi:|vim:|ex:}[white]{options} */
}
Esempio n. 27
0
File: entry.c Progetto: jonthn/ctags
extern void openTagFile (void)
{
	setDefaultTagFileName ();
	TagsToStdout = isDestinationStdout ();

	if (TagFile.vLine == NULL)
		TagFile.vLine = vStringNew ();

	/*  Open the tags file.
	 */
	if (TagsToStdout)
	{
		/* Open a tempfile with read and write mode. Read mode is used when
		 * write the result to stdout. */
		TagFile.fp = tempFile ("w+", &TagFile.name);
		if (isXtagEnabled (XTAG_PSEUDO_TAGS))
			addPseudoTags ();
	}
	else
	{
		boolean fileExists;

		TagFile.name = eStrdup (Option.tagFileName);
		fileExists = doesFileExist (TagFile.name);
		if (fileExists  &&  ! isTagFile (TagFile.name))
			error (FATAL,
			  "\"%s\" doesn't look like a tag file; I refuse to overwrite it.",
				  TagFile.name);

		if (Option.etags)
		{
			if (Option.append  &&  fileExists)
				TagFile.fp = fopen (TagFile.name, "a+b");
			else
				TagFile.fp = fopen (TagFile.name, "w+b");
		}
		else
		{
			if (Option.append  &&  fileExists)
			{
				TagFile.fp = fopen (TagFile.name, "r+");
				if (TagFile.fp != NULL)
				{
					TagFile.numTags.prev = updatePseudoTags (TagFile.fp);
					fclose (TagFile.fp);
					TagFile.fp = fopen (TagFile.name, "a+");
				}
			}
			else
			{
				TagFile.fp = fopen (TagFile.name, "w");
				if (TagFile.fp != NULL && isXtagEnabled (XTAG_PSEUDO_TAGS))
					addPseudoTags ();
			}
		}
		if (TagFile.fp == NULL)
			error (FATAL | PERROR, "cannot open tag file");
	}
	if (TagsToStdout)
		TagFile.directory = eStrdup (CurrentDirectory);
	else
		TagFile.directory = absoluteDirname (TagFile.name);
}
Esempio n. 28
0
static void findHaskellTags (int is_literate)
{
    vString *name = vStringNew ();
    char token[1001], arg[1001];
    int c;
    int in_tex_lit_code = 0;
    c = get_next_char();

    while (c != EOF)
    {
	if (c == '\n') {
	    c = get_next_char();
	    continue;
	}

	if (isspace(c)) {
	    skip_rest_of_line();
	    c = get_next_char();
	    continue;
	}
        if (is_literate && !in_tex_lit_code) {
            if (c == '>') {
                c = fileGetc();
                if (c == ' ') {
                    c = get_next_char();
		    if (!isident(c)) {
			    skip_rest_of_line();
			    c = get_next_char();
			    continue;
		    }
                } else {
                    skip_rest_of_line();
                    c = get_next_char();
                    continue;
                }
            } else if (c == '\\') {
                int n = get_line(token);
                if (strncmp(token, "begin{code}", 11) == 0) {
                    in_tex_lit_code = 1;
                    c = get_next_char();
                    continue;
		} else {
		    if (n > 0 && token[n-1] != '\n')
			skip_rest_of_line();
		    else
			c = get_next_char();
		}
		continue;
            } else {
                skip_rest_of_line();
                c = get_next_char();
                continue;
            }   
        }
        if (is_literate && in_tex_lit_code && c == '\\') {
            if (strncmp(token, "end{code}", 9) == 0) {
                in_tex_lit_code = 0;
                c = get_next_char();
                continue;
            }
        }
	token[0] = c;
	token[1] = '\0';
	if (!isident(c)) {
		skip_rest_of_line();
		c = get_next_char();
		continue;
	}
	if (!get_token(token, 1)) {
		c = get_next_char();
		continue;
	}
	do {
	    if ((c = fileGetc()) == EOF)
		return;
	} while (c == ' ' || c == '\t');
	arg[0] = c;
	get_token(arg, 1);
	if (strcmp(token, "data") == 0 || strcmp(token, "newtype") == 0) {
	    add_tag(arg, K_TYPE, name);
	    c = inside_datatype(name);
	    continue;
	}
	if (strcmp(token, "type") == 0)
	    add_tag(arg, K_TYPE, name);
	else if (strcmp(token, "module") == 0)
	    add_tag(arg, K_MODULE, name);
	else if (strcmp(token, "instance") == 0 ||
		 strcmp(token, "foreign") == 0 ||
		 strcmp(token, "import") == 0)
	    ;
	else {
	    if (arg[0] != ':')
		add_tag(token, K_FUNCTION, name);
	}
	skip_rest_of_line();
	c = get_next_char();
    }
    vStringDelete(name);
}
Esempio n. 29
0
static void findDiffTags (void)
{
    vString *filename = vStringNew ();
    vString *hunk = vStringNew ();
    const unsigned char *line, *tmp;
    int delim = DIFF_DELIM_MINUS;
    diffKind kind;
    int scope_index = SCOPE_NIL;

    while ((line = fileReadLine ()) != NULL)
    {
        const unsigned char* cp = line;

        if (strncmp ((const char*) cp, DiffDelims[delim], 4u) == 0)
        {
            scope_index = SCOPE_NIL;
            cp += 4;
            if (isspace ((int) *cp)) continue;
            /* when original filename is /dev/null use the new one instead */
            if (delim == DIFF_DELIM_MINUS &&
                    strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
                    (cp[9] == 0 || isspace (cp[9])))
            {
                delim = DIFF_DELIM_PLUS;
                continue;
            }

            tmp = stripAbsolute (cp);

            if (tmp != NULL)
            {
                while (! isspace(*tmp) && *tmp != '\0')
                {
                    vStringPut(filename, *tmp);
                    tmp++;
                }

                vStringTerminate(filename);
                if (delim == DIFF_DELIM_PLUS)
                    kind = K_NEW_FILE;
                else
                    kind = K_MODIFIED_FILE;
                scope_index = makeSimpleTag (filename, DiffKinds, kind);
                vStringClear (filename);
            }

            /* restore default delim */
            delim = DIFF_DELIM_MINUS;
        }
        else if ((scope_index > SCOPE_NIL)
                 && (strncmp ((const char*) cp, DiffDelims[1], 4u) == 0))
        {
            cp += 4;
            if (isspace ((int) *cp)) continue;
            /* when modified filename is /dev/null, the original name is deleted. */
            if (strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
                    (cp[9] == 0 || isspace (cp[9])))
                markTheLastTagAsDeletedFile (scope_index);
        }
        else if (strncmp ((const char*) cp, HunkDelim[0], 3u) == 0)
        {
            if (parseHunk (cp, hunk, scope_index) != SCOPE_NIL)
                vStringClear (hunk);
        }
    }
    vStringDelete (hunk);
    vStringDelete (filename);
}
Esempio n. 30
0
/* Algorithm adapted from from GNU etags.
 * Perl support by Bart Robinson <*****@*****.**>
 * Perl sub names: look for /^ [ \t\n]sub [ \t\n]+ [^ \t\n{ (]+/
 */
static void findPerlTags (void)
{
	vString *name = vStringNew ();
	vString *package = NULL;
	bool skipPodDoc = false;
	const unsigned char *line;

	while ((line = readLineFromInputFile ()) != NULL)
	{
		bool spaceRequired = false;
		bool qualified = false;
		const unsigned char *cp = line;
		perlKind kind = K_NONE;
		tagEntryInfo e;

		if (skipPodDoc)
		{
			if (strncmp ((const char*) line, "=cut", (size_t) 4) == 0)
				skipPodDoc = false;
			continue;
		}
		else if (line [0] == '=')
		{
			skipPodDoc = isPodWord ((const char*)line + 1);
			continue;
		}
		else if (strcmp ((const char*) line, "__DATA__") == 0)
			break;
		else if (strcmp ((const char*) line, "__END__") == 0)
			break;
		else if (line [0] == '#')
			continue;

		while (isspace (*cp))
			cp++;

		if (strncmp((const char*) cp, "sub", (size_t) 3) == 0)
		{
			TRACE("this looks like a sub\n");
			cp += 3;
			kind = K_SUBROUTINE;
			spaceRequired = true;
			qualified = true;
		}
		else if (strncmp((const char*) cp, "use", (size_t) 3) == 0)
		{
			cp += 3;
			if (!isspace(*cp))
				continue;
			while (*cp && isspace (*cp))
				++cp;
			if (strncmp((const char*) cp, "constant", (size_t) 8) != 0)
				continue;
			cp += 8;
			kind = K_CONSTANT;
			spaceRequired = true;
			qualified = true;
		}
		else if (strncmp((const char*) cp, "package", (size_t) 7) == 0)
		{
			/* This will point to space after 'package' so that a tag
			   can be made */
			const unsigned char *space = cp += 7;

			if (package == NULL)
				package = vStringNew ();
			else
				vStringClear (package);
			while (isspace (*cp))
				cp++;
			while ((int) *cp != ';'  &&  !isspace ((int) *cp))
			{
				vStringPut (package, (int) *cp);
				cp++;
			}
			vStringCatS (package, "::");

			cp = space;	 /* Rewind */
			kind = K_PACKAGE;
			spaceRequired = true;
			qualified = true;
		}
		else if (strncmp((const char*) cp, "format", (size_t) 6) == 0)
		{
			cp += 6;
			kind = K_FORMAT;
			spaceRequired = true;
			qualified = true;
		}
		else
		{
			if (isIdentifier1 (*cp))
			{
				const unsigned char *p = cp;
				while (isIdentifier (*p))
					++p;
				while (isspace (*p))
					++p;
				if ((int) *p == ':' && (int) *(p + 1) != ':')
					kind = K_LABEL;
			}
		}
		if (kind != K_NONE)
		{
			TRACE("cp0: %s\n", (const char *) cp);
			if (spaceRequired && *cp && !isspace (*cp))
				continue;

			TRACE("cp1: %s\n", (const char *) cp);
			while (isspace (*cp))
				cp++;

			while (!*cp || '#' == *cp) { /* Gobble up empty lines
				                            and comments */
				cp = readLineFromInputFile ();
				if (!cp)
					goto END_MAIN_WHILE;
				while (isspace (*cp))
					cp++;
			}

			while (isIdentifier (*cp) || (K_PACKAGE == kind && ':' == *cp))
			{
				vStringPut (name, (int) *cp);
				cp++;
			}

			if (K_FORMAT == kind &&
				vStringLength (name) == 0 && /* cp did not advance */
				'=' == *cp)
			{
				/* format's name is optional.  If it's omitted, 'STDOUT'
				   is assumed. */
				vStringCatS (name, "STDOUT");
			}

			TRACE("name: %s\n", name->buffer);

			if (0 == vStringLength(name)) {
				vStringClear(name);
				continue;
			}

			if (K_SUBROUTINE == kind)
			{
				/*
				 * isSubroutineDeclaration() may consume several lines.  So
				 * we record line positions.
				 */
				initTagEntry(&e, vStringValue(name), &(PerlKinds[kind]));

				if (true == isSubroutineDeclaration(cp)) {
					if (true == PerlKinds[K_SUBROUTINE_DECLARATION].enabled) {
						kind = K_SUBROUTINE_DECLARATION;
					} else {
						vStringClear (name);
						continue;
					}
				}

				makeTagEntry(&e);

				if (isXtagEnabled(XTAG_QUALIFIED_TAGS) && qualified &&
					package != NULL  && vStringLength (package) > 0)
				{
					vString *const qualifiedName = vStringNew ();
					vStringCopy (qualifiedName, package);
					vStringCat (qualifiedName, name);
					e.name = vStringValue(qualifiedName);
					makeTagEntry(&e);
					vStringDelete (qualifiedName);
				}
			} else if (vStringLength (name) > 0)
			{
				makeSimpleTag (name, PerlKinds, kind);
				if (isXtagEnabled(XTAG_QUALIFIED_TAGS) && qualified &&
					K_PACKAGE != kind &&
					package != NULL  && vStringLength (package) > 0)
				{
					vString *const qualifiedName = vStringNew ();
					vStringCopy (qualifiedName, package);
					vStringCat (qualifiedName, name);
					makeSimpleTag (qualifiedName, PerlKinds, kind);
					vStringDelete (qualifiedName);
				}
			}
			vStringClear (name);
		}
	}

END_MAIN_WHILE:
	vStringDelete (name);
	if (package != NULL)
		vStringDelete (package);
}