Example #1
0
void QScriptCompletionTaskPrivate::completeScriptExpression()
{
    int pos = cursorPosition;
    if ((pos > 0) && contents.at(pos-1).isNumber()) {
        // completion of numbers is pointless
        emitFinished();
        return;
    }

    while ((pos > 0) && isIdentChar(contents.at(pos-1)))
        --pos;
    int pos2 = cursorPosition - 1;
    while ((pos2+1 < contents.size()) && isIdentChar(contents.at(pos2+1)))
        ++pos2;
    QString ident = contents.mid(pos, pos2 - pos + 1);
    position = pos;

    QStringList path;
    path.append(ident);
    while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) {
        --pos;
        pos2 = pos;
        while ((pos > 0) && isIdentChar(contents.at(pos-1)))
            --pos;
        path.prepend(contents.mid(pos, pos2 - pos));
    }

    length = path.last().length();
    type = QScriptCompletionTask::ScriptIdentifierCompletion;

    QScriptDebuggerJob *job = new QScriptCompleteExpressionJob(frameIndex, path, this, commandScheduler);
    jobScheduler->scheduleJob(job);
}
Example #2
0
/*!
  \reimp
*/
bool QScriptDebuggerCodeView::event(QEvent *e)
{
    Q_D(QScriptDebuggerCodeView);
    if (e->type() == QEvent::ToolTip) {
        if (d->editor->executionLineNumber() == -1)
            return false;
        QHelpEvent *he = static_cast<QHelpEvent*>(e);
        QPoint pt = he->pos();
        pt.rx() -= d->editor->extraAreaWidth();
        pt.ry() -= 8;
        QTextCursor cursor = d->editor->cursorForPosition(pt);
        QTextBlock block = cursor.block();
        QString contents = block.text();
        if (contents.isEmpty())
            return false;
        int linePosition = cursor.position() - block.position();
        linePosition -= 3;
        if (linePosition < 0)
            linePosition = 0;

        // ### generalize -- same as in completiontask

        int pos = linePosition;
        if ((pos > 0) && contents.at(pos-1).isNumber()) {
            // tooltips for numbers is pointless
            return false;
        }

        while ((pos > 0) && isIdentChar(contents.at(pos-1)))
            --pos;
        if ((pos > 0) && ((contents.at(pos-1) == QLatin1Char('\''))
                          || (contents.at(pos-1) == QLatin1Char('\"')))) {
            // ignore string literals
            return false;
        }
        int pos2 = linePosition;
        while ((pos2 < contents.size()-1) && isIdentChar(contents.at(pos2+1)))
            ++pos2;
        QString ident = contents.mid(pos, pos2 - pos + 1);

        QStringList path;
        path.append(ident);
        while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) {
            --pos;
            pos2 = pos;
            while ((pos > 0) && isIdentChar(contents.at(pos-1)))
                --pos;
            path.prepend(contents.mid(pos, pos2 - pos));
        }

        if (!path.isEmpty()) {
            int lineNumber = cursor.blockNumber() + d->editor->baseLineNumber();
            emit toolTipRequest(he->globalPos(), lineNumber, path);
        }
    }
    return false;
}
Example #3
0
/*	Read a C identifier beginning with "firstChar" and places it into
 *	"name".
 */
static void parseIdentifier (vString *const string, const int firstChar)
{
	int c = firstChar;
	Assert (isIdentChar (c));
	do
	{
		vStringPut (string, c);
		c = fileGetc ();
	} while (isIdentChar (c));
	vStringTerminate (string);
	fileUngetc (c);		/* unget non-identifier character */
}
Example #4
0
QvBool
QvName::isIdentStartChar(char c)
{
    if (isdigit(c)) return FALSE;

    return isIdentChar(c);
}
Example #5
0
GvBool
GvName::isNodeNameStartChar(char c,GvBool vrml2)
{
	if (vrml2) return(isIdentStartChar(c,vrml2));

	// VRML 1.0
    // ////// if (isdigit(c)) return FALSE;

    return isIdentChar(c,vrml2);
}
Example #6
0
static void parseIdentifier (vString *const string, const int firstChar)
{
	int c = firstChar;
	do
	{
		vStringPut (string, (char) c);
		c = getcFromInputFile ();
	} while (isIdentChar (c));
	ungetcToInputFile (c);
}
Example #7
0
File: go.c Project: Dev0Null/ctags
static void parseIdentifier (vString *const string, const int firstChar)
{
	int c = firstChar;
	do
	{
		vStringPut (string, c);
		c = getcFromInputFile ();
	} while (isIdentChar (c));
	vStringTerminate (string);
	ungetcToInputFile (c);		/* always unget, LF might add a semicolon */
}
Example #8
0
/*  Read a VHDL identifier beginning with "firstChar" and place it into "name".
*/
static void parseIdentifier (vString * const string, const int firstChar)
{
	int c = firstChar;
	Assert (isIdentChar1 (c));
	do
	{
		vStringPut (string, c);
		c = getcFromInputFile ();
	} while (isIdentChar (c));
	if (!isspace (c))
		ungetcToInputFile (c);	/* unget non-identifier character */
}
Example #9
0
GvBool
GvName::isNodeNameChar(char c,GvBool vrml2)
{
	if (vrml2) return(isIdentChar(c,vrml2));

	// VRML 1.0

    if (isalnum(c)) return TRUE;


// (0x00 .. 0x1F or 0x7F) iscntl(c) removed 7.10.96 
    if ((strchr(badCharacters, c) != NULL) || isspace(c)) 
		return FALSE;

    return TRUE;
}
Example #10
0
void processLine(char *line)
{
    char *p;
    int quoteType;
    static char fnm[300];
    char *fname;
    int nn;

    p = line;
    while(isspace(*p)) p++;
    if (!*p) goto addToMaster;
    // see if the first thing on the line is an include directive
    if (*p=='.') p++;
    if (strnicmp(p, "include", 7)==0 && !isIdentChar(p[7]))
    {
        p += 7;
        // Capture the file name
        while(isspace(*p)) p++;
        if (*p=='"') { quoteType = '"'; p++; }
        else if (*p=='<') { quoteType = '>'; p++; }
        else quoteType = ' ';
        nn = 0;
        do {
           fnm[nn] = *p;
           p++; nn++;
           if (quoteType==' ' && isspace(*p)) break;
           else if (*p == quoteType) break;
           else if (*p=='\n') break;
        } while(nn < sizeof(fnm)/sizeof(char));
        fnm[nn] = '\0';
        fname = strdup(fnm);
        processFile(fname,1);
        free(fname);
        return;
    }
    // Not an include directive, then just copy the line to the master buffer.
addToMaster:
    strcpy(&masterFile[mfndx], line);
    mfndx += strlen(line);
}
Example #11
0
static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr)
{
	int c;
	int i;

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:
	i = 0;
	do
	{
		c = fileGetc ();
		i++;
	}
	while (c == '\t'  ||  c == ' ' ||
		   ((c == '\r' || c == '\n') && ! include_newlines));

	token->lineNumber   = getSourceLineNumber ();
	token->filePosition = getInputFilePosition ();

	if (repr)
	{
		if (i > 1)
			vStringPut (repr, ' ');
		vStringPut (repr, c);
	}

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;					break;
		case '(': token->type = TOKEN_OPEN_PAREN;			break;
		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
		case ';': token->type = TOKEN_SEMICOLON;			break;
		case ',': token->type = TOKEN_COMMA;				break;
		case '.': token->type = TOKEN_PERIOD;				break;
		case ':': token->type = TOKEN_COLON;				break;
		case '{': token->type = TOKEN_OPEN_CURLY;			break;
		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
		case '=': token->type = TOKEN_EQUAL_SIGN;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;

		case '+':
		case '-':
			{
				int d = fileGetc ();
				if (d == c) /* ++ or -- */
					token->type = TOKEN_POSTFIX_OPERATOR;
				else
				{
					fileUngetc (d);
					token->type = TOKEN_BINARY_OPERATOR;
				}
				break;
			}

		case '*':
		case '%':
		case '?':
		case '>':
		case '<':
		case '^':
		case '|':
		case '&':
			token->type = TOKEN_BINARY_OPERATOR;
			break;

		case '\r':
		case '\n':
			/* This isn't strictly correct per the standard, but following the
			 * real rules means understanding all statements, and that's not
			 * what the parser currently does.  What we do here is a guess, by
			 * avoiding inserting semicolons that would make the statement on
			 * the left invalid.  Hopefully this should not have false negatives
			 * (e.g. should not miss insertion of a semicolon) but might have
			 * false positives (e.g. it will wrongfully emit a semicolon for the
			 * newline in "foo\n+bar").
			 * This should however be mostly harmless as we only deal with
			 * newlines in specific situations where we know a false positive
			 * wouldn't hurt too bad. */
			switch (LastTokenType)
			{
				/* these cannot be the end of a statement, so hold the newline */
				case TOKEN_EQUAL_SIGN:
				case TOKEN_COLON:
				case TOKEN_PERIOD:
				case TOKEN_FORWARD_SLASH:
				case TOKEN_BINARY_OPERATOR:
				/* and these already end one, no need to duplicate it */
				case TOKEN_SEMICOLON:
				case TOKEN_COMMA:
				case TOKEN_CLOSE_CURLY:
				case TOKEN_OPEN_CURLY:
					include_newlines = FALSE; /* no need to recheck */
					goto getNextChar;
					break;
				default:
					token->type = TOKEN_SEMICOLON;
			}
			break;

		case '\'':
		case '"':
				  token->type = TOKEN_STRING;
				  parseString (token->string, c);
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  if (repr)
				  {
					  vStringCat (repr, token->string);
					  vStringPut (repr, c);
				  }
				  break;

		case '\\':
				  c = fileGetc ();
				  if (c != '\\'  && c != '"'  &&  !isspace (c))
					  fileUngetc (c);
				  token->type = TOKEN_CHARACTER;
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  break;

		case '/':
				  {
					  int d = fileGetc ();
					  if ( (d != '*') &&		/* is this the start of a comment? */
							  (d != '/') )		/* is a one line comment? */
					  {
						  fileUngetc (d);
						  switch (LastTokenType)
						  {
							  case TOKEN_CHARACTER:
							  case TOKEN_IDENTIFIER:
							  case TOKEN_STRING:
							  case TOKEN_CLOSE_CURLY:
							  case TOKEN_CLOSE_PAREN:
							  case TOKEN_CLOSE_SQUARE:
								  token->type = TOKEN_FORWARD_SLASH;
								  break;

							  default:
								  token->type = TOKEN_REGEXP;
								  parseRegExp ();
								  token->lineNumber = getSourceLineNumber ();
								  token->filePosition = getInputFilePosition ();
								  break;
						  }
					  }
					  else
					  {
						  if (repr) /* remove the / we added */
							  repr->buffer[--repr->length] = 0;
						  if (d == '*')
						  {
							  do
							  {
								  skipToCharacter ('*');
								  c = fileGetc ();
								  if (c == '/')
									  break;
								  else
									  fileUngetc (c);
							  } while (c != EOF && c != '\0');
							  goto getNextChar;
						  }
						  else if (d == '/')	/* is this the start of a comment?  */
						  {
							  skipToCharacter ('\n');
							  /* if we care about newlines, put it back so it is seen */
							  if (include_newlines)
								  fileUngetc ('\n');
							  goto getNextChar;
						  }
					  }
					  break;
				  }

		case '#':
				  /* skip shebang in case of e.g. Node.js scripts */
				  if (token->lineNumber > 1)
					  token->type = TOKEN_UNDEFINED;
				  else if ((c = fileGetc ()) != '!')
				  {
					  fileUngetc (c);
					  token->type = TOKEN_UNDEFINED;
				  }
				  else
				  {
					  skipToCharacter ('\n');
					  goto getNextChar;
				  }
				  break;

		default:
				  if (! isIdentChar (c))
					  token->type = TOKEN_UNDEFINED;
				  else
				  {
					  parseIdentifier (token->string, c);
					  token->lineNumber = getSourceLineNumber ();
					  token->filePosition = getInputFilePosition ();
					  token->keyword = analyzeToken (token->string);
					  if (isKeyword (token, KEYWORD_NONE))
						  token->type = TOKEN_IDENTIFIER;
					  else
						  token->type = TOKEN_KEYWORD;
					  if (repr && vStringLength (token->string) > 1)
						  vStringCatS (repr, vStringValue (token->string) + 1);
				  }
				  break;
	}

	LastTokenType = token->type;
}
Example #12
0
GvBool
GvName::isIdentStartChar(char c,GvBool vrml2)
{
    if (isdigit(c)) return FALSE;
    return isIdentChar(c,vrml2);
}
Example #13
0
File: sh.c Project: 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);
}
Example #14
0
/**
 * evallabel replace "...%2i..." occurences in label with value of i
 */
static const char * evalLabel (const char* src, Tree visited, Tree localValEnv)
{
    //std::cerr << "Eval Label : " << src;

    int             state = 0;  // current state
    std::string     dst;        // label once evaluated
    std::string     ident;      // current identifier
    std::string     format;     // current format

    while (state != -1) {

        char c = *src++;

        if (state == 0) {

            if (c == 0) {
                state = -1;
            } else if (c == '%') {
                ident = "";
                format = "";
                state = 1;
            } else {
                dst+=c;
                state = 0;
            }

        } else if (state == 1) {

            if (c == 0) {
                // fin et pas d'indentifiant, abandon
                dst += '%';
                dst += format;
                state = -1;
            } else if (isDigitChar(c)) {
                format += c;
                state = 1;
            } else if (isIdentChar(c)) {
                ident += c;
                state = 2;
            } else {
                // caractere de ponctuation et pas d'indentifiant, abandon
                dst += '%';
                dst += format;
                src--;
                state = 0;
            }

        } else if (state == 2) {

            if (isIdentChar(c)) {
                ident += c;
                state = 2;
            } else {
                writeIdentValue(dst, format, ident, visited, localValEnv);
                src--;
                state = 0;
            }

        } else {
            stringstream error;
            error << "internal error in evallabel : undefined state " << state << std::endl;
            throw faustexception(error.str());
        }
    }

    const char* val = strdup(dst.c_str());
    //std::cerr << "  ===> " << val << std::endl;
    return val;
}
Example #15
0
static void readToken (tokenInfo *const token)
{
	int c;

	token->type		= TOKEN_UNDEFINED;
	token->keyword	= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:

	if (! InPhp)
	{
		c = findPhpStart ();
		if (c != EOF)
			InPhp = TRUE;
	}
	else
		c = getcFromInputFile ();

	c = skipWhitespaces (c);

	token->lineNumber   = getInputLineNumber ();
	token->filePosition = getInputFilePosition ();

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;					break;
		case '(': token->type = TOKEN_OPEN_PAREN;			break;
		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
		case ';': token->type = TOKEN_SEMICOLON;			break;
		case ',': token->type = TOKEN_COMMA;				break;
		case '.': token->type = TOKEN_PERIOD;				break;
		case ':': token->type = TOKEN_COLON;				break;
		case '{': token->type = TOKEN_OPEN_CURLY;			break;
		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;
		case '&': token->type = TOKEN_AMPERSAND;			break;
		case '\\': token->type = TOKEN_BACKSLASH;			break;

		case '=':
		{
			int d = getcFromInputFile ();
			if (d == '=' || d == '>')
				token->type = TOKEN_OPERATOR;
			else
			{
				ungetcToInputFile (d);
				token->type = TOKEN_EQUAL_SIGN;
			}
			break;
		}

		case '\'':
		case '"':
			token->type = TOKEN_STRING;
			parseString (token->string, c);
			token->lineNumber = getInputLineNumber ();
			token->filePosition = getInputFilePosition ();
			break;

		case '<':
		{
			int d = getcFromInputFile ();
			if (d == '/')
			{
				/* </script[:white:]*> */
				if (tolower ((d = getcFromInputFile ())) == 's' &&
					tolower ((d = getcFromInputFile ())) == 'c' &&
					tolower ((d = getcFromInputFile ())) == 'r' &&
					tolower ((d = getcFromInputFile ())) == 'i' &&
					tolower ((d = getcFromInputFile ())) == 'p' &&
					tolower ((d = getcFromInputFile ())) == 't' &&
					(d = skipWhitespaces (getcFromInputFile ())) == '>')
				{
					InPhp = FALSE;
					goto getNextChar;
				}
				else
				{
					ungetcToInputFile (d);
					token->type = TOKEN_UNDEFINED;
				}
			}
			else if (d == '<' && (d = getcFromInputFile ()) == '<')
			{
				token->type = TOKEN_STRING;
				parseHeredoc (token->string);
			}
			else
			{
				ungetcToInputFile (d);
				token->type = TOKEN_UNDEFINED;
			}
			break;
		}

		case '#': /* comment */
			skipSingleComment ();
			goto getNextChar;
			break;

		case '+':
		case '-':
		case '*':
		case '%':
		{
			int d = getcFromInputFile ();
			if (d != '=' && ! (c == '-' && d == '>'))
				ungetcToInputFile (d);
			token->type = TOKEN_OPERATOR;
			break;
		}

		case '/': /* division or comment start */
		{
			int d = getcFromInputFile ();
			if (d == '/') /* single-line comment */
			{
				skipSingleComment ();
				goto getNextChar;
			}
			else if (d == '*')
			{
				do
				{
					c = skipToCharacter ('*');
					if (c != EOF)
					{
						c = getcFromInputFile ();
						if (c == '/')
							break;
						else
							ungetcToInputFile (c);
					}
				} while (c != EOF && c != '\0');
				goto getNextChar;
			}
			else
			{
				if (d != '=')
					ungetcToInputFile (d);
				token->type = TOKEN_OPERATOR;
			}
			break;
		}

		case '$': /* variable start */
		{
			int d = getcFromInputFile ();
			if (! isIdentChar (d))
			{
				ungetcToInputFile (d);
				token->type = TOKEN_UNDEFINED;
			}
			else
			{
				parseIdentifier (token->string, d);
				token->type = TOKEN_VARIABLE;
			}
			break;
		}

		case '?': /* maybe the end of the PHP chunk */
		{
			int d = getcFromInputFile ();
			if (d == '>')
			{
				InPhp = FALSE;
				goto getNextChar;
			}
			else
			{
				ungetcToInputFile (d);
				token->type = TOKEN_UNDEFINED;
			}
			break;
		}

		default:
			if (! isIdentChar (c))
				token->type = TOKEN_UNDEFINED;
			else
			{
				parseIdentifier (token->string, c);
				token->keyword = analyzeToken (token->string, getInputLanguage ());
				if (token->keyword == KEYWORD_NONE)
					token->type = TOKEN_IDENTIFIER;
				else
					token->type = TOKEN_KEYWORD;
			}
			break;
	}

	if (token->type == TOKEN_SEMICOLON ||
		token->type == TOKEN_OPEN_CURLY ||
		token->type == TOKEN_CLOSE_CURLY)
	{
		/* reset current statement details on statement end, and when entering
		 * a deeper scope.
		 * it is a bit ugly to do this in readToken(), but it makes everything
		 * a lot simpler. */
		CurrentStatement.access = ACCESS_UNDEFINED;
		CurrentStatement.impl = IMPL_UNDEFINED;
	}
}
Example #16
0
/* reads an HereDoc or a NowDoc (the part after the <<<).
 * 	<<<[ \t]*(ID|'ID'|"ID")
 * 	...
 * 	ID;?
 *
 * note that:
 *  1) starting ID must be immediately followed by a newline;
 *  2) closing ID is the same as opening one;
 *  3) closing ID must be immediately followed by a newline or a semicolon
 *     then a newline.
 *
 * Example of a *single* valid heredoc:
 * 	<<< FOO
 * 	something
 * 	something else
 * 	FOO this is not an end
 * 	FOO; this isn't either
 * 	FOO; # neither this is
 * 	FOO;
 * 	# previous line was the end, but the semicolon wasn't required
 */
static void parseHeredoc (vString *const string)
{
	int c;
	unsigned int len;
	char delimiter[64]; /* arbitrary limit, but more is crazy anyway */
	int quote = 0;

	do
	{
		c = getcFromInputFile ();
	}
	while (c == ' ' || c == '\t');

	if (c == '\'' || c == '"')
	{
		quote = c;
		c = getcFromInputFile ();
	}
	for (len = 0; len < ARRAY_SIZE (delimiter) - 1; len++)
	{
		if (! isIdentChar (c))
			break;
		delimiter[len] = (char) c;
		c = getcFromInputFile ();
	}
	delimiter[len] = 0;

	if (len == 0) /* no delimiter, give up */
		goto error;
	if (quote)
	{
		if (c != quote) /* no closing quote for quoted identifier, give up */
			goto error;
		c = getcFromInputFile ();
	}
	if (c != '\r' && c != '\n') /* missing newline, give up */
		goto error;

	do
	{
		c = getcFromInputFile ();

		if (c != '\r' && c != '\n')
			vStringPut (string, (char) c);
		else
		{
			/* new line, check for a delimiter right after */
			int nl = c;
			int extra = EOF;

			c = getcFromInputFile ();
			for (len = 0; c != 0 && (c - delimiter[len]) == 0; len++)
				c = getcFromInputFile ();

			if (delimiter[len] != 0)
				ungetcToInputFile (c);
			else
			{
				/* line start matched the delimiter, now check whether there
				 * is anything after it */
				if (c == '\r' || c == '\n')
				{
					ungetcToInputFile (c);
					break;
				}
				else if (c == ';')
				{
					int d = getcFromInputFile ();
					if (d == '\r' || d == '\n')
					{
						/* put back the semicolon since it's not part of the
						 * string.  we can't put back the newline, but it's a
						 * whitespace character nobody cares about it anyway */
						ungetcToInputFile (';');
						break;
					}
					else
					{
						/* put semicolon in the string and continue */
						extra = ';';
						ungetcToInputFile (d);
					}
				}
			}
			/* if we are here it wasn't a delimiter, so put everything in the
			 * string */
			vStringPut (string, (char) nl);
			vStringNCatS (string, delimiter, len);
			if (extra != EOF)
				vStringPut (string, (char) extra);
		}
	}
	while (c != EOF);

	vStringTerminate (string);

	return;

error:
	ungetcToInputFile (c);
}
Example #17
0
/*
* Copies the characters forming an identifier from *cp into
* name, leaving *cp pointing to the character after the identifier.
*/
static rubyKind parseIdentifier (
		const unsigned char** cp, vString* name, rubyKind kind)
{
	/* Method names are slightly different to class and variable names.
	 * A method name may optionally end with a question mark, exclamation
	 * point or equals sign. These are all part of the name.
	 * A method name may also contain a period if it's a singleton method.
	 */
	boolean had_sep = FALSE;
	const char* also_ok;
	if (kind == K_METHOD)
	{
		also_ok = ".?!=";
	}
	else if (kind == K_SINGLETON)
	{
		also_ok = "?!=";
	}
	else
	{
		also_ok = "";
	}

	skipWhitespace (cp);

	/* Check for an anonymous (singleton) class such as "class << HTTP". */
	if (kind == K_CLASS && **cp == '<' && *(*cp + 1) == '<')
	{
		return K_UNDEFINED;
	}

	/* Check for operators such as "def []=(key, val)". */
	if (kind == K_METHOD || kind == K_SINGLETON)
	{
		if (parseRubyOperator (name, cp))
		{
			return kind;
		}
	}

	/* Copy the identifier into 'name'. */
	while (**cp != 0 && (**cp == ':' || isIdentChar (**cp) || charIsIn (**cp, also_ok)))
	{
		char last_char = **cp;

		if (last_char == ':')
			had_sep = TRUE;
		else
		{
			if (had_sep)
			{
				vStringPut (name, SCOPE_SEPARATOR);
				had_sep = FALSE;
			}
			vStringPut (name, last_char);
		}
		++*cp;

		if (kind == K_METHOD)
		{
			/* Recognize singleton methods. */
			if (last_char == '.')
			{
				vStringTerminate (name);
				vStringClear (name);
				return parseIdentifier (cp, name, K_SINGLETON);
			}
		}

		if (kind == K_METHOD || kind == K_SINGLETON)
		{
			/* Recognize characters which mark the end of a method name. */
			if (charIsIn (last_char, "?!="))
			{
				break;
			}
		}
	}
	return kind;
}
Example #18
0
static void readToken (tokenInfo *const token)
{
	int c;

	token->type		= TOKEN_UNDEFINED;
	vStringClear (token->string);

getNextChar:

	c = getcFromInputFile ();
	c = skipWhitespaces (c);

	token->lineNumber   = getInputLineNumber ();
	token->filePosition = getInputFilePosition ();

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;					break;
		case '(': token->type = TOKEN_OPEN_PAREN;			break;
		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
		case ';': token->type = TOKEN_SEMICOLON;			break;
		case ',': token->type = TOKEN_COMMA;				break;
		case '.': token->type = TOKEN_PERIOD;				break;
		case ':': token->type = TOKEN_COLON;				break;
		case '{': token->type = TOKEN_OPEN_CURLY;			break;
		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;
		case '=': token->type = TOKEN_EQUAL_SIGN;			break;

		case '\'':
		case '"':
			token->type = TOKEN_STRING;
			parseString (token->string, c);
			token->lineNumber = getInputLineNumber ();
			token->filePosition = getInputFilePosition ();
			break;

		case '<':
		{
			int d = getcFromInputFile ();
			if (d == '#')
			{
				/* <# ... #> multiline comment */
				do
				{
					c = skipToCharacterInInputFile ('#');
					if (c != EOF)
					{
						c = getcFromInputFile ();
						if (c == '>')
							break;
						else
							ungetcToInputFile (c);
					}
				} while (c != EOF);
				goto getNextChar;
			}
			else
			{
				ungetcToInputFile (d);
				token->type = TOKEN_UNDEFINED;
			}
			break;
		}

		case '#': /* comment */
			skipSingleComment ();
			goto getNextChar;
			break;

		case '+':
		case '-':
		case '*':
		case '/':
		case '%':
		{
			int d = getcFromInputFile ();
			if (d != '=')
				ungetcToInputFile (d);
			token->type = TOKEN_OPERATOR;
			break;
		}

		case '$': /* variable start */
		{
			int d = getcFromInputFile ();
			if (! isIdentChar (d))
			{
				ungetcToInputFile (d);
				token->type = TOKEN_UNDEFINED;
			}
			else
			{
				parseIdentifier (token->string, d);
				token->type = TOKEN_VARIABLE;
			}
			break;
		}

		default:
			if (! isIdentChar (c))
				token->type = TOKEN_UNDEFINED;
			else
			{
				parseIdentifier (token->string, c);
				if (isTokenFunction (token->string))
					token->type = TOKEN_KEYWORD;
				else
					token->type = TOKEN_IDENTIFIER;
			}
			break;
	}
}
Example #19
0
static void readToken (tokenInfo *const token)
{
	int c;

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:
	do
	{
		c = fileGetc ();
	}
	while (c == '\t'  ||  c == ' ' ||  c == '\n');

	token->lineNumber   = getSourceLineNumber ();
	token->filePosition = getInputFilePosition ();

	switch (c)
	{
		case EOF: longjmp (Exception, (int)ExceptionEOF);	break;
		case '(': token->type = TOKEN_OPEN_PAREN;			break;
		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
		case ';': token->type = TOKEN_SEMICOLON;			break;
		case ',': token->type = TOKEN_COMMA;				break;
		case '.': token->type = TOKEN_PERIOD;				break;
		case ':': token->type = TOKEN_COLON;				break;
		case '{': token->type = TOKEN_OPEN_CURLY;			break;
		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
		case '=': token->type = TOKEN_EQUAL_SIGN;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;

		case '\'':
		case '"':
				  token->type = TOKEN_STRING;
				  parseString (token->string, c);
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  break;

		case '\\':
				  c = fileGetc ();
				  if (c != '\\'  && c != '"'  &&  !isspace (c))
					  fileUngetc (c);
				  token->type = TOKEN_CHARACTER;
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  break;

		case '/':
				  {
					  int d = fileGetc ();
					  if ( (d != '*') &&		/* is this the start of a comment? */
							  (d != '/') )		/* is a one line comment? */
					  {
						  fileUngetc (d);
						  switch (LastTokenType)
						  {
							  case TOKEN_CHARACTER:
							  case TOKEN_KEYWORD:
							  case TOKEN_IDENTIFIER:
							  case TOKEN_STRING:
							  case TOKEN_CLOSE_CURLY:
							  case TOKEN_CLOSE_PAREN:
							  case TOKEN_CLOSE_SQUARE:
								  token->type = TOKEN_FORWARD_SLASH;
								  break;

							  default:
								  token->type = TOKEN_REGEXP;
								  parseRegExp ();
								  token->lineNumber = getSourceLineNumber ();
								  token->filePosition = getInputFilePosition ();
								  break;
						  }
					  }
					  else
					  {
						  if (d == '*')
						  {
							  do
							  {
								  skipToCharacter ('*');
								  c = fileGetc ();
								  if (c == '/')
									  break;
								  else
									  fileUngetc (c);
							  } while (c != EOF && c != '\0');
							  goto getNextChar;
						  }
						  else if (d == '/')	/* is this the start of a comment?  */
						  {
							  skipToCharacter ('\n');
							  goto getNextChar;
						  }
					  }
					  break;
				  }

		default:
				  if (! isIdentChar (c))
					  token->type = TOKEN_UNDEFINED;
				  else
				  {
					  parseIdentifier (token->string, c);
					  token->lineNumber = getSourceLineNumber ();
					  token->filePosition = getInputFilePosition ();
					  token->keyword = analyzeToken (token->string);
					  if (isKeyword (token, KEYWORD_NONE))
						  token->type = TOKEN_IDENTIFIER;
					  else
						  token->type = TOKEN_KEYWORD;
				  }
				  break;
	}

	LastTokenType = token->type;
}
Example #20
0
/*
 * Extract a list of features from a table.
 */
static List *
analyzeTable(const char * table)
{
  static char fileName[MAXSTRING];
  char ** resolved;
  List * features = NULL;
  FileInfo info;
  int k;
  resolved = resolveTable(table, NULL);
  if (resolved == NULL)
    {
      logMessage(LOG_ERROR, "Cannot resolve table '%s'", table);
      return NULL;
    }
  sprintf(fileName, "%s", *resolved);
  k = 0;
  for (k = 0; resolved[k]; k++)
    free(resolved[k]);
  free(resolved);
  if (k > 1)
    {
      logMessage(LOG_ERROR, "Table '%s' resolves to more than one file", table);
      return NULL;
    }
  info.fileName = fileName;
  info.encoding = noEncoding;
  info.status = 0;
  info.lineNumber = 0;
  if ((info.in = fopen(info.fileName, "rb")))
    {
      while (getALine(&info))
	{
	  if (info.linelen == 0);
	  else if (info.line[0] == '#')
	    {
	      if (info.linelen >= 2 && info.line[1] == '+')
		{
		  widechar * key = NULL;
		  widechar * val = NULL;
		  size_t keySize = 0;
		  size_t valSize = 0;
		  info.linepos = 2;
		  if (info.linepos < info.linelen && isIdentChar(info.line[info.linepos]))
		    {
		      key = &info.line[info.linepos];
		      keySize = 1;
		      info.linepos++;
		      while (info.linepos < info.linelen && isIdentChar(info.line[info.linepos]))
			{
			  keySize++;
			  info.linepos++;
			}
		      if (info.linepos < info.linelen && info.line[info.linepos] == ':')
			{
			  info.linepos++;
			  while (info.linepos < info.linelen
				 && (info.line[info.linepos] == ' ' || info.line[info.linepos] == '\t'))
			    info.linepos++;
			  if (info.linepos < info.linelen && isIdentChar(info.line[info.linepos]))
			    {
			      val = &info.line[info.linepos];
			      valSize = 1;
			      info.linepos++;
			      while (info.linepos < info.linelen && isIdentChar(info.line[info.linepos]))
				{
				  valSize++;
				  info.linepos++;
				}
			    }
			  else
			    goto compile_error;
			}
		      if (info.linepos == info.linelen)
			{
			  char * k = widestrToStr(key, keySize);
			  char * v = val ? widestrToStr(val, valSize) : NULL;
			  Feature f = feature_new(k, v);
			  logMessage(LOG_DEBUG, "Table has feature '%s:%s'", f.key, f.val);
			  features = list_conj(features, memcpy(malloc(sizeof(f)), &f, sizeof(f)),
					       NULL, NULL, (void (*)(void *))feature_free);
			  free(k);
			  free(v);
			}
		      else
			goto compile_error;
		    }
		  else
		    goto compile_error;
		}
	    }
	  else
	    break;
	}
      fclose(info.in);
    }
  else
    logMessage (LOG_ERROR, "Cannot open table '%s'", info.fileName);
  return list_sort(features, (int (*)(void *, void *))cmpKeys);
 compile_error:
  if (info.linepos < info.linelen)
    logMessage(LOG_ERROR, "Unexpected character '%c' on line %d, column %d",
	       info.line[info.linepos],
	       info.lineNumber,
	       info.linepos);
  else
    logMessage(LOG_ERROR, "Unexpected newline on line %d", info.lineNumber);
  list_free(features);
  return NULL;
}
Example #21
0
/*
 * Parse a table query into a list of features. Features defined first get a
 * higher importance.
 */
static List *
parseQuery(const char * query)
{
  List * features = NULL;
  const char * key = NULL;
  const char * val = NULL;
  size_t keySize = 0;
  size_t valSize = 0;
  const char * c;
  int pos = 0;
  while (1)
    {
      c = &query[pos++];
      if (*c == ' ' || *c == '\t' || *c == '\n' | *c == '\0')
	{
	  if (key)
	    {
	      char * k = strndup(key, keySize);
	      char * v = val ? strndup(val, valSize) : NULL;
	      FeatureWithImportance f = { feature_new(k, v), 0 };
	      logMessage(LOG_DEBUG, "Query has feature '%s:%s'", f.feature.key, f.feature.val);
	      features = list_conj(features, memcpy(malloc(sizeof(f)), &f, sizeof(f)),
				   NULL, NULL, (void (*)(void *))feature_free);
	      free(k);
	      free(v);
	      key = val = NULL;
	      keySize = valSize = 0;
	    }
	  if (*c == '\0')
	    break;
	}
      else if (*c == ':')
	{
	  if (!key || val)
	    goto compile_error;
	  else
	    {
	      c = &query[pos++];
	      if (isIdentChar(*c))
		{
		  val = c;
		  valSize = 1;
		}
	      else
		goto compile_error;
	    }
	}
      else if (isIdentChar(*c))
	{
	  if (val)
	    valSize++;
	  else if (key)
	    keySize++;
	  else
	    {
	      key = c;
	      keySize = 1;
	    }
	}
      else
	goto compile_error;
    }
  int k = 1;
  List * l;
  for (l = features; l; l = l->tail)
    {
      FeatureWithImportance * f = l->head;
      f->importance = k++;
    }
  return list_sort(features, (int (*)(void *, void *))cmpKeys);
 compile_error:
  logMessage(LOG_ERROR, "Unexpected character '%c' at position %d", c, pos);
  list_free(features);
  return NULL;
}
Example #22
0
static void readTokenFull (tokenInfo *const token,
						   boolean includeStringRepr)
{
	int c;

	token->type = TOKEN_UNDEFINED;
	vStringClear (token->string);

	do
		c = getcFromInputFile ();
	while (c == '\t' || c == ' ' || c == '\r' || c == '\n');

	token->lineNumber   = getInputLineNumber ();
	token->filePosition = getInputFilePosition ();

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;	break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;	break;
		case '{': token->type = TOKEN_OPEN_CURLY;	break;
		case '}': token->type = TOKEN_CLOSE_CURLY;	break;
		case ':': token->type = TOKEN_COLON;		break;
		case ',': token->type = TOKEN_COMMA;		break;

		case '"':
		{
			boolean escaped = FALSE;
			token->type = TOKEN_STRING;
			while (TRUE)
			{
				c = getcFromInputFile ();
				/* we don't handle unicode escapes but they are safe */
				if (escaped)
					escaped = FALSE;
				else if (c == '\\')
					escaped = TRUE;
				else if (c >= 0x00 && c <= 0x1F)
					break; /* break on invalid, unescaped, control characters */
				else if (c == '"' || c == EOF)
					break;
				if (includeStringRepr)
					vStringPut (token->string, c);
			}
			vStringTerminate (token->string);
			break;
		}

		default:
			if (! isIdentChar (c))
				token->type = TOKEN_UNDEFINED;
			else
			{
				do
				{
					vStringPut (token->string, c);
					c = getcFromInputFile ();
				}
				while (c != EOF && isIdentChar (c));
				vStringTerminate (token->string);
				ungetcToInputFile (c);
				switch (lookupKeyword (vStringValue (token->string), Lang_json))
				{
					case KEYWORD_true:	token->type = TOKEN_TRUE;	break;
					case KEYWORD_false:	token->type = TOKEN_FALSE;	break;
					case KEYWORD_null:	token->type = TOKEN_NULL;	break;
					default:			token->type = TOKEN_NUMBER;	break;
				}
			}
			break;
	}
}
Example #23
0
static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr)
{
	int c;
	int i;
	boolean newline_encountered = FALSE;

	/* if we've got a token held back, emit it */
	if (NextToken)
	{
		copyToken (token, NextToken, FALSE);
		deleteToken (NextToken);
		NextToken = NULL;
		return;
	}

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:
	i = 0;
	do
	{
		c = fileGetc ();
		if (include_newlines && (c == '\r' || c == '\n'))
			newline_encountered = TRUE;
		i++;
	}
	while (c == '\t' || c == ' ' || c == '\r' || c == '\n');

	token->lineNumber   = getSourceLineNumber ();
	token->filePosition = getInputFilePosition ();

	if (repr)
	{
		if (i > 1)
			vStringPut (repr, ' ');
		vStringPut (repr, c);
	}

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;					break;
		case '(': token->type = TOKEN_OPEN_PAREN;			break;
		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
		case ';': token->type = TOKEN_SEMICOLON;			break;
		case ',': token->type = TOKEN_COMMA;				break;
		case '.': token->type = TOKEN_PERIOD;				break;
		case ':': token->type = TOKEN_COLON;				break;
		case '{': token->type = TOKEN_OPEN_CURLY;			break;
		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
		case '=': token->type = TOKEN_EQUAL_SIGN;			break;
		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;

		case '+':
		case '-':
			{
				int d = fileGetc ();
				if (d == c) /* ++ or -- */
					token->type = TOKEN_POSTFIX_OPERATOR;
				else
				{
					fileUngetc (d);
					token->type = TOKEN_BINARY_OPERATOR;
				}
				break;
			}

		case '*':
		case '%':
		case '?':
		case '>':
		case '<':
		case '^':
		case '|':
		case '&':
			token->type = TOKEN_BINARY_OPERATOR;
			break;

		case '\'':
		case '"':
				  token->type = TOKEN_STRING;
				  parseString (token->string, c);
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  if (repr)
				  {
					  vStringCat (repr, token->string);
					  vStringPut (repr, c);
				  }
				  break;

		case '`':
				  token->type = TOKEN_TEMPLATE_STRING;
				  parseTemplateString (token->string);
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  if (repr)
				  {
					  vStringCat (repr, token->string);
					  vStringPut (repr, c);
				  }
				  break;

		case '\\':
				  c = fileGetc ();
				  if (c != '\\'  && c != '"'  &&  !isspace (c))
					  fileUngetc (c);
				  token->type = TOKEN_CHARACTER;
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  break;

		case '/':
				  {
					  int d = fileGetc ();
					  if ( (d != '*') &&		/* is this the start of a comment? */
							  (d != '/') )		/* is a one line comment? */
					  {
						  fileUngetc (d);
						  switch (LastTokenType)
						  {
							  case TOKEN_CHARACTER:
							  case TOKEN_IDENTIFIER:
							  case TOKEN_STRING:
							  case TOKEN_TEMPLATE_STRING:
							  case TOKEN_CLOSE_CURLY:
							  case TOKEN_CLOSE_PAREN:
							  case TOKEN_CLOSE_SQUARE:
								  token->type = TOKEN_BINARY_OPERATOR;
								  break;

							  default:
								  token->type = TOKEN_REGEXP;
								  parseRegExp ();
								  token->lineNumber = getSourceLineNumber ();
								  token->filePosition = getInputFilePosition ();
								  break;
						  }
					  }
					  else
					  {
						  if (repr) /* remove the / we added */
							  repr->buffer[--repr->length] = 0;
						  if (d == '*')
						  {
							  do
							  {
								  fileSkipToCharacter ('*');
								  c = fileGetc ();
								  if (c == '/')
									  break;
								  else
									  fileUngetc (c);
							  } while (c != EOF && c != '\0');
							  goto getNextChar;
						  }
						  else if (d == '/')	/* is this the start of a comment?  */
						  {
							  fileSkipToCharacter ('\n');
							  /* if we care about newlines, put it back so it is seen */
							  if (include_newlines)
								  fileUngetc ('\n');
							  goto getNextChar;
						  }
					  }
					  break;
				  }

		case '#':
				  /* skip shebang in case of e.g. Node.js scripts */
				  if (token->lineNumber > 1)
					  token->type = TOKEN_UNDEFINED;
				  else if ((c = fileGetc ()) != '!')
				  {
					  fileUngetc (c);
					  token->type = TOKEN_UNDEFINED;
				  }
				  else
				  {
					  fileSkipToCharacter ('\n');
					  goto getNextChar;
				  }
				  break;

		default:
				  if (! isIdentChar (c))
					  token->type = TOKEN_UNDEFINED;
				  else
				  {
					  parseIdentifier (token->string, c);
					  token->lineNumber = getSourceLineNumber ();
					  token->filePosition = getInputFilePosition ();
					  token->keyword = analyzeToken (token->string, Lang_js);
					  if (isKeyword (token, KEYWORD_NONE))
						  token->type = TOKEN_IDENTIFIER;
					  else
						  token->type = TOKEN_KEYWORD;
					  if (repr && vStringLength (token->string) > 1)
						  vStringCatS (repr, vStringValue (token->string) + 1);
				  }
				  break;
	}

	if (include_newlines && newline_encountered)
	{
		/* This isn't strictly correct per the standard, but following the
		 * real rules means understanding all statements, and that's not
		 * what the parser currently does.  What we do here is a guess, by
		 * avoiding inserting semicolons that would make the statement on
		 * the left or right obviously invalid.  Hopefully this should not
		 * have false negatives (e.g. should not miss insertion of a semicolon)
		 * but might have false positives (e.g. it will wrongfully emit a
		 * semicolon sometimes, i.e. for the newline in "foo\n(bar)").
		 * This should however be mostly harmless as we only deal with
		 * newlines in specific situations where we know a false positive
		 * wouldn't hurt too bad. */

		/* these already end a statement, so no need to duplicate it */
		#define IS_STMT_SEPARATOR(t) ((t) == TOKEN_SEMICOLON    || \
		                              (t) == TOKEN_EOF          || \
		                              (t) == TOKEN_COMMA        || \
		                              (t) == TOKEN_CLOSE_CURLY  || \
		                              (t) == TOKEN_OPEN_CURLY)
		/* these cannot be the start or end of a statement */
		#define IS_BINARY_OPERATOR(t) ((t) == TOKEN_EQUAL_SIGN      || \
		                               (t) == TOKEN_COLON           || \
		                               (t) == TOKEN_PERIOD          || \
		                               (t) == TOKEN_BINARY_OPERATOR)

		if (! IS_STMT_SEPARATOR(LastTokenType) &&
		    ! IS_STMT_SEPARATOR(token->type) &&
		    ! IS_BINARY_OPERATOR(LastTokenType) &&
		    ! IS_BINARY_OPERATOR(token->type) &&
		    /* these cannot be followed by a semicolon */
		    ! (LastTokenType == TOKEN_OPEN_PAREN ||
		       LastTokenType == TOKEN_OPEN_SQUARE))
		{
			/* hold the token... */
			Assert (NextToken == NULL);
			NextToken = newToken ();
			copyToken (NextToken, token, FALSE);

			/* ...and emit a semicolon instead */
			token->type		= TOKEN_SEMICOLON;
			token->keyword	= KEYWORD_NONE;
			vStringClear (token->string);
			if (repr)
				vStringPut (token->string, '\n');
		}

		#undef IS_STMT_SEPARATOR
		#undef IS_BINARY_OPERATOR
	}

	LastTokenType = token->type;
}
Example #24
0
static boolean notIdentChar (int c)
{
	return ! isIdentChar (c);
}
Example #25
0
static void readToken (tokenInfo *const token)
{
    int c;

    token->type         = TOKEN_UNDEFINED;
    token->keyword      = KEYWORD_NONE;
    vStringClear (token->string);

getNextChar:
    do
    {
        c = fileGetc ();
        token->lineNumber   = getSourceLineNumber ();
        token->filePosition = getInputFilePosition ();
    }
    while (c == '\t'  ||  c == ' ' ||  c == '\n');

    switch (c)
    {
        case EOF: longjmp (Exception, (int)ExceptionEOF);   break;
        case '(': token->type = TOKEN_OPEN_PAREN;           break;
        case ')': token->type = TOKEN_CLOSE_PAREN;          break;
        case ';': token->type = TOKEN_SEMICOLON;            break;
        case ',': token->type = TOKEN_COMMA;                break;
        case '.': token->type = TOKEN_PERIOD;               break;
        case ':': token->type = TOKEN_COLON;                break;
        case '{': token->type = TOKEN_OPEN_CURLY;           break;
        case '}': token->type = TOKEN_CLOSE_CURLY;          break;
        case '=': token->type = TOKEN_EQUAL_SIGN;           break;
        case '[': token->type = TOKEN_OPEN_SQUARE;          break;
        case ']': token->type = TOKEN_CLOSE_SQUARE;         break;
        case '?': token->type = TOKEN_QUESTION_MARK;        break;
        case '*': token->type = TOKEN_STAR;                 break;

        case '\'':
        case '"':
                  token->type = TOKEN_STRING;
                  parseString (token->string, c);
                  token->lineNumber = getSourceLineNumber ();
                  token->filePosition = getInputFilePosition ();
                  break;

        case '\\':
                  /*
                   * All Tex tags start with a backslash.
                   * Check if the next character is an alpha character
                   * else it is not a potential tex tag.
                   */
                  c = fileGetc ();
                  if (! isalpha (c))
                      fileUngetc (c);
                  else
                  {
                      parseIdentifier (token->string, c);
                      token->lineNumber = getSourceLineNumber ();
                      token->filePosition = getInputFilePosition ();
                      token->keyword = analyzeToken (token->string, Lang_js);
                      if (isKeyword (token, KEYWORD_NONE))
                          token->type = TOKEN_IDENTIFIER;
                      else
                          token->type = TOKEN_KEYWORD;
                  }
                  break;

        case '%':
                  fileSkipToCharacter ('\n'); /* % are single line comments */
                  goto getNextChar;
                  break;

        default:
                  if (! isIdentChar (c))
                      token->type = TOKEN_UNDEFINED;
                  else
                  {
                      parseIdentifier (token->string, c);
                      token->lineNumber = getSourceLineNumber ();
                      token->filePosition = getInputFilePosition ();
                      token->type = TOKEN_IDENTIFIER;
                  }
                  break;
    }
}
Example #26
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);
}
Example #27
0
void processSegments()
{
    char *pinptr;
    int segment;
    
    if (verbose)
       printf("Processing segments.\r\n");
    inptr = &masterFile[0];
    pinptr = inptr;
    codendx = 0;
    datandx = 0;
    rodatandx = 0;
    tlsndx = 0;
    bssndx = 0;
    memset(codebuf,0,sizeof(codebuf));
    memset(databuf,0,sizeof(databuf));
    memset(rodatabuf,0,sizeof(rodatabuf));
    memset(tlsbuf,0,sizeof(tlsbuf));
    memset(bssbuf,0,sizeof(bssbuf));
    
    while (*inptr) {
        SkipSpaces();
        if (*inptr=='.') inptr++;
        if ((strnicmp(inptr,"code",4)==0) && !isIdentChar(inptr[4])) {
            segment = codeseg;
        }
        else if ((strnicmp(inptr,"data",4)==0) && !isIdentChar(inptr[4])) {
            segment = dataseg;
        }
        else if ((strnicmp(inptr,"rodata",6)==0) && !isIdentChar(inptr[6])) {
            segment = rodataseg;
        }
        else if ((strnicmp(inptr,"tls",3)==0) && !isIdentChar(inptr[3])) {
            segment = tlsseg;
        }
        else if ((strnicmp(inptr,"bss",3)==0) && !isIdentChar(inptr[3])) {
            segment = bssseg;
        }
        ScanToEOL();
        inptr++;
        switch(segment) {
        case codeseg:   
             strncpy(&codebuf[codendx], pinptr, inptr-pinptr);
             codendx += inptr-pinptr;
             break;
        case dataseg:
             strncpy(&databuf[datandx], pinptr, inptr-pinptr);
             datandx += inptr-pinptr;
             break;
        case rodataseg:
             strncpy(&rodatabuf[rodatandx], pinptr, inptr-pinptr);
             rodatandx += inptr-pinptr;
             break;
        case tlsseg:
             strncpy(&tlsbuf[tlsndx], pinptr, inptr-pinptr);
             tlsndx += inptr-pinptr;
             break;
        case bssseg:
             strncpy(&bssbuf[bssndx], pinptr, inptr-pinptr);
             bssndx += inptr-pinptr;
             break;
        }
        pinptr = inptr;
    }
    memset(masterFile,0,sizeof(masterFile));
    strcpy(masterFile, codebuf);
    strcat(masterFile, rodatabuf);
    strcat(masterFile, databuf);
    strcat(masterFile, bssbuf);
    strcat(masterFile, tlsbuf);
    if (debug) {
        FILE *fp;
        fp = fopen("a64-segments.asm", "w");
        if (fp) {
                fwrite(masterFile, 1, strlen(masterFile), fp);
                fclose(fp);
        }
    }
}