[anjuta] am-project: Evaluate all autotools variables at the end



commit 0dbbbc39e3e417456aad3e5fbb1d89c63e38d16e
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Sat May 21 17:20:09 2011 +0200

    am-project: Evaluate all autotools variables at the end

 libanjuta/anjuta-token-stream.c      |   67 ++++++++++++-----------
 libanjuta/anjuta-token-stream.h      |    1 +
 libanjuta/anjuta-token.c             |  101 +++++++++++++++++++++++++++++++++-
 libanjuta/anjuta-token.h             |    2 +
 libanjuta/anjuta-utils.c             |    2 +-
 plugins/am-project/am-scanner.l      |   78 +++++++++++++++++++++++++-
 plugins/am-project/amp-group.c       |   16 +++--
 plugins/am-project/tests/variable.at |   47 ++++++++++++++++
 8 files changed, 269 insertions(+), 45 deletions(-)
---
diff --git a/libanjuta/anjuta-token-stream.c b/libanjuta/anjuta-token-stream.c
index aa58203..60e0ee5 100644
--- a/libanjuta/anjuta-token-stream.c
+++ b/libanjuta/anjuta-token-stream.c
@@ -64,7 +64,7 @@ struct _AnjutaTokenStream
 	AnjutaToken *last;
 
 	/* Read position in input stream */
-	AnjutaToken *next;
+	AnjutaToken *token;
 	gsize pos;
 
 	/* Write position in input stream */
@@ -128,11 +128,11 @@ anjuta_token_stream_tokenize (AnjutaTokenStream *stream, gint type, gsize length
 
     for (end = stream->start; end != NULL;)
     {
-        if (anjuta_token_get_type (end) < ANJUTA_TOKEN_PARSED)
+        if ((anjuta_token_get_type (end) < ANJUTA_TOKEN_PARSED) || (anjuta_token_get_length (end) == 0))
         {
             gint toklen = anjuta_token_get_length (end);
             AnjutaToken *copy = anjuta_token_cut (end, stream->begin, length);
-    
+
             if (toklen >= (length + stream->begin))
             {
 
@@ -177,7 +177,7 @@ anjuta_token_stream_tokenize (AnjutaTokenStream *stream, gint type, gsize length
             stream->begin = 0;
         }
     }
-    
+
     anjuta_token_stream_append_token (stream, frag);
 
     return frag;
@@ -199,36 +199,36 @@ anjuta_token_stream_read (AnjutaTokenStream *stream, gchar *buffer, gsize max_si
 {
     gint result = 0;
 
-    if (stream->next != NULL)
+    if (stream->token != NULL)
     {
-        gsize length = anjuta_token_get_length (stream->next);
+        gsize length = anjuta_token_get_length (stream->token);
 
-        if ((anjuta_token_get_type (stream->next) >= ANJUTA_TOKEN_PARSED) || (stream->pos >= length))
+        if ((anjuta_token_get_type (stream->token) >= ANJUTA_TOKEN_PARSED) || (stream->pos >= length))
         {
             for (;;)
             {
                 /* Last token */
-                if (stream->next == stream->last) return 0;
+                if (stream->token== stream->last) return 0;
 
-                if (anjuta_token_get_type (stream->next) >= ANJUTA_TOKEN_PARSED)
+                if (anjuta_token_get_type (stream->token) >= ANJUTA_TOKEN_PARSED)
                 {
-                    stream->next = anjuta_token_next (stream->next);
+                    stream->token = anjuta_token_next (stream->token);
                 }
                 else
                 {
-                    stream->next = anjuta_token_next (stream->next);
+                    stream->token = anjuta_token_next (stream->token);
                 }
 
-                if ((stream->next == NULL) || (anjuta_token_get_type (stream->next) == ANJUTA_TOKEN_EOV))
+                if ((stream->token == NULL) || (anjuta_token_get_type (stream->token) == ANJUTA_TOKEN_EOV))
                 {
                     /* Last token */
                     return 0;
                 }
-                else if ((anjuta_token_get_length (stream->next) != 0) && (anjuta_token_get_type (stream->next) < ANJUTA_TOKEN_PARSED))
+                else if ((anjuta_token_get_length (stream->token) != 0) && (anjuta_token_get_type (stream->token) < ANJUTA_TOKEN_PARSED))
                 {
                     /* Find some data */
                     stream->pos = 0;
-                    length = anjuta_token_get_length (stream->next);
+                    length = anjuta_token_get_length (stream->token);
                     break;  
                 }
             }
@@ -236,7 +236,7 @@ anjuta_token_stream_read (AnjutaTokenStream *stream, gchar *buffer, gsize max_si
 
         if (stream->pos < length)
         {
-            const gchar *start = anjuta_token_get_string (stream->next);
+            const gchar *start = anjuta_token_get_string (stream->token);
 
             length -= stream->pos;
             
@@ -324,22 +324,9 @@ anjuta_token_stream_push (AnjutaTokenStream *parent, AnjutaToken *root, AnjutaTo
 	child->pos = 0;
 	child->begin = 0;
 	child->parent = parent;
-
-	/* If content is empty, anjuta_token_next returns following token which is
-	 * wrong */
-	if (anjuta_token_is_empty (content))
-	{
-		child->next = NULL;
-		child->start = NULL;
-		child->last = NULL;
-	}
-	else
-	{
-		child->next = anjuta_token_next (content);
-		child->start = child->next;
-		child->last = anjuta_token_last (content);
-		if (child->last == content) child->last = NULL;
-	}
+	child->token = content;
+	child->start = child->token;
+	child->last = anjuta_token_last (content);
 
 	child->root = root == NULL ? anjuta_token_new_static (ANJUTA_TOKEN_FILE, NULL) : root;
 	if (file == NULL)
@@ -358,7 +345,7 @@ anjuta_token_stream_push (AnjutaTokenStream *parent, AnjutaToken *root, AnjutaTo
 
 /**
  * anjuta_token_stream_pop:
- * @parent: a #AnjutaTokenStream object.
+ * @stream: a #AnjutaTokenStream object.
  *
  * Destroy the stream object and return the parent stream if it exists.
  *
@@ -378,3 +365,19 @@ anjuta_token_stream_pop (AnjutaTokenStream *stream)
 
 	return parent;
 }
+
+/**
+ * anjuta_token_stream_get_parent:
+ * @stream: a #AnjutaTokenStream object.
+ *
+ * Return the parent stream
+ *
+ * Return value: The parent stream or NULL if there is no parent.
+ */
+AnjutaTokenStream *
+anjuta_token_stream_get_parent (AnjutaTokenStream *stream)
+{
+	g_return_val_if_fail (stream != NULL, NULL);
+
+	return stream->parent;
+}
diff --git a/libanjuta/anjuta-token-stream.h b/libanjuta/anjuta-token-stream.h
index bfeb38f..35bf389 100644
--- a/libanjuta/anjuta-token-stream.h
+++ b/libanjuta/anjuta-token-stream.h
@@ -30,6 +30,7 @@ typedef struct _AnjutaTokenStream AnjutaTokenStream;
 
 AnjutaTokenStream *anjuta_token_stream_push (AnjutaTokenStream *stream, AnjutaToken *root, AnjutaToken *content, GFile *filename);
 AnjutaTokenStream *anjuta_token_stream_pop (AnjutaTokenStream *stream);
+AnjutaTokenStream *anjuta_token_stream_get_parent (AnjutaTokenStream *stream);
 
 AnjutaToken* anjuta_token_stream_get_root (AnjutaTokenStream *stream);
 GFile* anjuta_token_stream_get_current_directory (AnjutaTokenStream *stream);
diff --git a/libanjuta/anjuta-token.c b/libanjuta/anjuta-token.c
index e069f70..04c9737 100644
--- a/libanjuta/anjuta-token.c
+++ b/libanjuta/anjuta-token.c
@@ -1132,7 +1132,8 @@ AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
 	}
 }
 
-AnjutaToken *anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
+AnjutaToken *
+anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
 {
 	AnjutaToken *copy;
 
@@ -1165,10 +1166,108 @@ AnjutaToken *anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
 	return copy;
 }
 
+static void
+concat_token (AnjutaToken *token, gpointer user_data)
+{
+	AnjutaToken *first = (AnjutaToken *)user_data;
+
+	if (anjuta_token_get_length (token) > 0)
+	{
+		if (anjuta_token_get_string (first) == NULL)
+		{
+			anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
+		}
+		else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
+		{
+			anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
+		}
+		else
+		{
+			AnjutaToken *new;
+
+			new = anjuta_token_new_static_len (ANJUTA_TOKEN_CONTENT, anjuta_token_get_string (token), anjuta_token_get_length (token));
+			anjuta_token_insert_after (first, new);
+			anjuta_token_merge (first, new);
+		}
+	}
+}
+	
+
+AnjutaToken *
+anjuta_token_concat(AnjutaToken *token)
+{
+	AnjutaToken *new;
+
+	new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
+	anjuta_token_foreach_token (token, concat_token, new);
+	
+	anjuta_token_insert_token_before (token, new);
+	anjuta_token_free (token);
+
+	return new;
+}
+
 /* Token foreach
  *---------------------------------------------------------------------------*/
 
 void 
+anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
+{
+	if (token != NULL)
+	{
+		AnjutaToken *last_token;
+		gint child = 0;
+
+		last_token = token->last == NULL ? token : token->last;
+		while (token != NULL)
+		{
+			if (child == 0) func (token, user_data);
+
+			/* Check if we have found the last token */
+			if (token == last_token)
+			{
+				/* Find last token */
+				if (token->last == NULL)
+				{
+					break;
+				}	
+				/* Last token still include additional tokens */
+				last_token = token->last;
+			}
+
+			if (token->children != NULL)
+			{
+				/* Check children, only for last token */
+				child++;
+				token = token->children;
+			}
+			else if (token->next != NULL)
+			{
+				/* Get next sibling */
+				token = token->next;
+			}
+			else
+			{
+				/* Get parent */
+				for (;;)
+				{
+					child--;
+					token = token->parent;
+					if (token == NULL) break;
+					if (token->next != NULL) 
+					{
+						token = token->next;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	return;
+}
+
+void 
 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
 {
 	if (token != NULL)
diff --git a/libanjuta/anjuta-token.h b/libanjuta/anjuta-token.h
index 920268a..d20efdc 100644
--- a/libanjuta/anjuta-token.h
+++ b/libanjuta/anjuta-token.h
@@ -114,6 +114,7 @@ AnjutaToken *anjuta_token_parent (AnjutaToken *token);
 AnjutaToken *anjuta_token_list (AnjutaToken *token);
 AnjutaToken *anjuta_token_next_after_children (AnjutaToken *token);
 void anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data);
+void anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data);
 AnjutaToken *anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data);
 
 AnjutaToken *anjuta_token_first_item (AnjutaToken *list);
@@ -135,6 +136,7 @@ AnjutaToken *anjuta_token_merge_children (AnjutaToken *first, AnjutaToken *end);
 AnjutaToken *anjuta_token_merge_previous (AnjutaToken *first, AnjutaToken *end);
 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size);
 AnjutaToken *anjuta_token_cut (AnjutaToken *token, guint pos, guint size);
+AnjutaToken *anjuta_token_concat(AnjutaToken *token);
 
 gchar *anjuta_token_evaluate (AnjutaToken *token);
 gboolean anjuta_token_is_empty (AnjutaToken *token);
diff --git a/libanjuta/anjuta-utils.c b/libanjuta/anjuta-utils.c
index 33b1294..73552ec 100644
--- a/libanjuta/anjuta-utils.c
+++ b/libanjuta/anjuta-utils.c
@@ -400,7 +400,7 @@ anjuta_util_dialog_boolean_question (GtkWindow *parent, const gchar *mesg, ...)
 	{
 		real_parent = NULL;
 	}
-	
+
 	dialog = gtk_message_dialog_new (real_parent,
 									 GTK_DIALOG_DESTROY_WITH_PARENT,
 									 GTK_MESSAGE_QUESTION,
diff --git a/plugins/am-project/am-scanner.l b/plugins/am-project/am-scanner.l
index c5dad7f..de2130e 100644
--- a/plugins/am-project/am-scanner.l
+++ b/plugins/am-project/am-scanner.l
@@ -53,7 +53,9 @@ struct _AmpAmScanner
 	AmpProject *project;
 	AmpGroupNode *group;
 	GHashTable *orphan_properties;
+	GList *am_variables;
 	gboolean eof;		/* TRUE to emit EOF at the end */
+	gboolean expansion;		/* Expand variables */
 };
 
 %}
@@ -208,6 +210,26 @@ NAME          [^ \t\n\r:#=$"'`&@\\]*
 /* Private functions
  *---------------------------------------------------------------------------*/
 
+static void
+amp_am_scanner_reparse_token (AmpAmScanner *scanner, AnjutaToken *token, GFile *filename)
+{
+	AnjutaToken *root;
+	AnjutaToken *list;
+	
+	if (token == NULL) return;
+	
+	token = anjuta_token_concat (token);
+	
+	yylex_init(&scanner->scanner);
+	yyset_extra (scanner, scanner->scanner);
+		
+	root = anjuta_token_new_static (ANJUTA_TOKEN_FILE, NULL);
+	list = amp_am_scanner_parse_token (scanner, root, token, filename, NULL);
+	list = anjuta_token_delete_parent (list);
+	anjuta_token_insert_before (token, list);
+	anjuta_token_free (token);
+}
+
 static gint
 amp_am_scanner_parse_end (AmpAmScanner *scanner)
 {
@@ -223,8 +245,9 @@ amp_am_scanner_parse_end (AmpAmScanner *scanner)
 			scanner->eof = FALSE;
 			return END_OF_FILE;
 		}
-       	yypop_buffer_state(scanner->scanner);
-        scanner->stream = anjuta_token_stream_pop (scanner->stream);
+
+		yypop_buffer_state(scanner->scanner);
+    	scanner->stream = anjuta_token_stream_pop (scanner->stream);
 
 		if (scanner->stream == NULL)
 		{
@@ -240,6 +263,27 @@ amp_am_scanner_parse_end (AmpAmScanner *scanner)
 	}
 }
 
+static GList *
+list_used_variable (AnjutaToken *token)
+{
+	AnjutaToken *last = anjuta_token_last (token);
+	GList *list = NULL;
+
+	for (;;)
+	{
+		if (anjuta_token_get_type (token) == ANJUTA_TOKEN_VARIABLE)
+		{
+			list = g_list_prepend (list, token);
+		}
+		if (token == last) break;
+		token = anjuta_token_next (token);
+	}
+	list = g_list_reverse (list);
+	
+	return list;
+}
+
+
 /* Parser functions
  *---------------------------------------------------------------------------*/
 
@@ -262,7 +306,15 @@ amp_am_yyerror (YYLTYPE *loc, AmpAmScanner *scanner, char const *s)
 void
 amp_am_scanner_set_am_variable (AmpAmScanner *scanner, AnjutaToken *variable)
 {
-    amp_project_set_am_variable (scanner->project, scanner->group, variable, scanner->orphan_properties);
+	if (!scanner->expansion)
+	{
+		/* Keep variable token to expand them at the end */
+		scanner->am_variables = g_list_prepend (scanner->am_variables, variable);
+	}
+	else
+	{
+	    amp_project_set_am_variable (scanner->project, scanner->group, variable, scanner->orphan_properties);
+	}
 }
 
 void
@@ -299,7 +351,7 @@ amp_am_scanner_parse_variable (AmpAmScanner *scanner, AnjutaToken *variable)
 	AnjutaToken *value;
 
 	anjuta_token_set_type (variable, ANJUTA_TOKEN_VARIABLE);
-
+	
 	value = amp_group_node_get_variable_token (scanner->group, variable);
 	if (value != NULL)
 	{
@@ -316,6 +368,7 @@ amp_am_scanner_parse_token (AmpAmScanner *scanner, AnjutaToken *root, AnjutaToke
 {
     AnjutaToken *first;
     AnjutaTokenStream *stream;
+	GList *variable;
 
     stream = anjuta_token_stream_push (scanner->stream, root, content, filename);
     first = anjuta_token_stream_get_root (stream);
@@ -348,6 +401,18 @@ amp_am_scanner_parse_token (AmpAmScanner *scanner, AnjutaToken *root, AnjutaToke
         } while (status == YYPUSH_MORE);
         amp_am_yypstate_delete (ps);
 
+		/* Evaluate autotools variable at the end */
+		if (scanner->expansion == FALSE)
+		{
+			scanner->expansion = TRUE;
+			scanner->am_variables = g_list_reverse (scanner->am_variables);
+			for (variable = g_list_first (scanner->am_variables); variable != NULL; variable = g_list_next (variable))
+			{
+				AnjutaToken *token = (AnjutaToken *)variable->data;
+
+				amp_am_scanner_reparse_token (scanner, token, filename);				
+			}
+		}
     }
 
     return first;
@@ -370,6 +435,10 @@ amp_am_scanner_new (AmpProject *project, AmpGroupNode *group)
 	/* Create hash table for sources list */
 	scanner->orphan_properties = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)amp_target_node_free);
 
+	/* Create hash table for variable */
+	scanner->am_variables = NULL;
+	scanner->expansion = FALSE;
+
     yylex_init(&scanner->scanner);
     yyset_extra (scanner, scanner->scanner);
 
@@ -385,6 +454,7 @@ amp_am_scanner_free (AmpAmScanner *scanner)
 
 	/* Free unused sources files */
 	g_hash_table_destroy (scanner->orphan_properties);
+	g_list_free (scanner->am_variables);
 
 	g_free (scanner);
 }
diff --git a/plugins/am-project/amp-group.c b/plugins/am-project/amp-group.c
index e8f9fa7..10c8a78 100644
--- a/plugins/am-project/amp-group.c
+++ b/plugins/am-project/amp-group.c
@@ -508,22 +508,24 @@ AnjutaToken*
 amp_group_node_get_variable_token (AmpGroupNode *group, AnjutaToken *variable)
 {
 	guint length;
-	const gchar *string;
-	gchar *name;
+	gchar *string;
+	const gchar *name;
 	AmpVariable *var;
 		
-	length = anjuta_token_get_length (variable);
-	string = anjuta_token_get_string (variable);
+	string = anjuta_token_evaluate(variable);
+	length = strlen (string);
 	if (string[1] == '(')
 	{
-		name = g_strndup (string + 2, length - 3);
+		string[length - 1] = '\0';
+		name = string + 2;
 	}
 	else
 	{
-		name = g_strndup (string + 1, 1);
+		string[2] = '\0';
+		name = string + 1;
 	}
 	var = g_hash_table_lookup (group->variables, name);
-	g_free (name);
+	g_free (string);
 
 	return var != NULL ? var->value : NULL;
 }
diff --git a/plugins/am-project/tests/variable.at b/plugins/am-project/tests/variable.at
index a682aae..2c27076 100644
--- a/plugins/am-project/tests/variable.at
+++ b/plugins/am-project/tests/variable.at
@@ -1,4 +1,7 @@
 AT_SETUP([Variable in Makefile.am])
+
+
+
 AS_MKDIR_P([variable])
 AT_DATA([variable/configure.ac],
 [[AC_CONFIG_FILES(Makefile)
@@ -16,4 +19,48 @@ AT_DATA([expect],
 AT_PARSER_CHECK([load variable \
 		 list])
 AT_CHECK([diff -b output expect])
+
+
+
+AS_MKDIR_P([variable2])
+AT_DATA([variable2/configure.ac],
+[[AC_CONFIG_FILES(Makefile)
+]])
+AT_DATA([variable2/Makefile.am],
+[[
+bin_PROGRAMS = $(TARGETS)
+TARGETS = target1
+]])
+AT_DATA([expect],
+[[    GROUP (): variable2
+        TARGET (): target1
+            PROPERTY (Installation directory): bindir
+]])
+AT_PARSER_CHECK([load variable2 \
+		 list])
+AT_CHECK([diff -b output expect])
+
+
+
+AS_MKDIR_P([variable3])
+AT_DATA([variable3/configure.ac],
+[[AC_CONFIG_FILES(Makefile)
+]])
+AT_DATA([variable3/Makefile.am],
+[[
+bin_PROGRAMS = $(TARGETS)
+TARGETS1 = target1
+TARGETS = $(TARGETS1)
+]])
+AT_DATA([expect],
+[[    GROUP (): variable3
+        TARGET (): target1
+            PROPERTY (Installation directory): bindir
+]])
+AT_PARSER_CHECK([load variable3 \
+		 list])
+AT_CHECK([diff -b output expect])
+
+
+
 AT_CLEANUP



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]