⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fortran.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	     * character blank.
	     */
	    if (c == ' '  ||  c == '0')
		type = LTYPE_INITIAL;

	    /* 3.2.3  Continuation_Line.  A continuation line is any line that
	     * contains any character of the FORTRAN character set other than
	     * the character blank or the digit 0 in column 6 and contains
	     * only blank characters in columns 1 through 5.
	     */
	    else if (vStringLength (label) == 0)
		type = LTYPE_CONTINUATION;
	    else
		type = LTYPE_INVALID;
	}
	else if (c == ' ')
	    ;
	else if (c == EOF)
	    type = LTYPE_EOF;
	else if (c == '\n')
	    type = LTYPE_SHORT;
	else if (isdigit (c))
	    vStringPut (label, c);
	else
	    type = LTYPE_INVALID;

	++column;
    } while (column < 6  &&  type == LTYPE_UNDETERMINED);

    Assert (type != LTYPE_UNDETERMINED);

    if (vStringLength (label) > 0)
    {
	vStringTerminate (label);
	makeLabelTag (label);
	vStringClear (label);
    }
    return type;
}

static int getFixedFormChar (void)
{
    boolean newline = FALSE;
    lineType type;
    int c = '\0';

    if (Column > 0)
    {
#ifdef STRICT_FIXED_FORM
	/*  EXCEPTION! Some compilers permit more than 72 characters per line.
	 */
	if (Column > 71)
	    c = skipLine ();
	else
#endif
	{
	    c = fileGetc ();
	    ++Column;
	}
	if (c == '\n')
	{
	    newline = TRUE;	/* need to check for continuation line */
	    Column = 0;
	}
	else if (c == '!'  &&  ! ParsingString)
	{
	    c = skipLine ();
	    newline = TRUE;	/* need to check for continuation line */
	    Column = 0;
	}
	else if (c == '&')	/* check for free source form */
	{
	    const int c2 = fileGetc ();
	    if (c2 == '\n')
		longjmp (Exception, (int) ExceptionFixedFormat);
	    else
		fileUngetc (c2);
	}
    }
    while (Column == 0)
    {
	type = getLineType ();
	switch (type)
	{
	    case LTYPE_UNDETERMINED:
	    case LTYPE_INVALID:
		longjmp (Exception, (int) ExceptionFixedFormat);
		break;

	    case LTYPE_SHORT: break;
	    case LTYPE_COMMENT: skipLine (); break;

	    case LTYPE_EOF:
		Column = 6;
		if (newline)
		    c = '\n';
		else
		    c = EOF;
		break;

	    case LTYPE_INITIAL:
		if (newline)
		{
		    c = '\n';
		    Column = 6;
		    break;
		}
		/* fall through to next case */
	    case LTYPE_CONTINUATION:
		Column = 5;
		do
		{
		    c = fileGetc ();
		    ++Column;
		} while (isBlank (c));
		if (c == '\n')
		    Column = 0;
		else if (Column > 6)
		{
		    fileUngetc (c);
		    c = ' ';
		}
		break;

	    default:
		Assert ("Unexpected line type" == NULL);
	}
    }
    return c;
}

static int skipToNextLine (void)
{
    int c = skipLine ();
    if (c != EOF)
	c = fileGetc ();
    return c;
}

static int getFreeFormChar (void)
{
    static boolean newline = TRUE;
    boolean advanceLine = FALSE;
    int c = fileGetc ();

    /* If the last nonblank, non-comment character of a FORTRAN 90
     * free-format text line is an ampersand then the next non-comment
     * line is a continuation line.
     */
    if (c == '&')
    {
	do
	    c = fileGetc ();
	while (isspace (c)  &&  c != '\n');
	if (c == '\n')
	{
	    newline = TRUE;
	    advanceLine = TRUE;
	}
	else if (c == '!')
	    advanceLine = TRUE;
	else
	{
	    fileUngetc (c);
	    c = '&';
	}
    }
    else if (newline && (c == '!' || c == '#'))
	advanceLine = TRUE;
    while (advanceLine)
    {
	while (isspace (c))
	    c = fileGetc ();
	if (c == '!' || (newline && c == '#'))
	{
	    c = skipToNextLine ();
	    newline = TRUE;
	    continue;
	}
	if (c == '&')
	    c = fileGetc ();
	else
	    advanceLine = FALSE;
    }
    newline = (boolean) (c == '\n');
    return c;
}

static int getChar (void)
{
    int c;

    if (Ungetc != '\0')
    {
	c = Ungetc;
	Ungetc = '\0';
    }
    else if (FreeSourceForm)
	c = getFreeFormChar ();
    else
	c = getFixedFormChar ();

    return c;
}

static void ungetChar (const int c)
{
    Ungetc = c;
}

/*  If a numeric is passed in 'c', this is used as the first digit of the
 *  numeric being parsed.
 */
static vString *parseInteger (int c)
{
    static vString *string = NULL;

    if (string == NULL)
	string = vStringNew ();
    vStringClear (string);

    if (c == '-')
    {
	vStringPut (string, c);
	c = getChar ();
    }
    else if (! isdigit (c))
	c = getChar ();
    while (c != EOF  &&  isdigit (c))
    {
	vStringPut (string, c);
	c = getChar ();
    }
    vStringTerminate (string);

    if (c == '_')
    {
	do
	    c = getChar ();
	while (c != EOF  &&  isalpha (c));
    }
    ungetChar (c);

    return string;
}

static vString *parseNumeric (int c)
{
    static vString *string = NULL;

    if (string == NULL)
	string = vStringNew ();
    vStringCopy (string, parseInteger (c));

    c = getChar ();
    if (c == '.')
    {
	vStringPut (string, c);
	vStringCat (string, parseInteger ('\0'));
	c = getChar ();
    }
    if (tolower (c) == 'e')
    {
	vStringPut (string, c);
	vStringCat (string, parseInteger ('\0'));
    }
    else
	ungetChar (c);

    vStringTerminate (string);

    return string;
}

static void parseString (vString *const string, const int delimeter)
{
    const unsigned long inputLineNumber = getInputLineNumber ();
    int c;
    ParsingString = TRUE;
    c = getChar ();
    while (c != delimeter  &&  c != '\n'  &&  c != EOF)
    {
	vStringPut (string, c);
	c = getChar ();
    }
    if (c == '\n'  ||  c == EOF)
    {
	verbose ("%s: unterminated character string at line %lu\n",
		getInputFileName (), inputLineNumber);
	if (c == EOF)
	    longjmp (Exception, (int) ExceptionEOF);
	else if (! FreeSourceForm)
	    longjmp (Exception, (int) ExceptionFixedFormat);
    }
    vStringTerminate (string);
    ParsingString = FALSE;
}

/*  Read a C identifier beginning with "firstChar" and places it into "name".
 */
static void parseIdentifier (vString *const string, const int firstChar)
{
    int c = firstChar;

    do
    {
	vStringPut (string, c);
	c = getChar ();
    } while (isident (c));

    vStringTerminate (string);
    ungetChar (c);		/* unget non-identifier character */
}

/*  Analyzes the identifier contained in a statement described by the
 *  statement structure and adjusts the structure according the significance
 *  of the identifier.
 */
static keywordId analyzeToken (vString *const name)
{
    static vString *keyword = NULL;
    keywordId id;

    if (keyword == NULL)
	keyword = vStringNew ();
    vStringCopyToLower (keyword, name);
    id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_fortran);

    return id;
}

static void checkForLabel (void)
{
    tokenInfo* token = NULL;
    int length;
    int c;

    do
	c = getChar ();
    while (isBlank (c));

    for (length = 0  ;  isdigit (c)  &&  length < 5  ;  ++length)
    {
	if (token == NULL)
	{
	    token = newToken ();
	    token->type = TOKEN_LABEL;
	}
	vStringPut (token->string, c);
	c = getChar ();
    }
    if (length > 0)
    {
	Assert (token != NULL);
	vStringTerminate (token->string);
	makeFortranTag (token, TAG_LABEL);
	deleteToken (token);
    }
    ungetChar (c);
}

static void readIdentifier (tokenInfo *const token, const int c)
{
    parseIdentifier (token->string, c);
    token->keyword = analyzeToken (token->string);
    if (! isKeyword (token, KEYWORD_NONE))
	token->type = TOKEN_KEYWORD;
    else
    {
	token->type = TOKEN_IDENTIFIER;
	if (strncmp (vStringValue (token->string), "end", 3) == 0)
	{
	    vString *const sub = vStringNewInit (vStringValue (token->string) + 3);
	    const keywordId kw = analyzeToken (sub);
	    vStringDelete (sub);
	    if (kw != KEYWORD_NONE)
	    {
		token->secondary = newToken ();
		token->secondary->type = TOKEN_KEYWORD;
		token->secondary->keyword = kw;
		token->keyword = KEYWORD_end;
	    }
	}
    }
}

static void readToken (tokenInfo *const token)
{
    int c;

    deleteToken (token->secondary);
    token->type        = TOKEN_UNDEFINED;
    token->tag         = TAG_UNDEFINED;
    token->keyword     = KEYWORD_NONE;
    token->secondary   = NULL;
    vStringClear (token->string);

getNextChar:
    c = getChar ();

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

    switch (c)
    {
	case EOF:  longjmp (Exception, (int) ExceptionEOF);	break;
	case ' ':  goto getNextChar;
	case '\t': goto getNextChar;
	case ',':  token->type = TOKEN_COMMA;		break;
	case '(':  token->type = TOKEN_PAREN_OPEN;	break;
	case ')':  token->type = TOKEN_PAREN_CLOSE;	break;
	case '%':  token->type = TOKEN_PERCENT;		break;

	case '*':
	case '/':
	case '+':
	case '-':
	case '=':
	case '<':
	case '>':
	{
	    const char *const operatorChars = "*/+=<>";
	    do {
		vStringPut (token->string, c);
		c = getChar ();
	    } while (strchr (operatorChars, c) != NULL);
	    ungetChar (c);
	    vStringTerminate (token->string);
	    token->type = TOKEN_OPERATOR;
	    break;
	}

	case '!':
	    if (FreeSourceForm)
	    {
		do
		   c = getChar ();
		while (c != '\n');
	    }
	    else
	    {
		skipLine ();
		Column = 0;
	    }
	    /* fall through to newline case */
	case '\n':
	    token->type = TOKEN_STATEMENT_END;
	    if (FreeSourceForm)
		checkForLabel ();
	    break;

	case '.':
	    parseIdentifier (token->string, c);
	    c = getChar ();
	    if (c == '.')
	    {
		vStringPut (token->string, c);
		vStringTerminate (token->string);
		token->type = TOKEN_OPERATOR;
	    }
	    else
	    {
		ungetChar (c);
		token->type = TOKEN_UNDEFINED;
	    }
	    break;

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

	case ';':
	    token->type = TOKEN_STATEMENT_END;
	    break;

	case ':':
	    c = getChar ();
	    if (c == ':')
		token->type = TOKEN_DOUBLE_COLON;
	    else
	    {
		ungetChar (c);
		token->type = TOKEN_UNDEFINED;
	    }
	    break;

	default:
	    if (isalpha (c))
		readIdentifier (token, c);
	    else if (isdigit (c))
	    {
		vStringCat (token->string, parseNumeric (c));
		token->type = TOKEN_NUMERIC;
	    }
	    else
		token->type = TOKEN_UNDEFINED;
	    break;
    }
}

static void readSubToken (tokenInfo *const token)
{
    if (token->secondary == NULL)
    {
	token->secondary = newToken ();
	readToken (token->secondary);
    }
    Assert (token->secondary != NULL);
}

/*
*   Scanning functions
*/

static void skipToToken (tokenInfo *const token, tokenType type)
{
    while (! isType (token, type) && ! isType (token, TOKEN_STATEMENT_END) &&
	    !(token->secondary != NULL && isType (token->secondary, TOKEN_STATEMENT_END)))
	readToken (token);
}

static void skipPast (tokenInfo *const token, tokenType type)
{
    skipToToken (token, type);
    if (! isType (token, TOKEN_STATEMENT_END))
	readToken (token);
}

static void skipToNextStatement (tokenInfo *const token)
{
    do
    {
	skipToToken (token, TOKEN_STATEMENT_END);
	readToken (token);
    } while (isType (token, TOKEN_STATEMENT_END));
}

/* skip over parenthesis enclosed contents starting at next token.
 * Token is left at the first token following closing parenthesis. If an
 * opening parenthesis is not found, `token' is moved to the end of the
 * statement.
 */
static void skipOverParens (tokenInfo *const token)
{
    int level = 0;
    do {
	if (isType (token, TOKEN_STATEMENT_END))
	    break;
	else if (isType (token, TOKEN_PAREN_OPEN))
	    ++level;
	else if (isType (token, TOKEN_PAREN_CLOSE))
	    --level;
	readToken (token);
    } while (level > 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -