SF.net SVN: geany:[3184] trunk

eht16 at users.sourceforge.net eht16 at xxxxx
Fri Nov 7 14:37:17 UTC 2008


Revision: 3184
          http://geany.svn.sourceforge.net/geany/?rev=3184&view=rev
Author:   eht16
Date:     2008-11-07 14:37:17 +0000 (Fri, 07 Nov 2008)

Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/src/document.c
    trunk/tagmanager/c.c
    trunk/tagmanager/entry.c
    trunk/tagmanager/entry.h
    trunk/tagmanager/fortran.c
    trunk/tagmanager/get.c
    trunk/tagmanager/get.h
    trunk/tagmanager/include/tm_project.h
    trunk/tagmanager/js.c
    trunk/tagmanager/read.c
    trunk/tagmanager/read.h
    trunk/tagmanager/sql.c
    trunk/tagmanager/tm_source_file.c
    trunk/tagmanager/tm_tag.c

Modified: trunk/src/document.c
===================================================================
--- trunk/src/document.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/src/document.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -99,6 +99,7 @@
 
 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 @@
 }
 
 
+#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 @@
 	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,9 +1139,11 @@
 
 	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 @@
 		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 @@
 }
 
 
+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 @@
 			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");
 	}

Modified: trunk/tagmanager/c.c
===================================================================
--- trunk/tagmanager/c.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/c.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -169,6 +169,7 @@
     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 @@
     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 @@
 				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 @@
 	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 @@
 {
     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 @@
 	--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);

Modified: trunk/tagmanager/entry.c
===================================================================
--- trunk/tagmanager/entry.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/entry.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -403,6 +403,7 @@
     e->lineNumber	= getSourceLineNumber ();
     e->language		= getSourceLanguageName ();
     e->filePosition	= getInputFilePosition ();
+    e->bufferPosition	= getInputBufferPosition ();
     e->sourceFileName	= getSourceFileTagPath ();
     e->name		= name;
 }

Modified: trunk/tagmanager/entry.h
===================================================================
--- trunk/tagmanager/entry.h	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/entry.h	2008-11-07 14:37:17 UTC (rev 3184)
@@ -56,6 +56,7 @@
     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? */

Modified: trunk/tagmanager/fortran.c
===================================================================
--- trunk/tagmanager/fortran.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/fortran.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -155,6 +155,7 @@
     vString* string;
     unsigned long lineNumber;
     fpos_t filePosition;
+    int	bufferPosition;	/* buffer position of line containing name */
 } tokenInfo;
 
 /*
@@ -350,7 +351,10 @@
 	    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 @@
     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 @@
     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 @@
 
 getNextChar:
     token->lineNumber	= getSourceLineNumber ();
-    token->filePosition	= getInputFilePosition ();
+    if (useFile())
+	token->filePosition = getInputFilePosition ();
+    else
+	token->bufferPosition = getInputBufferPosition ();
 
     c = getChar ();
 

Modified: trunk/tagmanager/get.c
===================================================================
--- trunk/tagmanager/get.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/get.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -313,8 +313,16 @@
 		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 @@
 	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));

Modified: trunk/tagmanager/get.h
===================================================================
--- trunk/tagmanager/get.h	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/get.h	2008-11-07 14:37:17 UTC (rev 3184)
@@ -44,7 +44,8 @@
 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 */

Modified: trunk/tagmanager/include/tm_project.h
===================================================================
--- trunk/tagmanager/include/tm_project.h	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/include/tm_project.h	2008-11-07 14:37:17 UTC (rev 3184)
@@ -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 @@
 */
 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.

Modified: trunk/tagmanager/js.c
===================================================================
--- trunk/tagmanager/js.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/js.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -110,6 +110,7 @@
 	fpos_t 			filePosition;
 	int				nestLevel;
 	boolean			ignoreTag;
+    int	bufferPosition;	/* buffer position of line containing name */
 } tokenInfo;
 
 /*
@@ -197,7 +198,10 @@
 	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 @@
 	{
 		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 @@
 				  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 @@
 					  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 @@
 				  {
 					  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 @@
 {
 	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);

Modified: trunk/tagmanager/read.c
===================================================================
--- trunk/tagmanager/read.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/read.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -29,7 +29,12 @@
 */
 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 @@
 {
     int c;
     do
-	c = getc (File.fp);
+	c = readNextChar ();
     while (c == ' '  ||  c == '\t');
     return c;
 }
@@ -127,9 +132,9 @@
     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 @@
 
     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 @@
 
     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 @@
     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 @@
     }
 }
 
+/* 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 @@
 {
     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 @@
 		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 @@
 	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 @@
 	 *  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 @@
     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)
 {

Modified: trunk/tagmanager/read.h
===================================================================
--- trunk/tagmanager/read.h	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/read.h	2008-11-07 14:37:17 UTC (rev 3184)
@@ -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 @@
     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 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: */

Modified: trunk/tagmanager/sql.c
===================================================================
--- trunk/tagmanager/sql.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/sql.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -138,6 +138,7 @@
     vString *	scope;
     unsigned long lineNumber;
     fpos_t filePosition;
+    int	bufferPosition;	/* buffer position of line containing name */
 } tokenInfo;
 
 /*
@@ -274,30 +275,30 @@
     {
         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 @@
 	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 @@
 	    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 @@
 	    {
 		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))
 		{

Modified: trunk/tagmanager/tm_source_file.c
===================================================================
--- trunk/tagmanager/tm_source_file.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/tm_source_file.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -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 @@
 	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 @@
 		}
 		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;

Modified: trunk/tagmanager/tm_tag.c
===================================================================
--- trunk/tagmanager/tm_tag.c	2008-11-07 05:20:43 UTC (rev 3183)
+++ trunk/tagmanager/tm_tag.c	2008-11-07 14:37:17 UTC (rev 3184)
@@ -631,7 +631,7 @@
 	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 @@
 		/* 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 @@
 			++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;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list