Add support for updating tags from a memory buffer (code merged from Anjuta).

This still doesn't work and is currently disabled. It would only work for a few filetypes like C, Fortran and JavaScript.
The current implementation is still buggy, e.g. function signature parsing is broken.

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3184 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2008-11-07 14:37:17 +00:00
parent 71523b8a2b
commit 99860e187a
14 changed files with 477 additions and 66 deletions

View File

@ -99,6 +99,7 @@ typedef struct
static void document_undo_clear(GeanyDocument *doc);
static void document_redo_add(GeanyDocument *doc, guint type, gpointer data);
static gboolean update_tags_from_buffer(GeanyDocument *doc);
/* ignore the case of filenames and paths under WIN32, causes errors if not */
@ -975,6 +976,25 @@ static void set_indentation(GeanyEditor *editor)
}
#if 0
static gboolean auto_update_tag_list(gpointer data)
{
GeanyDocument *doc = data;
if (! doc || ! doc->is_valid || doc->tm_file == NULL)
return FALSE;
if (gtk_window_get_focus(GTK_WINDOW(main_widgets.window)) != GTK_WIDGET(doc->editor->sci))
return TRUE;
if (update_tags_from_buffer(doc))
treeviews_update_tag_list(doc, TRUE);
return TRUE;
}
#endif
/* To open a new file, set doc to NULL; filename should be locale encoded.
* To reload a file, set the doc for the document to be reloaded; filename should be NULL.
* pos is the cursor position, which can be overridden by --line and --column.
@ -990,10 +1010,6 @@ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename
GeanyFiletype *use_ft;
FileData filedata;
/*struct timeval tv, tv1;*/
/*struct timezone tz;*/
/*gettimeofday(&tv, &tz);*/
if (reload)
{
utf8_filename = g_strdup(doc->file_name);
@ -1123,8 +1139,10 @@ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename
g_free(utf8_filename);
g_free(locale_filename);
/*gettimeofday(&tv1, &tz);*/
/*geany_debug("%s: %d", filename, (gint)(tv1.tv_usec - tv.tv_usec)); */
/* TODO This could be used to automatically update the symbol list,
* based on a configurable interval */
/*g_timeout_add(10000, auto_update_tag_list, doc);*/
return doc;
}
@ -1532,10 +1550,10 @@ gboolean document_save_file(GeanyDocument *doc, gboolean force)
document_set_filetype(doc, doc->file_type);
tm_workspace_update(TM_WORK_OBJECT(app->tm_workspace), TRUE, TRUE, FALSE);
{
gtk_label_set_text(GTK_LABEL(doc->priv->tab_label), base_name);
gtk_label_set_text(GTK_LABEL(doc->priv->tabmenu_label), base_name);
}
gtk_label_set_text(GTK_LABEL(doc->priv->tab_label), base_name);
gtk_label_set_text(GTK_LABEL(doc->priv->tabmenu_label), base_name);
msgwin_status_add(_("File %s saved."), doc->file_name);
ui_update_statusbar(doc, -1);
g_free(base_name);
@ -1972,6 +1990,26 @@ gboolean document_replace_all(GeanyDocument *doc, const gchar *find_text, const
}
static gboolean update_tags_from_buffer(GeanyDocument *doc)
{
gboolean result;
#if 1
/* old code */
result = tm_source_file_update(doc->tm_file, TRUE, FALSE, TRUE);
#else
gsize len = sci_get_length(doc->editor->sci) + 1;
gchar *text = g_malloc(len);
/* we copy the whole text into memory instead using a direct char pointer from
* Scintilla because tm_source_file_buffer_update() does modify the string slightly */
sci_get_text(doc->editor->sci, len, text);
result = tm_source_file_buffer_update(doc->tm_file, (guchar*) text, len, TRUE);
g_free(text);
#endif
return result;
}
void document_update_tag_list(GeanyDocument *doc, gboolean update)
{
/* We must call treeviews_update_tag_list() before returning,
@ -2006,14 +2044,14 @@ void document_update_tag_list(GeanyDocument *doc, gboolean update)
else
{
if (update)
tm_source_file_update(doc->tm_file, TRUE, FALSE, TRUE);
update_tags_from_buffer(doc);
success = TRUE;
}
}
}
else
{
success = tm_source_file_update(doc->tm_file, TRUE, FALSE, TRUE);
success = update_tags_from_buffer(doc);
if (! success)
geany_debug("tag list updating failed");
}

View File

@ -169,6 +169,7 @@ typedef struct sTokenInfo {
vString* name; /* the name of the token */
unsigned long lineNumber; /* line number of tag */
fpos_t filePosition; /* file position of line containing name */
int bufferPosition; /* buffer position of line containing name */
} tokenInfo;
typedef enum eImplementation {
@ -506,7 +507,10 @@ static void initToken (tokenInfo* const token)
token->type = TOKEN_NONE;
token->keyword = KEYWORD_NONE;
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
vStringClear (token->name);
}
@ -1057,8 +1061,16 @@ static void addOtherFields (tagEntryInfo* const tag, const tagType type,
tag->extensionFields.access = accessField (st);
}
if ((TRUE == st->gotArgs) && (TRUE == Option.extensionFields.argList) &&
((TAG_FUNCTION == type) || (TAG_METHOD == type) || (TAG_PROTOTYPE == type))) {
tag->extensionFields.arglist = getArglistFromPos(tag->filePosition, tag->name);
((TAG_FUNCTION == type) || (TAG_METHOD == type) || (TAG_PROTOTYPE == type)))
{
if (useFile()) {
tag->extensionFields.arglist = getArglistFromFilePos(
tag->filePosition, tag->name);
}
else {
tag->extensionFields.arglist = getArglistFromBufferPos(
tag->bufferPosition, tag->name);
}
}
break;
}
@ -1233,8 +1245,11 @@ static void makeTag (const tokenInfo *const token,
initTagEntry (&e, vStringValue (token->name));
e.lineNumber = token->lineNumber;
e.filePosition = token->filePosition;
e.isFileScope = isFileScope;
if (useFile())
e.filePosition = token->filePosition;
else
e.bufferPosition = token->bufferPosition;
e.isFileScope = isFileScope;
e.kindName = tagName (type);
e.kind = tagLetter (type);
e.type = type;
@ -1688,7 +1703,10 @@ static void copyToken (tokenInfo *const dest, const tokenInfo *const src)
{
dest->type = src->type;
dest->keyword = src->keyword;
dest->filePosition = src->filePosition;
if (useFile())
dest->filePosition = src->filePosition;
else
dest->bufferPosition = src->bufferPosition;
dest->lineNumber = src->lineNumber;
vStringCopy (dest->name, src->name);
}
@ -2199,7 +2217,14 @@ static int parseParens (statementInfo *const st, parenInfo *const info)
--depth;
}
if (st->argEndPosition == 0)
st->argEndPosition = ftell(File.fp);
{
if (useFile())
st->argEndPosition = ftell(File.fp);
else
/* FIXME File.fpBufferPosition is wrong here, this breaks function signatures and
* so Geany's calltips */
st->argEndPosition = File.fpBufferPosition;
}
if (! info->isNameCandidate)
initToken (token);

View File

@ -403,6 +403,7 @@ extern void initTagEntry (tagEntryInfo *const e, const char *const name)
e->lineNumber = getSourceLineNumber ();
e->language = getSourceLanguageName ();
e->filePosition = getInputFilePosition ();
e->bufferPosition = getInputBufferPosition ();
e->sourceFileName = getSourceFileTagPath ();
e->name = name;
}

View File

@ -56,6 +56,7 @@ typedef struct sTagEntryInfo {
boolean lineNumberEntry;/* pattern or line number entry */
unsigned long lineNumber; /* line number of tag */
fpos_t filePosition; /* file position of line containing tag */
int bufferPosition; /* buffer position of line containing tag */
const char* language; /* language of source file */
boolean isFileScope; /* is tag visibile only within source file? */
boolean isFileEntry; /* is this just an entry for a file name? */

View File

@ -155,6 +155,7 @@ typedef struct sTokenInfo {
vString* string;
unsigned long lineNumber;
fpos_t filePosition;
int bufferPosition; /* buffer position of line containing name */
} tokenInfo;
/*
@ -350,7 +351,10 @@ static void makeFortranTag (tokenInfo *const token, tagType tag)
e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);
e.lineNumber = token->lineNumber;
e.filePosition = token->filePosition;
if (useFile())
e.filePosition = token->filePosition;
else
e.bufferPosition = token->bufferPosition;
e.isFileScope = isFileScope (token->tag);
e.kindName = FortranKinds [token->tag].name;
e.kind = FortranKinds [token->tag].letter;
@ -390,7 +394,10 @@ static void makeLabelTag (vString *const label)
token.tag = TAG_LABEL;
token.string = label;
token.lineNumber = getSourceLineNumber ();
token.filePosition = getInputFilePosition ();
if (useFile())
token.filePosition = getInputFilePosition ();
else
token.bufferPosition = getInputBufferPosition ();
makeFortranTag (&token, TAG_LABEL);
}
@ -728,7 +735,10 @@ static tokenInfo *newToken (void)
token->tag = TAG_UNDEFINED;
token->string = vStringNew ();
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
return token;
}
@ -797,7 +807,10 @@ static void readToken (tokenInfo *const token)
getNextChar:
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
c = getChar ();

View File

@ -313,8 +313,16 @@ static void makeDefineTag (const char *const name, boolean parameterized)
e.kindName = "macro";
e.kind = 'd';
if (parameterized)
e.extensionFields.arglist = getArglistFromPos(getInputFilePosition()
, e.name);
{
if (useFile()) {
e.extensionFields.arglist = getArglistFromFilePos(getInputFilePosition()
, e.name);
}
else {
e.extensionFields.arglist = getArglistFromBufferPos(getInputBufferPosition()
, e.name);
}
}
makeTagEntry (&e);
if (parameterized)
free((char *) e.extensionFields.arglist);
@ -676,16 +684,52 @@ process:
return c;
}
extern char *getArglistFromPos(fpos_t startPosition, const char *tokenName)
extern char *getArglistFromBufferPos(int startPosition, const char *tokenName)
{
int bufferOriginalPosition;
char *result = NULL;
char *arglist = NULL;
long pos1, pos2;
/* FIXME startPosition as well as getBufPos() are mostly wrong here */
pos2 = getBufPos();
if (!useFile()) {
bufferOriginalPosition = getBufPos ();
setBufPos(startPosition);
pos1 = File.fpBufferPosition;
}
else
return NULL;
if (pos2 > pos1)
{
result = (char *) g_malloc(sizeof(char ) * (pos2 - pos1 + 2));
if (result != NULL)
{
memcpy(result, &File.fpBuffer[getBufPos()], pos2 - pos1 + 1);
result[pos2-pos1+1] = '\0';
arglist = getArglistFromStr(result, tokenName);
free(result);
}
}
setBufPos (bufferOriginalPosition);
return arglist;
}
extern char *getArglistFromFilePos(fpos_t startPosition, const char *tokenName)
{
fpos_t originalPosition;
char *result = NULL;
char *arglist = NULL;
long pos1, pos2 = ftell(File.fp);
long pos1, pos2;
pos2 = ftell(File.fp);
fgetpos(File.fp, &originalPosition);
fsetpos(File.fp, &startPosition);
pos1 = ftell(File.fp);
if (pos2 > pos1)
{
result = (char *) g_malloc(sizeof(char ) * (pos2 - pos1 + 2));

View File

@ -44,7 +44,8 @@ extern void cppEndStatement (void);
extern void cppUngetc (const int c);
extern int cppGetc (void);
extern int skipOverCComment (void);
extern char *getArglistFromPos(fpos_t startPosition, const char *tokenName);
extern char *getArglistFromFilePos(fpos_t startPosition, const char *tokenName);
extern char *getArglistFromBufferPos(int startPosition, const char *tokenName);
extern char *getArglistFromStr(char *buf, const char *name);
#endif /* _GET_H */

View File

@ -13,6 +13,7 @@
#include <glib.h>
#include "tm_work_object.h"
/*! \file
The TMProject structure and associated functions can be used to group together
related source files in a "project". The update, open and save functions take
@ -142,6 +143,13 @@ TMWorkObject *tm_project_find_file(TMWorkObject *work_object, const char *file_n
*/
gboolean tm_project_remove_object(TMProject *project, TMWorkObject *w);
/*! Removes only the project-tags associated with the object. Then resort the project's tags.
\param project The project from which the file's tags are to be removed.
\param w The member work object (source file) to remove the tags.
\return TRUE on success, FALSE on failure
*/
gboolean tm_project_remove_tags_from_list(TMProject *project, TMWorkObject *w);
/*! Updates the project database and all the source files contained in the
project. All sorting and deduping is lost and should be redone.
\param work_object The project to update.

View File

@ -110,6 +110,7 @@ typedef struct sTokenInfo {
fpos_t filePosition;
int nestLevel;
boolean ignoreTag;
int bufferPosition; /* buffer position of line containing name */
} tokenInfo;
/*
@ -197,7 +198,10 @@ static tokenInfo *newToken (void)
token->nestLevel = 0;
token->ignoreTag = FALSE;
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
return token;
}
@ -353,8 +357,11 @@ getNextChar:
{
c = fileGetc ();
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
}
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
}
while (c == '\t' || c == ' ' || c == '\n');
switch (c)
@ -377,7 +384,10 @@ getNextChar:
token->type = TOKEN_STRING;
parseString (token->string, c);
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
break;
case '\\':
@ -386,7 +396,10 @@ getNextChar:
fileUngetc (c);
token->type = TOKEN_CHARACTER;
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
break;
case '/':
@ -429,7 +442,10 @@ getNextChar:
{
parseIdentifier (token->string, c);
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
token->keyword = analyzeToken (token->string);
if (isKeyword (token, KEYWORD_NONE))
token->type = TOKEN_IDENTIFIER;
@ -444,7 +460,10 @@ static void copyToken (tokenInfo *const dest, tokenInfo *const src)
{
dest->nestLevel = src->nestLevel;
dest->lineNumber = src->lineNumber;
dest->filePosition = src->filePosition;
if (useFile())
dest->filePosition = src->filePosition;
else
dest->bufferPosition = src->bufferPosition;
dest->type = src->type;
dest->keyword = src->keyword;
vStringCopy(dest->string, src->string);

View File

@ -29,6 +29,11 @@
*/
inputFile File; /* globally read through macros */
static fpos_t StartOfLine; /* holds deferred position of start of line */
static int bufferStartOfLine; /* the same as StartOfLine but for buffer */
static int readNextChar (void);
static int pushBackChar (int c);
/*
* FUNCTION DEFINITIONS
@ -115,7 +120,7 @@ static int skipWhite (void)
{
int c;
do
c = getc (File.fp);
c = readNextChar ();
while (c == ' ' || c == '\t');
return c;
}
@ -127,9 +132,9 @@ static unsigned long readLineNumber (void)
while (c != EOF && isdigit (c))
{
lNum = (lNum * 10) + (c - '0');
c = getc (File.fp);
c = readNextChar ();
}
ungetc (c, File.fp);
pushBackChar (c);
if (c != ' ' && c != '\t')
lNum = 0;
@ -152,17 +157,17 @@ static vString *readFileName (void)
if (c == '"')
{
c = getc (File.fp); /* skip double-quote */
c = readNextChar (); /* skip double-quote */
quoteDelimited = TRUE;
}
while (c != EOF && c != '\n' &&
(quoteDelimited ? (c != '"') : (c != ' ' && c != '\t')))
{
vStringPut (fileName, c);
c = getc (File.fp);
c = readNextChar ();
}
if (c == '\n')
ungetc (c, File.fp);
pushBackChar (c);
vStringPut (fileName, '\0');
return fileName;
@ -176,13 +181,13 @@ static boolean parseLineDirective (void)
if (isdigit (c))
{
ungetc (c, File.fp);
pushBackChar (c);
result = TRUE;
}
else if (c == 'l' && getc (File.fp) == 'i' &&
getc (File.fp) == 'n' && getc (File.fp) == 'e')
else if (c == 'l' && readNextChar () == 'i' &&
readNextChar () == 'n' && readNextChar () == 'e')
{
c = getc (File.fp);
c = readNextChar ();
if (c == ' ' || c == '\t')
{
DebugStatement ( lineStr = "line"; )
@ -283,6 +288,60 @@ extern boolean fileOpen (const char *const fileName, const langType language)
return opened;
}
/* The user should take care of allocate and free the buffer param.
* This func is NOT THREAD SAFE.
* The user should not tamper with the buffer while this func is executing.
*/
extern boolean bufferOpen (unsigned char *buffer, int buffer_size,
const char *const fileName, const langType language )
{
boolean opened = FALSE;
/* Check whether a file of a buffer were already open, then close them.
*/
if (File.fp != NULL) {
fclose (File.fp); /* close any open source file */
File.fp = NULL;
}
if (File.fpBuffer != NULL) {
error(PERROR, "An unallocated buffer was found. Please check you called \
correctly bufferClose ()\n");
File.fpBuffer = NULL;
}
/* check if we got a good buffer */
if (buffer == NULL || buffer_size == 0) {
opened = FALSE;
return opened;
}
opened = TRUE;
File.fpBuffer = buffer;
setInputFileName (fileName);
bufferStartOfLine = 0;
File.fpBufferPosition = 0;
File.fpBufferSize = buffer_size;
File.currentLine = NULL;
File.language = language;
File.lineNumber = 0L;
File.eof = FALSE;
File.newLine = TRUE;
if (File.line != NULL)
vStringClear (File.line);
setSourceFileParameters (vStringNewInit (fileName), language);
File.source.lineNumber = 0L;
verbose ("OPENING %s as %s language %sfile\n", fileName,
getLanguageName (language),
File.source.isHeader ? "include " : "");
return opened;
}
extern void fileClose (void)
{
if (File.fp != NULL)
@ -299,6 +358,14 @@ extern void fileClose (void)
}
}
/* user should take care of freeing the buffer */
extern void bufferClose (void)
{
if (File.fpBuffer != NULL) {
File.fpBuffer = NULL;
}
}
extern boolean fileEOF (void)
{
return File.eof;
@ -323,7 +390,7 @@ static int iFileGetc (void)
{
int c;
readnext:
c = getc (File.fp);
c = readNextChar ();
/* If previous character was a newline, then we're starting a line.
*/
@ -336,8 +403,13 @@ readnext:
goto readnext;
else
{
fsetpos (File.fp, &StartOfLine);
c = getc (File.fp);
/* FIXME: find out a better way to do this check */
if (File.fp != NULL)
fsetpos (File.fp, &StartOfLine);
else
File.fpBufferPosition = bufferStartOfLine;
c = readNextChar ();
}
}
}
@ -346,8 +418,10 @@ readnext:
File.eof = TRUE;
else if (c == NEWLINE)
{
File.newLine = TRUE;
fgetpos (File.fp, &StartOfLine);
if (File.fp != NULL) /* we have a file */
fgetpos (File.fp, &StartOfLine);
else /* it's a buffer */
bufferStartOfLine = File.fpBufferPosition;
}
else if (c == CRETURN)
{
@ -355,14 +429,17 @@ readnext:
* used forms if line breaks: LF (UNIX), CR (MacIntosh), and
* CR-LF (MS-DOS) are converted into a generic newline.
*/
const int next = getc (File.fp); /* is CR followed by LF? */
const int next = readNextChar (); /* is CR followed by LF? */
if (next != NEWLINE)
ungetc (next, File.fp);
pushBackChar (next);
c = NEWLINE; /* convert CR into newline */
File.newLine = TRUE;
fgetpos (File.fp, &StartOfLine);
if (File.fp != NULL)
fgetpos (File.fp, &StartOfLine);
else
bufferStartOfLine = File.fpBufferPosition;
}
DebugStatement ( debugPutc (DEBUG_RAW, c); )
return c;
@ -457,8 +534,67 @@ extern const unsigned char *fileReadLine (void)
return result;
}
/* Read a character choosing automatically between file or buffer, depending
* on which mode we are.
*/
static int readNextChar(void)
{
if (File.fp != NULL) {
return getc(File.fp);
}
else {
int c;
if (File.fpBufferPosition >= File.fpBufferSize)
return EOF;
c = File.fpBuffer[File.fpBufferPosition];
File.fpBufferPosition++;
return c;
}
}
/* Replaces ungetc() for file. In case of buffer we'll perform the same action:
* fpBufferPosition-- and write of the param char into the buf.
*/
static int pushBackChar (int c)
{
if (File.fp != NULL) {
return ungetc (c, File.fp);
}
else {
File.fpBufferPosition--;
if (File.fpBufferPosition < 0)
return EOF;
File.fpBuffer[File.fpBufferPosition] = c;
return File.fpBuffer[File.fpBufferPosition];
}
}
/* replacement for fsetpos, applied to a buffer */
extern void setBufPos (int new_position)
{
File.fpBufferPosition = new_position;
}
/* replacement for fgetpos, applied to a buffer */
extern int getBufPos (void)
{
return File.fpBufferPosition;
}
extern boolean useFile (void)
{
if (File.fp != NULL)
return TRUE;
else
return FALSE;
}
/*
* Source file line reading with automatic buffer sizing
* Does not perform file/buffer checks. Only file is supported.
*/
extern char *readLine (vString *const vLine, FILE *const fp)
{

View File

@ -33,6 +33,7 @@
#define getInputLineNumber() File.lineNumber
#define getInputFileName() vStringValue (File.source.name)
#define getInputFilePosition() File.filePosition
#define getInputBufferPosition() File.fpBufferPosition
#define getSourceFileName() vStringValue (File.source.name)
#define getSourceFileTagPath() File.source.tagPath
#define getSourceLanguage() File.source.language
@ -73,6 +74,10 @@ typedef struct sInputFile {
vString *line; /* last line read from file */
const unsigned char* currentLine; /* current line being worked on */
FILE *fp; /* stream used for reading the file */
unsigned char* fpBuffer; /* buffer which contains the text to be parsed.
This is optional to the use of a file-descriptor */
int fpBufferSize; /* size of the fpBuffer */
int fpBufferPosition; /* pointer to the current position in buffer */
unsigned long lineNumber; /* line number in the input file */
fpos_t filePosition; /* file position of current line */
int ungetch; /* a single character that was ungotten */
@ -116,6 +121,13 @@ extern const unsigned char *fileReadLine (void);
extern char *readLine (vString *const vLine, FILE *const fp);
extern char *readSourceLine (vString *const vLine, fpos_t location, long *const pSeekValue);
extern boolean bufferOpen (unsigned char *buffer, int buffer_size,
const char *const fileName, const langType language );
extern void bufferClose (void);
extern void setBufPos (int new_position);
extern int getBufPos ();
extern boolean useFile ();
#endif /* _READ_H */
/* vi:set tabstop=8 shiftwidth=4: */

View File

@ -138,6 +138,7 @@ typedef struct sTokenInfo {
vString * scope;
unsigned long lineNumber;
fpos_t filePosition;
int bufferPosition; /* buffer position of line containing name */
} tokenInfo;
/*
@ -274,30 +275,30 @@ static void dispToken (tokenInfo *const token, char * location)
{
if ( isType(token, TOKEN_IDENTIFIER) || isType(token, TOKEN_STRING) )
{
printf( "\n%s: token string t:%s s:%s l:%lu p:%ld\n"
printf( "\n%s: token string t:%s s:%s l:%lu p:%d\n"
, location
, vStringValue(token->string)
, vStringValue(token->scope)
, token->lineNumber
, token->filePosition
, token->bufferPosition
);
} else {
printf( "\n%s: token t:%d s:%s l:%lu p:%lu\n"
printf( "\n%s: token t:%d s:%s l:%lu p:%d\n"
, location
, token->type
, vStringValue(token->scope)
, token->lineNumber
, token->filePosition
, token->bufferPosition
);
}
} else {
printf( "\n%s: keyword:%s k:%d s:%s l:%lu p:%ld\n"
printf( "\n%s: keyword:%s k:%d s:%s l:%lu p:%d\n"
, location
, vStringValue(token->string)
, token->keyword
, vStringValue(token->scope)
, token->lineNumber
, token->filePosition
, token->bufferPosition
);
}
#endif
@ -391,7 +392,10 @@ static void makeConstTag (tokenInfo *const token, const sqlKind kind)
initTagEntry (&e, name);
e.lineNumber = token->lineNumber;
e.filePosition = token->filePosition;
if (useFile())
e.filePosition = token->filePosition;
else
e.bufferPosition = token->bufferPosition;
e.kindName = SqlKinds [kind].name;
e.kind = SqlKinds [kind].letter;
@ -491,7 +495,10 @@ getNextChar:
token->type = TOKEN_STRING;
parseString (token->string, c);
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
break;
case '-':
@ -557,7 +564,10 @@ getNextChar:
{
parseIdentifier (token->string, c);
token->lineNumber = getSourceLineNumber ();
token->filePosition = getInputFilePosition ();
if (useFile())
token->filePosition = getInputFilePosition ();
else
token->bufferPosition = getInputBufferPosition ();
token->keyword = analyzeToken (token->string);
if (isKeyword (token, KEYWORD_rem))
{

View File

@ -29,6 +29,7 @@
#include "tm_source_file.h"
#include "tm_tag.h"
guint source_file_class_id = 0;
static TMSourceFile *current_source_file = NULL;
@ -154,6 +155,76 @@ gboolean tm_source_file_parse(TMSourceFile *source_file)
return status;
}
gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size)
{
const char *file_name;
gboolean status = TRUE;
if ((NULL == source_file) || (NULL == source_file->work_object.file_name))
{
g_warning("Attempt to parse NULL file");
return FALSE;
}
if ((NULL == text_buf) || (0 == buf_size))
{
g_warning("Attempt to parse a NULL text buffer");
}
file_name = source_file->work_object.file_name;
if (NULL == LanguageTable)
{
initializeParsing();
installLanguageMapDefaults();
if (NULL == TagEntryFunction)
TagEntryFunction = tm_source_file_tags;
}
current_source_file = source_file;
if (LANG_AUTO == source_file->lang)
source_file->lang = getFileLanguage (file_name);
if (source_file->lang == LANG_IGNORE)
{
#ifdef TM_DEBUG
g_warning("ignoring %s (unknown language)\n", file_name);
#endif
}
else if (! LanguageTable [source_file->lang]->enabled)
{
#ifdef TM_DEBUG
g_warning("ignoring %s (language disabled)\n", file_name);
#endif
}
else
{
int passCount = 0;
while ((TRUE == status) && (passCount < 3))
{
if (source_file->work_object.tags_array)
tm_tags_array_free(source_file->work_object.tags_array, FALSE);
if (bufferOpen (text_buf, buf_size, file_name, source_file->lang))
{
if (LanguageTable [source_file->lang]->parser != NULL)
{
LanguageTable [source_file->lang]->parser ();
bufferClose ();
break;
}
else if (LanguageTable [source_file->lang]->parser2 != NULL)
status = LanguageTable [source_file->lang]->parser2 (passCount);
bufferClose ();
}
else
{
g_warning("Unable to open %s", file_name);
return FALSE;
}
++ passCount;
}
return TRUE;
}
return status;
}
int tm_source_file_tags(const tagEntryInfo *tag)
{
if (NULL == current_source_file)
@ -179,10 +250,42 @@ gboolean tm_source_file_update(TMWorkObject *source_file, gboolean force
}
return TRUE;
}
else
else {
#ifdef TM_DEBUG
g_message ("no parsing of %s has been done", source_file->file_name);
#endif
return FALSE;
}
}
gboolean tm_source_file_buffer_update(TMWorkObject *source_file, guchar* text_buf,
gint buf_size, gboolean update_parent)
{
#ifdef TM_DEBUG
g_message("Buffer updating based on source file %s", source_file->file_name);
#endif
tm_source_file_buffer_parse (TM_SOURCE_FILE(source_file), text_buf, buf_size);
tm_tags_sort(source_file->tags_array, NULL, FALSE);
source_file->analyze_time = time(NULL);
if ((source_file->parent) && update_parent)
{
#ifdef TM_DEBUG
g_message("Updating parent [project] from buffer..");
#endif
tm_work_object_update(source_file->parent, TRUE, FALSE, TRUE);
}
#ifdef TM_DEBUG
else
g_message("Skipping parent update because parent is %s and update_parent is %s"
, source_file->parent?"NOT NULL":"NULL", update_parent?"TRUE":"FALSE");
#endif
return TRUE;
}
gboolean tm_source_file_write(TMWorkObject *source_file, FILE *fp, guint attrs)
{
TMTag *tag;

View File

@ -631,7 +631,7 @@ TMTag **tm_tags_find(const GPtrArray *sorted_tags_array, const char *name,
s_partial = partial;
result = (TMTag **) bsearch(&tag, sorted_tags_array->pdata, sorted_tags_array->len
, sizeof(gpointer), tm_tag_compare);
/* there can be matches on both sides of result */
/* There can be matches on both sides of result */
if (result)
{
TMTag **last = (TMTag **) &sorted_tags_array->pdata[sorted_tags_array->len - 1];
@ -640,7 +640,7 @@ TMTag **tm_tags_find(const GPtrArray *sorted_tags_array, const char *name,
/* First look for any matches after result */
adv = result;
adv++;
for (; *adv && adv <= last; ++ adv)
for (; adv <= last && *adv; ++ adv)
{
if (0 != tm_tag_compare(&tag, adv))
break;
@ -654,7 +654,7 @@ TMTag **tm_tags_find(const GPtrArray *sorted_tags_array, const char *name,
++tagMatches;
}
*tagCount=tagMatches;
++ result; /* correct address for the last successful match */
++ result; /* Correct address for the last successful match */
}
s_partial = FALSE;
return (TMTag **) result;