[anjuta/newproject] pm: Implement adding and removing module node



commit a7c3a0c2c60089db3683abc620fe0d6f4358b8e5
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Sat Oct 30 19:59:35 2010 +0200

    pm: Implement adding and removing module node

 libanjuta/anjuta-token-file.c           |   49 ++++++----
 libanjuta/anjuta-token.c                |  145 ++++++++++++++++++++++------
 libanjuta/anjuta-token.h                |    4 +-
 plugins/am-project/ac-parser.y          |   12 +++
 plugins/am-project/ac-writer.c          |  160 ++++++++++++++++++++++++++++++-
 plugins/am-project/ac-writer.h          |    3 +
 plugins/am-project/am-node.c            |   33 +++++-
 plugins/am-project/am-node.h            |    5 +-
 plugins/am-project/am-project-private.h |    5 +-
 plugins/am-project/am-project.c         |   55 +++++++----
 plugins/am-project/am-writer.c          |   12 ++-
 plugins/am-project/am-writer.h          |    2 +-
 plugins/am-project/projectparser.c      |   19 ++++
 plugins/am-project/tests/Makefile.am    |    3 +-
 plugins/am-project/tests/module.at      |  101 +++++++++++++++++++
 plugins/am-project/tests/testsuite.at   |    1 +
 16 files changed, 514 insertions(+), 95 deletions(-)
---
diff --git a/libanjuta/anjuta-token-file.c b/libanjuta/anjuta-token-file.c
index 4433aa1..6e26c11 100644
--- a/libanjuta/anjuta-token-file.c
+++ b/libanjuta/anjuta-token-file.c
@@ -201,12 +201,11 @@ anjuta_token_file_move (AnjutaTokenFile *file, GFile *new_file)
 	file->file = new_file != NULL ? g_object_ref (new_file) : NULL;
 }
 
-static AnjutaToken *
-anjuta_token_file_remove_token (AnjutaTokenFile *file, AnjutaToken *token)
+static void
+remove_raw_token (AnjutaToken *token, gpointer user_data)
 {
-	AnjutaToken *last;
-	AnjutaToken *next;
-
+	AnjutaTokenFile *file = (AnjutaTokenFile *)user_data;
+	
 	if ((anjuta_token_get_length (token) > 0))
 	{
 		AnjutaToken *pos = anjuta_token_file_find_position (file, token);
@@ -227,19 +226,19 @@ anjuta_token_file_remove_token (AnjutaTokenFile *file, AnjutaToken *token)
 			}
 		}
 	}
-	
-	last = anjuta_token_last (token); 
-	if ((last != NULL) && (last != token))
-	{
-		next = anjuta_token_next (token);
-		while ((next != last) && (next != NULL))
-		{
-			next = anjuta_token_file_remove_token (file, next);
-		}
-		if (next != NULL) anjuta_token_file_remove_token (file, next);
-	}		
+}
 
-	return anjuta_token_free (token);
+static AnjutaToken *
+anjuta_token_file_remove_token (AnjutaTokenFile *file, AnjutaToken *token)
+{
+	AnjutaToken *last;
+	AnjutaToken *next = NULL;
+
+	if (token != NULL) next = anjuta_token_foreach_post_order (token, remove_raw_token, file);
+
+	next = anjuta_token_free (token);
+
+	return next;
 }
 
 /**
@@ -276,7 +275,18 @@ anjuta_token_file_update (AnjutaTokenFile *file, AnjutaToken *token)
 	for (;;)
 	{
 		gint flags = anjuta_token_get_flags (token);
-		if (flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED)) break;
+		if (flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))
+		{
+			/* Check previous token */
+			for (prev = token; prev != NULL; prev = anjuta_token_previous (prev))
+			{
+				gint flags = anjuta_token_get_flags (prev);
+				if (!(flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))) break;
+				token = prev;    
+			}
+				
+			break;
+		}
 		if (token == last)
 		{
 			/* No changed */
@@ -290,7 +300,6 @@ anjuta_token_file_update (AnjutaTokenFile *file, AnjutaToken *token)
 	{
 		gint flags = anjuta_token_get_flags (prev);
 		if ((anjuta_token_get_length (prev) != 0) && !(flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))) break;
-		token = prev;    
 	}
 	
 	/* Delete removed token and compute length of added token */
@@ -298,7 +307,7 @@ anjuta_token_file_update (AnjutaTokenFile *file, AnjutaToken *token)
 	for (next = token; (next != NULL) && (next != last);)
 	{
 		gint flags = anjuta_token_get_flags (next);
-		
+
 		if (flags & ANJUTA_TOKEN_REMOVED)
 		{
 			next = anjuta_token_file_remove_token (file, next);
diff --git a/libanjuta/anjuta-token.c b/libanjuta/anjuta-token.c
index 55a7962..a1cda97 100644
--- a/libanjuta/anjuta-token.c
+++ b/libanjuta/anjuta-token.c
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 /**
  * SECTION:anjuta-token
@@ -361,13 +362,51 @@ static void
 anjuta_token_show (AnjutaToken *token, gint indent, gchar parent)
 {
 	static gchar type[] = "\0";
+	const gchar *string;
+	gsize length;
+	const gchar *newline;
 	
 	type[0] = parent;
 	fprintf (stderr, "%*s%s %p", indent, "", type, token);
-	fprintf (stderr, ": %d \"%.*s\" %p/%p (%p/%p) %s\n",
-	    anjuta_token_get_type (token),
-	    anjuta_token_get_length (token),
-	    anjuta_token_get_string (token),
+	fprintf (stderr, ": %d ",
+	    anjuta_token_get_type (token));
+	string = anjuta_token_get_string (token);
+	length = anjuta_token_get_length (token);
+	newline = string == NULL ? NULL : g_strrstr_len (string, length, "\n");
+	if (newline == NULL)
+	{
+		/* Value doesn't contain a newline */	
+		fprintf (stderr, "\"%.*s\"",
+	    	length,
+	    	string);
+	}
+	else
+	{
+		/* Value contains a newline, take care of indentation */
+		newline++;
+		fprintf (stderr, "\"%.*s",
+	    	newline - string,
+	    	string);
+		for (;;)
+		{
+			length -= newline - string;
+			string = newline;
+
+			newline = g_strrstr_len (string, length, "\n");
+			if (newline == NULL) break;
+			
+			newline++;
+			fprintf (stderr, "%*s  %.*s",
+			    indent, "",
+			    newline - string,
+    			string);
+		}
+		fprintf (stderr, "%*s  %.*s\"",
+			    indent, "",
+			    length,
+    			string);
+	}
+	fprintf (stderr, " %p/%p (%p/%p) %s\n",
 	    token->last, token->children,
 		token->group, token->parent,
 	    anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED ? " (removed)" : "");
@@ -1167,12 +1206,13 @@ AnjutaToken *anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
 /* Token foreach
  *---------------------------------------------------------------------------*/
 
-void
-anjuta_token_foreach (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
+void 
+anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
 {
 	if (token != NULL)
 	{
-		AnjutaToken *last_parent;
+		AnjutaToken *last_parent;	/* If not NULL, token belong to a parent and
+		 							 * are not taken into account */
 		AnjutaToken *last_token;
 		gboolean expand = TRUE;
 
@@ -1246,7 +1286,7 @@ anjuta_token_foreach (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer
 				{
 					/* Get parent */
 					token = token->parent;
-					last_parent = token->last;
+					if (token != NULL) last_parent = token->last;
 					expand = FALSE;
 				}
 			}
@@ -1256,59 +1296,98 @@ anjuta_token_foreach (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer
 	return;
 }
 
-void
-anjuta_token_foreach_member (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
+AnjutaToken *
+anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
 {
 	if (token != NULL)
 	{
+		AnjutaToken *last_parent;	/* If not NULL, token belong to a parent */
 		AnjutaToken *last_token;
+		AnjutaToken buffer;			/* Temporary token allowing func to destroy
+		 							 * the current token */
 		gboolean expand = TRUE;
 
+		last_parent = NULL;
 		last_token = token->last == NULL ? token : token->last;
 		while (token != NULL)
 		{
 			if (expand && (token->children != NULL))
 			{
+				/* 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;
+				}
+
 				/* Enumerate children */
 				token = token->children;
 			}
 			else
 			{
-				if (token->children == NULL)
-				{    
-					/* Take into account only the content of group having no children */
-					func (token, user_data);
-				}
+				/* Save token data in case it is destroyed */
+				memcpy (&buffer, token, sizeof (buffer));
+				/* Take into account all token */
+				func (token, user_data);
 
 				/* Check if we have found the last token */
 				if (token == last_token)
 				{
 					/* Find last token */
-					if (token->last == NULL)
+					if (buffer.last == NULL)
 					{
+						token = &buffer;
 						break;
 					}	
 					/* Last token still include additional tokens */
-					last_token = token->last;
+					last_token = buffer.last;
 				}
 
-				if (token->next != NULL)
+				if (token == last_parent)
+				{
+					/* Find last parent */
+					if (buffer.last == NULL)
+					{
+						/* Found complete group having children */
+						last_parent = NULL;
+					}
+					else
+					{
+						/* Parent group has additional token */
+						last_parent = buffer.last;
+					}
+				}
+
+				if (buffer.next != NULL)
 				{
 					/* Get next sibling */
-					token = token->next;
+					token = buffer.next;
 					expand = TRUE;
 				}
 				else
 				{
 					/* Get parent */
-					token = token->parent;
+					token = buffer.parent;
+					if (token != NULL) last_parent = token->last;
 					expand = FALSE;
 				}
 			}
 		}
+
+		while ((token != NULL) && (token->next == NULL))
+		{
+			token = token->parent;
+		};
+
+		if (token != NULL) token = token->next;
 	}
 
-	return;
+	return token;
 }
 
 /* Token evaluation
@@ -1328,7 +1407,7 @@ anjuta_token_evaluate (AnjutaToken *token)
 {
 	GString *value = g_string_new (NULL);
 
-	anjuta_token_foreach (token, evaluate_raw_token, value);
+	anjuta_token_foreach_content (token, evaluate_raw_token, value);
 	
 	/* Return NULL and free data for an empty string */
 	return g_string_free (value, *(value->str) == '\0');
@@ -1523,22 +1602,26 @@ anjuta_token_free_children (AnjutaToken *token)
 	return token;	
 }
 
-AnjutaToken*
-anjuta_token_free (AnjutaToken *token)
+static void
+free_token (AnjutaToken *token, gpointer user_data)
 {
-	AnjutaToken *next;
-	
-	if (token == NULL) return NULL;
-
-	anjuta_token_free_children (token);
-
-	next = anjuta_token_next (token);
 	anjuta_token_unlink_token (token);
 	if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
 	{
 		g_free (token->data.pos);
 	}
 	g_slice_free (AnjutaToken, token);
+}
+ 
 
+AnjutaToken*
+anjuta_token_free (AnjutaToken *token)
+{
+	AnjutaToken *next;
+	
+	if (token == NULL) return NULL;
+
+	next = anjuta_token_foreach_post_order (token, free_token, NULL);
+	
 	return next;
 }
diff --git a/libanjuta/anjuta-token.h b/libanjuta/anjuta-token.h
index 94aace8..fa3009c 100644
--- a/libanjuta/anjuta-token.h
+++ b/libanjuta/anjuta-token.h
@@ -111,8 +111,8 @@ AnjutaToken *anjuta_token_last (AnjutaToken *token);
 AnjutaToken *anjuta_token_parent (AnjutaToken *token);
 AnjutaToken *anjuta_token_list (AnjutaToken *token);
 AnjutaToken *anjuta_token_next_after_children (AnjutaToken *token);
-void anjuta_token_foreach (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data);
-void anjuta_token_foreach_member (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data);
+void anjuta_token_foreach_content (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);
 AnjutaToken *anjuta_token_next_item (AnjutaToken *item);
diff --git a/plugins/am-project/ac-parser.y b/plugins/am-project/ac-parser.y
index 943fd3f..6b89ea9 100644
--- a/plugins/am-project/ac-parser.y
+++ b/plugins/am-project/ac-parser.y
@@ -184,6 +184,9 @@ dnl:
 
 pkg_check_modules:
     PKG_CHECK_MODULES arg_list {
+		$$ = anjuta_token_new_static (AC_TOKEN_PKG_CHECK_MODULES, NULL);
+		anjuta_token_merge ($$, $1);
+		anjuta_token_merge ($$, $2);
         amp_ac_scanner_load_module (scanner, $2);
     }
 	;
@@ -203,6 +206,9 @@ ac_macro_with_arg:
 
 ac_init:
     AC_INIT arg_list {
+		$$ = anjuta_token_new_static (AC_TOKEN_AC_INIT, NULL);
+		anjuta_token_merge ($$, $1);
+		anjuta_token_merge ($$, $2);
         amp_ac_scanner_load_properties (scanner, $1, $2);
     }
 
@@ -214,12 +220,18 @@ ac_output:
 
 obsolete_ac_output:
     OBSOLETE_AC_OUTPUT  arg_list {
+		$$ = anjuta_token_new_static (AC_TOKEN_OBSOLETE_AC_OUTPUT, NULL);
+		anjuta_token_merge ($$, $1);
+		anjuta_token_merge ($$, $2);
         amp_ac_scanner_load_config (scanner, $2);
     }
 	;
 	
 ac_config_files:
     AC_CONFIG_FILES  arg_list {
+		$$ = anjuta_token_new_static (AC_TOKEN_AC_CONFIG_FILES, NULL);
+		anjuta_token_merge ($$, $1);
+		anjuta_token_merge ($$, $2);
         amp_ac_scanner_load_config (scanner, $2);
     }
 	;
diff --git a/plugins/am-project/ac-writer.c b/plugins/am-project/ac-writer.c
index 557ebc9..c63586b 100644
--- a/plugins/am-project/ac-writer.c
+++ b/plugins/am-project/ac-writer.c
@@ -27,6 +27,7 @@
 #include "ac-writer.h"
 #include "ac-scanner.h"
 #include "ac-parser.h"
+#include "am-node.h"
 
 #include "am-project-private.h"
 
@@ -135,14 +136,16 @@ amp_project_update_ac_property (AmpProject *project, AnjutaProjectProperty *prop
 	{
 		gint types[] = {AC_TOKEN_AC_PREREQ, 0};
 		AnjutaToken *group;
+		AnjutaToken *configure;
 
-		token = find_tokens (project->configure_token, types);
+		configure = amp_root_get_configure_token (ANJUTA_AM_ROOT_NODE (project->root));
+		token = find_tokens (configure, types);
 		if (token == NULL)
 		{
-			token = skip_comment (project->configure_token);
+			token = skip_comment (configure);
 			if (token == NULL)
 			{
-				token = anjuta_token_append_child (project->configure_token, anjuta_token_new_string (COMMENT | ANJUTA_TOKEN_ADDED, "#"));
+				token = anjuta_token_append_child (configure, anjuta_token_new_string (COMMENT | ANJUTA_TOKEN_ADDED, "#"));
 				token = anjuta_token_insert_after (token, anjuta_token_new_string (SPACE | ANJUTA_TOKEN_ADDED, " Created by Anjuta project manager"));
 				token = anjuta_token_insert_after (token, anjuta_token_new_string (EOL | ANJUTA_TOKEN_ADDED, "\n"));
 				token = anjuta_token_insert_after (token, anjuta_token_new_string (EOL | ANJUTA_TOKEN_ADDED, "\n"));
@@ -172,7 +175,156 @@ amp_project_update_ac_property (AmpProject *project, AnjutaProjectProperty *prop
 	anjuta_token_style_format (project->arg_list, project->args);
 	//fprintf(stdout, "ac_init after update link\n");
 	//anjuta_token_dump (project->args);
-	anjuta_token_file_update (project->configure_file, token);
+	amp_root_update_configure (ANJUTA_AM_ROOT_NODE (project->root), token);
 	
 	return TRUE;
 }
+
+/* Module objects
+ *---------------------------------------------------------------------------*/
+
+static AnjutaToken *
+amp_project_write_module_list (AnjutaAmRootNode *root, const gchar *name, gboolean after, AnjutaToken* sibling)
+{
+	AnjutaToken *pos;
+	AnjutaToken *token;
+	static gint pkg_type[] = {AC_TOKEN_PKG_CHECK_MODULES, 0};
+	static gint eol_type[] = {ANJUTA_TOKEN_EOL, ANJUTA_TOKEN_SPACE, ANJUTA_TOKEN_COMMENT, 0};
+	AnjutaToken *configure;
+
+	configure = amp_root_get_configure_token (root);
+	
+	if (sibling == NULL)
+	{
+		pos = anjuta_token_find_type (configure, 0, pkg_type);
+		if (pos == NULL)
+		{
+			gint other_type[] = {AC_TOKEN_AC_INIT,
+				AC_TOKEN_PKG_CHECK_MODULES,
+				AC_TOKEN_AC_PREREQ,
+				0};
+			
+			pos = anjuta_token_find_type (configure, ANJUTA_TOKEN_SEARCH_LAST, other_type);
+			if (pos == NULL)
+			{
+				pos = anjuta_token_skip_comment (configure);
+			}
+			else
+			{
+				AnjutaToken* next;
+
+				next = anjuta_token_find_type (pos, ANJUTA_TOKEN_SEARCH_NOT, eol_type);
+			}
+		}
+		
+	}
+	else
+	{
+		pos = sibling;
+	}
+
+	if (after && (pos != NULL))
+	{
+		token = anjuta_token_find_type (pos, 0, eol_type);
+		if (token != NULL)
+		{
+			pos = token;
+		}
+		else
+		{
+			pos = anjuta_token_insert_token_list (after, pos,
+			    ANJUTA_TOKEN_EOL, "\n",
+			    NULL);
+			amp_root_update_configure (root, pos);
+		}
+	}
+	
+	pos = anjuta_token_insert_token_list (after, pos,
+		    ANJUTA_TOKEN_EOL, "\n",
+		    NULL);
+	amp_root_update_configure (root, pos);
+
+	token = anjuta_token_insert_token_list (FALSE, pos,
+	    		AC_TOKEN_AC_CONFIG_FILES, "PKG_CHECK_MODULES(",
+	    		ANJUTA_TOKEN_LIST, NULL,
+	    		ANJUTA_TOKEN_NAME, name,
+	    		ANJUTA_TOKEN_COMMA, ",",
+	    		ANJUTA_TOKEN_LAST, NULL,
+	    		RIGHT_PAREN, ")",
+	    		NULL);
+
+	return token;
+}
+
+
+gboolean 
+amp_module_create_token (AmpProject  *project, AnjutaAmModuleNode *module, GError **error)
+{
+	AnjutaAmRootNode *root;
+	gboolean after;
+	AnjutaToken *token;
+	AnjutaToken *prev;
+	AnjutaProjectNode *sibling;
+	gchar *relative_name;
+
+	/* Get parent target */
+	root = ANJUTA_AM_ROOT_NODE (anjuta_project_node_parent (ANJUTA_PROJECT_NODE (module)));
+	if ((root == NULL) || (anjuta_project_node_get_node_type (root) != ANJUTA_PROJECT_ROOT)) return FALSE;
+
+	
+	/* Add in configure.ac */
+	/* Find a sibling if possible */
+	prev = NULL;
+	after = TRUE;
+	for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (module)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
+	{
+		if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_MODULE)
+		{
+			prev = amp_module_get_token (ANJUTA_AM_MODULE_NODE (sibling));
+			if (prev != NULL) break;
+		}
+	}
+	if (prev == NULL)
+	{
+		after = FALSE;
+		for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (module)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
+		{
+			if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_MODULE)
+			{
+				prev = amp_module_get_token (ANJUTA_AM_MODULE_NODE (sibling));
+				if (prev != NULL) break;
+			}
+		}
+	}
+
+	token = amp_project_write_module_list (root, anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (module)), after, prev);
+	amp_root_update_configure (root, token);
+
+	return TRUE;
+}
+
+gboolean 
+amp_module_delete_token (AmpProject  *project, AnjutaAmModuleNode *module, GError **error)
+{
+	AnjutaProjectNode *root;
+	AnjutaToken *token;
+
+	/* Get root node */
+	root = anjuta_project_node_parent (ANJUTA_PROJECT_NODE (module));
+	if ((root == NULL) || (anjuta_project_node_get_node_type (root) != ANJUTA_PROJECT_ROOT))
+	{
+		return FALSE;
+	}
+
+	token = amp_module_get_token (module);
+	g_message ("amp_module_delete_token %p", token);
+	if (token != NULL)
+	{
+		token = anjuta_token_list (token);
+		anjuta_token_set_flags (token, ANJUTA_TOKEN_REMOVED);
+
+		amp_root_update_configure (ANJUTA_AM_ROOT_NODE (root), token);
+	}
+
+	return TRUE;
+}
diff --git a/plugins/am-project/ac-writer.h b/plugins/am-project/ac-writer.h
index 45be864..aa6afb3 100644
--- a/plugins/am-project/ac-writer.h
+++ b/plugins/am-project/ac-writer.h
@@ -31,6 +31,9 @@ G_BEGIN_DECLS
 
 gboolean amp_project_update_ac_property (AmpProject *project, AnjutaProjectProperty *property); 
 
+gboolean amp_module_create_token (AmpProject  *project, AnjutaAmModuleNode *module, GError **error);
+gboolean amp_module_delete_token (AmpProject  *project, AnjutaAmModuleNode *module, GError **error);
+
 G_END_DECLS
 
 #endif /* _AC_WRITER_H_ */
diff --git a/plugins/am-project/am-node.c b/plugins/am-project/am-node.c
index c8ee78d..432d9ce 100644
--- a/plugins/am-project/am-node.c
+++ b/plugins/am-project/am-node.c
@@ -242,6 +242,7 @@ amp_root_clear (AnjutaAmRootNode *node)
 {
 	if (node->configure_file != NULL) anjuta_token_file_free (node->configure_file);
 	node->configure_file = NULL;
+	if (node->configure_token) anjuta_token_free (node->configure_token);
 	
 	g_list_foreach (node->base.custom_properties, (GFunc)amp_property_free, NULL);
 	node->base.custom_properties = NULL;
@@ -259,9 +260,15 @@ amp_root_set_configure (AnjutaProjectNode *node, GFile *configure)
 }
 
 gboolean
-amp_root_update_configure (AnjutaAmRootNode *group, AnjutaToken *token)
+amp_root_update_configure (AnjutaAmRootNode *root, AnjutaToken *token)
 {
-	return anjuta_token_file_update (group->configure_file, token);
+	return anjuta_token_file_update (root->configure_file, token);
+}
+
+AnjutaToken*
+amp_root_get_configure_token (AnjutaAmRootNode *root)
+{
+	return root->configure_token;
 }
 
 /* GObjet implementation
@@ -279,6 +286,7 @@ static void
 anjuta_am_root_node_init (AnjutaAmRootNode *node)
 {
 	node->configure_file = NULL;
+	node->configure_token = NULL;
 }
 
 static void
@@ -305,8 +313,22 @@ anjuta_am_root_node_class_init (AnjutaAmRootNodeClass *klass)
 /* Module objects
  *---------------------------------------------------------------------------*/
 
+void
+amp_module_add_token (AnjutaAmModuleNode *module, AnjutaToken *token)
+{
+	module->module = token;
+	g_free (module->base.name);
+	module->base.name = anjuta_token_evaluate (anjuta_token_first_item (token));
+}
+
+AnjutaToken *
+amp_module_get_token (AnjutaAmModuleNode *node)
+{
+	return node->module;
+}
+
 AnjutaProjectNode*
-amp_module_new (AnjutaToken *token, GError **error)
+amp_module_new (const gchar *name, GError **error)
 {
 	AnjutaAmModuleNode *module = NULL;
 
@@ -315,10 +337,10 @@ amp_module_new (AnjutaToken *token, GError **error)
 	module->base.native_properties = amp_get_module_property_list();
 	module->base.custom_properties = NULL;
 	module->base.file = NULL;
-	module->base.name = anjuta_token_evaluate (token);
+	module->base.name = g_strdup (name);;
 	module->base.state = ANJUTA_PROJECT_CAN_ADD_PACKAGE |
 						ANJUTA_PROJECT_CAN_REMOVE;
-	module->module = token;
+	module->module = NULL;
 
 	return ANJUTA_PROJECT_NODE (module);
 }
@@ -677,7 +699,6 @@ anjuta_am_group_node_dispose (GObject *object)
 {
 	AnjutaAmGroupNode *node = ANJUTA_AM_GROUP_NODE (object);
 
-	g_message ("anjuta_am_group_node_dispose %p monitor %p", object, node->monitor);
 	if (node->monitor) g_object_unref (node->monitor);
 	node->monitor = NULL;
 	
diff --git a/plugins/am-project/am-node.h b/plugins/am-project/am-node.h
index fad9541..bbc6354 100644
--- a/plugins/am-project/am-node.h
+++ b/plugins/am-project/am-node.h
@@ -49,9 +49,12 @@ void amp_root_free (AnjutaAmRootNode *node);
 void amp_root_clear (AnjutaAmRootNode *node);
 AnjutaTokenFile* amp_root_set_configure (AnjutaProjectNode *node, GFile *configure);
 gboolean amp_root_update_configure (AnjutaAmRootNode *group, AnjutaToken *token);
+AnjutaToken* amp_root_get_configure_token (AnjutaAmRootNode *root);
 
-AnjutaProjectNode* amp_module_new (AnjutaToken *token, GError **error);
+AnjutaProjectNode* amp_module_new (const gchar *name, GError **error);
 void amp_module_free (AnjutaAmModuleNode *node);
+AnjutaToken *amp_module_get_token (AnjutaAmModuleNode *node);
+void amp_module_add_token (AnjutaAmModuleNode *group, AnjutaToken *token);
 
 AnjutaProjectNode* amp_package_new (const gchar *name, GError **error);
 void amp_package_free (AnjutaAmPackageNode *node);
diff --git a/plugins/am-project/am-project-private.h b/plugins/am-project/am-project-private.h
index f5ccc4f..5d0d241 100644
--- a/plugins/am-project/am-project-private.h
+++ b/plugins/am-project/am-project-private.h
@@ -48,10 +48,6 @@ struct _AmpProject {
 	 * can only work with native local files */
 	AnjutaProjectNode			*root;
 
-	/* project data */
-	AnjutaTokenFile		*configure_file;		/* configure.in file */
-	AnjutaToken			*configure_token;
-	
 	//AmpProperty			*property;
 	GList				*properties;
 	AnjutaToken			*ac_init;
@@ -95,6 +91,7 @@ GType anjuta_am_root_node_get_type (void) G_GNUC_CONST;
 struct _AnjutaAmRootNode {
 	AnjutaProjectNode base;
 	AnjutaTokenFile *configure_file;					/* Corresponding configure file */
+	AnjutaToken *configure_token;
 };
 
 
diff --git a/plugins/am-project/am-project.c b/plugins/am-project/am-project.c
index 4e4b529..bfaaac1 100644
--- a/plugins/am-project/am-project.c
+++ b/plugins/am-project/am-project.c
@@ -665,7 +665,7 @@ project_node_new (AmpProject *project, AnjutaProjectNodeType type, GFile *file,
 			}
 			break;
 		case ANJUTA_PROJECT_MODULE:
-			node = amp_module_new (NULL, error);
+			node = amp_module_new (name, error);
 			break;
 		case ANJUTA_PROJECT_PACKAGE:
 			node = amp_package_new (name, error);
@@ -797,18 +797,22 @@ amp_project_load_module (AmpProject *project, AnjutaToken *module_token)
 		/* Module name */
 		arg = anjuta_token_first_item (module_token);
 		value = anjuta_token_evaluate (arg);
-		module = amp_module_new (arg, NULL);
+		module = amp_module_new (value, NULL);
+		amp_module_add_token (module, module_token);
 		anjuta_project_node_append (project->root, module);
 		if (value != NULL) g_hash_table_insert (project->modules, value, module);
 
 		/* Package list */
 		arg = anjuta_token_next_word (arg);
-		scanner = amp_ac_scanner_new (project);
-		list = amp_ac_scanner_parse_token (scanner, arg, AC_SPACE_LIST_STATE, NULL);
-		anjuta_token_free_children (arg);
-		list = anjuta_token_delete_parent (list);
-		anjuta_token_prepend_items (arg, list);
-		amp_ac_scanner_free (scanner);
+		if (arg != NULL)
+		{
+			scanner = amp_ac_scanner_new (project);
+			list = amp_ac_scanner_parse_token (scanner, arg, AC_SPACE_LIST_STATE, NULL);
+			anjuta_token_free_children (arg);
+			list = anjuta_token_delete_parent (list);
+			anjuta_token_prepend_items (arg, list);
+			amp_ac_scanner_free (scanner);
+		}
 		
 		package = NULL;
 		compare = NULL;
@@ -1619,6 +1623,7 @@ amp_project_load_root (AmpProject *project, GError **error)
 	AnjutaAmGroupNode *group;
 	GFile *root_file;
 	GFile *configure_file;
+	AnjutaTokenFile *configure_token_file;
 	gboolean ok = TRUE;
 	GError *err = NULL;
 
@@ -1658,21 +1663,21 @@ amp_project_load_root (AmpProject *project, GError **error)
 	}
 
 	/* Parse configure */
-	project->configure_file = amp_root_set_configure (project->root, configure_file);
-	g_hash_table_insert (project->files, configure_file, project->configure_file);
-	g_object_add_toggle_ref (G_OBJECT (project->configure_file), remove_config_file, project);
-	arg = anjuta_token_file_load (project->configure_file, NULL);
+	configure_token_file = amp_root_set_configure (project->root, configure_file);
+	g_hash_table_insert (project->files, configure_file, configure_token_file);
+	g_object_add_toggle_ref (G_OBJECT (configure_token_file), remove_config_file, project);
+	arg = anjuta_token_file_load (configure_token_file, NULL);
 	//fprintf (stderr, "AC file before parsing\n");
 	//anjuta_token_dump (arg);
 	//fprintf (stderr, "\n");
 	scanner = amp_ac_scanner_new (project);
-	project->configure_token = amp_ac_scanner_parse_token (scanner, arg, 0, &err);
+	AMP_ROOT_DATA (project->root)->configure_token = amp_ac_scanner_parse_token (scanner, arg, 0, &err);
 	//fprintf (stderr, "AC file after parsing\n");
 	//anjuta_token_check (arg);
 	//anjuta_token_dump (project->configure_token);
 	//fprintf (stderr, "\n");
 	amp_ac_scanner_free (scanner);
-	if (project->configure_token == NULL)
+	if (AMP_ROOT_DATA (project->root)->configure_token == NULL)
 	{
 		g_set_error (error, IANJUTA_PROJECT_ERROR, 
 						IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED,
@@ -1840,10 +1845,6 @@ amp_project_unload (AmpProject *project)
 	/* project data */
 	if (project->root) project_node_destroy (project, project->root);
 
-	if (project->configure_file)	g_object_unref (G_OBJECT (project->configure_file));
-	project->configure_file = NULL;
-	if (project->configure_token) anjuta_token_free (project->configure_token);
-
 	g_list_foreach (project->properties, (GFunc)amp_property_free, NULL);
 	project->properties = amp_get_project_property_list ();
 	
@@ -2126,6 +2127,9 @@ amp_project_dump (AmpProject *project, AnjutaProjectNode *node)
 	case ANJUTA_PROJECT_GROUP:
 		anjuta_token_dump (AMP_GROUP_DATA (node)->make_token);
 		break;
+	case ANJUTA_PROJECT_ROOT:
+		anjuta_token_dump (AMP_ROOT_DATA (node)->configure_token);
+		break;
 	default:
 		break;
 	}
@@ -2354,6 +2358,11 @@ iproject_add_node_before (IAnjutaProject *obj, AnjutaProjectNode *parent, Anjuta
 			anjuta_project_node_insert_before (parent, sibling, node);
 			amp_source_create_token (AMP_PROJECT (obj), node, NULL);
 			break;
+		case ANJUTA_PROJECT_MODULE:
+			node = project_node_new (AMP_PROJECT (obj), type, file, name, err);
+			anjuta_project_node_insert_before (parent, sibling, node);
+			amp_module_create_token (AMP_PROJECT (obj), node, NULL);
+			break;
 		default:
 			node = project_node_new (AMP_PROJECT (obj), type, file, name, err);
 			anjuta_project_node_insert_before (parent, sibling, node);
@@ -2393,6 +2402,11 @@ iproject_add_node_after (IAnjutaProject *obj, AnjutaProjectNode *parent, AnjutaP
 			anjuta_project_node_insert_after (parent, sibling, node);
 			amp_source_create_token (AMP_PROJECT (obj), node, NULL);
 			break;
+		case ANJUTA_PROJECT_MODULE:
+			node = project_node_new (AMP_PROJECT (obj), type, file, name, err);
+			anjuta_project_node_insert_after (parent, sibling, node);
+			amp_module_create_token (AMP_PROJECT (obj), node, NULL);
+			break;
 		default:
 			node = project_node_new (AMP_PROJECT (obj), type, file, name, err);
 			anjuta_project_node_insert_after (parent, sibling, node);
@@ -2421,6 +2435,9 @@ iproject_remove_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err
 		case ANJUTA_PROJECT_SOURCE:
 			amp_source_delete_token (AMP_PROJECT (obj), node, NULL);
 			break;
+		case ANJUTA_PROJECT_MODULE:
+			amp_module_delete_token (AMP_PROJECT (obj), node, NULL);
+			break;
 		default:
 			break;
 	}
@@ -2611,8 +2628,6 @@ amp_project_instance_init (AmpProject *project)
 	
 	/* project data */
 	project->root = NULL;
-	project->configure_file = NULL;
-	project->configure_token = NULL;
 	project->properties = amp_get_project_property_list ();
 	project->ac_init = NULL;
 	project->args = NULL;
diff --git a/plugins/am-project/am-writer.c b/plugins/am-project/am-writer.c
index 8f6141b..2ccf9a7 100644
--- a/plugins/am-project/am-writer.c
+++ b/plugins/am-project/am-writer.c
@@ -57,8 +57,10 @@ amp_project_write_config_list (AmpProject *project)
 	AnjutaToken *token;
 	static gint output_type[] = {AC_TOKEN_AC_OUTPUT, 0};
 	static gint eol_type[] = {ANJUTA_TOKEN_EOL, ANJUTA_TOKEN_SPACE, ANJUTA_TOKEN_COMMENT, 0};
+	AnjutaToken *configure;
 	
-	pos = anjuta_token_find_type (project->configure_token, 0, output_type);
+	configure = amp_root_get_configure_token (ANJUTA_AM_ROOT_NODE (project->root));
+	pos = anjuta_token_find_type (configure, 0, output_type);
 	if (pos == NULL)
 	{
 		gint other_type[] = {AC_TOKEN_AC_INIT,
@@ -68,10 +70,10 @@ amp_project_write_config_list (AmpProject *project)
 			AC_TOKEN_AC_PREREQ,
 			0};
 			
-		pos = anjuta_token_find_type (project->configure_token, ANJUTA_TOKEN_SEARCH_LAST, other_type);
+		pos = anjuta_token_find_type (configure, ANJUTA_TOKEN_SEARCH_LAST, other_type);
 		if (pos == NULL)
 		{
-			pos = anjuta_token_skip_comment (project->configure_token);
+			pos = anjuta_token_skip_comment (configure);
 		}
 		else
 		{
@@ -134,8 +136,8 @@ amp_project_write_config_file (AmpProject *project, AnjutaToken *list, gboolean
 	
 	//fprintf (stdout, "Dump config list after format:\n");
 	//anjuta_token_dump (list);
-	
-	anjuta_token_file_update (project->configure_file, list);
+
+	amp_root_update_configure (ANJUTA_AM_ROOT_NODE (project->root), list);
 	
 	return token;
 }
diff --git a/plugins/am-project/am-writer.h b/plugins/am-project/am-writer.h
index 55f2201..a9a6a19 100644
--- a/plugins/am-project/am-writer.h
+++ b/plugins/am-project/am-writer.h
@@ -32,7 +32,7 @@ G_BEGIN_DECLS
 gboolean amp_project_update_am_property (AmpProject *project, AnjutaProjectNode *node, AnjutaProjectProperty *property); 
 
 gboolean amp_group_create_token (AmpProject *project, AnjutaAmGroupNode *group, GError **error);
-gboolean amp_group_delete_token (AmpProject  *project, AnjutaAmGroupNode *target, GError **error);
+gboolean amp_group_delete_token (AmpProject  *project, AnjutaAmGroupNode *group, GError **error);
 
 gboolean amp_target_create_token (AmpProject  *project, AnjutaAmTargetNode *target, GError **error);
 gboolean amp_target_delete_token (AmpProject  *project, AnjutaAmTargetNode *target, GError **error);
diff --git a/plugins/am-project/projectparser.c b/plugins/am-project/projectparser.c
index 648af9d..0a933f2 100644
--- a/plugins/am-project/projectparser.c
+++ b/plugins/am-project/projectparser.c
@@ -560,6 +560,25 @@ main(int argc, char *argv[])
 				}
 				g_object_unref (file);
 			}
+			else if (g_ascii_strcasecmp (command[1], "module") == 0)
+			{
+				if ((command[4] != NULL) && (g_ascii_strcasecmp (command[4], "before") == 0))
+				{
+					sibling = get_node (project, root, command[5]);
+					child = ianjuta_project_add_node_before (project, node, sibling, ANJUTA_PROJECT_MODULE, NULL, command[3], &error);
+					command += 2;
+				}
+				else if ((command[4] != NULL) && (g_ascii_strcasecmp (command[4], "after") == 0))
+				{
+					sibling = get_node (project, root, command[5]);
+					child = ianjuta_project_add_node_after (project, node, sibling, ANJUTA_PROJECT_MODULE, NULL, command[3], &error);
+					command += 2;
+				}
+				else
+				{
+					child = ianjuta_project_add_node_before (project, node, NULL, ANJUTA_PROJECT_MODULE, NULL, command[3], &error);
+				}
+			}
 			else
 			{
 				fprintf (stderr, "Error: unknown command %s\n", *command);
diff --git a/plugins/am-project/tests/Makefile.am b/plugins/am-project/tests/Makefile.am
index 3a55788..67c298e 100644
--- a/plugins/am-project/tests/Makefile.am
+++ b/plugins/am-project/tests/Makefile.am
@@ -24,7 +24,8 @@ TESTSUITE_AT = \
 	$(srcdir)/acinit.at \
 	$(srcdir)/include.at \
 	$(srcdir)/variable.at \
-	$(srcdir)/properties.at
+	$(srcdir)/properties.at \
+	$(srcdir)/module.at
 
 TESTSUITE = $(srcdir)/testsuite
 
diff --git a/plugins/am-project/tests/module.at b/plugins/am-project/tests/module.at
new file mode 100644
index 0000000..042df30
--- /dev/null
+++ b/plugins/am-project/tests/module.at
@@ -0,0 +1,101 @@
+AT_SETUP([Add module])
+AS_MKDIR_P([empty])
+AT_DATA([empty/configure.ac],
+[[AC_CONFIG_FILES(Makefile)
+]])
+AT_DATA([empty/Makefile.am],
+[[]])
+
+
+
+AT_DATA([expect],
+[[    MODULE (): MODULE1
+    GROUP (): empty1
+]])
+AT_DATA([reference.ac],
+[[PKG_CHECK_MODULES(MODULE1,)
+AC_CONFIG_FILES(Makefile)
+]])
+AT_PARSER_CHECK([load empty \
+		 move empty1 \
+		 add module : MODULE1 \
+		 list \
+		 save])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+AT_CHECK([diff -b empty1/configure.ac reference.ac])
+AT_PARSER_CHECK([load empty1 \
+		 list])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+
+
+
+AT_DATA([expect],
+[[    MODULE (): MODULE1
+    MODULE (): MODULE2
+    GROUP (): empty2
+]])
+AT_DATA([reference.ac],
+[[PKG_CHECK_MODULES(MODULE1,)
+PKG_CHECK_MODULES(MODULE2,)
+
+AC_CONFIG_FILES(Makefile)
+]])
+AT_PARSER_CHECK([load empty1 \
+		 move empty2 \
+		 add module : MODULE2 after 0\
+		 list \
+		 save])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+AT_CHECK([diff -b empty2/configure.ac reference.ac])
+AT_PARSER_CHECK([load empty2 \
+		 list])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+
+
+
+AT_DATA([expect],
+[[    MODULE (): MODULE2
+    GROUP (): empty3
+]])
+AT_DATA([reference.ac],
+[[
+PKG_CHECK_MODULES(MODULE2,)
+
+AC_CONFIG_FILES(Makefile)
+]])
+AT_PARSER_CHECK([load empty2 \
+		 move empty3 \
+		 remove 0 \
+		 list \
+		 save])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+AT_CHECK([diff -b empty3/configure.ac reference.ac])
+AT_PARSER_CHECK([load empty3 \
+		 list])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+
+
+
+AT_DATA([expect],
+[[    GROUP (): empty4
+]])
+AT_DATA([reference.ac],
+[[
+
+
+AC_CONFIG_FILES(Makefile)
+]])
+AT_PARSER_CHECK([load empty3 \
+		 move empty4 \
+		 remove 0 \
+		 list \
+		 save])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+AT_CHECK([diff -b empty4/configure.ac reference.ac])
+AT_PARSER_CHECK([load empty4 \
+		 list])
+AT_CHECK([[sed 's/^\(\s*\w\+\s*(\)[0-9]\+\()\)/\1\2/' output | diff - expect]])
+
+
+
+AT_CLEANUP
diff --git a/plugins/am-project/tests/testsuite.at b/plugins/am-project/tests/testsuite.at
index cda7dc2..5ef2bcf 100644
--- a/plugins/am-project/tests/testsuite.at
+++ b/plugins/am-project/tests/testsuite.at
@@ -8,3 +8,4 @@ m4_include([acinit.at])
 m4_include([include.at])
 m4_include([variable.at])
 m4_include([properties.at])
+m4_include([module.at])



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