[anjuta/newproject] Add new IAnjutaProject interface and replace autotools and makefile plugins
- From: Sebastien Granjoux <sgranjoux src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [anjuta/newproject] Add new IAnjutaProject interface and replace autotools and makefile plugins
- Date: Sat, 10 Oct 2009 20:18:50 +0000 (UTC)
commit 6716d853f0e934239cda1f01b28821a2de31c3c8
Author: Sébastien Granjoux <seb sfo free fr>
Date: Sat Oct 10 21:41:50 2009 +0200
Add new IAnjutaProject interface and replace autotools and makefile plugins
configure.in | 43 +-
libanjuta/Makefile.am | 14 +-
libanjuta/anjuta-project.c | 179 +
libanjuta/anjuta-project.h | 113 +
libanjuta/anjuta-token-file.c | 368 ++
libanjuta/anjuta-token-file.h | 60 +
libanjuta/anjuta-token-style.c | 491 +++
libanjuta/anjuta-token-style.h | 47 +
libanjuta/anjuta-token.c | 648 ++++
libanjuta/anjuta-token.h | 162 +
libanjuta/interfaces/libanjuta.idl | 254 ++-
libanjuta/libanjuta.h | 2 +
manuals/reference/libanjuta/libanjuta-sections.txt | 7 -
manuals/reference/libanjuta/libanjuta.types | 3 -
plugins/Makefile.am | 6 +-
plugins/am-project/Makefile.am | 95 +
plugins/am-project/ac-parser.y | 528 +++
plugins/am-project/ac-scanner.h | 64 +
plugins/am-project/ac-scanner.l | 443 +++
plugins/am-project/ac-writer.c | 146 +
plugins/am-project/ac-writer.h | 36 +
plugins/am-project/am-dialogs.c | 159 +
plugins/am-project/am-dialogs.h | 37 +
plugins/am-project/am-parser.y | 320 ++
.../am-project-plugin-48.png} | Bin 866 -> 866 bytes
plugins/am-project/am-project-private.h | 72 +
plugins/am-project/am-project.c | 2737 ++++++++++++++
plugins/am-project/am-project.h | 127 +
.../am-project.plugin.in} | 2 +-
plugins/am-project/am-project.ui | 419 +++
plugins/am-project/am-scanner.h | 60 +
plugins/am-project/am-scanner.l | 377 ++
plugins/{gbf-am => am-project}/plugin.c | 38 +-
plugins/{gbf-mkfile => am-project}/plugin.h | 26 +-
plugins/build-basic-autotools/executer.c | 4 +-
plugins/class-gen/plugin.c | 6 +-
plugins/debug-manager/start.c | 9 +-
plugins/file-wizard/file.c | 7 +-
plugins/gbf-am/GBF/AmFiles.pm | 1647 ---------
plugins/gbf-am/GBF/Makefile.am | 6 -
plugins/gbf-am/Makefile.am | 83 -
plugins/gbf-am/gbf-am-config.c | 385 --
plugins/gbf-am/gbf-am-config.h | 86 -
plugins/gbf-am/gbf-am-dialogs.ui | 419 ---
plugins/gbf-am/gbf-am-parse.in | 2615 --------------
plugins/gbf-am/gbf-am-project.c | 3781 --------------------
plugins/gbf-am/gbf-am-project.h | 131 -
plugins/gbf-am/gbf-am-properties.c | 1595 ---------
plugins/gbf-am/gbf-am-properties.h | 38 -
plugins/gbf-am/output.dtd | 39 -
plugins/gbf-am/program.xpm | 56 -
plugins/gbf-am/run-test.sh | 82 -
plugins/gbf-am/shared.xpm | 70 -
plugins/gbf-am/static.xpm | 57 -
plugins/gbf-am/test.c | 218 --
plugins/gbf-am/unknown.xpm | 119 -
plugins/gbf-mkfile/GBF/General.pm | 119 -
plugins/gbf-mkfile/GBF/Make.pm | 1321 -------
plugins/gbf-mkfile/GBF/Makefile.am | 6 -
plugins/gbf-mkfile/gbf-mkfile-config.c | 351 --
plugins/gbf-mkfile/gbf-mkfile-config.h | 89 -
plugins/gbf-mkfile/gbf-mkfile-parse.in | 1797 ----------
plugins/gbf-mkfile/gbf-mkfile-project.c | 3523 ------------------
plugins/gbf-mkfile/gbf-mkfile-project.h | 135 -
plugins/gbf-mkfile/gbf-mkfile-properties.c | 428 ---
plugins/gbf-mkfile/gbf-mkfile-properties.h | 42 -
plugins/glade/plugin.c | 5 +-
plugins/{gbf-mkfile => mk-project}/Makefile.am | 52 +-
plugins/mk-project/mk-parser.y | 504 +++
.../mk-project-plugin-48.png} | Bin 866 -> 866 bytes
plugins/mk-project/mk-project-private.h | 89 +
plugins/mk-project/mk-project.c | 1460 ++++++++
plugins/mk-project/mk-project.h | 119 +
.../mk-project.plugin.in} | 4 +-
plugins/mk-project/mk-project.ui | 419 +++
plugins/mk-project/mk-rule.c | 372 ++
plugins/mk-project/mk-rule.h | 38 +
plugins/mk-project/mk-scanner.h | 81 +
plugins/mk-project/mk-scanner.l | 294 ++
plugins/{gbf-mkfile => mk-project}/plugin.c | 39 +-
plugins/{gbf-am => mk-project}/plugin.h | 26 +-
plugins/project-manager/gbf-project-model.c | 196 +-
plugins/project-manager/gbf-project-model.h | 21 +-
plugins/project-manager/gbf-project-util.c | 128 +-
plugins/project-manager/gbf-project-util.h | 43 +-
plugins/project-manager/gbf-project-view.c | 8 +-
plugins/project-manager/gbf-project-view.h | 9 +-
plugins/project-manager/gbf-tree-data.c | 69 +-
plugins/project-manager/gbf-tree-data.h | 33 +-
plugins/project-manager/plugin.c | 688 ++--
plugins/project-manager/plugin.h | 5 +-
plugins/run-program/parameters.c | 2 +-
plugins/search/search-replace_backend.c | 2 +-
plugins/symbol-db/plugin.c | 4 +-
94 files changed, 11999 insertions(+), 20058 deletions(-)
---
diff --git a/configure.in b/configure.in
index 95e1de5..4ee8dd3 100644
--- a/configure.in
+++ b/configure.in
@@ -71,6 +71,14 @@ GNOME_DOC_INIT
#Check for C Compiler
AC_PROG_CC
AC_PROG_CPP
+AC_PROG_LEX
+if [["$LEX" != "flex"]]; then
+ AC_MSG_ERROR(flex is required)
+fi
+AC_PROG_YACC
+if [["$YACC" != "bison"]]; then
+ AC_MSG_ERROR(bison is required)
+fi
AC_LANG_C
AM_PROG_CC_C_O
@@ -153,29 +161,6 @@ if test x$AUTOGEN_PATH = xno; then
AC_MSG_ERROR([Couldn't find autogen, please install the autogen package. You can get it from http://autogen.sourceforge.net/])
fi
-dnl Check for perl required by gbf-am/mkfile
-dnl ----------------------------------------
-# Automake backend requirements
-# Also needed by Makefile backend
-AC_PATH_PROG(PERL, perl)
-if test -z "$PERL"; then
- AC_MSG_ERROR([perl not found])
-fi
-$PERL -e 'require 5.005;' || {
- AC_MSG_ERROR([perl 5.005 or better is required])
-}
-
-# Check for perl Locale::gettext module
-if test "x$PERL" != x; then
- AC_MSG_CHECKING(for perl module Locale::gettext)
- $PERL "-MLocale::gettext" -e exit > /dev/null 2>&1
- if test $? -ne 0; then
- AC_MSG_ERROR([not found, you should installed perl-gettext package for your distribution]);
- else
- AC_MSG_RESULT(ok);
- fi
-fi
-
dnl Check for Devhelp
dnl -----------------
@@ -309,6 +294,8 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name])
AM_GLIB_GNU_GETTEXT
IT_PROG_INTLTOOL([0.40.1])
+BISON_I18N
+
dnl ***************************************************************************
dnl Check for gtk-doc.
dnl ***************************************************************************
@@ -747,12 +734,6 @@ plugins/file-wizard/Makefile
plugins/terminal/Makefile
plugins/build-basic-autotools/Makefile
plugins/project-manager/Makefile
-plugins/gbf-am/Makefile
-plugins/gbf-am/gbf-am-parse
-plugins/gbf-am/GBF/Makefile
-plugins/gbf-mkfile/Makefile
-plugins/gbf-mkfile/gbf-mkfile-parse
-plugins/gbf-mkfile/GBF/Makefile
plugins/symbol-db/benchmark/Makefile
plugins/symbol-db/images/Makefile
plugins/symbol-db/Makefile
@@ -816,6 +797,8 @@ plugins/project-wizard/templates/library/Makefile
plugins/project-wizard/templates/library/src/Makefile
plugins/project-wizard/templates/library/po/Makefile
plugins/project-wizard/templates/m4/Makefile
+plugins/am-project/Makefile
+plugins/mk-project/Makefile
plugins/language-support-cpp-java/Makefile
plugins/run-program/Makefile
plugins/starter/Makefile
@@ -829,8 +812,6 @@ manuals/anjuta-faqs/Makefile
manuals/anjuta-build-tutorial/Makefile
mime/Makefile
])
-chmod +x ${ac_top_build_dir}plugins/gbf-am/gbf-am-parse
-chmod +x ${ac_top_build_dir}plugins/gbf-mkfile/gbf-mkfile-parse
echo " "
echo "-------------------------------------------------------------------"
echo "Conditionally built plugins:"
diff --git a/libanjuta/Makefile.am b/libanjuta/Makefile.am
index 5251aee..c280c92 100644
--- a/libanjuta/Makefile.am
+++ b/libanjuta/Makefile.am
@@ -81,7 +81,15 @@ libanjuta_la_SOURCES= \
gbf-project.c \
gbf-project.h \
anjuta-command-queue.c \
- anjuta-command-queue.h
+ anjuta-command-queue.h \
+ anjuta-token.c \
+ anjuta-token.h \
+ anjuta-token-style.c \
+ anjuta-token-style.h \
+ anjuta-token-file.c \
+ anjuta-token-file.h \
+ anjuta-project.h \
+ anjuta-project.c
if HAVE_PLUGIN_GLADE
@@ -140,7 +148,9 @@ libanjuta_include = \
anjuta-sync-command.h \
anjuta-version.h \
gbf-project.h \
- anjuta-command-queue.h
+ anjuta-command-queue.h \
+ anjuta-project.h \
+ anjuta-token.h
libanjutainclude_HEADERS = \
$(libanjuta_include) \
diff --git a/libanjuta/anjuta-project.c b/libanjuta/anjuta-project.c
new file mode 100644
index 0000000..75ea98b
--- /dev/null
+++ b/libanjuta/anjuta-project.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-project.c
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-project.h"
+
+#include "anjuta-debug.h"
+
+/* convenient shortcut macro the get the AnjutaProjectNode from a GNode */
+#define NODE_DATA(node) ((node) != NULL ? (AnjutaProjectNodeData *)((node)->data) : NULL)
+#define GROUP_DATA(node) ((node) != NULL ? (AnjutaProjectGroupData *)((node)->data) : NULL)
+#define TARGET_DATA(node) ((node) != NULL ? (AnjutaProjectTargetData *)((node)->data) : NULL)
+#define SOURCE_DATA(node) ((node) != NULL ? (AnjutaProjectSourceData *)((node)->data) : NULL)
+
+
+/* Node access functions
+ *---------------------------------------------------------------------------*/
+
+AnjutaProjectNode *
+anjuta_project_node_parent(AnjutaProjectNode *node)
+{
+ return node->parent;
+}
+
+AnjutaProjectNode *
+anjuta_project_node_first_child(AnjutaProjectNode *node)
+{
+ return g_node_first_child (node);
+}
+
+AnjutaProjectNode *
+anjuta_project_node_last_child(AnjutaProjectNode *node)
+{
+ return g_node_last_child (node);
+}
+
+AnjutaProjectNode *
+anjuta_project_node_next_sibling (AnjutaProjectNode *node)
+{
+ return g_node_next_sibling (node);
+}
+
+AnjutaProjectNode *
+anjuta_project_node_prev_sibling (AnjutaProjectNode *node)
+{
+ return g_node_prev_sibling (node);
+}
+
+AnjutaProjectNode *anjuta_project_node_nth_child (AnjutaProjectNode *node, guint n)
+{
+ return g_node_nth_child (node, n);
+}
+
+GList *
+anjuta_project_node_all_child (AnjutaProjectNode *parent, AnjutaProjectNodeType type)
+{
+ AnjutaProjectNode *node;
+ GList *list = NULL;
+
+ for (node = anjuta_project_node_first_child (parent); node != NULL; node = anjuta_project_node_next_sibling (node))
+ {
+ if (anjuta_project_node_get_type (node) == type)
+ {
+ list = g_list_prepend (list, node);
+ }
+ }
+
+ list = g_list_reverse (list);
+
+ return list;
+}
+
+GList *
+anjuta_project_node_all (AnjutaProjectNode *parent, AnjutaProjectNodeType type)
+{
+ AnjutaProjectNode *node;
+ GList *list = NULL;
+
+ for (node = anjuta_project_node_first_child (parent); node != NULL; node = anjuta_project_node_next_sibling (node))
+ {
+ if (anjuta_project_node_get_type (node) == type)
+ {
+ list = g_list_prepend (list, node);
+ }
+ if (anjuta_project_node_get_type (node) == ANJUTA_PROJECT_GROUP)
+ {
+ GList *child_list;
+
+ child_list = anjuta_project_node_all (node, type);
+ child_list = g_list_reverse (child_list);
+ list = g_list_concat (child_list, list);
+ }
+ }
+
+ list = g_list_reverse (list);
+
+ return list;
+}
+
+void
+anjuta_project_node_all_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data)
+{
+ g_node_traverse (node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, func, data);
+}
+
+AnjutaProjectNodeType
+anjuta_project_node_get_type (const AnjutaProjectNode *node)
+{
+ return NODE_DATA (node)->type;
+}
+
+/* Group access functions
+ *---------------------------------------------------------------------------*/
+
+GFile*
+anjuta_project_group_get_directory (const AnjutaProjectGroup *group)
+{
+ return GROUP_DATA (group)->directory;
+}
+
+/* Target access functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+anjuta_project_target_get_name (const AnjutaProjectTarget *target)
+{
+ return TARGET_DATA (target)->name;
+}
+
+AnjutaProjectTargetType
+anjuta_project_target_get_type (const AnjutaProjectTarget *target)
+{
+ return TARGET_DATA (target)->type;
+}
+
+/* Source access functions
+ *---------------------------------------------------------------------------*/
+
+GFile*
+anjuta_project_source_get_file (const AnjutaProjectSource *source)
+{
+ return SOURCE_DATA (source)->file;
+}
+
+/* Target type functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+anjuta_project_target_type_name (const AnjutaProjectTargetType type)
+{
+ return type->name;
+}
+
+const gchar *
+anjuta_project_target_type_mime (const AnjutaProjectTargetType type)
+{
+ return type->mime_type;
+}
+
+AnjutaProjectTargetClass
+anjuta_project_target_type_class (const AnjutaProjectTargetType type)
+{
+ return type->base;
+}
diff --git a/libanjuta/anjuta-project.h b/libanjuta/anjuta-project.h
new file mode 100644
index 0000000..31fbed1
--- /dev/null
+++ b/libanjuta/anjuta-project.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-project.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_PROJECT_H_
+#define _ANJUTA_PROJECT_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define ANJUTA_IS_PROJECT_GROUP(obj) (((AnjutaProjectNodeData *)obj->data)->type == ANJUTA_PROJECT_GROUP)
+#define ANJUTA_IS_PROJECT_TARGET(obj) (((AnjutaProjectNodeData *)obj->data)->type == ANJUTA_PROJECT_TARGET)
+#define ANJUTA_IS_PROJECT_NODE(obj) (1)
+
+typedef enum
+{
+ ANJUTA_PROJECT_UNKNOWN,
+ ANJUTA_PROJECT_GROUP,
+ ANJUTA_PROJECT_TARGET,
+ ANJUTA_PROJECT_SOURCE,
+ ANJUTA_PROJECT_VARIABLE
+} AnjutaProjectNodeType;
+
+typedef enum
+{
+ ANJUTA_TARGET_UNKNOWN,
+ ANJUTA_TARGET_SHAREDLIB,
+ ANJUTA_TARGET_STATICLIB,
+ ANJUTA_TARGET_EXECUTABLE,
+ ANJUTA_TARGET_PYTHON,
+ ANJUTA_TARGET_JAVA
+} AnjutaProjectTargetClass;
+
+typedef struct
+{
+ gchar *name;
+ AnjutaProjectTargetClass base;
+ gchar *mime_type;
+} AnjutaProjectTargetInformation;
+
+typedef AnjutaProjectTargetInformation* AnjutaProjectTargetType;
+
+typedef struct
+{
+ AnjutaProjectNodeType type;
+} AnjutaProjectNodeData;
+
+typedef struct {
+ AnjutaProjectNodeData node;
+ GFile *directory;
+} AnjutaProjectGroupData;
+
+typedef struct {
+ AnjutaProjectNodeData node;
+ gchar *name;
+ AnjutaProjectTargetType type;
+} AnjutaProjectTargetData;
+
+typedef struct {
+ AnjutaProjectNodeData node;
+ GFile *file;
+} AnjutaProjectSourceData;
+
+typedef GNode AnjutaProjectNode;
+typedef GNode AnjutaProjectGroup;
+typedef GNode AnjutaProjectTarget;
+typedef GNode AnjutaProjectSource;
+
+typedef GNodeTraverseFunc AnjutaProjectNodeFunc;
+
+AnjutaProjectNode *anjuta_project_node_parent (AnjutaProjectNode *node);
+AnjutaProjectNode *anjuta_project_node_first_child (AnjutaProjectNode *node);
+AnjutaProjectNode *anjuta_project_node_last_child (AnjutaProjectNode *node);
+AnjutaProjectNode *anjuta_project_node_next_sibling (AnjutaProjectNode *node);
+AnjutaProjectNode *anjuta_project_node_prev_sibling (AnjutaProjectNode *node);
+AnjutaProjectNode *anjuta_project_node_nth_child (AnjutaProjectNode *node, guint n);
+GList *anjuta_project_node_all_child (AnjutaProjectNode *node, AnjutaProjectNodeType type);
+GList *anjuta_project_node_all (AnjutaProjectNode *node, AnjutaProjectNodeType type);
+void anjuta_project_node_all_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data);
+
+AnjutaProjectNodeType anjuta_project_node_get_type (const AnjutaProjectNode *node);
+
+GFile *anjuta_project_group_get_directory (const AnjutaProjectGroup *group);
+
+const gchar *anjuta_project_target_get_name (const AnjutaProjectTarget *target);
+AnjutaProjectTargetType anjuta_project_target_get_type (const AnjutaProjectTarget *target);
+
+GFile *anjuta_project_source_get_file (const AnjutaProjectSource *source);
+
+const gchar *anjuta_project_target_type_name (const AnjutaProjectTargetType type);
+const gchar *anjuta_project_target_type_mime (const AnjutaProjectTargetType type);
+AnjutaProjectTargetClass anjuta_project_target_type_class (const AnjutaProjectTargetType type);
+
+G_END_DECLS
+
+#endif
diff --git a/libanjuta/anjuta-token-file.c b/libanjuta/anjuta-token-file.c
new file mode 100644
index 0000000..9fb09a8
--- /dev/null
+++ b/libanjuta/anjuta-token-file.c
@@ -0,0 +1,368 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token-file.c
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-token-file.h"
+
+#include "anjuta-debug.h"
+
+#include <glib-object.h>
+
+#include <stdio.h>
+#include <string.h>
+
+/* Types declarations
+ *---------------------------------------------------------------------------*/
+
+struct _AnjutaTokenFile
+{
+ GObject parent;
+
+ GFile* file;
+
+ gsize length;
+ gchar *content;
+
+ AnjutaToken *first;
+ AnjutaToken *last;
+
+ guint line_width;
+};
+
+struct _AnjutaTokenFileClass
+{
+ GObjectClass parent_class;
+};
+
+static GObjectClass *parent_class = NULL;
+
+/* Helpers functions
+ *---------------------------------------------------------------------------*/
+
+/* Create a directories, including parents if necessary. This function
+ * exists in GLIB 2.18, but we need only 2.16 currently.
+ * */
+
+static gboolean
+make_directory_with_parents (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GError *path_error = NULL;
+ GList *children = NULL;
+
+ for (;;)
+ {
+ if (g_file_make_directory (file, cancellable, &path_error))
+ {
+ /* Making child directory succeed */
+ if (children == NULL)
+ {
+ /* All directories have been created */
+ return TRUE;
+ }
+ else
+ {
+ /* Get next child directory */
+ g_object_unref (file);
+ file = (GFile *)children->data;
+ children = g_list_delete_link (children, children);
+ }
+ }
+ else if (g_error_matches (path_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ g_clear_error (&path_error);
+ children = g_list_prepend (children, file);
+ file = g_file_get_parent (file);
+ }
+ else
+ {
+ g_object_unref (file);
+ g_list_foreach (children, (GFunc)g_object_unref, NULL);
+ g_list_free (children);
+ g_propagate_error (error, path_error);
+
+ return FALSE;
+ }
+ }
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+anjuta_token_file_get_content (AnjutaTokenFile *file, GError **error)
+{
+ if (file->content == NULL)
+ {
+ gchar *content;
+ gsize length;
+
+ if (g_file_load_contents (file->file, NULL, &content, &length, NULL, error))
+ {
+ file->content = content;
+ file->length = length;
+ }
+ }
+
+ return file->content;
+}
+
+gsize
+anjuta_token_file_get_length (AnjutaTokenFile *file, GError **error)
+{
+ anjuta_token_file_get_content (file, error);
+
+ return file->length;
+}
+
+typedef struct _AnjutaTokenFileSaveData AnjutaTokenFileSaveData;
+
+struct _AnjutaTokenFileSaveData
+{
+ GError **error;
+ GFileOutputStream *stream;
+ gboolean fail;
+};
+
+static gboolean
+save_node (AnjutaToken *token, AnjutaTokenFileSaveData *data)
+{
+ if (!(anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED))
+ {
+ if (!(anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED) && (anjuta_token_get_length (token)))
+ {
+ if (g_output_stream_write (G_OUTPUT_STREAM (data->stream), anjuta_token_get_string (token), anjuta_token_get_length (token) * sizeof (char), NULL, data->error) < 0)
+ {
+ data->fail = TRUE;
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+anjuta_token_file_save (AnjutaTokenFile *file, GError **error)
+{
+ GFileOutputStream *stream;
+ gboolean ok;
+ GError *err = NULL;
+ AnjutaTokenFileSaveData data;
+
+ stream = g_file_replace (file->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &err);
+ if (stream == NULL)
+ {
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ /* Perhaps parent directory is missing, try to create it */
+ GFile *parent = g_file_get_parent (file->file);
+
+ if (make_directory_with_parents (parent, NULL, NULL))
+ {
+ g_object_unref (parent);
+ g_clear_error (&err);
+ stream = g_file_replace (file->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
+ if (stream == NULL) return FALSE;
+ }
+ else
+ {
+ g_object_unref (parent);
+ g_propagate_error (error, err);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+ }
+
+ data.error = error;
+ data.stream = stream;
+ data.fail = FALSE;
+ g_node_traverse ((GNode *)file->first, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)save_node, &data);
+ ok = g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
+ g_object_unref (stream);
+
+ return !data.fail;
+}
+
+void
+anjuta_token_file_move (AnjutaTokenFile *file, GFile *new_file)
+{
+ if (file->file) g_object_unref (file->file);
+ file->file = new_file != NULL ? g_object_ref (new_file) : NULL;
+}
+
+void
+anjuta_token_file_append (AnjutaTokenFile *file, AnjutaToken *token)
+{
+ if (file->last == NULL)
+ {
+ file->first = token;
+ }
+ else if (file->last == file->first)
+ {
+ g_node_insert_after ((GNode *)file->first, NULL, (GNode *)token);
+ }
+ else
+ {
+ while (((GNode *)file->last)->parent != (GNode *)file->first)
+ {
+ file->last = (AnjutaToken *)((GNode *)file->last)->parent;
+ }
+ g_node_insert_after ((GNode *)file->first, (GNode *)file->last, (GNode *)token);
+ }
+ file->last = token;
+}
+
+void
+anjuta_token_file_update_line_width (AnjutaTokenFile *file, guint width)
+{
+ if (width > file->line_width) file->line_width = width;
+}
+
+AnjutaToken*
+anjuta_token_file_first (AnjutaTokenFile *file)
+{
+ return file->first;
+}
+
+AnjutaToken*
+anjuta_token_file_last (AnjutaTokenFile *file)
+{
+ return file->last;
+}
+
+GFile*
+anjuta_token_file_get_file (AnjutaTokenFile *file)
+{
+ return file->file;
+}
+
+guint
+anjuta_token_file_get_line_width (AnjutaTokenFile *file)
+{
+ return file->line_width;
+}
+
+/* GObject functions
+ *---------------------------------------------------------------------------*/
+
+/* dispose is the first destruction step. It is used to unref object created
+ * with instance_init in order to break reference counting cycles. This
+ * function could be called several times. All function should still work
+ * after this call. It has to called its parents.*/
+
+static void
+anjuta_token_file_dispose (GObject *object)
+{
+ AnjutaTokenFile *file = ANJUTA_TOKEN_FILE (object);
+
+ anjuta_token_free (file->first);
+
+ if (file->content) g_free (file->content);
+ file->content = NULL;
+
+ if (file->file) g_object_unref (file->file);
+ file->file = NULL;
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/* instance_init is the constructor. All functions should work after this
+ * call. */
+
+static void
+anjuta_token_file_instance_init (AnjutaTokenFile *file)
+{
+ file->file = NULL;
+}
+
+/* class_init intialize the class itself not the instance */
+
+static void
+anjuta_token_file_class_init (AnjutaTokenFileClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ g_return_if_fail (klass != NULL);
+
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = anjuta_token_file_dispose;
+}
+
+GType
+anjuta_token_file_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (AnjutaTokenFileClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) anjuta_token_file_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (AnjutaTokenFile),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) anjuta_token_file_instance_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "AnjutaTokenFile", &type_info, 0);
+ }
+
+ return type;
+}
+
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+AnjutaTokenFile *
+anjuta_token_file_new (GFile *gfile)
+{
+ AnjutaTokenFile *file = g_object_new (ANJUTA_TOKEN_FILE_TYPE, NULL);
+
+ if (gfile)
+ {
+ file->file = g_object_ref (gfile);
+ file->first = anjuta_token_new_static (ANJUTA_TOKEN_FILE, NULL);
+ file->last = file->first;
+ }
+
+ return file;
+};
+
+void
+anjuta_token_file_free (AnjutaTokenFile *tfile)
+{
+ g_object_unref (tfile);
+}
diff --git a/libanjuta/anjuta-token-file.h b/libanjuta/anjuta-token-file.h
new file mode 100644
index 0000000..d1053f1
--- /dev/null
+++ b/libanjuta/anjuta-token-file.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token-file.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_TOKEN_FILE_H_
+#define _ANJUTA_TOKEN_FILE_H_
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <libanjuta/anjuta-token.h>
+
+G_BEGIN_DECLS
+
+#define ANJUTA_TOKEN_FILE_TYPE (anjuta_token_file_get_type ())
+#define ANJUTA_TOKEN_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TOKEN_FILE_TYPE, AnjutaTokenFile))
+#define ANJUTA_TOKEN_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TOKEN_FILE_TYPE, AnjutaTokenFileClass))
+#define IS_ANJUTA_TOKEN_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TOKEN_FILE_TYPE))
+#define IS_ANJUTA_TOKEN_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TOKEN_FILE_TYPE))
+#define GET_ANJUTA_TOKEN_FILE_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANJUTA_TOKEN_FILE_TYPE, AnjutaTokenFileClass))
+
+typedef struct _AnjutaTokenFile AnjutaTokenFile;
+typedef struct _AnjutaTokenFileClass AnjutaTokenFileClass;
+
+GType anjuta_token_file_get_type (void);
+
+AnjutaTokenFile *anjuta_token_file_new (GFile *file);
+void anjuta_token_file_free (AnjutaTokenFile *file);
+
+const gchar* anjuta_token_file_get_content (AnjutaTokenFile *file, GError **error);
+gsize anjuta_token_file_get_length (AnjutaTokenFile *file, GError **error);
+void anjuta_token_file_move (AnjutaTokenFile *file, GFile *new_file);
+gboolean anjuta_token_file_save (AnjutaTokenFile *file, GError **error);
+
+void anjuta_token_file_append (AnjutaTokenFile *file, AnjutaToken *token);
+void anjuta_token_file_update_line_width (AnjutaTokenFile *file, guint width);
+
+AnjutaToken* anjuta_token_file_first (AnjutaTokenFile *file);
+AnjutaToken* anjuta_token_file_last (AnjutaTokenFile *file);
+GFile *anjuta_token_file_get_file (AnjutaTokenFile *file);
+guint anjuta_token_file_get_line_width (AnjutaTokenFile *file);
+
+G_END_DECLS
+
+#endif
diff --git a/libanjuta/anjuta-token-style.c b/libanjuta/anjuta-token-style.c
new file mode 100644
index 0000000..87b8b7e
--- /dev/null
+++ b/libanjuta/anjuta-token-style.c
@@ -0,0 +1,491 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token-style.c
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-token-style.h"
+
+#include "libanjuta/anjuta-debug.h"
+
+#include <string.h>
+
+/* Type definition
+ *---------------------------------------------------------------------------*/
+
+typedef struct _AnjutaTokenStyleSeparator AnjutaTokenStyleSeparator;
+
+struct _AnjutaTokenStyleSeparator
+{
+ guint count;
+ gchar *value;
+ gboolean eol;
+};
+
+struct _AnjutaTokenStyle
+{
+ guint max_width;
+ GHashTable *separator;
+};
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+void free_separator (AnjutaTokenStyleSeparator *sep, gpointer user_data)
+{
+ DEBUG_PRINT ("free sep %p count %d", sep, sep->count);
+ g_free (sep->value);
+ g_slice_free (AnjutaTokenStyleSeparator, sep);
+}
+
+void free_separator_list (guint key, GList *value, gpointer user_data)
+{
+ /* Free list elements */
+ g_list_foreach (value, (GFunc)free_separator, NULL);
+ g_list_free (value);
+}
+
+AnjutaTokenStyleSeparator*
+anjuta_token_style_insert_separator (AnjutaTokenStyle *style, guint key, const gchar *value)
+{
+ GList *list;
+ GList *last = NULL;
+ GList *sibling = NULL;
+ AnjutaTokenStyleSeparator *sep;
+
+
+ /* Look the separator is already registered */
+ list = (GList *)g_hash_table_lookup (style->separator, GINT_TO_POINTER (key));
+ if (list != NULL)
+ {
+ for (sibling = list; sibling != NULL; sibling = g_list_next(sibling))
+ {
+ sep = (AnjutaTokenStyleSeparator *)sibling->data;
+
+ /* Keep the first separator with count = 1, to insert the new one if
+ * not found */
+ if ((last == NULL) && (sep->count == 1)) last = sibling;
+
+ if (value == NULL)
+ {
+ if (sep->value == NULL)
+ {
+ sep->count++;
+ break;
+ }
+ }
+ else if ((sep->value != NULL) && (strcmp (sep->value, value) == 0))
+ {
+ sep->count++;
+ break;
+ }
+ }
+ }
+
+ if (sibling != NULL)
+ {
+ /* Increment the separator count, Move it if needed */
+ for (last = g_list_previous (sibling); last != NULL; last = g_list_previous (sibling))
+ {
+ if (((AnjutaTokenStyleSeparator *)sibling->data)->count >= ((AnjutaTokenStyleSeparator *)last->data)->count)
+ {
+ last->next = sibling->next;
+ sibling->next = last;
+ sibling->prev = last->prev;
+ last->prev = sibling;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (last == NULL)
+ {
+ /* Update the list head */
+ list = sibling;
+ g_hash_table_replace (style->separator, GINT_TO_POINTER (key), list);
+ }
+
+ return (AnjutaTokenStyleSeparator *)sibling->data;
+ }
+ else
+ {
+ /* Create a new separator */
+ sep = g_slice_new0 (AnjutaTokenStyleSeparator);
+ sep->count = 1;
+ sep->value = g_strdup (value);
+ sep->eol = value == NULL ? FALSE : strchr (value, '\n') != NULL;
+ DEBUG_PRINT ("alloc sep %p count %d", sep, sep->count);
+ list = g_list_insert_before (list, last, sep);
+ g_hash_table_replace (style->separator, GINT_TO_POINTER (key), list);
+
+ return sep;
+ }
+}
+
+AnjutaTokenStyleSeparator*
+anjuta_token_style_insert_separator_between (AnjutaTokenStyle *style, gint next, gint prev, const gchar *value)
+{
+ return anjuta_token_style_insert_separator (style, ((guint)prev & 0xFFFF) | (((guint)next & 0xFFFF) << 16), value);
+}
+
+static AnjutaToken*
+anjuta_token_style_lookup (AnjutaTokenStyle *style)
+{
+ GList *list;
+
+ list = g_hash_table_lookup (style->separator, GINT_TO_POINTER (ANJUTA_TOKEN_NEXT));
+
+ return anjuta_token_new_string (ANJUTA_TOKEN_NEXT, ((AnjutaTokenStyleSeparator *)list->data)->value);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+void
+anjuta_token_style_update (AnjutaTokenStyle *style, AnjutaToken *list)
+{
+ AnjutaToken *token;
+ AnjutaToken *next_token;
+ guint prev = 0;
+ guint next = 0;
+ guint line_width = 0;
+ guint sep_count = 0;
+
+ /* Initialize first line width */
+ for (token = list; token != NULL; token = anjuta_token_previous (token))
+ {
+ gchar *value = anjuta_token_value (token);
+ const gchar *eol = strrchr (value, '\n');
+ gsize len = strlen (value);
+
+ g_free (value);
+
+
+ if (eol != NULL)
+ {
+ line_width = value + len - eol;
+ break;
+ }
+
+ line_width += len;
+ }
+
+ for (token = anjuta_token_next_child (list); token != NULL; token = next_token)
+ {
+ gchar *value = NULL;
+ const gchar *eol;
+ gsize len;
+ gint type;
+
+ next_token = anjuta_token_next_sibling (token);
+ type = anjuta_token_get_type (token);
+ next = next_token == NULL ? 0 : anjuta_token_get_type (next_token);
+
+ value = anjuta_token_value (token);
+ if (value == NULL) continue;
+
+ len = strlen (value);
+ eol = strrchr (value, '\n');
+ if (eol != NULL) len -= (eol - value);
+ g_free (value);
+
+ line_width += len;
+
+ switch (type)
+ {
+ case ANJUTA_TOKEN_START:
+ case ANJUTA_TOKEN_LAST:
+ case ANJUTA_TOKEN_NEXT:
+ break;
+ default:
+ if (eol != NULL)
+ {
+ line_width = len;
+ sep_count = 0;
+ }
+ continue;
+ }
+
+ value = anjuta_token_evaluate (token);
+ anjuta_token_style_insert_separator_between (style, 0, type, value);
+ if (type == ANJUTA_TOKEN_NEXT)
+ {
+ anjuta_token_style_insert_separator_between (style, next, prev, value);
+ anjuta_token_style_insert_separator_between (style, next, ANJUTA_TOKEN_ANY, value);
+ anjuta_token_style_insert_separator_between (style, ANJUTA_TOKEN_ANY, prev, value);
+ }
+ g_free (value);
+
+ if (eol == NULL)
+ {
+ sep_count++;
+ }
+ else
+ {
+ if ((sep_count > 1) && (line_width > style->max_width))
+ {
+ style->max_width = line_width;
+ }
+ sep_count = 0;
+ line_width = len;
+ }
+ }
+}
+
+static void
+anjuta_token_style_format_line (AnjutaTokenStyle *style, AnjutaToken *bol, AnjutaToken *eol)
+{
+
+}
+
+void
+anjuta_token_style_format (AnjutaTokenStyle *style, AnjutaToken *list)
+{
+ AnjutaToken *arg;
+
+ for (arg = anjuta_token_next_child (list); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ if ((anjuta_token_get_type (arg) == ANJUTA_TOKEN_NEXT) && (anjuta_token_get_flags (arg) & (ANJUTA_TOKEN_ADDED)))
+ {
+ anjuta_token_insert_after (arg, anjuta_token_style_lookup (style));
+ anjuta_token_free (arg);
+ }
+ }
+#if 0
+ AnjutaToken *arg;
+
+ if (style->sep == NULL)
+ {
+ for (arg = anjuta_token_next_child (list); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ if ((anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) && (anjuta_token_get_flags (arg) & (ANJUTA_TOKEN_ADDED)))
+ {
+ anjuta_token_insert_after (arg, anjuta_token_copy (style->eol));
+ anjuta_token_free (arg);
+ }
+ }
+ }
+ else
+ {
+ AnjutaToken *bol = anjuta_token_next_child (list);
+ gboolean modified = FALSE;
+
+ for (arg = bol; arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ gchar *value = anjuta_token_evaluate (arg);
+ if (anjuta_token_get_flags (arg) & (ANJUTA_TOKEN_REMOVED | ANJUTA_TOKEN_ADDED)) modified = TRUE;
+ if (strchr (value, '\n'))
+ {
+ if (modified) anjuta_token_style_format_line (style, list, arg);
+ bol = arg;
+ if (style->sep == NULL) modified = FALSE;
+ }
+ g_free (value);
+ }
+ if (modified) anjuta_token_style_format_line (style, bol, NULL);
+ }
+#endif
+}
+
+AnjutaToken *
+anjuta_token_list_first (AnjutaToken *list)
+{
+ AnjutaToken *token;
+
+ token = anjuta_token_next_child (list);
+ if (token == NULL) return token;
+
+ if (anjuta_token_get_type (token) == ANJUTA_TOKEN_START)
+ {
+ token = anjuta_token_next_sibling (token);
+ }
+
+ return token;
+}
+
+AnjutaToken *
+anjuta_token_list_last (AnjutaToken *list)
+{
+ AnjutaToken *token;
+
+ token = anjuta_token_list_first (list);
+ for (;;)
+ {
+ AnjutaToken *next = anjuta_token_list_next (list);
+ if (next == NULL) return token;
+ token = next;
+ }
+}
+
+AnjutaToken *
+anjuta_token_list_next (AnjutaToken *sibling)
+{
+ AnjutaToken *token;
+
+ token = anjuta_token_next_sibling (sibling);
+ if (token == NULL) return token;
+
+ if (anjuta_token_get_type (token) == ANJUTA_TOKEN_NEXT)
+ {
+ token = anjuta_token_next_sibling (token);
+ }
+
+ return token;
+}
+
+AnjutaToken *
+anjuta_token_list_replace (AnjutaToken *sibling, AnjutaToken *baby)
+{
+ AnjutaToken *token;
+
+ token = anjuta_token_insert_before (sibling, baby);
+ if ((anjuta_token_get_type (sibling) != ANJUTA_TOKEN_NEXT) && (anjuta_token_get_type (sibling) != ANJUTA_TOKEN_LAST))
+ {
+ anjuta_token_remove (sibling);
+ }
+
+ return token;
+}
+
+AnjutaToken *
+anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *baby)
+{
+ AnjutaToken *token;
+
+ token = anjuta_token_list_first (list);
+ if (token == NULL)
+ {
+ token = anjuta_token_insert_child (list, anjuta_token_new_static (ANJUTA_TOKEN_START | ANJUTA_TOKEN_ADDED, NULL));
+ token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL));
+ }
+
+ for (; n != 0; n--)
+ {
+ AnjutaToken *next;
+
+ switch (anjuta_token_get_type (token))
+ {
+ case ANJUTA_TOKEN_LAST:
+ anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
+ continue;
+ case ANJUTA_TOKEN_NEXT:
+ break;
+ default:
+ token = anjuta_token_next_sibling (token);
+ if (token == NULL)
+ {
+ token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
+ }
+ else if (anjuta_token_get_type (token) == ANJUTA_TOKEN_LAST)
+ {
+ token = anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
+ }
+ break;
+ }
+
+ next = anjuta_token_next_sibling (token);
+ if (next == NULL)
+ {
+ token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL));
+ }
+ else
+ {
+ token = next;
+ }
+ }
+
+ return anjuta_token_list_replace (token, baby);
+}
+
+AnjutaToken *
+anjuta_token_list_insert_after (AnjutaToken *sibling, AnjutaToken *baby)
+{
+ AnjutaToken *token = sibling;
+ AnjutaToken *separator;
+
+ if (anjuta_token_get_type (token) == ANJUTA_TOKEN_LAST)
+ {
+ token = anjuta_token_previous_sibling (token);
+ }
+ else if ((anjuta_token_get_type (token) != ANJUTA_TOKEN_NEXT) && (anjuta_token_next_sibling (token) != NULL))
+ {
+ token = anjuta_token_next_sibling (token);
+ }
+
+ separator = anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL);
+ token = anjuta_token_insert_after (token, separator);
+ token = anjuta_token_insert_after (token, baby);
+
+ return token;
+}
+
+void
+anjuta_token_list_remove (AnjutaToken *sibling)
+{
+ AnjutaToken *token;
+
+ if ((anjuta_token_get_type (sibling) != ANJUTA_TOKEN_NEXT) && (anjuta_token_get_type (sibling) != ANJUTA_TOKEN_LAST))
+ {
+ anjuta_token_remove (sibling);
+ }
+
+ token = anjuta_token_next_sibling (sibling);
+ if (anjuta_token_get_type (token) == ANJUTA_TOKEN_NEXT)
+ {
+ anjuta_token_remove (token);
+ return;
+ }
+
+ token = anjuta_token_previous_sibling (sibling);
+ if (anjuta_token_get_type (token) == ANJUTA_TOKEN_NEXT)
+ {
+ anjuta_token_remove (token);
+ return;
+ }
+
+ return;
+}
+
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+AnjutaTokenStyle *
+anjuta_token_style_new (const gchar *start, const gchar *next, const gchar *eol, const gchar *last, guint max_width)
+{
+ AnjutaTokenStyle *style;
+
+ style = g_slice_new0 (AnjutaTokenStyle);
+ style->max_width = max_width;
+
+ style->separator = g_hash_table_new (g_direct_hash, NULL);
+ anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_START, start);
+ anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_NEXT, next);
+ anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_NEXT, eol);
+ anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_LAST, last);
+
+ return style;
+}
+
+void
+anjuta_token_style_free (AnjutaTokenStyle *style)
+{
+ g_hash_table_foreach (style->separator, (GHFunc)free_separator_list, NULL);
+ g_hash_table_destroy (style->separator);
+ g_slice_free (AnjutaTokenStyle, style);
+}
diff --git a/libanjuta/anjuta-token-style.h b/libanjuta/anjuta-token-style.h
new file mode 100644
index 0000000..55a8859
--- /dev/null
+++ b/libanjuta/anjuta-token-style.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token-style.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_TOKEN_STYLE_H_
+#define _ANJUTA_TOKEN_STYLE_H_
+
+#include <glib.h>
+
+#include "anjuta-token.h"
+
+G_BEGIN_DECLS
+
+typedef struct _AnjutaTokenStyle AnjutaTokenStyle;
+
+AnjutaTokenStyle *anjuta_token_style_new (const gchar *start, const gchar *next, const gchar *eol, const gchar *last, guint max_width);
+void anjuta_token_style_free (AnjutaTokenStyle *style);
+
+void anjuta_token_style_update (AnjutaTokenStyle *style, AnjutaToken *list);
+void anjuta_token_style_format (AnjutaTokenStyle *style, AnjutaToken *list);
+
+AnjutaToken *anjuta_token_list_first (AnjutaToken *list);
+AnjutaToken *anjuta_token_list_last (AnjutaToken *list);
+AnjutaToken *anjuta_token_list_next (AnjutaToken *sibling);
+AnjutaToken *anjuta_token_list_replace (AnjutaToken *sibling, AnjutaToken *baby);
+AnjutaToken *anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *baby);
+AnjutaToken *anjuta_token_list_insert_after (AnjutaToken *sibling, AnjutaToken *baby);
+void anjuta_token_list_delete (AnjutaToken *sibling);
+
+G_END_DECLS
+
+#endif
diff --git a/libanjuta/anjuta-token.c b/libanjuta/anjuta-token.c
new file mode 100644
index 0000000..088e9f8
--- /dev/null
+++ b/libanjuta/anjuta-token.c
@@ -0,0 +1,648 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token.c
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-token.h"
+
+#include "anjuta-debug.h"
+
+#include <glib-object.h>
+
+#include <stdio.h>
+#include <string.h>
+
+typedef struct _AnjutaTokenData AnjutaTokenData;
+
+struct _AnjutaTokenData
+{
+ AnjutaTokenType type;
+ gint flags;
+ gchar *pos;
+ gsize length;
+};
+
+struct _AnjutaToken
+{
+ AnjutaTokenData *data;
+ AnjutaToken *next;
+ AnjutaToken *prev;
+ AnjutaToken *parent;
+ AnjutaToken *children;
+};
+
+#define ANJUTA_TOKEN_DATA(node) ((node) != NULL ? (AnjutaTokenData *)((node)->data) : NULL)
+
+
+/* Helpers functions
+ *---------------------------------------------------------------------------*/
+
+/* Return true and update end if the token is found.
+ * If a close token is found, return FALSE but still update end */
+gboolean
+anjuta_token_match (AnjutaToken *token, gint flags, AnjutaToken *sequence, AnjutaToken **end)
+{
+
+ for (; sequence != NULL; /*sequence = flags & ANJUTA_SEARCH_BACKWARD ? anjuta_token_previous (sequence) : anjuta_token_next (sequence)*/)
+ {
+ AnjutaToken *toka;
+ AnjutaToken *tokb = token;
+
+ for (toka = sequence; toka != NULL; toka = anjuta_token_next_sibling (toka))
+ {
+ if (anjuta_token_compare (toka, tokb))
+ {
+ tokb = anjuta_token_next (tokb);
+ if (tokb == NULL)
+ {
+ if (end) *end = sequence;
+ return TRUE;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (flags & ANJUTA_SEARCH_BACKWARD)
+ {
+ sequence = flags & ANJUTA_SEARCH_INTO ? anjuta_token_previous (sequence) : anjuta_token_previous_sibling (sequence);
+ }
+ else
+ {
+ sequence = flags & ANJUTA_SEARCH_INTO ? anjuta_token_next (sequence) : anjuta_token_next_sibling (sequence);
+ }
+ }
+ /*g_message ("matched %p %d", sequence, level);*/
+
+ if (end) *end = sequence;
+
+ return FALSE;
+}
+
+
+gboolean
+anjuta_token_remove (AnjutaToken *token)
+{
+ ANJUTA_TOKEN_DATA (token)->flags |= ANJUTA_TOKEN_REMOVED;
+
+ return TRUE;
+}
+
+gboolean
+anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
+{
+ AnjutaTokenData *data = ANJUTA_TOKEN_DATA (toka);
+ AnjutaTokenData *datb = ANJUTA_TOKEN_DATA (tokb);
+
+ if (datb->type)
+ {
+ if (datb->type != data->type) return FALSE;
+ }
+
+ if (datb != ANJUTA_TOKEN_NONE)
+ {
+ if (datb->length != 0)
+ {
+ if (data->length != datb->length) return FALSE;
+
+ if ((data->flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (datb->flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
+ {
+ if (g_ascii_strncasecmp (data->pos, datb->pos, data->length) != 0) return FALSE;
+ }
+ else
+ {
+ if (strncmp (data->pos, datb->pos, data->length) != 0) return FALSE;
+ }
+ }
+ }
+
+ if (datb->flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
+ {
+ if ((data->flags & datb->flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+AnjutaToken *
+anjuta_token_next_after_children (AnjutaToken *token)
+{
+ if (token->next != NULL)
+ {
+ return token->next;
+ }
+ else if (token->parent != NULL)
+ {
+ return anjuta_token_next_after_children (token->parent);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+AnjutaToken *
+anjuta_token_next (AnjutaToken *token)
+{
+ if (token->children != NULL)
+ {
+ return token->children;
+ }
+ else if (token->next != NULL)
+ {
+ return token->next;
+ }
+ else if (token->parent != NULL)
+ {
+ return anjuta_token_next_after_children (token->parent);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+AnjutaToken *
+anjuta_token_previous (AnjutaToken *token)
+{
+ if (token->prev != NULL)
+ {
+ return token->prev;
+ }
+ else
+ {
+ return token->parent;
+ }
+}
+
+AnjutaToken *
+anjuta_token_next_sibling (AnjutaToken *token)
+{
+ return token ? token->next : NULL;
+}
+
+AnjutaToken *
+anjuta_token_next_child (AnjutaToken *token)
+{
+ return token ? token->children : NULL;
+}
+
+AnjutaToken *
+anjuta_token_previous_sibling (AnjutaToken *token)
+{
+ return token->prev;
+}
+
+AnjutaToken *
+anjuta_token_last_child (AnjutaToken *token)
+{
+ AnjutaToken *last = NULL;
+
+ for (; token != NULL; token = (AnjutaToken *)g_node_last_child ((GNode *)last))
+ {
+ last = token;
+ }
+
+ return last;
+}
+
+AnjutaToken *
+anjuta_token_parent (AnjutaToken *token)
+{
+ return token->parent;
+}
+
+void
+anjuta_token_set_type (AnjutaToken *token, gint type)
+{
+ ANJUTA_TOKEN_DATA (token)->type = type;
+}
+
+void
+anjuta_token_set_flags (AnjutaToken *token, gint flags)
+{
+ ANJUTA_TOKEN_DATA (token)->flags |= flags;
+}
+
+void
+anjuta_token_clear_flags (AnjutaToken *token, gint flags)
+{
+ ANJUTA_TOKEN_DATA (token)->flags &= ~flags;
+}
+
+gint
+anjuta_token_get_type (AnjutaToken *token)
+{
+ return ANJUTA_TOKEN_DATA (token)->type;
+}
+
+gint
+anjuta_token_get_flags (AnjutaToken *token)
+{
+ return ANJUTA_TOKEN_DATA (token)->flags;
+}
+
+gchar *
+anjuta_token_get_value (AnjutaToken *token)
+{
+ AnjutaTokenData *data = ANJUTA_TOKEN_DATA (token);
+
+ return data && (data->pos != NULL) ? g_strndup (data->pos, data->length) : NULL;
+}
+
+const gchar *
+anjuta_token_get_string (AnjutaToken *token)
+{
+ return ANJUTA_TOKEN_DATA (token)->pos;
+}
+
+guint
+anjuta_token_get_length (AnjutaToken *token)
+{
+ return ANJUTA_TOKEN_DATA (token)->length;
+}
+
+static void
+anjuta_token_evaluate_token (AnjutaToken *token, GString *value, gboolean raw)
+{
+ if ((token != NULL) && (ANJUTA_TOKEN_DATA (token)->length != 0))
+ {
+ if (!raw)
+ {
+ gint type = anjuta_token_get_type (token);
+ if ((type == ANJUTA_TOKEN_COMMENT) || (type == ANJUTA_TOKEN_OPEN_QUOTE) || (type == ANJUTA_TOKEN_CLOSE_QUOTE) || (type == ANJUTA_TOKEN_ESCAPE))
+ {
+ return;
+ }
+ }
+ g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
+ }
+}
+
+gchar *
+anjuta_token_evaluate_range (AnjutaToken *start, AnjutaToken *end)
+{
+ GString *value = g_string_new (NULL);
+
+ for (;;)
+ {
+ if (start == NULL) break;
+ anjuta_token_evaluate_token (start, value, FALSE);
+ if (start == end) break;
+
+ start = anjuta_token_next (start);
+ }
+
+
+ return g_string_free (value, FALSE);
+}
+
+static void
+anjuta_token_evaluate_child (AnjutaToken *token, GString *value, gboolean raw)
+{
+ anjuta_token_evaluate_token (token, value, raw);
+
+ if (token->children) anjuta_token_evaluate_child (token->children, value, raw);
+
+ if (token->next) anjuta_token_evaluate_child (token->next, value, raw);
+}
+
+gchar *
+anjuta_token_evaluate (AnjutaToken *token)
+{
+ GString *value = g_string_new (NULL);
+ gchar *str;
+
+ if (token != NULL)
+ {
+ anjuta_token_evaluate_token (token, value, FALSE);
+ if (token->children) anjuta_token_evaluate_child (token->children, value, FALSE);
+ }
+
+ str = g_string_free (value, FALSE);
+ return *str == '\0' ? NULL : str;
+}
+
+gchar *
+anjuta_token_value (AnjutaToken *token)
+{
+ GString *value = g_string_new (NULL);
+ gchar *str;
+
+ if (token != NULL)
+ {
+ anjuta_token_evaluate_token (token, value, TRUE);
+ if (token->children) anjuta_token_evaluate_child (token->children, value, TRUE);
+ }
+
+ str = g_string_free (value, FALSE);
+ return *str == '\0' ? NULL : str;
+}
+
+AnjutaToken *
+anjuta_token_merge (AnjutaToken *first, AnjutaToken *end)
+{
+ AnjutaToken *child;
+ AnjutaToken *tok;
+
+ if (first == end) return first;
+
+ child = (AnjutaToken *)g_node_last_child ((GNode *)first);
+ do
+ {
+ tok = (AnjutaToken *)g_node_next_sibling ((GNode *)first);
+ if (tok == NULL) break;
+
+ g_node_unlink ((GNode *)tok);
+ child = (AnjutaToken *)g_node_insert_after ((GNode *)first, (GNode *)child, (GNode *)tok);
+
+ }
+ while (tok != end);
+
+ return first;
+}
+
+AnjutaToken *
+anjuta_token_merge_previous (AnjutaToken *first, AnjutaToken *end)
+{
+ AnjutaToken *child;
+ AnjutaToken *tok;
+
+ if (first == end) return first;
+
+ child = (AnjutaToken *)g_node_first_child ((GNode *)first);
+ do
+ {
+ tok = (AnjutaToken *)g_node_prev_sibling ((GNode *)first);
+ if (tok == NULL) break;
+
+ g_node_unlink ((GNode *)tok);
+ child = (AnjutaToken *)g_node_insert_before ((GNode *)first, (GNode *)child, (GNode *)tok);
+
+ }
+ while (tok != end);
+
+ return first;
+}
+
+AnjutaToken *
+anjuta_token_copy (const AnjutaToken *token)
+{
+ AnjutaToken *copy = NULL;
+
+ if (token != NULL)
+ {
+ AnjutaTokenData *org = ANJUTA_TOKEN_DATA (token);
+ AnjutaTokenData *data = NULL;
+ AnjutaToken *child;
+ AnjutaToken *last;
+
+ data = g_slice_new0 (AnjutaTokenData);
+ data->type =org->type;
+ data->flags = org->type;
+ if ((data->flags & ANJUTA_TOKEN_STATIC) || (org->pos == NULL))
+ {
+ data->pos = org->pos;
+ }
+ else
+ {
+ data->pos = g_strdup (ANJUTA_TOKEN_DATA (token)->pos);
+ }
+ data->length = org->length;
+
+ copy = (AnjutaToken *)g_node_new (data);
+
+ last = NULL;
+ for (child = anjuta_token_next_child (token); child != NULL; child = anjuta_token_next_sibling (child))
+ {
+ AnjutaToken *new_child = anjuta_token_copy (child);
+ last = last == NULL ? anjuta_token_insert_child (copy, new_child) : anjuta_token_insert_after (last, new_child);
+ }
+ }
+
+ return copy;
+}
+
+AnjutaToken *
+anjuta_token_clear (AnjutaToken *token)
+{
+ AnjutaTokenData *data = ANJUTA_TOKEN_DATA (token);
+
+ if (!(data->flags & ANJUTA_TOKEN_STATIC))
+ {
+ g_free (data->pos);
+ }
+ data->length = 0;
+ data->pos = NULL;
+
+ return token;
+}
+
+AnjutaToken *
+anjuta_token_delete (AnjutaToken *token)
+{
+ GNode *last;
+ GNode *child;
+ AnjutaToken *next;
+
+ for (child = g_node_first_child ((GNode *)token); child != NULL; child = g_node_first_child ((GNode *)token))
+ {
+ g_node_unlink (child);
+ last = g_node_insert_after (((GNode *)token)->parent, last, child);
+ }
+
+ next = (AnjutaToken *)g_node_next_sibling (token);
+ anjuta_token_clear (token);
+ g_node_destroy ((GNode *)token);
+
+ return next;
+}
+
+AnjutaToken *
+anjuta_token_insert_child (AnjutaToken *parent, AnjutaToken *child)
+{
+ return (AnjutaToken *)g_node_insert_after ((GNode *)parent, (GNode *)NULL, (GNode *)child);
+}
+
+AnjutaToken *
+anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *token)
+{
+ return (AnjutaToken *)g_node_insert_after ((GNode *)sibling->parent, (GNode *)sibling, (GNode *)token);
+}
+
+AnjutaToken *
+anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *baby)
+{
+ return (AnjutaToken *)g_node_insert_before ((GNode *)sibling->parent, (GNode *)sibling, (GNode *)baby);
+}
+
+AnjutaToken *anjuta_token_group (AnjutaToken *parent, AnjutaToken *last)
+{
+ AnjutaToken *child;
+ AnjutaToken *tok;
+
+ if (parent == last) return parent;
+ if (parent->children == last) return parent;
+
+ child = (AnjutaToken *)g_node_last_child ((GNode *)parent);
+ do
+ {
+ tok = (AnjutaToken *)g_node_next_sibling ((GNode *)parent);
+ if (tok == NULL) break;
+
+ g_node_unlink ((GNode *)tok);
+ child = (AnjutaToken *)g_node_insert_after ((GNode *)parent, (GNode *)child, (GNode *)tok);
+
+ }
+ while (tok != last);
+
+ return parent;
+
+}
+
+AnjutaToken *anjuta_token_group_new (AnjutaTokenType type, AnjutaToken* first)
+{
+ AnjutaToken *parent = anjuta_token_new_static (type, NULL);
+
+ g_node_insert_before ((GNode *)first->parent, (GNode *)first, (GNode *)parent);
+ return anjuta_token_group (parent, first);
+}
+
+AnjutaToken *anjuta_token_ungroup (AnjutaToken *token)
+{
+ GNode *last = (GNode *)token;
+ GNode *child;
+
+ for (child = g_node_first_child ((GNode *)token); child != NULL; child = g_node_first_child ((GNode *)token))
+ {
+ g_node_unlink (child);
+ last = g_node_insert_after (((GNode *)token)->parent, last, child);
+ }
+
+ return token;
+}
+
+AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
+{
+ if (ANJUTA_TOKEN_DATA (token)->length > size)
+ {
+ AnjutaToken *copy;
+
+ copy = anjuta_token_copy (token);
+ g_node_insert_before ((GNode *)token->parent, (GNode *)token, (GNode *)copy);
+
+ ANJUTA_TOKEN_DATA (copy)->length = size;
+ if (ANJUTA_TOKEN_DATA (token)->flags & ANJUTA_TOKEN_STATIC)
+ {
+ ANJUTA_TOKEN_DATA (token)->pos += size;
+ ANJUTA_TOKEN_DATA (token)->length -= size;
+ }
+ else
+ {
+ memcpy(ANJUTA_TOKEN_DATA (token)->pos, ANJUTA_TOKEN_DATA (token)->pos + size, ANJUTA_TOKEN_DATA (token)->length - size);
+ }
+
+ return copy;
+ }
+ else
+ {
+ return token;
+ }
+}
+
+AnjutaToken *anjuta_token_get_next_arg (AnjutaToken *arg, gchar ** value)
+{
+ for (;arg != NULL;)
+ {
+ switch (anjuta_token_get_type (arg))
+ {
+ case ANJUTA_TOKEN_START:
+ case ANJUTA_TOKEN_NEXT:
+ case ANJUTA_TOKEN_LAST:
+ arg = anjuta_token_next_sibling (arg);
+ continue;
+ default:
+ *value = anjuta_token_evaluate (arg);
+ arg = anjuta_token_next_sibling (arg);
+ break;
+ }
+ break;
+ }
+
+ return arg;
+}
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const char *value)
+{
+ if (value == NULL)
+ {
+ return anjuta_token_new_static (type, NULL);
+ }
+ else
+ {
+ AnjutaTokenData *data;
+
+ data = g_slice_new0 (AnjutaTokenData);
+ data->type = type & ANJUTA_TOKEN_TYPE;
+ data->flags = type & ANJUTA_TOKEN_FLAGS;
+ data->pos = g_strdup (value);
+ data->length = strlen (value);
+
+ return (AnjutaToken *)g_node_new (data);
+ }
+}
+
+AnjutaToken *
+anjuta_token_new_fragment (gint type, const gchar *pos, gsize length)
+{
+ AnjutaTokenData *data;
+
+ data = g_slice_new0 (AnjutaTokenData);
+ data->type = type & ANJUTA_TOKEN_TYPE;
+ data->flags = (type & ANJUTA_TOKEN_FLAGS) | ANJUTA_TOKEN_STATIC;
+ data->pos = (gchar *)pos;
+ data->length = length;
+
+ return (AnjutaToken *)g_node_new (data);
+};
+
+AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
+{
+ return anjuta_token_new_fragment (type, value, value == NULL ? 0 : strlen (value));
+}
+
+
+static void
+free_token_data (GNode *node, gpointer data)
+{
+ g_slice_free (AnjutaTokenData, node->data);
+}
+
+void
+anjuta_token_free (AnjutaToken *token)
+{
+ if (token == NULL) return;
+
+ g_node_children_foreach ((GNode *)token, G_TRAVERSE_ALL, free_token_data, NULL);
+ g_node_destroy ((GNode *)token);
+}
diff --git a/libanjuta/anjuta-token.h b/libanjuta/anjuta-token.h
new file mode 100644
index 0000000..ed6c319
--- /dev/null
+++ b/libanjuta/anjuta-token.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta-token.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_TOKEN_H_
+#define _ANJUTA_TOKEN_H_
+
+#include <gio/gio.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ ANJUTA_TOKEN_NONE = 0,
+ ANJUTA_TOKEN_EOL = '\n',
+ ANJUTA_TOKEN_COMMA =',',
+
+ ANJUTA_TOKEN_TYPE = 0xFFFF,
+
+ ANJUTA_TOKEN_FIRST = 16384,
+ ANJUTA_TOKEN_FILE = 16384,
+ ANJUTA_TOKEN_KEYWORD,
+ ANJUTA_TOKEN_OPERATOR,
+ ANJUTA_TOKEN_NAME,
+ ANJUTA_TOKEN_VALUE,
+ ANJUTA_TOKEN_MACRO,
+ ANJUTA_TOKEN_VARIABLE,
+ ANJUTA_TOKEN_DEFINITION,
+ ANJUTA_TOKEN_STATEMENT,
+ ANJUTA_TOKEN_NUMBER,
+ ANJUTA_TOKEN_JUNK,
+ ANJUTA_TOKEN_COMMENT,
+ ANJUTA_TOKEN_OPEN_QUOTE,
+ ANJUTA_TOKEN_CLOSE_QUOTE,
+ ANJUTA_TOKEN_ESCAPE,
+ ANJUTA_TOKEN_FUNCTION,
+ ANJUTA_TOKEN_SPACE,
+ ANJUTA_TOKEN_START,
+ ANJUTA_TOKEN_NEXT,
+ ANJUTA_TOKEN_LAST,
+ ANJUTA_TOKEN_ARGUMENT,
+ ANJUTA_TOKEN_ITEM,
+ ANJUTA_TOKEN_STRING,
+ ANJUTA_TOKEN_ERROR,
+ ANJUTA_TOKEN_WORD,
+ ANJUTA_TOKEN_LIST,
+ ANJUTA_TOKEN_ANY,
+ ANJUTA_TOKEN_USER,
+
+ ANJUTA_TOKEN_FLAGS = 0xFFFF << 16,
+
+ ANJUTA_TOKEN_PUBLIC_FLAGS = 0x00FF << 16,
+
+ ANJUTA_TOKEN_IRRELEVANT = 1 << 16,
+ ANJUTA_TOKEN_OPEN = 1 << 17,
+ ANJUTA_TOKEN_CLOSE = 1 << 18,
+ ANJUTA_TOKEN_SIGNIFICANT = 1 << 20,
+
+ ANJUTA_TOKEN_PRIVATE_FLAGS = 0x00FF << 24,
+
+ ANJUTA_TOKEN_CASE_INSENSITIVE = 1 << 24,
+ ANJUTA_TOKEN_STATIC = 1 << 25,
+ ANJUTA_TOKEN_REMOVED = 1 << 26,
+ ANJUTA_TOKEN_ADDED = 1 << 27
+
+} AnjutaTokenType;
+
+//typedef GNode AnjutaToken;
+typedef struct _AnjutaToken AnjutaToken;
+
+typedef struct _AnjutaTokenRange
+{
+ AnjutaToken *first;
+ AnjutaToken *last;
+} AnjutaTokenRange;
+
+enum AnjutaTokenSearchFlag
+{
+ ANJUTA_SEARCH_OVER = 0,
+ ANJUTA_SEARCH_INTO = 1 << 0,
+ ANJUTA_SEARCH_ALL = 1 << 1,
+ ANJUTA_SEARCH_BACKWARD = 1 << 2
+};
+
+AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value);
+AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const gchar *value);
+AnjutaToken *anjuta_token_new_fragment (gint type, const gchar *pos, gsize length);
+
+void anjuta_token_free (AnjutaToken *token);
+
+AnjutaToken *anjuta_token_merge (AnjutaToken *first, AnjutaToken *end);
+AnjutaToken *anjuta_token_merge_previous (AnjutaToken *first, AnjutaToken *end);
+AnjutaToken *anjuta_token_copy (const AnjutaToken *token);
+AnjutaToken *anjuta_token_clear (AnjutaToken *token);
+AnjutaToken *anjuta_token_delete (AnjutaToken *token);
+
+AnjutaToken *anjuta_token_group_new (AnjutaTokenType type, AnjutaToken *first);
+AnjutaToken *anjuta_token_group (AnjutaToken *parent, AnjutaToken *last);
+AnjutaToken *anjuta_token_ungroup (AnjutaToken *parent);
+
+AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size);
+
+AnjutaToken * anjuta_token_insert_child (AnjutaToken *parent, AnjutaToken *child);
+AnjutaToken *anjuta_token_insert_after (AnjutaToken *token, AnjutaToken *sibling);
+AnjutaToken *anjuta_token_insert_before (AnjutaToken *token, AnjutaToken *sibling);
+gboolean anjuta_token_match (AnjutaToken *token, gint flags, AnjutaToken *sequence, AnjutaToken **end);
+
+//AnjutaToken *anjuta_token_copy (AnjutaToken *token);
+//AnjutaToken *anjuta_token_copy_include_range (AnjutaToken *token, AnjutaToken *end);
+//AnjutaToken *anjuta_token_copy_exclude_range (AnjutaToken *token, AnjutaToken *end);
+//void anjuta_token_foreach (AnjutaToken *token, GFunc func, gpointer user_data);
+gboolean anjuta_token_remove (AnjutaToken *token);
+//gboolean anjuta_token_free_range (AnjutaToken *token, AnjutaToken *end);
+//GList *anjuta_token_split_list (AnjutaToken *token);
+
+void anjuta_token_set_type (AnjutaToken *token, gint type);
+void anjuta_token_set_flags (AnjutaToken *token, gint flags);
+void anjuta_token_clear_flags (AnjutaToken *token, gint flags);
+
+gchar *anjuta_token_evaluate_range (AnjutaToken *start, AnjutaToken *end);
+gchar *anjuta_token_evaluate (AnjutaToken *token);
+gchar *anjuta_token_value (AnjutaToken *token);
+
+AnjutaToken *anjuta_token_next (AnjutaToken *token);
+AnjutaToken *anjuta_token_next_after_children (AnjutaToken *token);
+AnjutaToken *anjuta_token_next_sibling (AnjutaToken *token);
+AnjutaToken *anjuta_token_next_child (AnjutaToken *token);
+AnjutaToken *anjuta_token_previous (AnjutaToken *token);
+AnjutaToken *anjuta_token_previous_sibling (AnjutaToken *token);
+AnjutaToken *anjuta_token_last_child (AnjutaToken *token);
+AnjutaToken *anjuta_token_parent (AnjutaToken *token);
+gboolean anjuta_token_compare (AnjutaToken *tokena, AnjutaToken *tokenb);
+
+AnjutaToken *anjuta_token_get_next_arg (AnjutaToken *arg, gchar ** value);
+
+
+gint anjuta_token_get_type (AnjutaToken *token);
+gint anjuta_token_get_flags (AnjutaToken *token);
+gchar *anjuta_token_get_value (AnjutaToken *token);
+gchar *anjuta_token_get_value_range (AnjutaToken *token, AnjutaToken *end);
+const gchar *anjuta_token_get_string (AnjutaToken *token);
+guint anjuta_token_get_length (AnjutaToken *token);
+
+G_END_DECLS
+
+#endif
diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl
index d64c03d..9b32391 100644
--- a/libanjuta/interfaces/libanjuta.idl
+++ b/libanjuta/interfaces/libanjuta.idl
@@ -2954,6 +2954,199 @@ interface IAnjutaTerminal
}
/**
+ * SECTION:ianjuta-project
+ * @title: IAnjutaProject
+ * @short_description: Interface implemented by project backend
+ * @see_also:
+ * @stability: Unstable
+ * @include: libanjuta/interfaces/ianjuta-project-backend.h
+ *
+ * This is the new interface that is replacing Gnome Build.
+ */
+interface IAnjutaProject
+{
+ #include <libanjuta/anjuta-project.h>
+ #include <gtk/gtk.h>
+
+ /* Types */
+ enum Error
+ {
+ ERROR_SUCCESS = 0,
+ ERROR_DOESNT_EXIST,
+ ERROR_ALREADY_EXISTS,
+ ERROR_VALIDATION_FAILED,
+ ERROR_PROJECT_MALFORMED,
+ ERROR_GENERAL_FAILURE
+ }
+
+ enum Probe
+ PROBE_FILES = 10,
+ PROBE_MAKE_FILES = 100,
+ PROBE_PROJECT_FILES = 200
+ }
+
+ enum Capabilities
+ {
+ CAN_ADD_NONE = 0,
+ CAN_ADD_GROUP = 1 << 0,
+ CAN_ADD_TARGET = 1 << 1,
+ CAN_ADD_SOURCE = 1 << 2,
+ HAS_PACKAGES = 1 << 3
+ }
+
+ /* Signals */
+
+ /**
+ * IAnjutaProject::project_updated:
+ * @obj: Self
+ *
+ * This signal is emitted when the project is changed.
+ */
+ void ::project_updated ();
+
+ /**
+ * ianjuta_project_load:
+ * @obj: Self
+ * @file: Project directory
+ * @err: Error propagation and reporting
+ *
+ * Load a project
+ *
+ * Return value: TRUE is loaded without errors
+ */
+ gboolean load (GFile *file);
+
+ /**
+ * ianjuta_project_refresh:
+ * @obj: Self
+ * @err: Error propagation and reporting
+ *
+ * Reload the current project
+ *
+ * Return value: TRUE is loaded without errors
+ */
+ gboolean refresh ();
+
+ /**
+ * ianjuta_project_get_capabilities:
+ * @obj: Self
+ * @err: Error propagation and reporting.
+ *
+ * Returns the capabilites of project whether it can add group, target
+ * sources etc.
+ *
+ * Returns: Supported capabilites.
+ */
+ guint get_capabilities ();
+
+ /*
+ * ianjuta_project_get_target_types
+ * @obj: Self
+ * @err: Error propagation and reporting.
+ *
+ * Returns: the list of supported target types
+ */
+ List<AnjutaProjectTargetType> get_target_types();
+
+ /**
+ * ianjuta_project_configure:
+ * @obj: Self
+ * @err: Error propagation and reporting.
+ *
+ * Return a widget that can be use to set any options needed by the project
+ *
+ * Returns: A GtkWidget
+ */
+ GtkWidget* configure ();
+
+ /**
+ * ianjuta_project_get_root:
+ * @obj: Self
+ * @err: Error propagation and reporting.
+ *
+ * Get the root node of the project (always a group)
+ *
+ * Returns: The new group or NULL on error.
+ */
+ AnjutaProjectGroup* get_root ();
+
+ /*
+ * ianjuta_project_get_packages
+ * @obj: Self
+ * @err: Error propagation and reporting.
+ *
+ * Returns: the list of pkg-config packages that the current project
+ * requires in it's configure.ac. Can be NULL if there is no project
+ * opened currently or no package is required.
+ */
+ List<gchar*> get_packages();
+
+ /**
+ * ianjuta_project_add_group:
+ * @obj: Self
+ * @parent: parent group
+ * @name: new group name
+ * @err: Error propagation and reporting.
+ *
+ * Create a new group, parent can be NULL.
+ *
+ * Returns: The new group or NULL on error.
+ */
+ AnjutaProjectGroup* add_group (AnjutaProjectGroup *parent, const gchar *name);
+
+ /**
+ * ianjuta_project_add_target:
+ * @obj: Self
+ * @parent: parent group
+ * @name: new target name
+ * @type: new target type
+ * @err: Error propagation and reporting.
+ *
+ * Create a new target, parent cannot be NULL
+ *
+ * Returns: The new target or NULL on error.
+ */
+ AnjutaProjectTarget* add_target (AnjutaProjectGroup *parent, const gchar *name, AnjutaProjectTargetType type);
+
+ /**
+ * ianjuta_project_add_source:
+ * @obj: Self
+ * @parent: parent target
+ * @file: source file
+ * @err: Error propagation and reporting.
+ *
+ * Create a new source, parent cannot be NULL
+ *
+ * Returns: The new source or NULL on error.
+ */
+ AnjutaProjectSource* add_source (AnjutaProjectTarget *parent, GFile *file);
+
+ /**
+ * ianjuta_project_remove_node:
+ * @obj: Self
+ * @node: node to configure
+ * @err: Error propagation and reporting.
+ *
+ * Remove a node (a group, a target or a source) from the project.
+ *
+ * Returns: TRUE if the node has been removed
+ */
+ gboolean remove_node (AnjutaProjectNode *node);
+
+ /**
+ * ianjuta_project_configure_node:
+ * @obj: Self
+ * @node: node to configure
+ * @err: Error propagation and reporting.
+ *
+ * Return a widget that can be use to set any options needed by this node
+ *
+ * Returns: A GtkWidget
+ */
+ GtkWidget* configure_node (AnjutaProjectNode *node);
+}
+
+/**
* SECTION:ianjuta-project-backend
* @title: IAnjutaProjectBackend
* @short_description: Interface for creating new project
@@ -2964,7 +3157,7 @@ interface IAnjutaTerminal
*/
interface IAnjutaProjectBackend
{
- #include <libanjuta/gbf-project.h>
+ #include "ianjuta-project.h"
/**
* ianjuta_project_backend_new_project:
@@ -2975,7 +3168,22 @@ interface IAnjutaProjectBackend
*
* Return value: An object derived from GbfProject
*/
- GbfProject* new_project ();
+ IAnjutaProject* new_project ();
+
+
+ /**
+ * ianjuta_project_backend_probe:
+ * @obj: Self
+ * @file: Project directory
+ * @err: Error propagation and reporting
+ *
+ * Check if the directory contains a project supported by this
+ * backend
+ *
+ * Return value: 0 if the project is invalid and > 0 if the
+ * project is valid.
+ */
+ gint probe (GFile *directory);
}
/**
@@ -2989,6 +3197,10 @@ interface IAnjutaProjectBackend
*/
interface IAnjutaProjectManager
{
+
+ #include <libanjuta/anjuta-project.h>
+ #include <libanjuta/interfaces/ianjuta-project.h>
+
/**
* IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
*
@@ -3003,30 +3215,6 @@ interface IAnjutaProjectManager
*/
#define CURRENT_URI "project_manager_current_uri"
- enum ElementType
- {
- UNKNOWN,
- SOURCE,
- TARGET,
- GROUP
- }
-
- enum TargetType
- {
- TARGET_UNKNOWN,
- TARGET_SHAREDLIB,
- TARGET_STATICLIB,
- TARGET_EXECUTABLE
- }
-
- enum Capabilities
- {
- CAN_ADD_NONE = 0,
- CAN_ADD_GROUP = 1 << 0,
- CAN_ADD_TARGET = 1 << 1,
- CAN_ADD_SOURCE = 1 << 2
- }
-
// Signals
/**
@@ -3071,7 +3259,7 @@ interface IAnjutaProjectManager
*
* Returns: fixme
*/
- ElementType get_element_type (const gchar *element_uri);
+ AnjutaProjectNodeType get_element_type (const gchar *element_uri);
/**
* ianjuta_project_manager_get_elements:
@@ -3083,7 +3271,7 @@ interface IAnjutaProjectManager
*
* Returns: fixme
*/
- List<const gchar*> get_elements (ElementType element_type);
+ List<const gchar*> get_elements (AnjutaProjectNodeType element_type);
/**
* ianjuta_project_manager_get_target_type:
@@ -3095,7 +3283,7 @@ interface IAnjutaProjectManager
*
* Returns: fixme
*/
- TargetType get_target_type (const gchar *target_uri);
+ AnjutaProjectTargetClass get_target_type (const gchar *target_uri);
/**
* ianjuta_project_manager_get_targets:
@@ -3107,7 +3295,7 @@ interface IAnjutaProjectManager
*
* Returns: fixme
*/
- List<const gchar*> get_targets (TargetType target_type);
+ List<const gchar*> get_targets (AnjutaProjectTargetClass target_type);
/**
* ianjuta_project_manager_get_parent:
@@ -3150,7 +3338,7 @@ interface IAnjutaProjectManager
*
* fixme
*/
- gchar* get_selected_id (ElementType element_type);
+ gchar* get_selected_id (AnjutaProjectNodeType element_type);
/**
* ianjuta_project_manager_get_capabilities:
@@ -3162,7 +3350,7 @@ interface IAnjutaProjectManager
*
* Returns: Supported capabilites.
*/
- Capabilities get_capabilities ();
+ guint get_capabilities ();
/**
* ianjuta_project_manager_add_source:
@@ -3189,7 +3377,7 @@ interface IAnjutaProjectManager
*
* Returns: element ID. Must be freed when no longer required.
*/
- gchar* add_source_quiet (const gchar *source_uri_to_add, const gchar *target_id);
+ gchar* add_source_quiet (const gchar *source_uri_to_add, const gchar *target_uri);
/**
* ianjuta_project_manager_add_sources:
diff --git a/libanjuta/libanjuta.h b/libanjuta/libanjuta.h
index ae341e8..bc5d661 100644
--- a/libanjuta/libanjuta.h
+++ b/libanjuta/libanjuta.h
@@ -51,5 +51,7 @@
#include <libanjuta/anjuta-async-notify.h>
#include <libanjuta/anjuta-sync-command.h>
#include <libanjuta/gbf-project.h>
+#include <libanjuta/anjuta-project.h>
+#include <libanjuta/anjuta-token.h>
#endif
diff --git a/manuals/reference/libanjuta/libanjuta-sections.txt b/manuals/reference/libanjuta/libanjuta-sections.txt
index a9fa8e8..1949be6 100644
--- a/manuals/reference/libanjuta/libanjuta-sections.txt
+++ b/manuals/reference/libanjuta/libanjuta-sections.txt
@@ -1554,17 +1554,11 @@ IANJUTA_PRINT_GET_IFACE
<SECTION>
<FILE>ianjuta-project-manager</FILE>
-IANJUTA_TYPE_PROJECT_MANAGER_CAPABILITIES
-IANJUTA_TYPE_PROJECT_MANAGER_ELEMENT_TYPE
-IANJUTA_TYPE_PROJECT_MANAGER_TARGET_TYPE
IANJUTA_PROJECT_MANAGER_ERROR
IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
IANJUTA_PROJECT_MANAGER_CURRENT_URI
IAnjutaProjectManager
IAnjutaProjectManagerIface
-IAnjutaProjectManagerCapabilities
-IAnjutaProjectManagerElementType
-IAnjutaProjectManagerTargetType
ianjuta_project_manager_element_type_get_type
ianjuta_project_manager_target_type_get_type
ianjuta_project_manager_error_quark
@@ -1587,7 +1581,6 @@ ianjuta_project_manager_is_open
IANJUTA_PROJECT_MANAGER
IANJUTA_IS_PROJECT_MANAGER
IANJUTA_TYPE_PROJECT_MANAGER
-ianjuta_project_manager_capabilities_get_type
IANJUTA_PROJECT_MANAGER_GET_IFACE
</SECTION>
diff --git a/manuals/reference/libanjuta/libanjuta.types b/manuals/reference/libanjuta/libanjuta.types
index 83b2d8c..fe09a1a 100644
--- a/manuals/reference/libanjuta/libanjuta.types
+++ b/manuals/reference/libanjuta/libanjuta.types
@@ -98,9 +98,6 @@ ianjuta_plugin_factory_error_get_type
ianjuta_plugin_factory_get_type
ianjuta_preferences_get_type
ianjuta_print_get_type
-ianjuta_project_manager_capabilities_get_type
-ianjuta_project_manager_element_type_get_type
-ianjuta_project_manager_target_type_get_type
ianjuta_project_manager_get_type
ianjuta_stream_get_type
ianjuta_stream_loader_get_type
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index e5099b1..dd017b6 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -29,8 +29,8 @@ SUBDIRS = . \
git \
sourceview \
run-program \
- gbf-am \
- gbf-mkfile \
- starter
+ starter \
+ am-project \
+ mk-project
-include $(top_srcdir)/git.mk
diff --git a/plugins/am-project/Makefile.am b/plugins/am-project/Makefile.am
new file mode 100644
index 0000000..29ee16d
--- /dev/null
+++ b/plugins/am-project/Makefile.am
@@ -0,0 +1,95 @@
+# Plugin UI file
+plugin_uidir = $(anjuta_ui_dir)
+plugin_ui_DATA =
+
+# Plugin glade file
+plugin_gladedir = $(anjuta_glade_dir)
+plugin_glade_DATA = am-project.ui
+
+# Plugin icon file
+plugin_pixmapsdir = $(anjuta_image_dir)
+plugin_pixmaps_DATA = am-project-plugin-48.png
+
+# Plugin description file
+plugin_in_files = am-project.plugin.in
+%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+plugindir = $(anjuta_plugin_dir)
+plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
+
+AM_CPPFLAGS = \
+ $(WARN_CFLAGS) \
+ $(DEPRECATED_FLAGS) \
+ $(GIO_CFLAGS) \
+ $(LIBANJUTA_CFLAGS) \
+ -DG_LOG_DOMAIN=\"am-project\"
+
+plugin_LTLIBRARIES = \
+ libam-project.la
+
+libam_project_la_SOURCES = \
+ plugin.c \
+ plugin.h \
+ am-project.c \
+ am-project.h \
+ am-scanner.l \
+ am-parser.y \
+ am-scanner.h \
+ ac-scanner.l \
+ ac-parser.y \
+ ac-scanner.h \
+ ac-writer.h \
+ ac-writer.c \
+ am-project-private.h \
+ am-dialogs.h \
+ am-dialogs.c
+
+libam_project_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
+
+libam_project_la_LIBADD = \
+ $(GIO_LIBS) \
+ $(LIBANJUTA_LIBS)
+
+AM_YFLAGS = -t -v -g -rall
+
+ac-scanner.c: $(srcdir)/ac-scanner.l ac-parser.c
+ $(LEXCOMPILE) -o $@ $<
+
+ac-parser.c: $(srcdir)/ac-parser.y
+ $(YACCCOMPILE) -o $@ $<
+
+ac-scanner.h: ac-parser.c
+
+am-scanner.c: $(srcdir)/am-scanner.l am-parser.c
+ $(LEXCOMPILE) -o $@ $<
+
+am-parser.c: $(srcdir)/am-parser.y
+ $(YACCCOMPILE) -o $@ $<
+
+am-scanner.h: am-parser.c
+
+# Test program
+
+#noinst_PROGRAMS = test
+
+test_SOURCES = \
+ test.c
+
+test_LDADD = \
+ mk-project.la \
+ $(LIBANJUTA_LIBS)
+
+
+EXTRA_DIST = \
+ $(plugin_in_files) \
+ $(plugin_DATA) \
+ $(plugin_ui_DATA) \
+ $(plugin_pixmaps_DATA) \
+ $(plugin_glade_DATA) \
+ ac-parser.h \
+ am-parser.h
+
+DISTCLEANFILES = \
+ $(plugin_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/am-project/ac-parser.y b/plugins/am-project/ac-parser.y
new file mode 100644
index 0000000..959675e
--- /dev/null
+++ b/plugins/am-project/ac-parser.y
@@ -0,0 +1,528 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * ac-parser.y
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+%{
+
+#include <stdlib.h>
+#include "ac-scanner.h"
+#include "ac-parser.h"
+
+//#define YYDEBUG 1
+
+#include "libanjuta/anjuta-debug.h"
+
+//static void amp_ac_yyerror (YYLTYPE *loc, void *scanner, char const *s);
+
+//amp_ac_yydebug = 1;
+
+%}
+
+/*%union {
+ AnjutaToken *token;
+}*/
+
+%token EOL '\n'
+
+%token SPACE ' '
+
+%token HASH '#'
+%token LEFT_PAREN '('
+%token RIGHT_PAREN ')'
+%token LEFT_CURLY '{'
+%token RIGHT_CURLY '}'
+%token LEFT_BRACE '['
+%token RIGHT_BRACE ']'
+%token EQUAL '='
+%token COMMA ','
+%token LOWER '<'
+%token GREATER '>'
+
+%token NAME
+%token VARIABLE
+%token MACRO
+%token OPERATOR
+%token WORD
+%token JUNK
+
+%token START_SPACE_LIST
+
+%left ARG
+%left EMPTY
+
+/* M4 macros */
+
+%token DNL
+
+
+/* Autoconf macros */
+
+%token AC_MACRO_WITH_ARG
+%token AC_MACRO_WITHOUT_ARG
+
+%token PKG_CHECK_MODULES
+%token OBSOLETE_AC_OUTPUT
+%token AC_OUTPUT
+%token AC_CONFIG_FILES
+%token AC_SUBST
+%token AC_INIT
+
+/*%type pkg_check_modules obsolete_ac_output ac_output ac_config_files
+%type dnl
+%type ac_macro_with_arg ac_macro_without_arg
+%type spaces
+%type separator
+%type arg_string arg arg_list arg_list_body shell_string_body raw_string_body
+
+%type expression comment macro
+%type arg_string_body arg_body expression_body
+
+%type any_space*/
+
+%defines
+
+%pure_parser
+
+%parse-param {AmpAcScanner* scanner}
+%lex-param {AmpAcScanner* scanner}
+
+%name-prefix="amp_ac_yy"
+
+%locations
+
+%start input
+
+%debug
+
+
+%{
+static void amp_ac_yyerror (YYLTYPE *loc, AmpAcScanner *scanner, char const *s);
+
+%}
+
+
+%%
+
+input:
+ START_SPACE_LIST space_list
+ | file
+ ;
+
+file:
+ /* empty */
+ | file statement
+ ;
+
+statement:
+ line
+ | macro
+ ;
+
+line:
+ space_token
+ | comment
+ | shell_string
+ | args_token
+ | EQUAL
+ | LOWER
+ | GREATER
+ | NAME
+ | VARIABLE
+ | WORD
+ ;
+
+macro:
+ dnl
+ | ac_macro_with_arg
+ | ac_macro_without_arg
+ | ac_init
+ | pkg_check_modules
+ | obsolete_ac_output
+ | ac_output
+ | ac_config_files
+ ;
+
+/* Space list
+ *----------------------------------------------------------------------------*/
+
+space_list:
+ /* empty */
+ | space_list_body
+ | space_list_body spaces
+ ;
+
+space_list_body:
+ item
+ | spaces item {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_NEXT);
+ }
+ | space_list_body spaces item {
+ anjuta_token_set_type ($2, ANJUTA_TOKEN_NEXT);
+ }
+ ;
+
+item:
+ name
+ | operator
+ ;
+
+operator:
+ OPERATOR {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_OPERATOR);
+ }
+ ;
+
+name:
+ not_operator_token
+ | name word_token {
+ anjuta_token_group ($1, $2);
+ }
+ ;
+
+junks:
+ JUNK
+ | junks JUNK {
+ anjuta_token_group ($1, $2);
+ }
+ ;
+
+/* Macros
+ *----------------------------------------------------------------------------*/
+
+dnl:
+ DNL not_eol_list EOL {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_COMMENT);
+ anjuta_token_group ($1, $3);
+ }
+ ;
+
+
+pkg_check_modules:
+ PKG_CHECK_MODULES arg_list {
+ anjuta_token_set_type ($1, AC_TOKEN_PKG_CHECK_MODULES);
+ $$ = anjuta_token_group ($1, $2);
+ }
+ ;
+
+ac_macro_without_arg:
+ AC_MACRO_WITHOUT_ARG
+ ;
+
+optional_arg:
+ /* empty */ %prec EMPTY
+ | COMMA NAME %prec ARG
+ ;
+
+ac_macro_with_arg:
+ AC_MACRO_WITH_ARG optional_arg RIGHT_PAREN {
+ anjuta_token_group ($1, $1);
+ }
+ ;
+
+ac_init:
+ AC_INIT arg_list {
+ anjuta_token_set_type ($1, AC_TOKEN_AC_INIT);
+ $$ = anjuta_token_group ($1, $2);
+ }
+
+ac_output:
+ AC_OUTPUT {
+ anjuta_token_set_type ($1, AC_TOKEN_AC_OUTPUT);
+ }
+ ;
+
+obsolete_ac_output:
+ OBSOLETE_AC_OUTPUT arg_list {
+ anjuta_token_set_type ($1, AC_TOKEN_OBSOLETE_AC_OUTPUT);
+ $$ = anjuta_token_group ($1, $2);
+ }
+ ;
+
+ac_config_files:
+ AC_CONFIG_FILES arg_list {
+ anjuta_token_set_type ($1, AC_TOKEN_AC_CONFIG_FILES);
+ $$ = anjuta_token_group ($1, $2);
+ }
+ ;
+
+/* Lists
+ *----------------------------------------------------------------------------*/
+
+arg_list:
+ arg_list_body RIGHT_PAREN {
+ anjuta_token_set_type ($2, ANJUTA_TOKEN_LAST);
+ $$ = $2;
+ }
+ | spaces arg_list_body RIGHT_PAREN {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_START);
+ anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ $$ = $3;
+ }
+ ;
+
+arg_list_body:
+ arg
+ | arg_list_body separator arg
+ ;
+
+comment:
+ HASH not_eol_list EOL {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_COMMENT);
+ anjuta_token_group ($1, $3);
+ }
+ ;
+
+not_eol_list:
+ /* empty */
+ | not_eol_list not_eol_token
+ ;
+
+
+shell_string:
+ LEFT_BRACE shell_string_body RIGHT_BRACE {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_STRING);
+ anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ $$ = anjuta_token_group ($1, $3);
+ }
+ ;
+
+shell_string_body:
+ /* empty */
+ | shell_string_body not_brace_token
+ | shell_string_body shell_string
+ ;
+
+raw_string:
+ LEFT_BRACE raw_string_body RIGHT_BRACE {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_STRING);
+ anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ $$ = anjuta_token_group ($1, $3);
+ }
+ ;
+
+raw_string_body:
+ /* empty */
+ | raw_string_body not_brace_token
+ | raw_string_body raw_string
+ ;
+
+arg_string:
+ LEFT_BRACE arg_string_body RIGHT_BRACE {
+ $$ = anjuta_token_group_new (NAME, $1);
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_OPEN_QUOTE);
+ anjuta_token_set_type ($3, ANJUTA_TOKEN_CLOSE_QUOTE);
+ anjuta_token_group ($$, $3);
+ }
+ ;
+
+arg_string_body:
+ /* empty */
+ | arg_string_body space_token
+ | arg_string_body HASH
+ | arg_string_body LEFT_PAREN
+ | arg_string_body RIGHT_PAREN
+ | arg_string_body COMMA
+ | arg_string_body EQUAL
+ | arg_string_body GREATER
+ | arg_string_body LOWER
+ | arg_string_body NAME
+ | arg_string_body VARIABLE
+ | arg_string_body WORD
+ | arg_string_body macro
+ | arg_string_body raw_string
+ ;
+
+/* Items
+ *----------------------------------------------------------------------------*/
+
+arg:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | arg_part arg_body {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_ARGUMENT, $1);
+ if ($2 != NULL) anjuta_token_group ($$, $2);
+ }
+ ;
+
+arg_body:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | arg_body arg_part_or_space {
+ $$ = $2;
+ }
+ ;
+
+arg_part_or_space:
+ space_token
+ | arg_part
+ ;
+
+arg_part:
+ arg_string
+ | expression
+ | macro
+ | HASH
+ | EQUAL
+ | LOWER
+ | GREATER
+ | NAME
+ | VARIABLE
+ | WORD
+ ;
+
+separator:
+ COMMA {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_NEXT, $1);
+ }
+ | COMMA spaces {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_NEXT, $1);
+ anjuta_token_group ($$, $2);
+ }
+ ;
+
+expression:
+ LEFT_PAREN expression_body RIGHT_PAREN {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_STRING);
+ anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ $$ = anjuta_token_group ($1, $3);
+ }
+ ;
+
+expression_body:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | expression_body space_token
+ | expression_body comment
+ | expression_body COMMA
+ | expression_body EQUAL
+ | expression_body LOWER
+ | expression_body GREATER
+ | expression_body NAME
+ | expression_body VARIABLE
+ | expression_body WORD
+ | expression_body macro
+ | expression_body expression
+ ;
+
+spaces:
+ space_token
+ | spaces space_token {
+ anjuta_token_group ($$, $2);
+ }
+ | spaces JUNK {
+ anjuta_token_group ($$, $2);
+ }
+ ;
+
+/* Tokens
+ *----------------------------------------------------------------------------*/
+
+not_eol_token:
+ SPACE
+ | word_token
+ ;
+
+not_brace_token:
+ space_token
+ | args_token
+ | HASH
+ | EQUAL
+ | LOWER
+ | GREATER
+ | OPERATOR
+ | NAME
+ | VARIABLE
+ | WORD
+ | any_macro
+ ;
+
+space_token:
+ SPACE
+ | EOL
+ ;
+
+args_token:
+ LEFT_PAREN
+ | RIGHT_PAREN
+ | COMMA
+ ;
+
+operator_token:
+ EQUAL
+ | LOWER
+ | GREATER
+ ;
+
+not_operator_token:
+ HASH
+ | LEFT_BRACE
+ | RIGHT_BRACE
+ | LEFT_PAREN
+ | RIGHT_PAREN
+ | COMMA
+ | NAME
+ | VARIABLE
+ | WORD
+ | any_macro
+ ;
+
+word_token:
+ HASH
+ | LEFT_BRACE
+ | RIGHT_BRACE
+ | LEFT_PAREN
+ | RIGHT_PAREN
+ | COMMA
+ | OPERATOR
+ | EQUAL
+ | LOWER
+ | GREATER
+ | NAME
+ | VARIABLE
+ | WORD
+ | any_macro
+ ;
+
+any_macro:
+ AC_CONFIG_FILES
+ | AC_MACRO_WITH_ARG
+ | AC_MACRO_WITHOUT_ARG
+ | AC_OUTPUT
+ | DNL
+ | OBSOLETE_AC_OUTPUT
+ | PKG_CHECK_MODULES
+ ;
+
+%%
+
+static void
+amp_ac_yyerror (YYLTYPE *loc, AmpAcScanner *scanner, char const *s)
+{
+ gchar *filename;
+
+ g_message ("scanner %p", scanner);
+ filename = amp_ac_scanner_get_filename ((AmpAcScanner *)scanner);
+ if (filename == NULL) filename = "?";
+ g_message ("%s (%d:%d-%d:%d) %s\n", filename, loc->first_line, loc->first_column, loc->last_line, loc->last_column, s);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
diff --git a/plugins/am-project/ac-scanner.h b/plugins/am-project/ac-scanner.h
new file mode 100644
index 0000000..f3d03a6
--- /dev/null
+++ b/plugins/am-project/ac-scanner.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * ac-scanner.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AC_SCANNER_H_
+#define _AC_SCANNER_H_
+
+#include "libanjuta/anjuta-token.h"
+#include "libanjuta/anjuta-token-file.h"
+
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define YYSTYPE AnjutaToken*
+
+typedef struct _AmpAcScanner AmpAcScanner;
+
+AmpAcScanner *amp_ac_scanner_new (void);
+void amp_ac_scanner_free (AmpAcScanner *scanner);
+
+gboolean amp_ac_scanner_parse (AmpAcScanner *scanner, AnjutaTokenFile *file, GError **error);
+gboolean amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *token, gint start, GError **error);
+
+
+const gchar* amp_ac_scanner_get_filename (AmpAcScanner *scanner);
+
+enum
+{
+ AC_TOKEN_AC_INIT = ANJUTA_TOKEN_USER,
+ AC_TOKEN_PKG_CHECK_MODULES,
+ AC_TOKEN_AC_CONFIG_FILES,
+ AC_TOKEN_OBSOLETE_AC_OUTPUT,
+ AC_TOKEN_AC_OUTPUT,
+ AC_TOKEN_SPACE_LIST,
+ AC_TOKEN_OPEN_STRING,
+ AC_TOKEN_CLOSE_STRING
+};
+
+enum
+{
+ AC_SPACE_LIST_STATE = 1
+};
+
+G_END_DECLS
+
+#endif
diff --git a/plugins/am-project/ac-scanner.l b/plugins/am-project/ac-scanner.l
new file mode 100644
index 0000000..b1868a2
--- /dev/null
+++ b/plugins/am-project/ac-scanner.l
@@ -0,0 +1,443 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * ac-scanner.l
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ac-scanner.h"
+#include "ac-parser.h"
+
+#include "libanjuta/anjuta-debug.h"
+
+/* Eliminate warning */
+#define YY_NO_UNPUT 1
+
+#define YY_INPUT(buf, result, max_size) result = amp_ac_scanner_input (yyextra, buf, max_size)
+
+#define YY_USER_ACTION amp_update_location(yylloc, yytext, yyleng);
+
+#define YY_EXTRA_TYPE AmpAcScanner*
+
+#define YY_DECL static int ac_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner)
+
+//#define YY_USER_INIT {yy_flex_debug = 1;}
+
+static AnjutaToken* amp_ac_scanner_append_token (AmpAcScanner *scanner, gint token);
+static void amp_update_location (YYLTYPE *loc, const gchar *text, gint length);
+static gint amp_ac_scanner_input (AmpAcScanner *scanner, gchar *buffer, gsize max_size);
+
+gboolean amp_ac_yyparse (AmpAcScanner *scanner);
+
+
+#define RETURN(tok) *yylval = amp_ac_scanner_append_token (yyextra, tok); \
+ return tok
+
+
+struct _AmpAcScanner
+{
+ yyscan_t scanner;
+
+ AnjutaTokenFile *file;
+ gchar *filename;
+
+ AnjutaToken *token;
+ gint first;
+
+ /* Beginning of current token */
+ AnjutaToken *start;
+ gsize begin;
+
+ /* Position in buffer */
+ AnjutaToken *next;
+ gsize pos;
+};
+
+%}
+
+%option reentrant stack noyywrap yylineno
+
+%option prefix="amp_ac_yy"
+
+/* Necessary because autotools wrapper always looks for a file named "lex.yy.c",
+ * not "lex.amp_ac_yy.c"
+%option outfile="lex.yy.c"*/
+
+%option bison-bridge bison-locations
+
+%option never-interactive
+
+%option batch
+
+%option debug
+
+WS [ \t\r\v]+
+NL \n
+WSNL [ \t\v\r\n]+
+COMMENT #
+OPENQUOTE \[
+CLOSEQUOTE \]
+OPENPARG \(
+CLOSEPARG \)
+COMMA ,
+EQUAL =
+LOWER <
+GREATER >
+NAME [A-Za-z_][A-Za-z0-9_]*
+VARIABLE $[A-Za-z_0-9]+
+OTHER [^ \t\r\v\n#\[\]\\(),=><$_A-Za-z_]+
+
+%x SPACE_LIST
+
+%%
+
+{WS} { RETURN (SPACE); }
+
+\\\n { RETURN (SPACE); }
+
+{NL} { RETURN (EOL); }
+
+{COMMENT} { RETURN (HASH); }
+
+{OPENQUOTE} { RETURN (LEFT_BRACE); }
+
+{CLOSEQUOTE} { RETURN (RIGHT_BRACE); }
+
+{OPENPARG} { RETURN (LEFT_PAREN); }
+
+{CLOSEPARG} { RETURN (RIGHT_PAREN); }
+
+{COMMA} { RETURN (COMMA); }
+
+{EQUAL} { RETURN (EQUAL); }
+
+{LOWER} { RETURN (LOWER); }
+
+{GREATER} { RETURN (GREATER); }
+
+dnl { RETURN (DNL); }
+
+PKG_CHECK_MODULES\( { RETURN (PKG_CHECK_MODULES); }
+
+AC_OUTPUT\( { RETURN (OBSOLETE_AC_OUTPUT); }
+
+AC_OUTPUT { RETURN (AC_OUTPUT); }
+
+AC_INIT\( { RETURN (AC_INIT); }
+
+AC_CONFIG_FILES\( { RETURN (AC_CONFIG_FILES); }
+
+{NAME} { RETURN (NAME); }
+
+{VARIABLE} { RETURN (VARIABLE); }
+
+{OTHER}|\$|\\ { RETURN (WORD); }
+
+
+<SPACE_LIST>{
+
+{WSNL} { RETURN (SPACE); }
+
+=|<|>|<=|>= { RETURN (OPERATOR); }
+
+{NAME} { RETURN (WORD); }
+
+. {RETURN (WORD);}
+}
+
+%%
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static AnjutaToken*
+amp_ac_scanner_append_token (AmpAcScanner *scanner, gint token)
+{
+ AnjutaToken *frag;
+
+ if (scanner->file != NULL)
+ {
+ const gchar *start = anjuta_token_file_get_content (scanner->file, NULL);
+
+ frag = anjuta_token_new_fragment (token, start + scanner->begin, yyget_leng (scanner->scanner));
+ anjuta_token_file_append (scanner->file, frag);
+ scanner->begin += yyget_leng (scanner->scanner);
+ }
+ else if (scanner->token != NULL)
+ {
+ gsize length = yyget_leng (scanner->scanner);
+ AnjutaToken *end;
+
+ for (end = scanner->start; end != NULL; end = anjuta_token_next_sibling (end))
+ {
+ if (anjuta_token_get_type (end) < ANJUTA_TOKEN_FIRST)
+ {
+ gint toklen = anjuta_token_get_length (end);
+
+ if (toklen >= length)
+ {
+ if (toklen > length)
+ {
+ AnjutaToken *start = end;
+
+ end = anjuta_token_split (end, length);
+ if (start == scanner->start)
+ {
+ scanner->start = end;
+ }
+ }
+
+ if (end == scanner->start)
+ {
+ /* Get whole token */
+ frag = end;
+ anjuta_token_set_type (frag, token);
+ scanner->start = anjuta_token_next_sibling (end);
+ }
+ else
+ {
+ frag = anjuta_token_new_fragment (token, NULL, 0);
+ anjuta_token_insert_before (scanner->start, frag);
+ scanner->start = anjuta_token_next_sibling (end);
+ anjuta_token_group (frag, end);
+ }
+ break;
+ }
+ else
+ {
+ length -= toklen;
+ }
+ }
+ }
+ }
+
+ return frag;
+}
+
+static void
+amp_update_location (YYLTYPE *loc, const gchar *text, gint length)
+{
+ const gchar *ptr;
+ const gchar *end = text + length;
+
+ loc->first_line = loc->last_line;
+ loc->first_column = loc->last_column + 1;
+
+ for (ptr = text; ptr != end; ptr++)
+ {
+ if (*ptr == '\n')
+ {
+ loc->last_column = 0;
+ loc->last_line++;
+ length -= (ptr + 1 - text);
+ }
+ }
+
+ loc->last_column += length;
+}
+
+static gint
+amp_ac_scanner_input (AmpAcScanner *scanner, gchar *buffer, gsize max_size)
+{
+ gint result = YY_NULL;
+
+ if (scanner->file != NULL)
+ {
+ gsize length = anjuta_token_file_get_length (scanner->file, NULL);
+ if (scanner->pos < length)
+ {
+ const gchar *start = anjuta_token_file_get_content (scanner->file, NULL);
+
+ length -= scanner->pos;
+
+ if (length > max_size) length = max_size;
+ memcpy (buffer, start + scanner->pos, length);
+ scanner->pos += length;
+ result = length;
+ }
+ }
+ else if (scanner->token != NULL)
+ {
+ if (scanner->next)
+ {
+ gsize length = anjuta_token_get_length (scanner->next);
+
+ if ((anjuta_token_get_type (scanner->next) >= ANJUTA_TOKEN_FIRST) || (scanner->pos >= length))
+ {
+ for (;;)
+ {
+ scanner->next = anjuta_token_next_sibling (scanner->next);
+ if (scanner->next == NULL)
+ {
+ /* Last token */
+ break;
+ }
+ else if ((anjuta_token_get_length (scanner->next) != 0) && (anjuta_token_get_type (scanner->next) < ANJUTA_TOKEN_FIRST))
+ {
+ /* Find some data */
+ scanner->pos = 0;
+ length = anjuta_token_get_length (scanner->next);
+ break;
+ }
+ }
+ }
+
+ if (scanner->pos < length)
+ {
+ const gchar *start = anjuta_token_get_string (scanner->next);
+
+ length -= scanner->pos;
+
+ if (length > max_size) length = max_size;
+ memcpy (buffer, start + scanner->pos, length);
+ scanner->pos += length;
+ result = length;
+ }
+ }
+
+ }
+
+ return result;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+int
+amp_ac_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,AmpAcScanner *scanner)
+{
+ /* Return a special start token for bison */
+ switch (scanner->first)
+ {
+ case AC_SPACE_LIST_STATE:
+ scanner->first = 0;
+ yy_push_state (SPACE_LIST, scanner->scanner);
+ return START_SPACE_LIST;
+ default:
+ break;
+ }
+
+ /* Parse unknown data */
+ return ac_yylex (yylval_param, yylloc_param, scanner->scanner);
+}
+
+gboolean
+amp_ac_scanner_parse (AmpAcScanner *scanner, AnjutaTokenFile *file, GError **error)
+{
+
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ scanner->file = file;
+ scanner->pos = 0;
+ scanner->begin = 0;
+ scanner->token = NULL;
+ scanner->first = 0;
+
+ return amp_ac_yyparse (scanner) == 0;
+}
+
+gboolean
+amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *token, gint start, GError **error)
+{
+ AnjutaToken *child;
+
+ scanner->token = token;
+ scanner->pos = 0;
+ scanner->begin = 0;
+ scanner->file = NULL;
+ scanner->first = start;
+
+ if (anjuta_token_get_length (token) != 0)
+ {
+ AnjutaToken *copy = anjuta_token_copy (token);
+
+ anjuta_token_insert_child (token, copy);
+ anjuta_token_clear (token);
+ }
+
+ /* Move all know data in a list */
+ for (child = anjuta_token_next_child (token); child != NULL;)
+ {
+ if (anjuta_token_get_type (child) < ANJUTA_TOKEN_FIRST)
+ {
+ child = anjuta_token_ungroup (child);
+ if (anjuta_token_get_length (child) == 0)
+ {
+ child = anjuta_token_delete (child);
+ continue;
+ }
+ }
+ child = anjuta_token_next_sibling (child);
+ }
+
+ scanner->next = anjuta_token_next_child (token);
+ scanner->start = scanner->next;
+
+ return amp_ac_yyparse (scanner) == 0;
+}
+
+const gchar*
+amp_ac_scanner_get_filename (AmpAcScanner *scanner)
+{
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+ if (scanner->file != NULL)
+ {
+ scanner->filename = g_file_get_path (anjuta_token_file_get_file (scanner->file));
+ }
+ else if (scanner->token != NULL)
+ {
+ scanner->filename = anjuta_token_value (scanner->token);
+ }
+
+ return scanner->filename;
+}
+
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+AmpAcScanner *
+amp_ac_scanner_new (void)
+{
+ AmpAcScanner *scanner;
+
+ scanner = g_new0 (AmpAcScanner, 1);
+
+ yylex_init(&scanner->scanner);
+
+ yyset_extra (scanner, scanner->scanner);
+
+ return scanner;
+};
+
+void
+amp_ac_scanner_free (AmpAcScanner *scanner)
+{
+ g_return_if_fail (scanner != NULL);
+
+ //if (scanner->buffer != NULL) yy_delete_buffer (scanner->buffer, scanner->scanner);
+ yylex_destroy(scanner->scanner);
+
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+
+ g_free (scanner);
+}
diff --git a/plugins/am-project/ac-writer.c b/plugins/am-project/ac-writer.c
new file mode 100644
index 0000000..71d2bfc
--- /dev/null
+++ b/plugins/am-project/ac-writer.c
@@ -0,0 +1,146 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* ac-writer.c
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ac-writer.h"
+
+#include "am-project-private.h"
+
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+/* Types
+ *---------------------------------------------------------------------------*/
+
+
+/* Helper functions
+ *---------------------------------------------------------------------------*/
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static gboolean
+remove_list_item (AnjutaToken *token, AnjutaTokenStyle *user_style)
+{
+ AnjutaTokenStyle *style;
+ AnjutaToken *space;
+
+ DEBUG_PRINT ("remove list item");
+
+ style = user_style != NULL ? user_style : anjuta_token_style_new (NULL," ","\\n",NULL,0);
+ anjuta_token_style_update (style, anjuta_token_parent (token));
+
+ anjuta_token_remove (token);
+ space = anjuta_token_next_sibling (token);
+ if (space && (anjuta_token_get_type (space) == ANJUTA_TOKEN_SPACE) && (anjuta_token_next (space) != NULL))
+ {
+ /* Remove following space */
+ anjuta_token_remove (space);
+ }
+ else
+ {
+ space = anjuta_token_previous_sibling (token);
+ if (space && (anjuta_token_get_type (space) == ANJUTA_TOKEN_SPACE) && (anjuta_token_previous (space) != NULL))
+ {
+ anjuta_token_remove (space);
+ }
+ }
+
+ anjuta_token_style_format (style, anjuta_token_parent (token));
+ if (user_style == NULL) anjuta_token_style_free (style);
+
+ return TRUE;
+}
+
+static gboolean
+add_list_item (AnjutaToken *list, AnjutaToken *token, AnjutaTokenStyle *user_style)
+{
+ AnjutaTokenStyle *style;
+ AnjutaToken *space;
+
+ style = user_style != NULL ? user_style : anjuta_token_style_new (NULL," ","\\n",NULL,0);
+ anjuta_token_style_update (style, anjuta_token_parent (list));
+
+ space = anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " ");
+ space = anjuta_token_insert_after (list, space);
+ anjuta_token_insert_after (space, token);
+
+ anjuta_token_style_format (style, anjuta_token_parent (list));
+ if (user_style == NULL) anjuta_token_style_free (style);
+
+ return TRUE;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+amp_project_update_property (AmpProject *project, AmpPropertyType type)
+{
+ AnjutaToken *token;
+ guint pos;
+ const gchar *value;
+
+ if (project->property == NULL)
+ {
+ return FALSE;
+ }
+ gchar *name;
+ gchar *version;
+ gchar *bug_report;
+ gchar *tarname;
+ gchar *url;
+
+ switch (type)
+ {
+ case AMP_PROPERTY_NAME:
+ pos = 0;
+ value = project->property->name;
+ break;
+ case AMP_PROPERTY_VERSION:
+ pos = 1;
+ value = project->property->version;
+ break;
+ case AMP_PROPERTY_BUG_REPORT:
+ pos = 2;
+ value = project->property->bug_report;
+ break;
+ case AMP_PROPERTY_TARNAME:
+ pos = 3;
+ value = project->property->tarname;
+ break;
+ case AMP_PROPERTY_URL:
+ pos = 4;
+ value = project->property->url;
+ break;
+ }
+
+ token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, value);
+ anjuta_token_list_replace_nth (project->property->ac_init, pos, token);
+ anjuta_token_style_format (project->arg_list, project->property->ac_init);
+
+ return TRUE;
+}
+
diff --git a/plugins/am-project/ac-writer.h b/plugins/am-project/ac-writer.h
new file mode 100644
index 0000000..7a5c200
--- /dev/null
+++ b/plugins/am-project/ac-writer.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* ac-writer.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _AC_WRITER_H_
+#define _AC_WRITER_H_
+
+#include "am-project.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean amp_project_update_property (AmpProject *project, AmpPropertyType type);
+
+G_END_DECLS
+
+#endif /* _AC_WRITER_H_ */
diff --git a/plugins/am-project/am-dialogs.c b/plugins/am-project/am-dialogs.c
new file mode 100644
index 0000000..8a53b9b
--- /dev/null
+++ b/plugins/am-project/am-dialogs.c
@@ -0,0 +1,159 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-dialogs.c
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "am-dialogs.h"
+
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+#define GLADE_FILE PACKAGE_DATA_DIR "/glade/am-project.ui"
+
+/* Types
+ *---------------------------------------------------------------------------*/
+
+typedef struct _AmpConfigureProjectDialog
+{
+ AmpProject *project;
+
+ GtkWidget *top_level;
+} AmpConfigureProjectDialog;
+
+
+/* Helper functions
+ *---------------------------------------------------------------------------*/
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static void
+on_project_widget_destroy (GtkWidget *wid, AmpConfigureProjectDialog *dlg)
+{
+ g_object_unref (dlg->top_level);
+ g_free (dlg);
+}
+
+static void
+add_entry (AmpProject *project, const gchar *id, const gchar *display_name, AmpPropertyType type, GtkWidget *table, gint position)
+{
+ GtkWidget *label;
+ GtkWidget *entry;
+ gchar *value;
+
+ label = gtk_label_new (display_name);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, position, position+1,
+ GTK_FILL, GTK_FILL, 5, 3);
+
+ entry = gtk_entry_new ();
+ value = amp_project_get_property (project, type);
+ gtk_entry_set_text (GTK_ENTRY (entry), value);
+ g_free (value);
+ gtk_misc_set_alignment (GTK_MISC (entry), 0, -1);
+ gtk_widget_show (entry);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, position, position+1,
+ GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 3);
+}
+
+static void
+add_label (const gchar *display_name, const gchar *value, GtkWidget *table, gint position)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new (display_name);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, position, position+1,
+ GTK_FILL, GTK_FILL, 5, 3);
+
+ label = gtk_label_new (value);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 1, 2, position, position+1,
+ GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 3);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+GtkWidget *
+amp_configure_project_dialog (AmpProject *project, GError **error)
+{
+ GtkBuilder *bxml = gtk_builder_new ();
+ GtkWidget *top_level;
+ AmpConfigureProjectDialog *dlg;
+ GtkWidget *table;
+ gchar *name;
+
+ bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
+ if (!bxml) return NULL;
+
+ dlg = g_new0 (AmpConfigureProjectDialog, 1);
+ anjuta_util_builder_get_objects (bxml,
+ "top_level", &top_level,
+ "general_properties_table", &table,
+ NULL);
+ dlg->top_level = top_level;
+ g_object_ref (top_level);
+ g_signal_connect (top_level, "destroy", G_CALLBACK (on_project_widget_destroy), dlg);
+
+ name = g_file_get_parse_name (amp_project_get_file (project));
+ add_label (_("Path:"), name, table, 0);
+ g_free (name);
+
+ add_entry (project, NULL, _("Name:"), AMP_PROPERTY_NAME, table, 1);
+ add_entry (project, NULL, _("Version:"), AMP_PROPERTY_VERSION, table, 2);
+ add_entry (project, NULL, _("Bug report URL:"), AMP_PROPERTY_BUG_REPORT, table, 3);
+ add_entry (project, NULL, _("Package name:"), AMP_PROPERTY_TARNAME, table, 4);
+ add_entry (project, NULL, _("URL:"), AMP_PROPERTY_URL, table, 5);
+
+ gtk_widget_show_all (top_level);
+ g_object_unref (bxml);
+
+ g_message ("get config dialog %p", top_level);
+
+ return top_level;
+}
+
+GtkWidget *
+amp_configure_group_dialog (AmpProject *project, AmpGroup *group, GError **error)
+{
+ return NULL;
+}
+
+GtkWidget *
+amp_configure_target_dialog (AmpProject *project, AmpTarget *target, GError **error)
+{
+ return NULL;
+}
+
+GtkWidget *
+amp_configure_source_dialog (AmpProject *project, AmpSource *target, GError **error)
+{
+ return NULL;
+}
diff --git a/plugins/am-project/am-dialogs.h b/plugins/am-project/am-dialogs.h
new file mode 100644
index 0000000..99027d2
--- /dev/null
+++ b/plugins/am-project/am-dialogs.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-dialogs.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _AM_DIALOGS_H_
+#define _AM_DIALOGS_H_
+
+#include <gtk/gtk.h>
+#include "am-project.h"
+
+G_BEGIN_DECLS
+
+GtkWidget *amp_configure_project_dialog (AmpProject *project, GError **error);
+GtkWidget *amp_configure_group_dialog (AmpProject *project, AmpGroup *group, GError **error);
+GtkWidget *amp_configure_target_dialog (AmpProject *project, AmpTarget *target, GError **error);
+GtkWidget *amp_configure_source_dialog (AmpProject *project, AmpSource *target, GError **error);
+
+G_END_DECLS
+
+#endif /* _AM_DIALOGS_H_ */
diff --git a/plugins/am-project/am-parser.y b/plugins/am-project/am-parser.y
new file mode 100644
index 0000000..a6fbcd7
--- /dev/null
+++ b/plugins/am-project/am-parser.y
@@ -0,0 +1,320 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * am-parser.y
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+%{
+
+#include <am-scanner.h>
+
+#include <stdlib.h>
+
+#define YYDEBUG 1
+
+%}
+
+/* Defining an union allow to use 2 protocol blocks (enclosed by %{ %}) which
+ * is useful when redefining YYSTYPE. */
+%union {
+ AnjutaToken *token;
+ AnjutaTokenRange range;
+}
+
+%token <token> EOL '\n'
+%token <token> SPACE
+%token <token> TAB '\t'
+%token <token> MACRO
+%token <token> VARIABLE
+%token <token> COLON ':'
+%token <token> DOUBLE_COLON "::"
+%token <token> ORDER '|'
+%token <token> SEMI_COLON ';'
+%token <token> EQUAL '='
+%token <token> IMMEDIATE_EQUAL ":="
+%token <token> CONDITIONAL_EQUAL "?="
+%token <token> APPEND "+="
+%token <token> CHARACTER
+%token <token> NAME
+%token <token> AM_VARIABLE
+
+%type <token> head_token target_token value_token name_token space_token rule_token equal_token token automake_token prerequisite_token
+%type <token> am_variable
+%type <token> value head space prerequisite target depend rule variable commands head_with_space
+%type <token> value_list strip_value_list prerequisite_list target_list token_list target_list2
+%type <token> optional_space space_list_value
+
+%defines
+
+%pure_parser
+
+/* Necessary because autotools wrapper always looks for a file named "y.tab.c",
+ * not "amp-scanner.c"
+%output="y.tab.c"*/
+
+%glr-parser
+
+%parse-param {void* scanner}
+%lex-param {void* scanner}
+
+%name-prefix="amp_am_yy"
+
+%locations
+
+%start file
+
+%debug
+
+%{
+
+//amp_am_yydebug = 1;
+
+static void amp_am_yyerror (YYLTYPE *loc, AmpAmScanner *scanner, char const *s);
+
+%}
+
+
+%%
+
+file:
+ optional_space statement
+ | file EOL optional_space statement
+ ;
+
+statement:
+ /* empty */
+ | line
+ | am_variable
+ ;
+
+line:
+ name_token
+ | line token
+ ;
+
+variable:
+ head_with_space equal_token optional_space value_list optional_space
+ | head equal_token optional_space value_list optional_space
+ ;
+
+rule:
+ depend
+ | depend SEMI_COLON commands
+ | depend EOL TAB commands
+ ;
+
+depend:
+ target_list rule_token optional_space prerequisite_list optional_space ORDER optional_space prerequisite_list
+ ;
+
+commands:
+ token_list
+ | commands EOL TAB token_list
+ ;
+
+am_variable:
+ AM_VARIABLE space_list_value {
+ $$ = anjuta_token_merge (
+ anjuta_token_insert_before ($1,
+ anjuta_token_new_static (ANJUTA_TOKEN_STATEMENT, NULL)),
+ $2);
+ }
+ | AM_VARIABLE optional_space equal_token optional_space
+ ;
+
+space_list_value: optional_space equal_token value_list {
+ $$ = $3;
+ }
+ ;
+
+value_list:
+ optional_space strip_value_list optional_space {
+ if ($1) anjuta_token_merge_previous ($2, $1);
+ if ($3) anjuta_token_merge ($2, $3);
+ $$ = $2;
+ }
+
+strip_value_list:
+ value {
+ $$ = anjuta_token_merge (
+ anjuta_token_insert_before ($1,
+ anjuta_token_new_static (ANJUTA_TOKEN_LIST, NULL)),
+ $1);
+ }
+ | strip_value_list space value {
+ anjuta_token_merge ($1, $3);
+ }
+ ;
+
+target_list:
+ head
+ | head_with_space
+ | head_with_space target_list2 optional_space
+ ;
+
+target_list2:
+ target
+ | target_list2 space target {
+ anjuta_token_merge ($1, $3);
+ }
+ ;
+
+token_list:
+ token
+ | token_list token
+ ;
+
+prerequisite_list:
+ prerequisite
+ | prerequisite_list space prerequisite {
+ anjuta_token_merge ($1, $3);
+ }
+ ;
+
+
+
+optional_space:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | space
+ ;
+
+
+head_with_space:
+ head space
+ ;
+
+head:
+ head_token
+ | head name_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+target:
+ head_token
+ | target target_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+value:
+ value_token
+ | value value_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+prerequisite:
+ prerequisite_token
+ | prerequisite prerequisite_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+space:
+ space_token
+ | space space_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+
+token:
+ space_token
+ | value_token
+ ;
+
+value_token:
+ equal_token
+ | rule_token
+ | target_token
+ ;
+
+prerequisite_token:
+ equal_token
+ | rule_token
+ | name_token
+ | automake_token
+ | ORDER
+ | SEMI_COLON
+ ;
+
+target_token:
+ head_token
+ | automake_token
+ ;
+
+
+space_token:
+ SPACE
+ | TAB
+ ;
+
+equal_token:
+ EQUAL
+ | IMMEDIATE_EQUAL
+ | CONDITIONAL_EQUAL
+ | APPEND
+ ;
+
+rule_token:
+ COLON
+ | DOUBLE_COLON
+ ;
+
+head_token:
+ MACRO
+ | VARIABLE
+ | NAME
+ | CHARACTER
+ | ORDER
+ | SEMI_COLON
+ ;
+
+name_token:
+ MACRO
+ | VARIABLE
+ | NAME
+ | CHARACTER
+ ;
+
+automake_token:
+ AM_VARIABLE
+ ;
+
+%%
+
+static void
+amp_am_yyerror (YYLTYPE *loc, AmpAmScanner *scanner, char const *s)
+{
+ gchar *filename;
+
+ g_message ("scanner %p", scanner);
+ filename = amp_am_scanner_get_filename ((AmpAmScanner *)scanner);
+ if (filename == NULL) filename = "?";
+ g_message ("%s (%d:%d-%d:%d) %s\n", filename, loc->first_line, loc->first_column, loc->last_line, loc->last_column, s);
+}
+
+/*static void
+amp_am_yyerror (YYLTYPE *loc, void *scanner, char const *s)
+{
+ g_message ("(%d:%d-%d:%d) %s\n", loc->first_line, loc->first_column, loc->last_line, loc->last_column, s);
+}*/
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
diff --git a/plugins/gbf-am/gbf-am-plugin-48.png b/plugins/am-project/am-project-plugin-48.png
similarity index 100%
rename from plugins/gbf-am/gbf-am-plugin-48.png
rename to plugins/am-project/am-project-plugin-48.png
diff --git a/plugins/am-project/am-project-private.h b/plugins/am-project/am-project-private.h
new file mode 100644
index 0000000..c49c1c3
--- /dev/null
+++ b/plugins/am-project/am-project-private.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-project-private.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _AM_PROJECT_PRIVATE_H_
+#define _AM_PROJECT_PRIVATE_H_
+
+#include "am-project.h"
+
+G_BEGIN_DECLS
+
+struct _AmpProperty {
+ AnjutaToken *ac_init; /* AC_INIT macro */
+ gchar *name;
+ gchar *version;
+ gchar *bug_report;
+ gchar *tarname;
+ gchar *url;
+};
+
+struct _AmpProject {
+ GObject parent;
+
+ /* uri of the project; this can be a full uri, even though we
+ * can only work with native local files */
+ GFile *root_file;
+
+ /* project data */
+ AnjutaTokenFile *configure_file; /* configure.in file */
+
+ AmpProperty *property;
+
+ AmpGroup *root_node; /* tree containing project data;
+ * each GNode's data is a
+ * AmpNode, and the root of
+ * the tree is the root group. */
+
+ /* shortcut hash tables, mapping id -> GNode from the tree above */
+ GHashTable *groups;
+ GHashTable *files;
+ GHashTable *configs; /* Config file from configure_file */
+
+ GHashTable *modules;
+
+ /* project files monitors */
+ GHashTable *monitors;
+
+ /* Keep list style */
+ AnjutaTokenStyle *space_list;
+ AnjutaTokenStyle *arg_list;
+};
+
+G_END_DECLS
+
+#endif /* _AM_PROJECT_PRIVATE_H_ */
diff --git a/plugins/am-project/am-project.c b/plugins/am-project/am-project.c
new file mode 100644
index 0000000..38ba080
--- /dev/null
+++ b/plugins/am-project/am-project.c
@@ -0,0 +1,2737 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-project.c
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "am-project.h"
+
+#include "am-project-private.h"
+
+#include <libanjuta/interfaces/ianjuta-project.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <glib.h>
+
+#include "ac-scanner.h"
+#include "ac-writer.h"
+#include "am-scanner.h"
+#include "am-dialogs.h"
+//#include "am-config.h"
+//#include "am-properties.h"
+
+
+#define UNIMPLEMENTED G_STMT_START { g_warning (G_STRLOC": unimplemented"); } G_STMT_END
+
+/* Constant strings for parsing perl script error output */
+#define ERROR_PREFIX "ERROR("
+#define WARNING_PREFIX "WARNING("
+#define MESSAGE_DELIMITER ": "
+
+static const gchar *valid_am_makefiles[] = {"GNUmakefile.am", "makefile.am", "Makefile.am", NULL};
+
+/* convenient shortcut macro the get the AnjutaProjectNode from a GNode */
+#define AMP_NODE_DATA(node) ((node) != NULL ? (AnjutaProjectNodeData *)((node)->data) : NULL)
+#define AMP_GROUP_DATA(node) ((node) != NULL ? (AmpGroupData *)((node)->data) : NULL)
+#define AMP_TARGET_DATA(node) ((node) != NULL ? (AmpTargetData *)((node)->data) : NULL)
+#define AMP_SOURCE_DATA(node) ((node) != NULL ? (AmpSourceData *)((node)->data) : NULL)
+
+typedef struct _AmpPackage AmpPackage;
+
+struct _AmpPackage {
+ gchar *name;
+ gchar *version;
+};
+
+typedef struct _AmpModule AmpModule;
+
+struct _AmpModule {
+ GList *packages;
+ AnjutaToken *module;
+};
+
+typedef enum {
+ AM_GROUP_TOKEN_CONFIGURE,
+ AM_GROUP_TOKEN_SUBDIRS,
+ AM_GROUP_TOKEN_DIST_SUBDIRS,
+ AM_GROUP_TARGET,
+ AM_GROUP_TOKEN_LAST
+} AmpGroupTokenCategory;
+
+typedef struct _AmpGroupData AmpGroupData;
+
+struct _AmpGroupData {
+ AnjutaProjectGroupData base; /* Common node data */
+ gboolean dist_only; /* TRUE if the group is distributed but not built */
+ GFile *makefile; /* GFile corresponding to group makefile */
+ AnjutaTokenFile *tfile; /* Corresponding Makefile */
+ GList *tokens[AM_GROUP_TOKEN_LAST]; /* List of token used by this group */
+};
+
+typedef enum _AmpTargetFlag
+{
+ AM_TARGET_CHECK = 1 << 0,
+ AM_TARGET_NOINST = 1 << 1,
+ AM_TARGET_DIST = 1 << 2,
+ AM_TARGET_NODIST = 1 << 3,
+ AM_TARGET_NOBASE = 1 << 4,
+ AM_TARGET_NOTRANS = 1 << 5,
+ AM_TARGET_MAN = 1 << 6,
+ AM_TARGET_MAN_SECTION = 31 << 7
+} AmpTargetFlag;
+
+typedef struct _AmpTargetData AmpTargetData;
+
+struct _AmpTargetData {
+ AnjutaProjectTargetData base;
+ gchar *install;
+ gint flags;
+ GList* tokens;
+};
+
+typedef struct _AmpSourceData AmpSourceData;
+
+struct _AmpSourceData {
+ AnjutaProjectSourceData base;
+ AnjutaToken* token;
+};
+
+typedef struct _AmpConfigFile AmpConfigFile;
+
+struct _AmpConfigFile {
+ GFile *file;
+ AnjutaToken *token;
+};
+
+typedef struct _AmpTargetInformation AmpTargetInformation;
+
+struct _AmpTargetInformation {
+ AnjutaProjectTargetInformation base;
+ AnjutaTokenType token;
+ const gchar *prefix;
+ const gchar *install;
+};
+
+/* Target types
+ *---------------------------------------------------------------------------*/
+
+static AmpTargetInformation AmpTargetTypes[] = {
+ {{N_("Unknown"), ANJUTA_TARGET_UNKNOWN,
+ "text/plain"},
+ ANJUTA_TOKEN_NONE,
+ NULL,
+ NULL},
+
+ {{N_("Program"), ANJUTA_TARGET_EXECUTABLE,
+ "application/x-executable"},
+ AM_TOKEN__PROGRAMS,
+ "_PROGRAMS",
+ "bin"},
+
+ {{N_("Shared Library"), ANJUTA_TARGET_SHAREDLIB,
+ "application/x-sharedlib"},
+ AM_TOKEN__LTLIBRARIES,
+ "_LTLIBRARIES",
+ "lib"},
+
+ {{N_("Static Library"), ANJUTA_TARGET_STATICLIB,
+ "application/x-archive"},
+ AM_TOKEN__LIBRARIES,
+ "_LIBRARIES",
+ "lib"},
+
+ {{N_("Header Files"), ANJUTA_TARGET_UNKNOWN,
+ "text/x-chdr"},
+ AM_TOKEN__HEADERS,
+ "_HEADERS",
+ "include"},
+
+ {{N_("Man Documentation"), ANJUTA_TARGET_UNKNOWN,
+ "text/x-troff-man"},
+ AM_TOKEN__MANS,
+ "_MANS",
+ "man"},
+
+ {{N_("Miscellaneous Data"), ANJUTA_TARGET_UNKNOWN,
+ "application/octet-stream"},
+ AM_TOKEN__DATA,
+ "_DATA",
+ "data"},
+
+ {{N_("Script"), ANJUTA_TARGET_EXECUTABLE,
+ "text/x-shellscript"},
+ AM_TOKEN__SCRIPTS,
+ "_SCRIPTS",
+ "bin"},
+
+ {{N_("Info Documentation"), ANJUTA_TARGET_UNKNOWN,
+ "application/x-tex-info"},
+ AM_TOKEN__TEXINFOS,
+ "_TEXINFOS",
+ "info"},
+
+ {{N_("Java Module"), ANJUTA_TARGET_JAVA,
+ "application/x-java"},
+ AM_TOKEN__JAVA,
+ "_JAVA",
+ NULL},
+
+ {{N_("Python Module"), ANJUTA_TARGET_PYTHON,
+ "application/x-python"},
+ AM_TOKEN__PYTHON,
+ "_PYTHON",
+ NULL},
+
+ {{N_("Lisp Module"), ANJUTA_TARGET_UNKNOWN,
+ "text/plain"},
+ AM_TOKEN__LISP,
+ "_LISP",
+ "lisp"},
+
+ {{NULL, ANJUTA_TARGET_UNKNOWN,
+ NULL},
+ ANJUTA_TOKEN_NONE,
+ NULL,
+ NULL}
+};
+
+
+/* ----- Standard GObject types and variables ----- */
+
+enum {
+ PROP_0,
+ PROP_PROJECT_DIR
+};
+
+static GObject *parent_class;
+
+/* Helper functions
+ *---------------------------------------------------------------------------*/
+
+static void
+error_set (GError **error, gint code, const gchar *message)
+{
+ if (error != NULL) {
+ if (*error != NULL) {
+ gchar *tmp;
+
+ /* error already created, just change the code
+ * and prepend the string */
+ (*error)->code = code;
+ tmp = (*error)->message;
+ (*error)->message = g_strconcat (message, "\n\n", tmp, NULL);
+ g_free (tmp);
+
+ } else {
+ *error = g_error_new_literal (IANJUTA_PROJECT_ERROR,
+ code,
+ message);
+ }
+ }
+}
+
+/* Work even if file is not a descendant of parent */
+static gchar*
+get_relative_path (GFile *parent, GFile *file)
+{
+ gchar *relative;
+
+ relative = g_file_get_relative_path (parent, file);
+ if (relative == NULL)
+ {
+ if (g_file_equal (parent, file))
+ {
+ relative = g_strdup ("");
+ }
+ else
+ {
+ GFile *grand_parent = g_file_get_parent (parent);
+ gint level;
+ gchar *grand_relative;
+ gchar *ptr;
+ gsize len;
+
+
+ for (level = 1; !g_file_has_prefix (file, grand_parent); level++)
+ {
+ GFile *next = g_file_get_parent (grand_parent);
+
+ g_object_unref (grand_parent);
+ grand_parent = next;
+ }
+
+ grand_relative = g_file_get_relative_path (grand_parent, file);
+ g_object_unref (grand_parent);
+
+ len = strlen (grand_relative);
+ relative = g_new (gchar, len + level * 3 + 1);
+ ptr = relative;
+ for (; level; level--)
+ {
+ memcpy(ptr, ".." G_DIR_SEPARATOR_S, 3);
+ ptr += 3;
+ }
+ memcpy (ptr, grand_relative, len + 1);
+ g_free (grand_relative);
+ }
+ }
+
+ return relative;
+}
+
+static GFileType
+file_type (GFile *file, const gchar *filename)
+{
+ GFile *child;
+ GFileInfo *info;
+ GFileType type;
+
+ child = filename != NULL ? g_file_get_child (file, filename) : g_object_ref (file);
+
+ //g_message ("check file %s", g_file_get_path (child));
+
+ info = g_file_query_info (child,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info != NULL)
+ {
+ type = g_file_info_get_file_type (info);
+ g_object_unref (info);
+ }
+ else
+ {
+ type = G_FILE_TYPE_UNKNOWN;
+ }
+
+ g_object_unref (child);
+
+ return type;
+}
+
+gboolean
+remove_list_item (AnjutaToken *token, AnjutaTokenStyle *user_style)
+{
+ AnjutaTokenStyle *style;
+ AnjutaToken *space;
+
+ DEBUG_PRINT ("remove list item");
+
+ style = user_style != NULL ? user_style : anjuta_token_style_new (NULL," ","\\n",NULL,0);
+ anjuta_token_style_update (style, anjuta_token_parent (token));
+
+ anjuta_token_remove (token);
+ space = anjuta_token_next_sibling (token);
+ if (space && (anjuta_token_get_type (space) == ANJUTA_TOKEN_SPACE) && (anjuta_token_next (space) != NULL))
+ {
+ /* Remove following space */
+ anjuta_token_remove (space);
+ }
+ else
+ {
+ space = anjuta_token_previous_sibling (token);
+ if (space && (anjuta_token_get_type (space) == ANJUTA_TOKEN_SPACE) && (anjuta_token_previous (space) != NULL))
+ {
+ anjuta_token_remove (space);
+ }
+ }
+
+ anjuta_token_style_format (style, anjuta_token_parent (token));
+ if (user_style == NULL) anjuta_token_style_free (style);
+
+ return TRUE;
+}
+
+static gboolean
+add_list_item (AnjutaToken *list, AnjutaToken *token, AnjutaTokenStyle *user_style)
+{
+ AnjutaTokenStyle *style;
+ AnjutaToken *space;
+
+ style = user_style != NULL ? user_style : anjuta_token_style_new (NULL," ","\\n",NULL,0);
+ anjuta_token_style_update (style, anjuta_token_parent (list));
+
+ space = anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " ");
+ space = anjuta_token_insert_after (list, space);
+ anjuta_token_insert_after (space, token);
+
+ anjuta_token_style_format (style, anjuta_token_parent (list));
+ if (user_style == NULL) anjuta_token_style_free (style);
+
+ return TRUE;
+}
+
+/* Automake parsing function
+ *---------------------------------------------------------------------------*/
+
+/* Remove invalid character according to automake rules */
+gchar*
+canonicalize_automake_variable (gchar *name)
+{
+ gchar *canon_name = g_strdup (name);
+ gchar *ptr;
+
+ for (ptr = canon_name; *ptr != '\0'; ptr++)
+ {
+ if (!g_ascii_isalnum (*ptr) && (*ptr != '@'))
+ {
+ *ptr = '_';
+ }
+ }
+
+ return canon_name;
+}
+
+gboolean
+split_automake_variable (gchar *name, gint *flags, gchar **module, gchar **primary)
+{
+ GRegex *regex;
+ GMatchInfo *match_info;
+ gint start_pos;
+ gint end_pos;
+
+ regex = g_regex_new ("(nobase_|notrans_)?"
+ "(dist_|nodist_)?"
+ "(noinst_|check_|man_|man[0-9al]_)?"
+ "(.*_)?"
+ "([^_]+)",
+ G_REGEX_ANCHORED,
+ G_REGEX_MATCH_ANCHORED,
+ NULL);
+
+ if (!g_regex_match (regex, name, G_REGEX_MATCH_ANCHORED, &match_info)) return FALSE;
+
+ if (flags)
+ {
+ *flags = 0;
+ g_match_info_fetch_pos (match_info, 1, &start_pos, &end_pos);
+ if (start_pos >= 0)
+ {
+ if (*(name + start_pos + 2) == 'b') *flags |= AM_TARGET_NOBASE;
+ if (*(name + start_pos + 2) == 't') *flags |= AM_TARGET_NOTRANS;
+ }
+
+ g_match_info_fetch_pos (match_info, 2, &start_pos, &end_pos);
+ if (start_pos >= 0)
+ {
+ if (*(name + start_pos) == 'd') *flags |= AM_TARGET_DIST;
+ if (*(name + start_pos) == 'n') *flags |= AM_TARGET_NODIST;
+ }
+
+ g_match_info_fetch_pos (match_info, 3, &start_pos, &end_pos);
+ if (start_pos >= 0)
+ {
+ if (*(name + start_pos) == 'n') *flags |= AM_TARGET_NOINST;
+ if (*(name + start_pos) == 'c') *flags |= AM_TARGET_CHECK;
+ if (*(name + start_pos) == 'm')
+ {
+ gchar section = *(name + end_pos - 1);
+ *flags |= AM_TARGET_MAN;
+ if (section != 'n') *flags |= (section & 0x1F) << 7;
+ }
+ }
+ }
+
+ if (module)
+ {
+ g_match_info_fetch_pos (match_info, 4, &start_pos, &end_pos);
+ if (start_pos >= 0)
+ {
+ *module = name + start_pos;
+ *(name + end_pos - 1) = '\0';
+ }
+ else
+ {
+ *module = NULL;
+ }
+ }
+
+ if (primary)
+ {
+ g_match_info_fetch_pos (match_info, 5, &start_pos, &end_pos);
+ if (start_pos >= 0)
+ {
+ *primary = name + start_pos;
+ }
+ else
+ {
+ *primary = NULL;
+ }
+ }
+
+ g_regex_unref (regex);
+
+ return TRUE;
+}
+
+gchar*
+ac_init_default_tarname (const gchar *name)
+{
+ gchar *tarname;
+
+ /* Remove GNU prefix */
+ if (strncmp (name, "GNU ", 4) == 0) name += 4;
+
+ tarname = g_ascii_strdown (name, -1);
+ g_strcanon (tarname, "abcdefghijklmnopqrstuvwxyz0123456789", '-');
+
+ return tarname;
+}
+
+/* Config file objects
+ *---------------------------------------------------------------------------*/
+
+static AmpConfigFile*
+amp_config_file_new (const gchar *pathname, GFile *project_root, AnjutaToken *token)
+{
+ AmpConfigFile *config;
+
+ g_return_val_if_fail ((pathname != NULL) && (project_root != NULL), NULL);
+
+ config = g_slice_new0(AmpConfigFile);
+ config->file = g_file_resolve_relative_path (project_root, pathname);
+ config->token = token;
+
+ return config;
+}
+
+static void
+amp_config_file_free (AmpConfigFile *config)
+{
+ if (config)
+ {
+ g_object_unref (config->file);
+ g_slice_free (AmpConfigFile, config);
+ }
+}
+
+/* Package objects
+ *---------------------------------------------------------------------------*/
+
+void
+amp_package_set_version (AmpPackage *package, const gchar *compare, const gchar *version)
+{
+ g_return_if_fail (package != NULL);
+ g_return_if_fail ((version == NULL) || (compare != NULL));
+
+ g_free (package->version);
+ package->version = version != NULL ? g_strconcat (compare, version, NULL) : NULL;
+}
+
+static AmpPackage*
+amp_package_new (const gchar *name)
+{
+ AmpPackage *package;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ package = g_slice_new0(AmpPackage);
+ package->name = g_strdup (name);
+
+ return package;
+}
+
+static void
+amp_package_free (AmpPackage *package)
+{
+ if (package)
+ {
+ g_free (package->name);
+ g_free (package->version);
+ g_slice_free (AmpPackage, package);
+ }
+}
+
+/* Module objects
+ *---------------------------------------------------------------------------*/
+
+static AmpModule*
+amp_module_new (AnjutaToken *token)
+{
+ AmpModule *module;
+
+ module = g_slice_new0(AmpModule);
+ module->module = token;
+
+ return module;
+}
+
+static void
+amp_module_free (AmpModule *module)
+{
+ if (module)
+ {
+ g_list_foreach (module->packages, (GFunc)amp_package_free, NULL);
+ g_slice_free (AmpModule, module);
+ }
+}
+
+static void
+amp_project_new_module_hash (AmpProject *project)
+{
+ project->modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)amp_module_free);
+}
+
+static void
+amp_project_free_module_hash (AmpProject *project)
+{
+ if (project->modules != NULL)
+ {
+ g_hash_table_destroy (project->modules);
+ project->modules = NULL;
+ }
+}
+
+/* Property objects
+ *---------------------------------------------------------------------------*/
+
+static AmpProperty*
+amp_property_new (AnjutaToken *token)
+{
+ AmpProperty *prop;
+ AnjutaToken *arg;
+
+ prop = g_slice_new0(AmpProperty);
+ prop->ac_init = token;
+
+ arg = anjuta_token_next_child (token);
+ arg = anjuta_token_get_next_arg (arg, &prop->name);
+ arg = anjuta_token_get_next_arg (arg, &prop->version);
+ arg = anjuta_token_get_next_arg (arg, &prop->bug_report);
+ arg = anjuta_token_get_next_arg (arg, &prop->tarname);
+ arg = anjuta_token_get_next_arg (arg, &prop->url);
+
+ return prop;
+}
+
+static void
+amp_property_free (AmpProperty *prop)
+{
+ g_free (prop->name);
+ g_free (prop->version);
+ g_free (prop->bug_report);
+ g_free (prop->tarname);
+ g_slice_free (AmpProperty, prop);
+}
+
+/* Group objects
+ *---------------------------------------------------------------------------*/
+
+static void
+amp_group_add_token (AmpGroup *node, AnjutaToken *token, AmpGroupTokenCategory category)
+{
+ AmpGroupData *group;
+
+ g_return_if_fail ((node != NULL) && (node->data != NULL));
+
+ group = AMP_GROUP_DATA (node);
+ group->tokens[category] = g_list_prepend (group->tokens[category], token);
+}
+
+static GList *
+amp_group_get_token (AmpGroup *node, AmpGroupTokenCategory category)
+{
+ AmpGroupData *group;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ group = AMP_GROUP_DATA (node);
+ return group->tokens[category];
+}
+
+static void
+amp_group_set_dist_only (AmpGroup *node, gboolean dist_only)
+{
+ g_return_if_fail ((node != NULL) && (node->data != NULL));
+
+ AMP_GROUP_DATA (node)->dist_only = dist_only;
+}
+
+static AnjutaTokenFile*
+amp_group_set_makefile (AmpGroup *node, GFile *makefile)
+{
+ AmpGroupData *group;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ group = AMP_GROUP_DATA (node);
+ if (group->makefile != NULL) g_object_unref (group->makefile);
+ if (group->tfile != NULL) anjuta_token_file_free (group->tfile);
+ if (makefile != NULL)
+ {
+ group->makefile = g_object_ref (makefile);
+ group->tfile = anjuta_token_file_new (makefile);
+ }
+ else
+ {
+ group->makefile = NULL;
+ group->tfile = NULL;
+ }
+
+ return group->tfile;
+}
+
+static AmpGroup*
+amp_group_new (GFile *file, gboolean dist_only)
+{
+ AmpGroupData *group = NULL;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ group = g_slice_new0(AmpGroupData);
+ group->base.node.type = ANJUTA_PROJECT_GROUP;
+ group->base.directory = g_object_ref (file);
+ group->dist_only = dist_only;
+
+ return g_node_new (group);
+}
+
+static void
+amp_group_free (AmpGroup *node)
+{
+ AmpGroupData *group = (AmpGroupData *)node->data;
+ gint i;
+
+ if (group->base.directory) g_object_unref (group->base.directory);
+ if (group->tfile) anjuta_token_file_free (group->tfile);
+ if (group->makefile) g_object_unref (group->makefile);
+ for (i = 0; i < AM_GROUP_TOKEN_LAST; i++)
+ {
+ if (group->tokens[i] != NULL) g_list_free (group->tokens[i]);
+ }
+ g_slice_free (AmpGroupData, group);
+
+ g_node_destroy (node);
+}
+
+/* Target objects
+ *---------------------------------------------------------------------------*/
+
+static void
+amp_target_add_token (AmpGroup *node, AnjutaToken *token)
+{
+ AmpTargetData *target;
+
+ g_return_if_fail ((node != NULL) && (node->data != NULL));
+
+ target = AMP_TARGET_DATA (node);
+ target->tokens = g_list_prepend (target->tokens, token);
+}
+
+static GList *
+amp_target_get_token (AmpGroup *node)
+{
+ AmpTargetData *target;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ target = AMP_TARGET_DATA (node);
+ return target->tokens;
+}
+
+
+static AmpTarget*
+amp_target_new (const gchar *name, AnjutaProjectTargetType type, const gchar *install, gint flags)
+{
+ AmpTargetData *target = NULL;
+
+ target = g_slice_new0(AmpTargetData);
+ target->base.node.type = ANJUTA_PROJECT_TARGET;
+ target->base.name = g_strdup (name);
+ target->base.type = type;
+ target->install = g_strdup (install);
+ target->flags = flags;
+
+ return g_node_new (target);
+}
+
+static void
+amp_target_free (AmpTarget *node)
+{
+ AmpTargetData *target = AMP_TARGET_DATA (node);
+
+ g_free (target->base.name);
+ g_free (target->install);
+ g_slice_free (AmpTargetData, target);
+
+ g_node_destroy (node);
+}
+
+/* Source objects
+ *---------------------------------------------------------------------------*/
+
+static AmpSource*
+amp_source_new (GFile *file)
+{
+ AmpSourceData *source = NULL;
+
+ source = g_slice_new0(AmpSourceData);
+ source->base.node.type = ANJUTA_PROJECT_SOURCE;
+ source->base.file = g_object_ref (file);
+
+ return g_node_new (source);
+}
+
+static void
+amp_source_free (AmpSource *node)
+{
+ AmpSourceData *source = AMP_SOURCE_DATA (node);
+
+ g_object_unref (source->base.file);
+ g_slice_free (AmpSourceData, source);
+
+ g_node_destroy (node);
+}
+
+/*
+ * File monitoring support --------------------------------
+ * FIXME: review these
+ */
+static void
+monitor_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer data)
+{
+ AmpProject *project = data;
+
+ g_return_if_fail (project != NULL && AMP_IS_PROJECT (project));
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ /* monitor will be removed here... is this safe? */
+ amp_project_reload (project, NULL);
+ g_signal_emit_by_name (G_OBJECT (project), "project-updated");
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void
+monitor_add (AmpProject *project, GFile *file)
+{
+ GFileMonitor *monitor = NULL;
+
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (project->monitors != NULL);
+
+ if (file == NULL)
+ return;
+
+ monitor = g_hash_table_lookup (project->monitors, file);
+ if (!monitor) {
+ gboolean exists;
+
+ /* FIXME clarify if uri is uri, path or both */
+ exists = g_file_query_exists (file, NULL);
+
+ if (exists) {
+ monitor = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
+ if (monitor != NULL)
+ {
+ g_signal_connect (G_OBJECT (monitor),
+ "changed",
+ G_CALLBACK (monitor_cb),
+ project);
+ g_hash_table_insert (project->monitors,
+ g_object_ref (file),
+ monitor);
+ }
+ }
+ }
+}
+
+static void
+monitors_remove (AmpProject *project)
+{
+ g_return_if_fail (project != NULL);
+
+ if (project->monitors)
+ g_hash_table_destroy (project->monitors);
+ project->monitors = NULL;
+}
+
+static void
+group_hash_foreach_monitor (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ AmpGroup *group_node = value;
+ AmpProject *project = user_data;
+
+ monitor_add (project, AMP_GROUP_DATA(group_node)->base.directory);
+}
+
+static void
+monitors_setup (AmpProject *project)
+{
+ g_return_if_fail (project != NULL);
+
+ monitors_remove (project);
+
+ /* setup monitors hash */
+ project->monitors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+ (GDestroyNotify) g_file_monitor_cancel);
+
+ monitor_add (project, anjuta_token_file_get_file (project->configure_file));
+ if (project->groups)
+ g_hash_table_foreach (project->groups, group_hash_foreach_monitor, project);
+}
+
+
+/*
+ * ---------------- Data structures managment
+ */
+
+static void
+amp_dump_node (GNode *g_node)
+{
+ gchar *name = NULL;
+
+ switch (AMP_NODE_DATA (g_node)->type) {
+ case ANJUTA_PROJECT_GROUP:
+ name = g_file_get_uri (AMP_GROUP_DATA (g_node)->base.directory);
+ DEBUG_PRINT ("GROUP: %s", name);
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ name = g_strdup (AMP_TARGET_DATA (g_node)->base.name);
+ DEBUG_PRINT ("TARGET: %s", name);
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ name = g_file_get_uri (AMP_SOURCE_DATA (g_node)->base.file);
+ DEBUG_PRINT ("SOURCE: %s", name);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ g_free (name);
+}
+
+static gboolean
+foreach_node_destroy (GNode *g_node,
+ gpointer data)
+{
+ switch (AMP_NODE_DATA (g_node)->type) {
+ case ANJUTA_PROJECT_GROUP:
+ //g_hash_table_remove (project->groups, g_file_get_uri (AMP_GROUP_NODE (g_node)->file));
+ amp_group_free (g_node);
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ amp_target_free (g_node);
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ //g_hash_table_remove (project->sources, AMP_NODE (g_node)->id);
+ amp_source_free (g_node);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+
+ return FALSE;
+}
+
+static void
+project_node_destroy (AmpProject *project, GNode *g_node)
+{
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (AMP_IS_PROJECT (project));
+
+ if (g_node) {
+ /* free each node's data first */
+ g_node_traverse (g_node,
+ G_POST_ORDER, G_TRAVERSE_ALL, -1,
+ foreach_node_destroy, project);
+
+ /* now destroy the tree itself */
+ //g_node_destroy (g_node);
+ }
+}
+
+static gboolean
+project_reload_property (AmpProject *project)
+{
+ AnjutaToken *ac_init_tok;
+ AnjutaToken *sequence;
+ AnjutaToken *init;
+
+ ac_init_tok = anjuta_token_new_static (AC_TOKEN_AC_INIT, NULL);
+
+ sequence = anjuta_token_file_first (project->configure_file);
+ if (anjuta_token_match (ac_init_tok, ANJUTA_SEARCH_INTO, sequence, &init))
+ {
+ g_message ("find ac_init");
+ anjuta_token_style_update (project->arg_list, init);
+ project->property = amp_property_new (init);
+ }
+
+ return TRUE;
+}
+
+static void
+project_reload_packages (AmpProject *project)
+{
+ AnjutaToken *pkg_check_tok;
+ AnjutaToken *sequence;
+ AmpAcScanner *scanner = NULL;
+
+ pkg_check_tok = anjuta_token_new_static (AC_TOKEN_PKG_CHECK_MODULES, "PKG_CHECK_MODULES(");
+
+ sequence = anjuta_token_file_first (project->configure_file);
+ for (;;)
+ {
+ AnjutaToken *module;
+ AnjutaToken *arg;
+ gchar *value;
+ AmpModule *mod;
+ AmpPackage *pack;
+ gchar *compare;
+
+ if (!anjuta_token_match (pkg_check_tok, ANJUTA_SEARCH_INTO, sequence, &module)) break;
+
+ arg = anjuta_token_next_child (module); /* Name */
+
+ value = anjuta_token_evaluate (arg);
+ mod = amp_module_new (arg);
+ mod->packages = NULL;
+ g_hash_table_insert (project->modules, value, mod);
+
+ arg = anjuta_token_next_sibling (arg); /* Separator */
+
+ arg = anjuta_token_next_sibling (arg); /* Package list */
+ if (scanner == NULL) scanner = amp_ac_scanner_new ();
+ amp_ac_scanner_parse_token (scanner, arg, AC_SPACE_LIST_STATE, NULL);
+
+ pack = NULL;
+ compare = NULL;
+ for (arg = anjuta_token_next_child (arg); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ switch (anjuta_token_get_type (arg))
+ {
+ case ANJUTA_TOKEN_START:
+ case ANJUTA_TOKEN_NEXT:
+ case ANJUTA_TOKEN_LAST:
+ case ANJUTA_TOKEN_JUNK:
+ continue;
+ default:
+ break;
+ }
+
+ value = anjuta_token_evaluate (arg);
+ if (value == NULL) continue; /* Empty value, a comment of a quote by example */
+
+ if ((pack != NULL) && (compare != NULL))
+ {
+ amp_package_set_version (pack, compare, value);
+ g_free (value);
+ g_free (compare);
+ pack = NULL;
+ compare = NULL;
+ }
+ else if ((pack != NULL) && (anjuta_token_get_type (arg) == ANJUTA_TOKEN_OPERATOR))
+ {
+ compare = value;
+ }
+ else
+ {
+ pack = amp_package_new (value);
+ mod->packages = g_list_prepend (mod->packages, pack);
+ g_free (value);
+ compare = NULL;
+ }
+ }
+ mod->packages = g_list_reverse (mod->packages);
+
+ sequence = anjuta_token_next_sibling (module);
+ }
+ anjuta_token_free (pkg_check_tok);
+ if (scanner) amp_ac_scanner_free (scanner);
+}
+
+/* Add a GFile in the list for each makefile in the token list */
+void
+amp_project_add_config_files (AmpProject *project, AnjutaToken *list)
+{
+ AnjutaToken* arg;
+
+ for (arg = anjuta_token_next_child (list); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ gchar *value;
+ AmpConfigFile *cfg;
+
+ switch (anjuta_token_get_type (arg))
+ {
+ case ANJUTA_TOKEN_START:
+ case ANJUTA_TOKEN_NEXT:
+ case ANJUTA_TOKEN_LAST:
+ case ANJUTA_TOKEN_JUNK:
+ continue;
+ default:
+ break;
+ }
+
+ value = anjuta_token_evaluate (arg);
+ if (value == NULL) continue;
+
+ cfg = amp_config_file_new (value, project->root_file, arg);
+ g_hash_table_insert (project->configs, cfg->file, cfg);
+ g_free (value);
+ }
+}
+
+static gboolean
+project_list_config_files (AmpProject *project)
+{
+ AnjutaToken *config_files_tok;
+ AnjutaToken *sequence;
+ AmpAcScanner *scanner = NULL;
+
+ //g_message ("load config project %p root file %p", project, project->root_file);
+ /* Search the new AC_CONFIG_FILES macro */
+ config_files_tok = anjuta_token_new_static (AC_TOKEN_AC_CONFIG_FILES, NULL);
+
+ sequence = anjuta_token_file_first (project->configure_file);
+ while (sequence != NULL)
+ {
+ AnjutaToken *arg;
+
+ if (!anjuta_token_match (config_files_tok, ANJUTA_SEARCH_INTO, sequence, &sequence)) break;
+ arg = anjuta_token_next_child (sequence); /* List */
+ if (scanner == NULL) scanner = amp_ac_scanner_new ();
+ amp_ac_scanner_parse_token (scanner, arg, AC_SPACE_LIST_STATE, NULL);
+ amp_project_add_config_files (project, arg);
+ sequence = anjuta_token_next_sibling (sequence);
+ }
+
+ /* Search the old AC_OUTPUT macro */
+ anjuta_token_free(config_files_tok);
+ config_files_tok = anjuta_token_new_static (AC_TOKEN_OBSOLETE_AC_OUTPUT, NULL);
+
+ sequence = anjuta_token_file_first (project->configure_file);
+ while (sequence != NULL)
+ {
+ AnjutaToken *arg;
+
+ if (!anjuta_token_match (config_files_tok, ANJUTA_SEARCH_INTO, sequence, &sequence)) break;
+ arg = anjuta_token_next_child (sequence); /* List */
+ if (scanner == NULL) scanner = amp_ac_scanner_new ();
+ amp_ac_scanner_parse_token (scanner, arg, AC_SPACE_LIST_STATE, NULL);
+ amp_project_add_config_files (project, arg);
+ sequence = anjuta_token_next_sibling (sequence);
+ }
+
+ if (scanner) amp_ac_scanner_free (scanner);
+ anjuta_token_free (config_files_tok);
+
+ return TRUE;
+}
+
+static void
+find_target (GNode *node, gpointer data)
+{
+ if (AMP_NODE_DATA (node)->type == ANJUTA_PROJECT_TARGET)
+ {
+ if (strcmp (AMP_TARGET_DATA (node)->base.name, *(gchar **)data) == 0)
+ {
+ /* Find target, return node value in pointer */
+ *(GNode **)data = node;
+
+ return;
+ }
+ }
+}
+
+static void
+find_canonical_target (GNode *node, gpointer data)
+{
+ if (AMP_NODE_DATA (node)->type == ANJUTA_PROJECT_TARGET)
+ {
+ gchar *canon_name = canonicalize_automake_variable (AMP_TARGET_DATA (node)->base.name);
+ DEBUG_PRINT ("compare canon %s vs %s node %p", canon_name, *(gchar **)data, node);
+ if (strcmp (canon_name, *(gchar **)data) == 0)
+ {
+ /* Find target, return node value in pointer */
+ *(GNode **)data = node;
+ g_free (canon_name);
+
+ return;
+ }
+ g_free (canon_name);
+ }
+}
+
+static AnjutaToken*
+project_load_target (AmpProject *project, AnjutaToken *start, GNode *parent, GHashTable *orphan_sources)
+{
+ AnjutaToken *arg;
+ AnjutaProjectTargetType type = NULL;
+ gchar *install;
+ gchar *name;
+ gint flags;
+ AmpTargetInformation *targets = AmpTargetTypes;
+
+ type = (AnjutaProjectTargetType)targets;
+ while (targets->base.name != NULL)
+ {
+ if (anjuta_token_get_type (start) == targets->token)
+ {
+ type = (AnjutaProjectTargetType)targets;
+ break;
+ }
+ targets++;
+ }
+
+ name = anjuta_token_get_value (start);
+ split_automake_variable (name, &flags, &install, NULL);
+ g_free (name);
+
+ amp_group_add_token (parent, start, AM_GROUP_TARGET);
+
+ arg = anjuta_token_next_sibling (start); /* Get variable data */
+ if (arg == NULL) return NULL;
+ if (anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) arg = anjuta_token_next_sibling (arg); /* Skip space */
+ if (arg == NULL) return NULL;
+ arg = anjuta_token_next_sibling (arg); /* Skip equal */
+ if (arg == NULL) return NULL;
+
+ for (arg = anjuta_token_next_child (arg); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ gchar *value;
+ gchar *canon_id;
+ AmpTarget *target;
+ GList *sources;
+ gchar *orig_key;
+ gpointer find;
+
+ if ((anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) || (anjuta_token_get_type (arg) == ANJUTA_TOKEN_COMMENT)) continue;
+
+ value = anjuta_token_evaluate (arg);
+ canon_id = canonicalize_automake_variable (value);
+
+ /* Check if target already exists */
+ find = value;
+ g_node_children_foreach (parent, G_TRAVERSE_ALL, find_target, &find);
+ if ((gchar *)find != value)
+ {
+ /* Find target */
+ g_free (canon_id);
+ g_free (value);
+ continue;
+ }
+
+ /* Create target */
+ target = amp_target_new (value, type, install, flags);
+ amp_target_add_token (target, arg);
+ g_node_append (parent, target);
+ DEBUG_PRINT ("create target %p name %s", target, value);
+
+ /* Check if there are source availables */
+ if (g_hash_table_lookup_extended (orphan_sources, canon_id, (gpointer *)&orig_key, (gpointer *)&sources))
+ {
+ GList *src;
+ g_hash_table_steal (orphan_sources, canon_id);
+ for (src = sources; src != NULL; src = g_list_next (src))
+ {
+ AmpSource *source = src->data;
+
+ g_node_prepend (target, source);
+ }
+ g_free (orig_key);
+ g_list_free (sources);
+ }
+
+ g_free (canon_id);
+ g_free (value);
+ }
+
+ return NULL;
+}
+
+static AnjutaToken*
+project_load_sources (AmpProject *project, AnjutaToken *start, GNode *parent, GHashTable *orphan_sources)
+{
+ AnjutaToken *arg;
+ AmpGroupData *group = AMP_GROUP_DATA (parent);
+ GFile *parent_file = g_object_ref (group->base.directory);
+ gchar *target_id = NULL;
+ GList *orphan = NULL;
+
+ target_id = anjuta_token_get_value (start);
+ if (target_id)
+ {
+ gchar *end = strrchr (target_id, '_');
+ if (end)
+ {
+ *end = '\0';
+ }
+ }
+
+ if (target_id)
+ {
+ gpointer find;
+
+ find = target_id;
+ DEBUG_PRINT ("search for canonical %s", target_id);
+ g_node_children_foreach (parent, G_TRAVERSE_ALL, find_canonical_target, &find);
+ parent = (gchar *)find != target_id ? (GNode *)find : NULL;
+
+ arg = anjuta_token_next_sibling (start); /* Get variable data */
+ if (arg == NULL) return NULL;
+ if (anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) arg = anjuta_token_next_sibling (arg); /* Skip space */
+ if (arg == NULL) return NULL;
+ arg = anjuta_token_next_sibling (arg); /* Skip equal */
+ if (arg == NULL) return NULL;
+
+ for (arg = anjuta_token_next_child (arg); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ gchar *value;
+ AmpSource *source;
+ GFile *src_file;
+
+ if ((anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) || (anjuta_token_get_type (arg) == ANJUTA_TOKEN_COMMENT)) continue;
+
+ value = anjuta_token_evaluate (arg);
+
+ /* Create source */
+ src_file = g_file_get_child (parent_file, value);
+ source = amp_source_new (src_file);
+ g_object_unref (src_file);
+ AMP_SOURCE_DATA(source)->token = arg;
+
+ if (parent == NULL)
+ {
+ /* Add in orphan list */
+ orphan = g_list_prepend (orphan, source);
+ }
+ else
+ {
+ DEBUG_PRINT ("add target child %p", parent);
+ /* Add as target child */
+ g_node_append (parent, source);
+ }
+
+ g_free (value);
+ }
+
+ if (parent == NULL)
+ {
+ gchar *orig_key;
+ GList *orig_sources;
+
+ if (g_hash_table_lookup_extended (orphan_sources, target_id, (gpointer *)&orig_key, (gpointer *)&orig_sources))
+ {
+ g_hash_table_steal (orphan_sources, target_id);
+ orphan = g_list_concat (orphan, orig_sources);
+ g_free (orig_key);
+ }
+ g_hash_table_insert (orphan_sources, target_id, orphan);
+ }
+ else
+ {
+ g_free (target_id);
+ }
+ }
+
+ g_object_unref (parent_file);
+
+ return NULL;
+}
+
+static AmpGroup* project_load_makefile (AmpProject *project, GFile *file, AmpGroup *parent, gboolean dist_only);
+
+static void
+project_load_subdirs (AmpProject *project, AnjutaToken *start, AmpGroup *parent, gboolean dist_only)
+{
+ AnjutaToken *arg;
+
+ arg = anjuta_token_next_sibling (start); /* Get variable data */
+ if (arg == NULL) return;
+ if (anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) arg = anjuta_token_next_sibling (arg); /* Skip space */
+ if (arg == NULL) return;
+ arg = anjuta_token_next_sibling (arg); /* Skip equal */
+ if (arg == NULL) return;
+
+ for (arg = anjuta_token_next_child (arg); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ gchar *value;
+
+ if ((anjuta_token_get_type (arg) == ANJUTA_TOKEN_SPACE) || (anjuta_token_get_type (arg) == ANJUTA_TOKEN_COMMENT)) continue;
+
+ value = anjuta_token_evaluate (arg);
+
+ /* Skip ., it is a special case, used to defined build order */
+ if (strcmp (value, ".") != 0)
+ {
+ GFile *subdir;
+ gchar *group_id;
+ AmpGroup *group;
+
+ subdir = g_file_resolve_relative_path (AMP_GROUP_DATA (parent)->base.directory, value);
+
+ /* Look for already existing group */
+ group_id = g_file_get_uri (subdir);
+ group = g_hash_table_lookup (project->groups, group_id);
+ g_free (group_id);
+
+ if (group != NULL)
+ {
+ /* Already existing group, mark for built if needed */
+ if (!dist_only) amp_group_set_dist_only (group, FALSE);
+ }
+ else
+ {
+ /* Create new group */
+ group = project_load_makefile (project, subdir, parent, dist_only);
+ }
+ amp_group_add_token (group, arg, dist_only ? AM_GROUP_TOKEN_DIST_SUBDIRS : AM_GROUP_TOKEN_SUBDIRS);
+ g_object_unref (subdir);
+ }
+ g_free (value);
+ }
+}
+
+static void
+free_source_list (GList *source_list)
+{
+ g_list_foreach (source_list, (GFunc)amp_source_free, NULL);
+ g_list_free (source_list);
+}
+
+static void
+remove_config_file (gpointer data, GObject *object, gboolean is_last_ref)
+{
+ if (is_last_ref)
+ {
+ AmpProject *project = (AmpProject *)data;
+ g_hash_table_remove (project->files, anjuta_token_file_get_file (ANJUTA_TOKEN_FILE (object)));
+ }
+}
+
+static AmpGroup*
+project_load_makefile (AmpProject *project, GFile *file, GNode *parent, gboolean dist_only)
+{
+ GHashTable *orphan_sources = NULL;
+ const gchar **filename;
+ AmpAmScanner *scanner;
+ AmpGroup *group;
+ AnjutaToken *significant_tok;
+ AnjutaToken *arg;
+ AnjutaTokenFile *tfile;
+ GFile *makefile = NULL;
+ gboolean found;
+
+ /* Create group */
+ group = amp_group_new (file, dist_only);
+ g_hash_table_insert (project->groups, g_file_get_uri (file), group);
+ if (parent == NULL)
+ {
+ project->root_node = group;
+ }
+ else
+ {
+ g_node_append (parent, group);
+ }
+
+ /* Find makefile name
+ * It has to be in the config_files list with .am extension */
+ for (filename = valid_am_makefiles; *filename != NULL; filename++)
+ {
+ makefile = g_file_get_child (file, *filename);
+ if (file_type (file, *filename) == G_FILE_TYPE_REGULAR)
+ {
+ gchar *final_filename = g_strdup (*filename);
+ gchar *ptr;
+ GFile *final_file;
+ AmpConfigFile *config;
+
+ ptr = g_strrstr (final_filename,".am");
+ if (ptr != NULL) *ptr = '\0';
+ final_file = g_file_get_child (file, final_filename);
+ g_free (final_filename);
+
+ config = g_hash_table_lookup (project->configs, final_file);
+ g_object_unref (final_file);
+ if (config != NULL)
+ {
+ amp_group_add_token (group, config->token, AM_GROUP_TOKEN_CONFIGURE);
+ break;
+ }
+ }
+ g_object_unref (makefile);
+ }
+
+ if (*filename == NULL)
+ {
+ /* Unable to find automake file */
+ return group;
+ }
+
+ /* Parse makefile.am */
+ DEBUG_PRINT ("Parse: %s", g_file_get_uri (makefile));
+ tfile = amp_group_set_makefile (group, makefile);
+ g_hash_table_insert (project->files, makefile, tfile);
+ g_object_add_toggle_ref (G_OBJECT (tfile), remove_config_file, project);
+ scanner = amp_am_scanner_new ();
+ amp_am_scanner_parse (scanner, tfile, NULL);
+ amp_am_scanner_free (scanner);
+
+ /* Find significant token */
+ significant_tok = anjuta_token_new_static (ANJUTA_TOKEN_STATEMENT, NULL);
+
+ arg = anjuta_token_file_first (AMP_GROUP_DATA (group)->tfile);
+ //anjuta_token_old_dump_range (arg, NULL);
+
+ /* Create hash table for sources list */
+ orphan_sources = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)free_source_list);
+
+ for (found = anjuta_token_match (significant_tok, ANJUTA_SEARCH_INTO, arg, &arg); found; found = anjuta_token_match (significant_tok, ANJUTA_SEARCH_INTO, anjuta_token_next_sibling (arg), &arg))
+ {
+ AnjutaToken *name = anjuta_token_next_child (arg);
+
+ switch (anjuta_token_get_type (name))
+ {
+ case AM_TOKEN_SUBDIRS:
+ project_load_subdirs (project, name, group, FALSE);
+ break;
+ case AM_TOKEN_DIST_SUBDIRS:
+ project_load_subdirs (project, name, group, TRUE);
+ break;
+ case AM_TOKEN__DATA:
+ case AM_TOKEN__HEADERS:
+ case AM_TOKEN__LIBRARIES:
+ case AM_TOKEN__LISP:
+ case AM_TOKEN__LTLIBRARIES:
+ case AM_TOKEN__MANS:
+ case AM_TOKEN__PROGRAMS:
+ case AM_TOKEN__PYTHON:
+ case AM_TOKEN__JAVA:
+ case AM_TOKEN__SCRIPTS:
+ case AM_TOKEN__TEXINFOS:
+ project_load_target (project, name, group, orphan_sources);
+ break;
+ case AM_TOKEN__SOURCES:
+ project_load_sources (project, name, group, orphan_sources);
+ break;
+ }
+ }
+
+ /* Free unused sources files */
+ g_hash_table_destroy (orphan_sources);
+
+ return group;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+amp_project_reload (AmpProject *project, GError **error)
+{
+ AmpAcScanner *scanner;
+ GFile *root_file;
+ GFile *configure_file;
+ gboolean ok;
+ GError *err = NULL;
+
+ /* Unload current project */
+ root_file = g_object_ref (project->root_file);
+ amp_project_unload (project);
+ project->root_file = root_file;
+ DEBUG_PRINT ("reload project %p root file %p", project, project->root_file);
+
+ /* shortcut hash tables */
+ project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
+ project->configs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, amp_config_file_free);
+
+ /* Initialize list styles */
+ project->space_list = anjuta_token_style_new (NULL, " ", "\\n", NULL, 0);
+ project->arg_list = anjuta_token_style_new (NULL, ", ", ",\\n ", ")", 0);
+
+ /* Find configure file */
+ if (file_type (root_file, "configure.ac") == G_FILE_TYPE_REGULAR)
+ {
+ configure_file = g_file_get_child (root_file, "configure.ac");
+ }
+ else if (file_type (root_file, "configure.in") == G_FILE_TYPE_REGULAR)
+ {
+ configure_file = g_file_get_child (root_file, "configure.in");
+ }
+ else
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Project doesn't exist or invalid path"));
+
+ return FALSE;
+ }
+
+ /* Parse configure */
+ project->configure_file = anjuta_token_file_new (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);
+ scanner = amp_ac_scanner_new ();
+ ok = amp_ac_scanner_parse (scanner, project->configure_file, &err);
+ amp_ac_scanner_free (scanner);
+ if (!ok)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED,
+ err == NULL ? _("Unable to parse project file") : err->message);
+ if (err != NULL) g_error_free (err);
+
+ return FALSE;
+ }
+
+ monitors_setup (project);
+
+ project_reload_property (project);
+
+ amp_project_new_module_hash (project);
+ project_reload_packages (project);
+
+ /* Load all makefiles recursively */
+ project_list_config_files (project);
+ if (project_load_makefile (project, project->root_file, NULL, FALSE) == NULL)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Project doesn't exist or invalid path"));
+
+ ok = FALSE;
+ }
+
+ return ok;
+}
+
+gboolean
+amp_project_load (AmpProject *project,
+ GFile *directory,
+ GError **error)
+{
+ g_return_val_if_fail (directory != NULL, FALSE);
+
+ project->root_file = g_object_ref (directory);
+ if (!amp_project_reload (project, error))
+ {
+ g_object_unref (project->root_file);
+ project->root_file = NULL;
+ }
+
+ return project->root_file != NULL;
+}
+
+void
+amp_project_unload (AmpProject *project)
+{
+ monitors_remove (project);
+
+ /* project data */
+ project_node_destroy (project, project->root_node);
+ project->root_node = NULL;
+
+ if (project->configure_file) g_object_unref (G_OBJECT (project->configure_file));
+ project->configure_file = NULL;
+
+ if (project->root_file) g_object_unref (project->root_file);
+ project->root_file = NULL;
+
+ if (project->property) amp_property_free (project->property);
+ project->property = NULL;
+
+ /* shortcut hash tables */
+ if (project->groups) g_hash_table_destroy (project->groups);
+ if (project->files) g_hash_table_destroy (project->files);
+ if (project->configs) g_hash_table_destroy (project->configs);
+ project->groups = NULL;
+ project->files = NULL;
+ project->configs = NULL;
+
+ /* List styles */
+ if (project->space_list) anjuta_token_style_free (project->space_list);
+ if (project->arg_list) anjuta_token_style_free (project->arg_list);
+
+ amp_project_free_module_hash (project);
+}
+
+gint
+amp_project_probe (GFile *file,
+ GError **error)
+{
+ gint probe;
+ gboolean dir;
+
+ dir = (file_type (file, NULL) == G_FILE_TYPE_DIRECTORY);
+ if (!dir)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Project doesn't exist or invalid path"));
+ }
+
+ probe = dir;
+ if (probe)
+ {
+ const gchar **makefile;
+
+ /* Look for makefiles */
+ probe = FALSE;
+ for (makefile = valid_am_makefiles; *makefile != NULL; makefile++)
+ {
+ if (file_type (file, *makefile) == G_FILE_TYPE_REGULAR)
+ {
+ probe = TRUE;
+ break;
+ }
+ }
+
+ if (probe)
+ {
+ probe = ((file_type (file, "configure.ac") == G_FILE_TYPE_REGULAR) ||
+ (file_type (file, "configure.in") == G_FILE_TYPE_REGULAR));
+ }
+ }
+
+ return probe ? IANJUTA_PROJECT_PROBE_PROJECT_FILES : 0;
+}
+
+AmpGroup*
+amp_project_add_group (AmpProject *project,
+ AmpGroup *parent,
+ const gchar *name,
+ GError **error)
+{
+ AmpGroup *last;
+ AmpGroup *child;
+ GFile *directory;
+ GFile *makefile;
+ AnjutaToken* token;
+ AnjutaToken* prev_token;
+ GList *token_list;
+ gchar *basename;
+ gchar *uri;
+ AnjutaTokenFile* tfile;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (parent != NULL, NULL);
+
+ /* Validate group name */
+ if (!name || strlen (name) <= 0)
+ {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Please specify group name"));
+ return NULL;
+ }
+ {
+ gboolean failed = FALSE;
+ const gchar *ptr = name;
+ while (*ptr) {
+ if (!isalnum (*ptr) && *ptr != '.' && *ptr != '-' &&
+ *ptr != '_')
+ failed = TRUE;
+ ptr++;
+ }
+ if (failed) {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Group name can only contain alphanumeric, '_', '-' or '.' characters"));
+ return NULL;
+ }
+ }
+
+ /* Check that the new group doesn't already exist */
+ directory = g_file_get_child (AMP_GROUP_DATA (parent)->base.directory, name);
+ uri = g_file_get_uri (directory);
+ if (g_hash_table_lookup (project->groups, uri) != NULL)
+ {
+ g_free (uri);
+ error_set (error, IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Group already exists"));
+ return NULL;
+ }
+
+ /* Add group node in project tree */
+ child = amp_group_new (directory, FALSE);
+ g_hash_table_insert (project->groups, uri, child);
+ g_object_unref (directory);
+ g_node_append (parent, child);
+
+ /* Create directory */
+ g_file_make_directory (directory, NULL, NULL);
+
+ /* Create Makefile.am */
+ basename = g_file_get_basename (AMP_GROUP_DATA (parent)->makefile);
+ if (basename != NULL)
+ {
+ makefile = g_file_get_child (directory, basename);
+ g_free (basename);
+ }
+ else
+ {
+ makefile = g_file_get_child (directory, "Makefile.am");
+ }
+ g_file_replace_contents (makefile, "", 0, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
+ tfile = amp_group_set_makefile (child, makefile);
+ g_hash_table_insert (project->files, makefile, tfile);
+ g_object_add_toggle_ref (G_OBJECT (tfile), remove_config_file, project);
+
+ /* Add in configure */
+ token_list= amp_group_get_token (parent, AM_GROUP_TOKEN_CONFIGURE);
+ if (token_list != NULL)
+ {
+ gchar *relative_make;
+ gchar *ext;
+ AnjutaTokenStyle *style;
+
+ prev_token = (AnjutaToken *)token_list->data;
+
+ relative_make = g_file_get_relative_path (project->root_file, makefile);
+ ext = relative_make + strlen (relative_make) - 3;
+ if (strcmp (ext, ".am") == 0)
+ {
+ *ext = '\0';
+ }
+ token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, relative_make);
+ g_free (relative_make);
+
+ style = anjuta_token_style_new (NULL," ","\\n",NULL,0);
+ add_list_item (prev_token, token, style);
+ anjuta_token_style_free (style);
+ }
+
+ /* Add in Makefile.am */
+ for (last = g_node_prev_sibling (child); (last != NULL) && (AMP_NODE_DATA (last)->type != ANJUTA_PROJECT_GROUP); last = g_node_prev_sibling (last));
+ if (last == NULL)
+ {
+ AnjutaToken *prev_token;
+ gint space = 0;
+ AnjutaToken *list;
+
+ /* Skip comment and one space at the beginning */
+ for (prev_token = anjuta_token_next_child (anjuta_token_file_first (AMP_GROUP_DATA (parent)->tfile)); prev_token != NULL; prev_token = anjuta_token_next_sibling (prev_token))
+ {
+ switch (anjuta_token_get_type (prev_token))
+ {
+ case ANJUTA_TOKEN_COMMENT:
+ space = 0;
+ continue;
+ case ANJUTA_TOKEN_SPACE:
+ if (space == 0)
+ {
+ space = 1;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (prev_token == NULL)
+ {
+ prev_token = anjuta_token_next_child (anjuta_token_file_first (AMP_GROUP_DATA (parent)->tfile));
+ if (prev_token)
+ {
+ prev_token = anjuta_token_file_last (AMP_GROUP_DATA (parent)->tfile);
+ }
+ }
+
+ token = anjuta_token_new_static (ANJUTA_TOKEN_STATEMENT | ANJUTA_TOKEN_ADDED, NULL);
+ if (prev_token == NULL)
+ {
+ prev_token = anjuta_token_insert_child (anjuta_token_file_first (AMP_GROUP_DATA (parent)->tfile), token);
+ }
+ else
+ {
+ prev_token = anjuta_token_insert_after (prev_token, token);
+ }
+ list = prev_token;
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (AM_TOKEN_SUBDIRS | ANJUTA_TOKEN_ADDED, "SUBDIRS"));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_OPERATOR | ANJUTA_TOKEN_ADDED, "="));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_static (ANJUTA_TOKEN_LIST, NULL));
+ token = prev_token;
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name));
+ anjuta_token_merge (token, prev_token);
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, "\n"));
+ anjuta_token_merge (list, prev_token);
+ }
+ else
+ {
+ token_list = amp_group_get_token (parent, AM_GROUP_TOKEN_SUBDIRS);
+ if (token_list != NULL)
+ {
+ prev_token = (AnjutaToken *)token_list->data;
+
+ token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
+ add_list_item (prev_token, token, NULL);
+ }
+ }
+ amp_group_add_token (child, token, AM_GROUP_TOKEN_SUBDIRS);
+
+ return child;
+}
+
+void
+amp_project_remove_group (AmpProject *project,
+ AmpGroup *group,
+ GError **error)
+{
+ GList *token_list;
+
+ if (AMP_NODE_DATA (group)->type != ANJUTA_PROJECT_GROUP) return;
+
+ for (token_list = amp_group_get_token (group, AM_GROUP_TOKEN_CONFIGURE); token_list != NULL; token_list = g_list_next (token_list))
+ {
+ remove_list_item ((AnjutaToken *)token_list->data, NULL);
+ }
+ for (token_list = amp_group_get_token (group, AM_GROUP_TOKEN_SUBDIRS); token_list != NULL; token_list = g_list_next (token_list))
+ {
+ remove_list_item ((AnjutaToken *)token_list->data, NULL);
+ }
+ for (token_list = amp_group_get_token (group, AM_GROUP_TOKEN_DIST_SUBDIRS); token_list != NULL; token_list = g_list_next (token_list))
+ {
+ remove_list_item ((AnjutaToken *)token_list->data, NULL);
+ }
+
+ amp_group_free (group);
+}
+
+AmpTarget*
+amp_project_add_target (AmpProject *project,
+ AmpGroup *parent,
+ const gchar *name,
+ AnjutaProjectTargetType type,
+ GError **error)
+{
+ AmpTarget *child;
+ AnjutaToken* token;
+ AnjutaToken* prev_token;
+ AnjutaToken *list;
+ gchar *targetname;
+ gchar *find;
+ GList *last;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (parent != NULL, NULL);
+
+ /* Validate target name */
+ if (!name || strlen (name) <= 0)
+ {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Please specify target name"));
+ return NULL;
+ }
+ {
+ gboolean failed = FALSE;
+ const gchar *ptr = name;
+ while (*ptr) {
+ if (!isalnum (*ptr) && *ptr != '.' && *ptr != '-' &&
+ *ptr != '_')
+ failed = TRUE;
+ ptr++;
+ }
+ if (failed) {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Target name can only contain alphanumeric, '_', '-' or '.' characters"));
+ return NULL;
+ }
+ }
+ if (type->base == ANJUTA_TARGET_SHAREDLIB) {
+ if (strlen (name) < 7 ||
+ strncmp (name, "lib", strlen("lib")) != 0 ||
+ strcmp (&name[strlen(name) - 3], ".la") != 0) {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Shared library target name must be of the form 'libxxx.la'"));
+ return NULL;
+ }
+ }
+ else if (type->base == ANJUTA_TARGET_STATICLIB) {
+ if (strlen (name) < 6 ||
+ strncmp (name, "lib", strlen("lib")) != 0 ||
+ strcmp (&name[strlen(name) - 2], ".a") != 0) {
+ error_set (error, IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+ _("Static library target name must be of the form 'libxxx.a'"));
+ return NULL;
+ }
+ }
+
+ /* Check that the new target doesn't already exist */
+ find = (gchar *)name;
+ g_node_children_foreach (parent, G_TRAVERSE_ALL, find_target, &find);
+ if ((gchar *)find != name)
+ {
+ error_set (error, IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Target already exists"));
+
+ return NULL;
+ }
+
+ /* Add target node in project tree */
+ child = amp_target_new (name, type, "", 0);
+ g_node_append (parent, child);
+
+ /* Add in Makefile.am */
+ targetname = g_strconcat (((AmpTargetInformation *)type)->install, ((AmpTargetInformation *)type)->prefix, NULL);
+
+ for (last = amp_group_get_token (parent, AM_GROUP_TARGET); last != NULL; last = g_list_next (last))
+ {
+ gchar *value = anjuta_token_evaluate ((AnjutaToken *)last->data);
+
+ if ((value != NULL) && (strcmp (targetname, value) == 0))
+ {
+ g_free (value);
+ break;
+ }
+ g_free (value);
+ }
+
+ token = anjuta_token_new_string (((AmpTargetInformation *)type)->token, targetname);
+ g_free (targetname);
+
+ if (last == NULL)
+ {
+ prev_token = anjuta_token_next_child (anjuta_token_file_first (AMP_GROUP_DATA (parent)->tfile));
+ if (prev_token != NULL)
+ {
+ /* Add at the end of the file */
+ while (anjuta_token_next_sibling (prev_token) != NULL)
+ {
+ prev_token = anjuta_token_next_sibling (prev_token);
+ }
+ }
+
+ list = anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, "\n");
+ if (prev_token == NULL)
+ {
+ prev_token = anjuta_token_insert_child (anjuta_token_file_first (AMP_GROUP_DATA (parent)->tfile), list);
+ }
+ else
+ {
+ prev_token = anjuta_token_insert_after (prev_token, list);
+ }
+
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_static (ANJUTA_TOKEN_STATEMENT | ANJUTA_TOKEN_ADDED, NULL));
+ list = prev_token;
+ prev_token = anjuta_token_insert_after (prev_token, token);
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_OPERATOR | ANJUTA_TOKEN_ADDED, "="));
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_static (ANJUTA_TOKEN_LIST, NULL));
+ token = prev_token;
+ prev_token = anjuta_token_insert_after (prev_token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ anjuta_token_merge (token, prev_token);
+ anjuta_token_merge (list, token);
+ anjuta_token_insert_after (token, anjuta_token_new_string (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, "\n"));
+ token = prev_token;
+ }
+ else
+ {
+ for (token = (AnjutaToken *)last->data; anjuta_token_get_type (token) != ANJUTA_TOKEN_LIST; token = anjuta_token_next_sibling (token));
+
+ if (anjuta_token_next_child (token) == NULL)
+ {
+ token = anjuta_token_insert_child (token, anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ }
+ else
+ {
+ token = anjuta_token_next_child (token);
+ }
+
+ for (; anjuta_token_next_sibling (token) != NULL; token = anjuta_token_next_sibling (token));
+ }
+
+ if (anjuta_token_get_type (token) != ANJUTA_TOKEN_SPACE)
+ {
+ token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ }
+ token = anjuta_token_insert_after (token, anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name));
+ amp_target_add_token (child, token);
+
+ return child;
+}
+
+void
+amp_project_remove_target (AmpProject *project,
+ AmpTarget *target,
+ GError **error)
+{
+ GList *token_list;
+
+ if (AMP_NODE_DATA (target)->type != ANJUTA_PROJECT_TARGET) return;
+
+ for (token_list = amp_target_get_token (target); token_list != NULL; token_list = g_list_next (token_list))
+ {
+ anjuta_token_remove ((AnjutaToken *)token_list->data);
+ }
+
+ amp_target_free (target);
+}
+
+AmpSource*
+amp_project_add_source (AmpProject *project,
+ AmpTarget *target,
+ GFile *file,
+ GError **error)
+{
+ AmpGroup *group;
+ AmpSource *last;
+ AmpSource *source;
+ AnjutaToken* token;
+ gchar *relative_name;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (target != NULL, NULL);
+
+ if (AMP_NODE_DATA (target)->type != ANJUTA_PROJECT_TARGET) return NULL;
+
+ group = (AmpGroup *)(target->parent);
+ relative_name = g_file_get_relative_path (AMP_GROUP_DATA (group)->base.directory, file);
+
+ /* Add token */
+ last = g_node_last_child (target);
+ if (last == NULL)
+ {
+ /* First child */
+ AnjutaToken *tok;
+ AnjutaToken *close_tok;
+ AnjutaToken *eol_tok;
+ gchar *target_var;
+ gchar *canon_name;
+
+ /* Search where the target is declared */
+ tok = (AnjutaToken *)amp_target_get_token (target)->data;
+ close_tok = anjuta_token_new_static (ANJUTA_TOKEN_CLOSE, NULL);
+ eol_tok = anjuta_token_new_static (ANJUTA_TOKEN_EOL, NULL);
+ //anjuta_token_match (close_tok, ANJUTA_SEARCH_OVER, tok, &tok);
+ anjuta_token_match (eol_tok, ANJUTA_SEARCH_OVER, tok, &tok);
+ anjuta_token_free (close_tok);
+ anjuta_token_free (eol_tok);
+
+ /* Add a _SOURCES variable just after */
+ canon_name = canonicalize_automake_variable (AMP_TARGET_DATA (target)->base.name);
+ target_var = g_strconcat (canon_name, "_SOURCES", NULL);
+ g_free (canon_name);
+ tok = anjuta_token_insert_after (tok, anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, target_var));
+ g_free (target_var);
+ tok = anjuta_token_insert_after (tok, anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ tok = anjuta_token_insert_after (tok, anjuta_token_new_static (ANJUTA_TOKEN_OPERATOR | ANJUTA_TOKEN_ADDED, "="));
+ tok = anjuta_token_insert_after (tok, anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " "));
+ token = anjuta_token_new_static (ANJUTA_TOKEN_SPACE | ANJUTA_TOKEN_ADDED, " ");
+ tok = anjuta_token_insert_after (tok, token);
+ token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, relative_name);
+ tok = anjuta_token_insert_after (tok, token);
+ tok = anjuta_token_insert_after (tok, anjuta_token_new_static (ANJUTA_TOKEN_EOL | ANJUTA_TOKEN_ADDED, "\n"));
+ }
+ else
+ {
+ token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, relative_name);
+ add_list_item (AMP_SOURCE_DATA (last)->token, token, NULL);
+ }
+ g_free (relative_name);
+
+ /* Add source node in project tree */
+ source = amp_source_new (file);
+ AMP_SOURCE_DATA(source)->token = token;
+ g_node_append (target, source);
+
+ return source;
+}
+
+void
+amp_project_remove_source (AmpProject *project,
+ AmpSource *source,
+ GError **error)
+{
+ amp_dump_node (source);
+ if (AMP_NODE_DATA (source)->type != ANJUTA_PROJECT_SOURCE) return;
+
+ remove_list_item (AMP_SOURCE_DATA (source)->token, NULL);
+
+ amp_source_free (source);
+}
+
+GList *
+amp_project_get_config_modules (AmpProject *project, GError **error)
+{
+ return project->modules == NULL ? NULL : g_hash_table_get_keys (project->modules);
+}
+
+GList *
+amp_project_get_config_packages (AmpProject *project,
+ const gchar* module,
+ GError **error)
+{
+ AmpModule *mod;
+ GList *packages = NULL;
+
+ g_return_val_if_fail (project != NULL, NULL);
+ g_return_val_if_fail (module != NULL, NULL);
+
+ mod = g_hash_table_lookup (project->modules, module);
+
+ if (mod != NULL)
+ {
+ GList *node;
+
+ for (node = mod->packages; node != NULL; node = g_list_next (node))
+ {
+ packages = g_list_prepend (packages, ((AmpPackage *)node->data)->name);
+ }
+
+ packages = g_list_reverse (packages);
+ }
+
+ return packages;
+}
+
+GList *
+amp_project_get_target_types (AmpProject *project, GError **error)
+{
+ AmpTargetInformation *targets = AmpTargetTypes;
+ GList *types = NULL;
+
+ while (targets->base.name != NULL)
+ {
+ types = g_list_prepend (types, targets);
+ targets++;
+ }
+ types = g_list_reverse (types);
+
+ return types;
+}
+
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+amp_project_save (AmpProject *project, GError **error)
+{
+ gpointer key;
+ gpointer value;
+ GHashTableIter iter;
+
+ g_return_val_if_fail (project != NULL, FALSE);
+
+ g_hash_table_iter_init (&iter, project->files);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GError *error = NULL;
+ AnjutaTokenFile *tfile = (AnjutaTokenFile *)value;
+ ;
+ anjuta_token_file_save (tfile, &error);
+ }
+
+ return TRUE;
+}
+
+gboolean
+amp_project_move (AmpProject *project, const gchar *path)
+{
+ GFile *old_root_file;
+ GFile *new_file;
+ gchar *relative;
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ AnjutaTokenFile *tfile;
+ AmpConfigFile *cfg;
+ GHashTable* old_hash;
+
+ /* Change project root directory */
+ old_root_file = project->root_file;
+ project->root_file = g_file_new_for_path (path);
+
+ /* Change project root directory in groups */
+ old_hash = project->groups;
+ project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_hash_table_iter_init (&iter, old_hash);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ AmpGroup *group = (AmpGroup *)value;
+
+ relative = get_relative_path (old_root_file, AMP_GROUP_DATA (group)->base.directory);
+ new_file = g_file_resolve_relative_path (project->root_file, relative);
+ g_free (relative);
+ g_object_unref (AMP_GROUP_DATA (group)->base.directory);
+ AMP_GROUP_DATA (group)->base.directory = new_file;
+
+ g_hash_table_insert (project->groups, g_file_get_uri (new_file), group);
+ }
+ g_hash_table_destroy (old_hash);
+
+ /* Change all files */
+ old_hash = project->files;
+ project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
+ g_hash_table_iter_init (&iter, old_hash);
+ while (g_hash_table_iter_next (&iter, &key, (gpointer *)&tfile))
+ {
+ relative = get_relative_path (old_root_file, anjuta_token_file_get_file (tfile));
+ new_file = g_file_resolve_relative_path (project->root_file, relative);
+ g_free (relative);
+ anjuta_token_file_move (tfile, new_file);
+
+ g_hash_table_insert (project->files, new_file, tfile);
+ g_object_unref (key);
+ }
+ g_hash_table_steal_all (old_hash);
+ g_hash_table_destroy (old_hash);
+
+ /* Change all configs */
+ old_hash = project->configs;
+ project->configs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, amp_config_file_free);
+ g_hash_table_iter_init (&iter, old_hash);
+ while (g_hash_table_iter_next (&iter, &key, (gpointer *)&cfg))
+ {
+ relative = get_relative_path (old_root_file, cfg->file);
+ new_file = g_file_resolve_relative_path (project->root_file, relative);
+ g_free (relative);
+ g_object_unref (cfg->file);
+ cfg->file = new_file;
+
+ g_hash_table_insert (project->configs, new_file, cfg);
+ }
+ g_hash_table_steal_all (old_hash);
+ g_hash_table_destroy (old_hash);
+
+
+ g_object_unref (old_root_file);
+
+ return TRUE;
+}
+
+AmpProject *
+amp_project_new (void)
+{
+ return AMP_PROJECT (g_object_new (AMP_TYPE_PROJECT, NULL));
+}
+
+/* Project access functions
+ *---------------------------------------------------------------------------*/
+
+AmpGroup *
+amp_project_get_root (AmpProject *project)
+{
+ AmpGroup *g_node = NULL;
+
+ if (project->root_file != NULL)
+ {
+ gchar *id = g_file_get_uri (project->root_file);
+ g_node = (AmpGroup *)g_hash_table_lookup (project->groups, id);
+ g_free (id);
+ }
+
+ return g_node;
+}
+
+AmpGroup *
+amp_project_get_group (AmpProject *project, const gchar *id)
+{
+ return (AmpGroup *)g_hash_table_lookup (project->groups, id);
+}
+
+AmpTarget *
+amp_project_get_target (AmpProject *project, const gchar *id)
+{
+ AmpTarget **buffer;
+ AmpTarget *target;
+ gsize dummy;
+
+ buffer = (AmpTarget **)g_base64_decode (id, &dummy);
+ target = *buffer;
+ g_free (buffer);
+
+ return target;
+}
+
+AmpSource *
+amp_project_get_source (AmpProject *project, const gchar *id)
+{
+ AmpSource **buffer;
+ AmpSource *source;
+ gsize dummy;
+
+ buffer = (AmpSource **)g_base64_decode (id, &dummy);
+ source = *buffer;
+ g_free (buffer);
+
+ return source;
+}
+
+gchar *
+amp_project_get_node_id (AmpProject *project, const gchar *path)
+{
+ GNode *node = NULL;
+
+ if (path != NULL)
+ {
+ for (; *path != '\0';)
+ {
+ gchar *end;
+ guint child = g_ascii_strtoull (path, &end, 10);
+
+ if (end == path)
+ {
+ /* error */
+ return NULL;
+ }
+
+ if (node == NULL)
+ {
+ if (child == 0) node = project->root_node;
+ }
+ else
+ {
+ node = g_node_nth_child (node, child);
+ }
+ if (node == NULL)
+ {
+ /* no node */
+ return NULL;
+ }
+
+ if (*end == '\0') break;
+ path = end + 1;
+ }
+ }
+
+ switch (AMP_NODE_DATA (node)->type)
+ {
+ case ANJUTA_PROJECT_GROUP:
+ return g_file_get_uri (AMP_GROUP_DATA (node)->base.directory);
+ case ANJUTA_PROJECT_TARGET:
+ case ANJUTA_PROJECT_SOURCE:
+ return g_base64_encode ((guchar *)&node, sizeof (node));
+ default:
+ return NULL;
+ }
+}
+
+gchar *
+amp_project_get_uri (AmpProject *project)
+{
+ g_return_val_if_fail (project != NULL, NULL);
+
+ return project->root_file != NULL ? g_file_get_uri (project->root_file) : NULL;
+}
+
+GFile*
+amp_project_get_file (AmpProject *project)
+{
+ g_return_val_if_fail (project != NULL, NULL);
+
+ return project->root_file;
+}
+
+gchar *
+amp_project_get_property (AmpProject *project, AmpPropertyType type)
+{
+ const gchar *value = NULL;
+
+ if (project->property != NULL)
+ {
+ switch (type)
+ {
+ case AMP_PROPERTY_NAME:
+ value = project->property->name;
+ break;
+ case AMP_PROPERTY_VERSION:
+ value = project->property->version;
+ break;
+ case AMP_PROPERTY_BUG_REPORT:
+ value = project->property->bug_report;
+ break;
+ case AMP_PROPERTY_TARNAME:
+ value = project->property->tarname;
+ if (value == NULL) return ac_init_default_tarname (project->property->name);
+ break;
+ case AMP_PROPERTY_URL:
+ value = project->property->url;
+ break;
+ }
+ }
+
+ return value == NULL ? NULL : g_strdup (value);
+}
+
+gboolean
+amp_project_set_property (AmpProject *project, AmpPropertyType type, const gchar *value)
+{
+ if (project->property != NULL)
+ {
+ switch (type)
+ {
+ case AMP_PROPERTY_NAME:
+ project->property->name = g_strdup (value);
+ break;
+ case AMP_PROPERTY_VERSION:
+ project->property->version = g_strdup (value);
+ break;
+ case AMP_PROPERTY_BUG_REPORT:
+ project->property->bug_report = g_strdup (value);
+ break;
+ case AMP_PROPERTY_TARNAME:
+ project->property->tarname = g_strdup (value);
+ break;
+ case AMP_PROPERTY_URL:
+ project->property->url = g_strdup (value);
+ break;
+ }
+ return amp_project_update_property (project, type);
+ }
+
+ return TRUE;
+}
+
+/* Implement IAnjutaProject
+ *---------------------------------------------------------------------------*/
+
+static AnjutaProjectGroup*
+iproject_add_group (IAnjutaProject *obj, AnjutaProjectGroup *parent, const gchar *name, GError **err)
+{
+ return amp_project_add_group (AMP_PROJECT (obj), AMP_GROUP (parent), name, err);
+}
+
+static AnjutaProjectSource*
+iproject_add_source (IAnjutaProject *obj, AnjutaProjectGroup *parent, GFile *file, GError **err)
+{
+ return amp_project_add_source (AMP_PROJECT (obj), AMP_TARGET (parent), file, err);
+}
+
+static AnjutaProjectTarget*
+iproject_add_target (IAnjutaProject *obj, AnjutaProjectGroup *parent, const gchar *name, AnjutaProjectTargetType type, GError **err)
+{
+ return amp_project_add_target (AMP_PROJECT (obj), AMP_GROUP (parent), name, type, err);
+}
+
+static GtkWidget*
+iproject_configure (IAnjutaProject *obj, GError **err)
+{
+ return amp_configure_project_dialog (AMP_PROJECT (obj), err);
+}
+
+static guint
+iproject_get_capabilities (IAnjutaProject *obj, GError **err)
+{
+ return (IANJUTA_PROJECT_CAN_ADD_GROUP |
+ IANJUTA_PROJECT_CAN_ADD_TARGET |
+ IANJUTA_PROJECT_CAN_ADD_SOURCE);
+}
+
+static GList*
+iproject_get_packages (IAnjutaProject *obj, GError **err)
+{
+ GList *modules;
+ GList *packages;
+ GList* node;
+ GHashTable *all = g_hash_table_new (g_str_hash, g_str_equal);
+
+ modules = amp_project_get_config_modules (AMP_PROJECT (obj), NULL);
+ for (node = modules; node != NULL; node = g_list_next (node))
+ {
+ GList *pack;
+
+ packages = amp_project_get_config_packages (AMP_PROJECT (obj), (const gchar *)node->data, NULL);
+ for (pack = packages; pack != NULL; pack = g_list_next (pack))
+ {
+ g_hash_table_replace (all, pack->data, NULL);
+ }
+ g_list_free (packages);
+ }
+ g_list_free (modules);
+
+ packages = g_hash_table_get_keys (all);
+ g_hash_table_destroy (all);
+
+ return packages;
+}
+
+static AnjutaProjectGroup*
+iproject_get_root (IAnjutaProject *obj, GError **err)
+{
+ return amp_project_get_root (AMP_PROJECT (obj));
+}
+
+static GList*
+iproject_get_target_types (IAnjutaProject *obj, GError **err)
+{
+ return amp_project_get_target_types (AMP_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_load (IAnjutaProject *obj, GFile *file, GError **err)
+{
+ return amp_project_load (AMP_PROJECT (obj), file, err);
+}
+
+static gboolean
+iproject_refresh (IAnjutaProject *obj, GError **err)
+{
+ return amp_project_reload (AMP_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_remove_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+{
+ return TRUE;
+}
+
+static void
+iproject_iface_init(IAnjutaProjectIface* iface)
+{
+ iface->add_group = iproject_add_group;
+ iface->add_source = iproject_add_source;
+ iface->add_target = iproject_add_target;
+ iface->configure = iproject_configure;
+ iface->get_capabilities = iproject_get_capabilities;
+ iface->get_packages = iproject_get_packages;
+ iface->get_root = iproject_get_root;
+ iface->get_target_types = iproject_get_target_types;
+ iface->load = iproject_load;
+ iface->refresh = iproject_refresh;
+ iface->remove_node = iproject_remove_node;
+}
+
+/* Group access functions
+ *---------------------------------------------------------------------------*/
+
+GFile*
+amp_group_get_directory (AmpGroup *group)
+{
+ return AMP_GROUP_DATA (group)->base.directory;
+}
+
+GFile*
+amp_group_get_makefile (AmpGroup *group)
+{
+ return AMP_GROUP_DATA (group)->makefile;
+}
+
+gchar *
+amp_group_get_id (AmpGroup *group)
+{
+ return g_file_get_uri (AMP_GROUP_DATA (group)->base.directory);
+}
+
+/* Target access functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+amp_target_get_name (AmpTarget *target)
+{
+ return AMP_TARGET_DATA (target)->base.name;
+}
+
+AnjutaProjectTargetType
+amp_target_get_type (AmpTarget *target)
+{
+ return AMP_TARGET_DATA (target)->base.type;
+}
+
+gchar *
+amp_target_get_id (AmpTarget *target)
+{
+ return g_base64_encode ((guchar *)&target, sizeof (target));
+}
+
+/* Source access functions
+ *---------------------------------------------------------------------------*/
+
+gchar *
+amp_source_get_id (AmpSource *source)
+{
+ return g_base64_encode ((guchar *)&source, sizeof (source));
+}
+
+GFile*
+amp_source_get_file (AmpSource *source)
+{
+ return AMP_SOURCE_DATA (source)->base.file;
+}
+
+/* GbfProject implementation
+ *---------------------------------------------------------------------------*/
+
+static void
+amp_project_dispose (GObject *object)
+{
+ g_return_if_fail (AMP_IS_PROJECT (object));
+
+ amp_project_unload (AMP_PROJECT (object));
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+amp_project_instance_init (AmpProject *project)
+{
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (AMP_IS_PROJECT (project));
+
+ /* project data */
+ project->root_file = NULL;
+ project->configure_file = NULL;
+ project->root_node = NULL;
+ project->property = NULL;
+
+ project->space_list = NULL;
+ project->arg_list = NULL;
+}
+
+static void
+amp_project_class_init (AmpProjectClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = amp_project_dispose;
+}
+
+ANJUTA_TYPE_BEGIN(AmpProject, amp_project, G_TYPE_OBJECT);
+ANJUTA_TYPE_ADD_INTERFACE(iproject, IANJUTA_TYPE_PROJECT);
+ANJUTA_TYPE_END;
+//GBF_BACKEND_BOILERPLATE (AmpProject, amp_project);
diff --git a/plugins/am-project/am-project.h b/plugins/am-project/am-project.h
new file mode 100644
index 0000000..9298272
--- /dev/null
+++ b/plugins/am-project/am-project.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-project.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _AM_PROJECT_H_
+#define _AM_PROJECT_H_
+
+#include <glib-object.h>
+
+#include <libanjuta/anjuta-project.h>
+#include <libanjuta/anjuta-token.h>
+#include <libanjuta/anjuta-token-file.h>
+#include <libanjuta/anjuta-token-style.h>
+
+G_BEGIN_DECLS
+
+#define AMP_TYPE_PROJECT (amp_project_get_type ())
+#define AMP_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AMP_TYPE_PROJECT, AmpProject))
+#define AMP_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AMP_TYPE_PROJECT, AmpProjectClass))
+#define AMP_IS_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AMP_TYPE_PROJECT))
+#define AMP_IS_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), AMP_TYPE_PROJECT))
+
+#define AMP_GROUP(obj) ((AmpGroup *)obj)
+#define AMP_TARGET(obj) ((AmpTarget *)obj)
+#define AMP_SOURCE(obj) ((AmpSource *)obj)
+
+
+typedef struct _AmpProject AmpProject;
+typedef struct _AmpProjectClass AmpProjectClass;
+
+struct _AmpProjectClass {
+ GObjectClass parent_class;
+};
+
+typedef AnjutaProjectGroup AmpGroup;
+typedef AnjutaProjectTarget AmpTarget;
+typedef AnjutaProjectSource AmpSource;
+typedef struct _AmpProperty AmpProperty;
+
+typedef enum {
+ AMP_PROPERTY_NAME = 0,
+ AMP_PROPERTY_VERSION,
+ AMP_PROPERTY_BUG_REPORT,
+ AMP_PROPERTY_TARNAME,
+ AMP_PROPERTY_URL
+} AmpPropertyType;
+
+
+GType amp_project_get_type (void);
+AmpProject *amp_project_new (void);
+
+gint amp_project_probe (GFile *directory, GError **error);
+gboolean amp_project_load (AmpProject *project, GFile *directory, GError **error);
+gboolean amp_project_reload (AmpProject *project, GError **error);
+void amp_project_unload (AmpProject *project);
+
+AmpGroup *amp_project_get_root (AmpProject *project);
+AmpGroup *amp_project_get_group (AmpProject *project, const gchar *id);
+AmpTarget *amp_project_get_target (AmpProject *project, const gchar *id);
+AmpSource *amp_project_get_source (AmpProject *project, const gchar *id);
+
+
+gboolean amp_project_move (AmpProject *project, const gchar *path);
+gboolean amp_project_save (AmpProject *project, GError **error);
+
+gchar * amp_project_get_uri (AmpProject *project);
+GFile* amp_project_get_file (AmpProject *project);
+
+AmpGroup* amp_project_add_group (AmpProject *project, AmpGroup *parent, const gchar *name, GError **error);
+void amp_project_remove_group (AmpProject *project, AmpGroup *group, GError **error);
+
+AmpTarget* amp_project_add_target (AmpProject *project, AmpGroup *parent, const gchar *name, AnjutaProjectTargetType type, GError **error);
+void amp_project_remove_target (AmpProject *project, AmpTarget *target, GError **error);
+
+AmpSource* amp_project_add_source (AmpProject *project, AmpTarget *parent, GFile *file, GError **error);
+void amp_project_remove_source (AmpProject *project, AmpSource *source, GError **error);
+
+
+GList *amp_project_get_config_modules (AmpProject *project, GError **error);
+GList *amp_project_get_config_packages (AmpProject *project, const gchar* module, GError **error);
+
+GList *amp_project_get_target_types (AmpProject *project, GError **error);
+
+gchar* amp_project_get_property (AmpProject *project, AmpPropertyType type);
+gboolean amp_project_set_property (AmpProject *project, AmpPropertyType type, const gchar* value);
+
+gchar * amp_project_get_node_id (AmpProject *project, const gchar *path);
+
+AnjutaProjectNode *amp_node_parent (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_first_child (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_last_child (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_next_sibling (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_prev_sibling (AnjutaProjectNode *node);
+AnjutaProjectNodeType amp_node_get_type (AnjutaProjectNode *node);
+void amp_node_all_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data);
+
+GFile *amp_group_get_directory (AmpGroup *group);
+GFile *amp_group_get_makefile (AmpGroup *group);
+gchar *amp_group_get_id (AmpGroup *group);
+
+const gchar *amp_target_get_name (AmpTarget *target);
+AnjutaProjectTargetType amp_target_get_type (AmpTarget *target);
+gchar *amp_target_get_id (AmpTarget *target);
+
+gchar *amp_source_get_id (AmpSource *source);
+GFile *amp_source_get_file (AmpSource *source);
+
+G_END_DECLS
+
+#endif /* _AM_PROJECT_H_ */
diff --git a/plugins/gbf-am/gbf-am.plugin.in b/plugins/am-project/am-project.plugin.in
similarity index 90%
rename from plugins/gbf-am/gbf-am.plugin.in
rename to plugins/am-project/am-project.plugin.in
index 74590b3..87a82bc 100644
--- a/plugins/gbf-am/gbf-am.plugin.in
+++ b/plugins/am-project/am-project.plugin.in
@@ -1,7 +1,7 @@
[Anjuta Plugin]
_Name=Autotools backend
_Description=Autotools backend for project manager
-Location=gbf-am:GbfAmPlugin
+Location=am-project:AmpPlugin
Icon=gbf-am-plugin-48.png
Interfaces=IAnjutaProjectBackend
Dependencies=anjuta-project-manager:ProjectManagerPlugin
diff --git a/plugins/am-project/am-project.ui b/plugins/am-project/am-project.ui
new file mode 100644
index 0000000..931f50b
--- /dev/null
+++ b/plugins/am-project/am-project.ui
@@ -0,0 +1,419 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="package_selection_dialog">
+ <property name="title" translatable="yes">Select package</property>
+ <property name="default_width">600</property>
+ <property name="default_height">500</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="pkg_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Select Package to add:</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancelbutton1">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okbutton1">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancelbutton1</action-widget>
+ <action-widget response="-3">okbutton1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkNotebook" id="top_level">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkTable" id="general_properties_table">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="n_rows">7</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="height_request">300</property>
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">5</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="add_module_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon-size">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add _module</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_package_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon-size">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add _Package</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_button">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTreeView" id="packages_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Packages</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="visible">True</property>
+ <property name="spacing">5</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="add_variable_button">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_variable_button">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="variables_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Variables</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/am-project/am-scanner.h b/plugins/am-project/am-scanner.h
new file mode 100644
index 0000000..70a8a4a
--- /dev/null
+++ b/plugins/am-project/am-scanner.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * am-scanner.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AM_SCANNER_H_
+#define _AM_SCANNER_H_
+
+#include "libanjuta/anjuta-token.h"
+#include "libanjuta/anjuta-token-file.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct _AmpAmScanner AmpAmScanner;
+
+AmpAmScanner *amp_am_scanner_new (void);
+void amp_am_scanner_free (AmpAmScanner *scanner);
+
+gboolean amp_am_scanner_parse (AmpAmScanner *scanner, AnjutaTokenFile *file, GError **error);
+
+const gchar* amp_am_scanner_get_filename (AmpAmScanner *scanner);
+
+typedef enum
+{
+ AM_TOKEN_SUBDIRS = ANJUTA_TOKEN_USER,
+ AM_TOKEN_DIST_SUBDIRS,
+ AM_TOKEN__DATA,
+ AM_TOKEN__HEADERS,
+ AM_TOKEN__LIBRARIES,
+ AM_TOKEN__LISP,
+ AM_TOKEN__LTLIBRARIES,
+ AM_TOKEN__MANS,
+ AM_TOKEN__PROGRAMS,
+ AM_TOKEN__PYTHON,
+ AM_TOKEN__SCRIPTS,
+ AM_TOKEN__SOURCES,
+ AM_TOKEN__TEXINFOS,
+ AM_TOKEN__JAVA
+} AmTokenType;
+
+G_END_DECLS
+
+#endif
diff --git a/plugins/am-project/am-scanner.l b/plugins/am-project/am-scanner.l
new file mode 100644
index 0000000..fe574c4
--- /dev/null
+++ b/plugins/am-project/am-scanner.l
@@ -0,0 +1,377 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * am-scanner.l
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <stdlib.h>
+#include <string.h>
+#include "am-scanner.h"
+#include "am-parser.h"
+
+#include "libanjuta/anjuta-debug.h"
+
+
+/* Eliminate warning */
+#define YY_NO_UNPUT 1
+
+#define YY_INPUT(buf,result,the_max_size) \
+ result = 0;
+
+#define YY_USER_ACTION amp_update_location(yylloc, yytext, yyleng);
+
+#define YY_EXTRA_TYPE AmpAmScanner*
+
+//#define YY_USER_INIT {yy_flex_debug = 1;}
+
+static AnjutaToken* amp_am_scanner_append_token (AmpAmScanner *scanner, gint token);
+static gint amp_am_scanner_last_token (AmpAmScanner *scanner);
+static gint amp_am_scanner_last_flags (AmpAmScanner *scanner);
+static void amp_am_scanner_update_line_width (AmpAmScanner *scanner, YYLTYPE *loc);
+static void amp_update_location (YYLTYPE *loc, const gchar *text, gint length);
+static int amp_am_parse (yyscan_t scanner);
+
+%}
+
+%option reentrant stack noyywrap yylineno
+
+%option prefix="amp_am_yy"
+
+/* Necessary because autotools wrapper always looks for a file named "lex.yy.c",
+ * not "lex.amp_am_yy.c"
+%option outfile="lex.yy.c"*/
+
+%option bison-bridge bison-locations
+
+%option never-interactive
+
+%option batch
+
+%option debug
+
+NAME [^ \t\n\r:#=$"'`&@\\]*
+
+%%
+
+<INITIAL>\n {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_EOL);
+ return EOL;
+}
+
+<INITIAL>([ ]|\\\n)([ \t]|\\\n)* {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_SPACE);
+ return SPACE;
+}
+
+<INITIAL>([ \t])*#.*\n {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_COMMENT);
+ return EOL;
+}
+
+<INITIAL>\t {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_SPACE);
+ return TAB;
+}
+
+<INITIAL>@{NAME}@ {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_MACRO);
+ return MACRO;
+}
+
+<INITIAL>\$\([^ \t\n\r:#=$)]+\) {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_VARIABLE);
+ amp_am_scanner_update_line_width (yyextra, yylloc);
+ return VARIABLE;
+}
+
+<INITIAL>\$\{[^ \t\n\r:#=$}]+\} {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_VARIABLE);
+ amp_am_scanner_update_line_width (yyextra, yylloc);
+ return VARIABLE;
+}
+
+<INITIAL>\$[^ \t\n\r\(\{] {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_VARIABLE);
+ amp_am_scanner_update_line_width (yyextra, yylloc);
+ return VARIABLE;
+}
+
+<INITIAL>: {
+ yylval->token = amp_am_scanner_append_token (yyextra, ':');
+ return COLON;
+}
+
+<INITIAL>:: {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return DOUBLE_COLON;
+}
+
+<INITIAL>; {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return SEMI_COLON;
+}
+
+<INITIAL>\| {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return ORDER;
+}
+
+<INITIAL>\= {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return EQUAL;
+}
+
+<INITIAL>:= {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return IMMEDIATE_EQUAL;
+}
+
+<INITIAL>\?= {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return CONDITIONAL_EQUAL;
+}
+
+<INITIAL>\+= {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return APPEND;
+}
+
+<INITIAL>\\[ ] {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return CHARACTER;
+}
+
+<INITIAL>\\: {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return CHARACTER;
+}
+
+<INITIAL>\\= {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return CHARACTER;
+}
+
+<INITIAL>\\# {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_OPERATOR);
+ return CHARACTER;
+}
+
+<INITIAL>SUBDIRS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN_SUBDIRS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>DIST_SUBDIRS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN_DIST_SUBDIRS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_DATA {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__DATA);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_HEADERS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__HEADERS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_LIBRARIES {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__LIBRARIES);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_LISP {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__LISP);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_LTLIBRARIES {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__LTLIBRARIES);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_MANS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__MANS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_PROGRAMS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__PROGRAMS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_PYTHON {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__PYTHON);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_JAVA {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__JAVA);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_SCRIPTS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__SCRIPTS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_SOURCES {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__SOURCES);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME}_TEXINFOS {
+ yylval->token = amp_am_scanner_append_token (yyextra, AM_TOKEN__TEXINFOS);
+ return AM_VARIABLE;
+}
+
+<INITIAL>{NAME} {
+ yylval->token = amp_am_scanner_append_token (yyextra, ANJUTA_TOKEN_NAME);
+ amp_am_scanner_update_line_width (yyextra, yylloc);
+ return NAME;
+}
+
+<INITIAL>. {
+ yylval->token = amp_am_scanner_append_token (yyextra, *yytext);
+ return CHARACTER;
+}
+
+%%
+
+struct _AmpAmScanner
+{
+ const gchar *pos;
+ yyscan_t scanner;
+ YY_BUFFER_STATE buffer;
+
+ AnjutaTokenFile *file;
+ gchar *filename;
+
+ guint line_width;
+};
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static AnjutaToken*
+amp_am_scanner_append_token (AmpAmScanner *scanner, gint token)
+{
+ AnjutaToken *frag;
+
+ frag = anjuta_token_new_fragment (token, scanner->pos, yyget_leng (scanner->scanner));
+ anjuta_token_file_append (scanner->file, frag);
+ scanner->pos += yyget_leng (scanner->scanner);
+ //anjuta_token_old_dump (frag);
+
+ return frag;
+}
+
+static void
+amp_am_scanner_update_line_width (AmpAmScanner *scanner, YYLTYPE *loc)
+{
+ anjuta_token_file_update_line_width (scanner->file, loc->last_column);
+}
+
+static void
+amp_update_location (YYLTYPE *loc, const gchar *text, gint length)
+{
+ const gchar *ptr;
+ const gchar *end = text + length;
+
+ loc->first_line = loc->last_line;
+ loc->first_column = loc->last_column + 1;
+
+ for (ptr = text; ptr != end; ptr++)
+ {
+ if (*ptr == '\n')
+ {
+ loc->last_column = 0;
+ loc->last_line++;
+ length -= (ptr + 1 - text);
+ }
+ }
+
+ loc->last_column += length;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+amp_am_scanner_parse (AmpAmScanner *scanner, AnjutaTokenFile *file, GError **error)
+{
+ if (scanner->buffer != NULL) yy_delete_buffer (scanner->buffer, scanner->scanner);
+
+ scanner->file = file;
+ if (scanner->file== NULL) return FALSE;
+
+ scanner->pos = anjuta_token_file_get_content (scanner->file, error);
+ if (scanner->pos == NULL) return FALSE;
+
+ scanner->buffer = yy_scan_string (scanner->pos, scanner->scanner);
+
+ return amp_am_yyparse (scanner->scanner) == 0;
+}
+
+guint
+amp_am_scanner_get_line_width (AmpAmScanner *scanner)
+{
+ return scanner->line_width;
+}
+
+const gchar*
+amp_am_scanner_get_filename (AmpAmScanner *scanner)
+{
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+ if (scanner->file) scanner->filename = g_file_get_path (anjuta_token_file_get_file (scanner->file));
+
+ return scanner->filename;
+}
+
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+AmpAmScanner *
+amp_am_scanner_new (void)
+{
+ AmpAmScanner *scanner;
+
+ scanner = g_new0 (AmpAmScanner, 1);
+
+ yylex_init(&scanner->scanner);
+ yyset_extra (scanner, scanner->scanner);
+
+ return scanner;
+};
+
+void
+amp_am_scanner_free (AmpAmScanner *scanner)
+{
+ g_return_if_fail (scanner != NULL);
+
+ if (scanner->buffer != NULL) yy_delete_buffer (scanner->buffer, scanner->scanner);
+ yylex_destroy(scanner->scanner);
+
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+
+ g_free (scanner);
+}
diff --git a/plugins/gbf-am/plugin.c b/plugins/am-project/plugin.c
similarity index 77%
rename from plugins/gbf-am/plugin.c
rename to plugins/am-project/plugin.c
index 1325da6..d8d5809 100644
--- a/plugins/gbf-am/plugin.c
+++ b/plugins/am-project/plugin.c
@@ -24,10 +24,10 @@
#include <libanjuta/interfaces/ianjuta-project-backend.h>
#include "plugin.h"
-#include "gbf-am-project.h"
+#include "am-project.h"
-#define ICON_FILE "gfb-am-plugin-48.png"
+#define ICON_FILE "am-project-plugin-48.png"
/* AnjutaPlugin functions
*---------------------------------------------------------------------------*/
@@ -35,7 +35,7 @@
static gboolean
activate_plugin (AnjutaPlugin *plugin)
{
- DEBUG_PRINT ("GbfAmPlugin: Activating Gnome build am backend Plugin ...");
+ DEBUG_PRINT ("AmpPlugin: Activating Anjuta am backend Plugin ...");
return TRUE;
}
@@ -43,7 +43,7 @@ activate_plugin (AnjutaPlugin *plugin)
static gboolean
deactivate_plugin (AnjutaPlugin *plugin)
{
- DEBUG_PRINT ("GbfAmPlugin: Deacctivating Gnome build am backend Plugin ...");
+ DEBUG_PRINT ("AmpPlugin: Deacctivating Anjuta am backend Plugin ...");
return TRUE;
}
@@ -51,20 +51,29 @@ deactivate_plugin (AnjutaPlugin *plugin)
/* IAnjutaProjectBackend implementation
*---------------------------------------------------------------------------*/
-static GbfProject*
+static IAnjutaProject*
iproject_backend_new_project (IAnjutaProjectBackend* backend, GError** err)
{
- GbfProject *project;
-
- project = gbf_am_project_new ();
+ IAnjutaProject *project;
+ DEBUG_PRINT("create new amp project");
+ project = (IAnjutaProject *)(g_object_new (AMP_TYPE_PROJECT, NULL));
return project;
}
+static gint
+iproject_backend_probe (IAnjutaProjectBackend* backend, GFile *directory, GError** err)
+{
+ DEBUG_PRINT("probe amp project");
+
+ return amp_project_probe (directory, err);
+}
+
static void
iproject_backend_iface_init(IAnjutaProjectBackendIface *iface)
{
iface->new_project = iproject_backend_new_project;
+ iface->probe = iproject_backend_probe;
}
/* GObject functions
@@ -74,7 +83,7 @@ iproject_backend_iface_init(IAnjutaProjectBackendIface *iface)
static gpointer parent_class;
static void
-gbf_am_plugin_instance_init (GObject *obj)
+amp_plugin_instance_init (GObject *obj)
{
}
@@ -95,7 +104,7 @@ finalize (GObject *obj)
}
static void
-gbf_am_plugin_class_init (GObjectClass *klass)
+amp_plugin_class_init (GObjectClass *klass)
{
AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
@@ -110,13 +119,8 @@ gbf_am_plugin_class_init (GObjectClass *klass)
/* AnjutaPlugin declaration
*---------------------------------------------------------------------------*/
-ANJUTA_PLUGIN_BEGIN (GbfAmPlugin, gbf_am_plugin);
+ANJUTA_PLUGIN_BEGIN (AmpPlugin, amp_plugin);
ANJUTA_PLUGIN_ADD_INTERFACE (iproject_backend, IANJUTA_TYPE_PROJECT_BACKEND);
ANJUTA_PLUGIN_END;
-G_MODULE_EXPORT void
-anjuta_glue_register_components (GTypeModule *module)
-{
- gbf_am_plugin_get_type (module);
- gbf_am_project_get_type (module);
-}
+ANJUTA_SIMPLE_PLUGIN (AmpPlugin, amp_plugin);
diff --git a/plugins/gbf-mkfile/plugin.h b/plugins/am-project/plugin.h
similarity index 54%
rename from plugins/gbf-mkfile/plugin.h
rename to plugins/am-project/plugin.h
index b04aab1..d6a3fa7 100644
--- a/plugins/gbf-mkfile/plugin.h
+++ b/plugins/am-project/plugin.h
@@ -23,23 +23,23 @@
#include <libanjuta/anjuta-plugin.h>
-extern GType gbf_mkfile_plugin_get_type (GTypeModule *module);
-#define GBF_TYPE_PLUGIN_MKFILE (gbf_mkfile_plugin_get_type (NULL))
-#define GBF_PLUGIN_MKFILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GBF_TYPE_PLUGIN_MKFILE, GbfMkfilePlugin))
-#define GBF_PLUGIN_MKFILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GBF_TYPE_PLUGIN_MKFILE, GbfMkfilePluginClass))
-#define GBF_IS_PLUGIN_MKFILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GBF_TYPE_PLUGIN_MKFILE))
-#define GBF_IS_PLUGIN_MKFILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GBF_TYPE_PLUGIN_MKFILE))
-#define GBF_PLUGIN_MKFILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GBF_TYPE_PLUGIN_MKFILE, GbfMkfilePluginClass))
-
-typedef struct _GbfMkfilePlugin GbfMkfilePlugin;
-typedef struct _GbfMkfilePluginClass GbfMkfilePluginClass;
-
-struct _GbfMkfilePlugin
+extern GType amp_plugin_get_type (GTypeModule *module);
+#define ANJUTA_TYPE_PLUGIN_AMP (amp_plugin_get_type (NULL))
+#define ANJUTA_PLUGIN_AMP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_TYPE_PLUGIN_AMP, AmpPlugin))
+#define ANJUTA_PLUGIN_AMP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_TYPE_PLUGIN_AMP, AmpPluginClass))
+#define ANJUTA_IS_PLUGIN_AMP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_TYPE_PLUGIN_AMP))
+#define ANJUTA_IS_PLUGIN_AMP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_TYPE_PLUGIN_AMP))
+#define ANJUTA_PLUGIN_AMP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_TYPE_PLUGIN_AMP, AmpPluginClass))
+
+typedef struct _AmpPlugin AmpPlugin;
+typedef struct _AmpPluginClass AmpPluginClass;
+
+struct _AmpPlugin
{
AnjutaPlugin parent;
};
-struct _GbfMkfilePluginClass
+struct _AmpPluginClass
{
AnjutaPluginClass parent_class;
};
diff --git a/plugins/build-basic-autotools/executer.c b/plugins/build-basic-autotools/executer.c
index 45284ff..87bbcd2 100644
--- a/plugins/build-basic-autotools/executer.c
+++ b/plugins/build-basic-autotools/executer.c
@@ -64,8 +64,8 @@ get_program_parameters (BasicAutotoolsPlugin *plugin,
g_return_val_if_fail (pm != NULL, FALSE);
exec_targets =
ianjuta_project_manager_get_targets (pm,
- IANJUTA_PROJECT_MANAGER_TARGET_EXECUTABLE,
- NULL);
+ ANJUTA_TARGET_EXECUTABLE,
+ NULL);
if (!exec_targets)
{
anjuta_util_dialog_error(GTK_WINDOW (ANJUTA_PLUGIN(plugin)->shell),
diff --git a/plugins/class-gen/plugin.c b/plugins/class-gen/plugin.c
index c1a8bf1..f178601 100644
--- a/plugins/class-gen/plugin.c
+++ b/plugins/class-gen/plugin.c
@@ -447,8 +447,8 @@ iwizard_activate (IAnjutaWizard *wiz, G_GNUC_UNUSED GError **err)
AnjutaClassGenPlugin *cg_plugin;
gchar *user_name;
gchar *user_email;
- IAnjutaProjectManagerCapabilities caps =
- IANJUTA_PROJECT_MANAGER_CAN_ADD_NONE;
+ IAnjutaProjectCapabilities caps =
+ IANJUTA_PROJECT_CAN_ADD_NONE;
cg_plugin = ANJUTA_PLUGIN_CLASS_GEN (wiz);
@@ -481,7 +481,7 @@ iwizard_activate (IAnjutaWizard *wiz, G_GNUC_UNUSED GError **err)
caps = ianjuta_project_manager_get_capabilities (manager, NULL);
}
- if((caps & IANJUTA_PROJECT_MANAGER_CAN_ADD_SOURCE) == FALSE)
+ if((caps & IANJUTA_PROJECT_CAN_ADD_SOURCE) == FALSE)
{
cg_window_set_add_to_project (cg_plugin->window, FALSE);
cg_window_enable_add_to_project (cg_plugin->window, FALSE);
diff --git a/plugins/debug-manager/start.c b/plugins/debug-manager/start.c
index 82d0cd1..3fdf464 100644
--- a/plugins/debug-manager/start.c
+++ b/plugins/debug-manager/start.c
@@ -36,6 +36,7 @@
/*#define DEBUG*/
#include <libanjuta/anjuta-debug.h>
#include <libanjuta/resources.h>
+#include <libanjuta/anjuta-project.h>
#include <libanjuta/interfaces/ianjuta-project-manager.h>
#include <libanjuta/interfaces/ianjuta-document-manager.h>
#include <libanjuta/interfaces/ianjuta-builder.h>
@@ -208,12 +209,12 @@ get_source_directories (AnjutaPlugin *plugin)
{
slibs_dirs =
ianjuta_project_manager_get_targets (pm,
- IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB,
- NULL);
+ ANJUTA_TARGET_SHAREDLIB,
+ NULL);
libs_dirs =
ianjuta_project_manager_get_targets (pm,
- IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB,
- NULL);
+ ANJUTA_TARGET_STATICLIB,
+ NULL);
}
}
slibs_dirs = g_list_reverse (slibs_dirs);
diff --git a/plugins/file-wizard/file.c b/plugins/file-wizard/file.c
index bc4b5d3..9d8d00a 100644
--- a/plugins/file-wizard/file.c
+++ b/plugins/file-wizard/file.c
@@ -36,6 +36,7 @@
#include <libanjuta/interfaces/ianjuta-document-manager.h>
#include <libanjuta/interfaces/ianjuta-macro.h>
#include <libanjuta/interfaces/ianjuta-file.h>
+#include <libanjuta/interfaces/ianjuta-project.h>
#include <libanjuta/interfaces/ianjuta-project-manager.h>
#include <libanjuta/interfaces/ianjuta-vcs.h>
@@ -125,8 +126,8 @@ void
display_new_file(AnjutaFileWizardPlugin *plugin,
IAnjutaDocumentManager *docman)
{
- IAnjutaProjectManagerCapabilities caps =
- IANJUTA_PROJECT_MANAGER_CAN_ADD_NONE;
+ IAnjutaProjectCapabilities caps =
+ IANJUTA_PROJECT_CAN_ADD_NONE;
if (!nfg)
if (!create_new_file_dialog (docman))
@@ -147,7 +148,7 @@ display_new_file(AnjutaFileWizardPlugin *plugin,
G_CALLBACK(on_add_to_project_toggled),
nfg);
- if ((caps & IANJUTA_PROJECT_MANAGER_CAN_ADD_SOURCE) == FALSE) {
+ if ((caps & IANJUTA_PROJECT_CAN_ADD_SOURCE) == FALSE) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (nfg->add_to_project),
FALSE);
gtk_widget_set_sensitive (nfg->add_to_project, FALSE);
diff --git a/plugins/glade/plugin.c b/plugins/glade/plugin.c
index 0bcf9be..c696ae6 100644
--- a/plugins/glade/plugin.c
+++ b/plugins/glade/plugin.c
@@ -316,9 +316,10 @@ value_added_pm_current_uri (AnjutaPlugin *plugin, const char *name,
ui = anjuta_shell_get_ui (plugin->shell, NULL);
action = anjuta_ui_get_action (ui, "ActionGroupGlade", "ActionSetDefaultTarget");
selected_id = ianjuta_project_manager_get_selected_id (projman,
- IANJUTA_PROJECT_MANAGER_TARGET,
+ ANJUTA_PROJECT_TARGET,
NULL);
gtk_action_set_sensitive (action, selected_id != NULL);
+ g_free (selected_id);
}
static void
@@ -3871,7 +3872,7 @@ on_set_default_resource_target (GtkAction* action, GladePlugin* plugin)
anjuta_shell_get_interface (ANJUTA_PLUGIN(plugin)->shell,
IAnjutaProjectManager, NULL);
- selected = ianjuta_project_manager_get_selected_id (projman, IANJUTA_PROJECT_MANAGER_TARGET, NULL);
+ selected = ianjuta_project_manager_get_selected_id (projman, ANJUTA_PROJECT_TARGET, NULL);
DEBUG_PRINT ("Selected element is %s", selected);
set_default_resource_target (selected, plugin);
g_free (selected);
diff --git a/plugins/gbf-mkfile/Makefile.am b/plugins/mk-project/Makefile.am
similarity index 54%
rename from plugins/gbf-mkfile/Makefile.am
rename to plugins/mk-project/Makefile.am
index 80befb7..bcd751b 100644
--- a/plugins/gbf-mkfile/Makefile.am
+++ b/plugins/mk-project/Makefile.am
@@ -4,18 +4,14 @@ plugin_ui_DATA =
# Plugin glade file
plugin_gladedir = $(anjuta_glade_dir)
-plugin_glade_DATA =
+plugin_glade_DATA = mk-project.ui
# Plugin icon file
plugin_pixmapsdir = $(anjuta_image_dir)
-plugin_pixmaps_DATA = gbf-mkfile-plugin-48.png
-
-# Plugin scripts
-scriptsdir = $(bindir)
-scripts_SCRIPTS = gbf-mkfile-parse
+plugin_pixmaps_DATA = mk-project-plugin-48.png
# Plugin description file
-plugin_in_files = gbf-mkfile.plugin.in
+plugin_in_files = mk-project.plugin.in
%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugindir = $(anjuta_plugin_dir)
@@ -26,37 +22,49 @@ AM_CPPFLAGS = \
$(DEPRECATED_FLAGS) \
$(GIO_CFLAGS) \
$(LIBANJUTA_CFLAGS) \
- -DSCRIPTS_DIR=\"$(scriptsdir)\"
+ -DG_LOG_DOMAIN=\"mk-project\"
plugin_LTLIBRARIES = \
- libgbf-mkfile.la
+ libmk-project.la
-libgbf_mkfile_la_SOURCES = \
+libmk_project_la_SOURCES = \
plugin.c \
plugin.h \
- gbf-mkfile-project.c \
- gbf-mkfile-project.h \
- gbf-mkfile-config.c \
- gbf-mkfile-config.h \
- gbf-mkfile-properties.c \
- gbf-mkfile-properties.h
+ mk-project.c \
+ mk-project.h \
+ mk-scanner.l \
+ mk-parser.y \
+ mk-scanner.h \
+ mk-rule.c \
+ mk-rule.h \
+ mk-project-private.h
-libgbf_mkfile_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
+libmk_project_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
-libgbf_mkfile_la_LIBADD = \
+libmk_project_la_LIBADD = \
$(GIO_LIBS) \
$(LIBANJUTA_LIBS)
+AM_YFLAGS = -t -v -g -rall
+
+mk-scanner.c: $(srcdir)/mk-scanner.l mk-parser.c
+ $(LEXCOMPILE) -o $@ $<
+
+mk-parser.c: $(srcdir)/mk-parser.y
+ $(YACCCOMPILE) -o $@ $<
+
+mk-scanner.h: mk-parser.c
+
+
EXTRA_DIST = \
$(plugin_in_files) \
$(plugin_DATA) \
$(plugin_ui_DATA) \
- $(plugin_pixmaps_DATA)
+ $(plugin_pixmaps_DATA) \
+ $(plugin_glade_DATA) \
+ mk-parser.h
DISTCLEANFILES = \
$(plugin_DATA)
-SUBDIRS = GBF
-
-
-include $(top_srcdir)/git.mk
diff --git a/plugins/mk-project/mk-parser.y b/plugins/mk-project/mk-parser.y
new file mode 100644
index 0000000..31d1da0
--- /dev/null
+++ b/plugins/mk-project/mk-parser.y
@@ -0,0 +1,504 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * mk-parser.y
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+%{
+
+#include "mk-scanner.h"
+#include "mk-parser.h"
+
+#include <stdlib.h>
+
+#define YYDEBUG 1
+
+%}
+
+%token EOL '\n'
+%token SPACE
+%token TAB '\t'
+%token HASH '#'
+%token MACRO
+%token VARIABLE
+%token COMMA ','
+%token COLON ':'
+%token DOUBLE_COLON "::"
+%token ORDER '|'
+%token SEMI_COLON ';'
+%token EQUAL '='
+%token IMMEDIATE_EQUAL ":="
+%token CONDITIONAL_EQUAL "?="
+%token APPEND "+="
+%token CHARACTER
+%token NAME
+%token MK_VARIABLE
+%token _PHONY
+%token _SUFFIXES
+%token _DEFAULT
+%token _PRECIOUS
+%token _INTERMEDIATE
+%token _SECONDARY
+%token _SECONDEXPANSION
+%token _DELETE_ON_ERROR
+%token _IGNORE
+%token _LOW_RESOLUTION_TIME
+%token _SILENT
+%token _EXPORT_ALL_VARIABLES
+%token _NOTPARALLEL
+
+
+%defines
+
+%pure_parser
+
+/* Necessary because autotools wrapper always looks for a file named "y.tab.c",
+ * not "amp-scanner.c"
+%output="y.tab.c"*/
+
+/*%glr-parser*/
+
+%parse-param {void* scanner}
+%lex-param {void* scanner}
+
+%name-prefix="mkp_yy"
+
+%locations
+
+%expect 1
+
+%start file
+
+%debug
+
+%{
+
+//mkp_yydebug = 1;
+
+static void mkp_yyerror (YYLTYPE *loc, MkpScanner *scanner, char const *s);
+static gint mkp_special_target (AnjutaToken *list);
+static gint mkp_special_prerequisite (AnjutaToken *token);
+
+%}
+
+
+%%
+
+file:
+ statement
+ | file statement
+ ;
+
+statement:
+ end_of_line
+ | space end_of_line
+ | definition end_of_line
+ | rule command_list {
+ if ($2 != NULL) $$ = anjuta_token_group ($1, $2);
+ mkp_scanner_add_rule (scanner, $$);
+ }
+ ;
+
+definition:
+ head_list equal_token value_list {
+ $$ = anjuta_token_merge (
+ anjuta_token_insert_before ($1,
+ anjuta_token_new_static (ANJUTA_TOKEN_DEFINITION, NULL)),
+ $3 != NULL ? $3 : $2);
+ mkp_scanner_update_variable (scanner, $$);
+ }
+ ;
+
+rule:
+ depend_list end_of_line {
+ $$ = anjuta_token_group ($1, $2);
+ }
+ | depend_list SEMI_COLON command_line EOL {
+ $$ = anjuta_token_group ($1, $4);
+ }
+ ;
+
+depend_list:
+ head_list rule_token prerequisite_list {
+ $$ = anjuta_token_group_new (MK_TOKEN_RULE, $1);
+ anjuta_token_set_type ($1, MK_TOKEN_TARGET);
+ mkp_special_target ($1);
+ switch (anjuta_token_get_type ($2))
+ {
+ case COLON:
+ anjuta_token_set_type ($2, MK_TOKEN_COLON);
+ break;
+ case DOUBLE_COLON:
+ anjuta_token_set_type ($2, MK_TOKEN_DOUBLE_COLON);
+ break;
+ default:
+ break;
+ }
+ anjuta_token_group ($$, $3 != NULL ? $3 : $2);
+ }
+ ;
+
+command_list:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | command_list TAB command_line EOL {
+ $$ = $4;
+ }
+ ;
+
+
+/* Lists
+ *----------------------------------------------------------------------------*/
+
+end_of_line:
+ EOL
+ | comment
+ ;
+
+comment:
+ HASH not_eol_list EOL {
+ anjuta_token_set_type ($1, ANJUTA_TOKEN_COMMENT);
+ anjuta_token_group ($1, $3);
+ }
+ ;
+
+not_eol_list:
+ /* empty */
+ | not_eol_list not_eol_token
+ ;
+
+value_list:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | space {
+ $$ = $1;
+ }
+ | optional_space value_list_body optional_space {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_VALUE, $1 != NULL ? $1 : $2);
+ if ($1) anjuta_token_set_type ($1, ANJUTA_TOKEN_START);
+ if ($3) anjuta_token_set_type ($1, ANJUTA_TOKEN_LAST);
+ anjuta_token_group ($$, $3 != NULL ? $3 : $2);
+ }
+ ;
+
+value_list_body:
+ value
+ | value_list_body space value {
+ anjuta_token_set_type ($2, ANJUTA_TOKEN_NEXT);
+ $$ = $3;
+ }
+ ;
+
+prerequisite_list:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | optional_space prerequisite_list_body optional_space {
+ $$ = anjuta_token_group_new (MK_TOKEN_PREREQUISITE, $1 != NULL ? $1 : $2);
+ if ($1) anjuta_token_set_type ($1, ANJUTA_TOKEN_START);
+ if ($3) anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ anjuta_token_group ($$, $3 != NULL ? $3 : $2);
+ }
+ ;
+
+prerequisite_list_body:
+ prerequisite
+ | prerequisite_list_body space prerequisite {
+ anjuta_token_set_type ($2, ANJUTA_TOKEN_NEXT);
+ $$ = $3;
+ }
+ ;
+
+head_list:
+ optional_space head_list_body optional_space {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_NAME, $1 != NULL ? $1 : $2);
+ if ($1) anjuta_token_set_type ($1, ANJUTA_TOKEN_START);
+ if ($3) anjuta_token_set_type ($3, ANJUTA_TOKEN_LAST);
+ anjuta_token_group ($$, $3 != NULL ? $3 : $2);
+ }
+ ;
+
+head_list_body:
+ head
+ | head_list_body space head {
+ anjuta_token_set_type ($2, ANJUTA_TOKEN_NEXT);
+ $$ = $3;
+ }
+ ;
+
+command_line:
+ /* empty */
+ | command_line command_token
+ ;
+
+/* Items
+ *----------------------------------------------------------------------------*/
+
+optional_space:
+ /* empty */ {
+ $$ = NULL;
+ }
+ | space
+ ;
+
+space:
+ space_token
+ | space space_token {
+ anjuta_token_merge ($1, $2);
+ }
+ ;
+
+head:
+ head_token {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_NAME, $1);
+ }
+ | head head_token {
+ anjuta_token_group ($$, $2);
+ }
+ ;
+
+value:
+ value_token {
+ $$ = anjuta_token_group_new (ANJUTA_TOKEN_VALUE, $1);
+ }
+ | value value_token {
+ anjuta_token_group ($$, $2);
+ }
+ ;
+
+prerequisite:
+ prerequisite_token {
+ $$ = anjuta_token_group_new (mkp_special_prerequisite ($$), $1);
+ }
+ | prerequisite prerequisite_token {
+ $$ = anjuta_token_group ($1, $2);
+ anjuta_token_set_type ($$, ANJUTA_TOKEN_VALUE);
+ }
+ ;
+
+/* Tokens
+ *----------------------------------------------------------------------------*/
+
+not_eol_token:
+ word_token
+ | space_token
+ ;
+
+prerequisite_token:
+ name_token
+ | equal_token
+ | rule_token
+ ;
+
+command_token:
+ name_token
+ | equal_token
+ | rule_token
+ | depend_token
+ | space_token
+ ;
+
+value_token:
+ name_token
+ | equal_token
+ | rule_token
+ | depend_token
+ ;
+
+head_token:
+ name_token
+ | depend_token
+ ;
+
+name_token:
+ VARIABLE {
+ anjuta_token_set_type ($$, MK_TOKEN_VARIABLE);
+ }
+ | NAME
+ | CHARACTER
+ | COMMA
+ | ORDER
+ | _PHONY
+ | _SUFFIXES
+ | _DEFAULT
+ | _PRECIOUS
+ | _INTERMEDIATE
+ | _SECONDARY
+ | _SECONDEXPANSION
+ | _DELETE_ON_ERROR
+ | _IGNORE
+ | _LOW_RESOLUTION_TIME
+ | _SILENT
+ | _EXPORT_ALL_VARIABLES
+ | _NOTPARALLEL
+ ;
+
+rule_token:
+ COLON
+ | DOUBLE_COLON
+ ;
+
+depend_token:
+ SEMI_COLON
+ ;
+
+word_token:
+ VARIABLE
+ | NAME
+ | CHARACTER
+ | ORDER
+ | HASH
+ | COMMA
+ | COLON
+ | DOUBLE_COLON
+ | SEMI_COLON
+ | EQUAL
+ | IMMEDIATE_EQUAL
+ | CONDITIONAL_EQUAL
+ | APPEND
+ | _PHONY
+ | _SUFFIXES
+ | _DEFAULT
+ | _PRECIOUS
+ | _INTERMEDIATE
+ | _SECONDARY
+ | _SECONDEXPANSION
+ | _DELETE_ON_ERROR
+ | _IGNORE
+ | _LOW_RESOLUTION_TIME
+ | _SILENT
+ | _EXPORT_ALL_VARIABLES
+ | _NOTPARALLEL
+ ;
+
+space_token:
+ SPACE
+ | TAB
+ ;
+
+equal_token:
+ EQUAL {
+ anjuta_token_set_type ($$, MK_TOKEN_EQUAL);
+ }
+ | IMMEDIATE_EQUAL {
+ anjuta_token_set_type ($$, MK_TOKEN_IMMEDIATE_EQUAL);
+ }
+ | CONDITIONAL_EQUAL {
+ anjuta_token_set_type ($$, MK_TOKEN_CONDITIONAL_EQUAL);
+ }
+ | APPEND {
+ anjuta_token_set_type ($$, MK_TOKEN_APPEND);
+ }
+ ;
+
+%%
+
+static void
+mkp_yyerror (YYLTYPE *loc, MkpScanner *scanner, char const *s)
+{
+ gchar *filename;
+
+ g_message ("scanner %p", scanner);
+ filename = mkp_scanner_get_filename ((MkpScanner *)scanner);
+ if (filename == NULL) filename = "?";
+ g_message ("%s (%d:%d-%d:%d) %s\n", filename, loc->first_line, loc->first_column, loc->last_line, loc->last_column, s);
+}
+
+static gint
+mkp_special_prerequisite (AnjutaToken *token)
+{
+ switch (anjuta_token_get_type (token))
+ {
+ case ORDER:
+ return MK_TOKEN_ORDER;
+ default:
+ return ANJUTA_TOKEN_NAME;
+ }
+}
+
+static gint
+mkp_special_target (AnjutaToken *list)
+{
+ AnjutaToken *arg;
+
+ for (arg = anjuta_token_list_first (list); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ AnjutaToken *child = anjuta_token_next_child (arg);
+
+ if ((child != NULL) && (anjuta_token_next_sibling (child) == NULL))
+ {
+ gint mk_token = 0;
+
+ switch (anjuta_token_get_type (child))
+ {
+ case _PHONY:
+ mk_token = MK_TOKEN__PHONY;
+ break;
+ case _SUFFIXES:
+ mk_token = MK_TOKEN__SUFFIXES;
+ break;
+ case _DEFAULT:
+ mk_token = MK_TOKEN__DEFAULT;
+ break;
+ case _PRECIOUS:
+ mk_token = MK_TOKEN__PRECIOUS;
+ break;
+ case _INTERMEDIATE:
+ mk_token = MK_TOKEN__INTERMEDIATE;
+ break;
+ case _SECONDARY:
+ mk_token = MK_TOKEN__SECONDARY;
+ break;
+ case _SECONDEXPANSION:
+ mk_token = MK_TOKEN__SECONDEXPANSION;
+ break;
+ case _DELETE_ON_ERROR:
+ mk_token = MK_TOKEN__DELETE_ON_ERROR;
+ break;
+ case _IGNORE:
+ mk_token = MK_TOKEN__IGNORE;
+ break;
+ case _LOW_RESOLUTION_TIME:
+ mk_token = MK_TOKEN__LOW_RESOLUTION_TIME;
+ break;
+ case _SILENT:
+ mk_token = MK_TOKEN__SILENT;
+ break;
+ case _EXPORT_ALL_VARIABLES:
+ mk_token = MK_TOKEN__EXPORT_ALL_VARIABLES;
+ break;
+ case _NOTPARALLEL:
+ mk_token = MK_TOKEN__NOTPARALLEL;
+ break;
+ case ORDER:
+ mk_token = MK_TOKEN_ORDER;
+ break;
+ default:
+ break;
+ }
+
+ if (mk_token)
+ {
+ anjuta_token_set_type (arg, mk_token);
+ }
+ }
+ }
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
diff --git a/plugins/gbf-mkfile/gbf-mkfile-plugin-48.png b/plugins/mk-project/mk-project-plugin-48.png
similarity index 100%
rename from plugins/gbf-mkfile/gbf-mkfile-plugin-48.png
rename to plugins/mk-project/mk-project-plugin-48.png
diff --git a/plugins/mk-project/mk-project-private.h b/plugins/mk-project/mk-project-private.h
new file mode 100644
index 0000000..b9bda25
--- /dev/null
+++ b/plugins/mk-project/mk-project-private.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* mk-project-private.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MK_PROJECT_PRIVATE_H_
+#define _MK_PROJECT_PRIVATE_H_
+
+#include "mk-project.h"
+
+G_BEGIN_DECLS
+
+struct _MkpProperty {
+ AnjutaToken *ac_init; /* AC_INIT macro */
+ gchar *name;
+ gchar *version;
+ gchar *bug_report;
+ gchar *tarname;
+ gchar *url;
+};
+
+struct _MkpProject {
+ GObject parent;
+
+ /* uri of the project; this can be a full uri, even though we
+ * can only work with native local files */
+ GFile *root_file;
+
+ /* project data */
+ AnjutaTokenFile *make_file; /* make file */
+
+ MkpProperty *property;
+
+ MkpGroup *root_node; /* tree containing project data;
+ * each GNode's data is a
+ * AmpNode, and the root of
+ * the tree is the root group. */
+
+ /* shortcut hash tables, mapping id -> GNode from the tree above */
+ GHashTable *groups;
+ GHashTable *files;
+ GHashTable *variables;
+
+ GHashTable *rules;
+ GHashTable *suffix;
+
+ /* project files monitors */
+ GHashTable *monitors;
+
+ /* Keep list style */
+ AnjutaTokenStyle *space_list;
+ AnjutaTokenStyle *arg_list;
+};
+
+struct _MkpRule {
+ gchar *name;
+ const gchar *part;
+ gboolean phony;
+ gboolean pattern;
+ GList *prerequisite;
+ AnjutaToken *rule;
+};
+
+gchar *mkp_project_token_evaluate (MkpProject *project, AnjutaToken *token);
+
+MkpTarget* mkp_target_new (const gchar *name, AnjutaProjectTargetType type);
+void mkp_target_free (MkpTarget *node);
+void mkp_target_add_token (MkpGroup *node, AnjutaToken *token);
+MkpSource* mkp_source_new (GFile *file);
+
+G_END_DECLS
+
+#endif /* _MK_PROJECT_PRIVATE_H_ */
diff --git a/plugins/mk-project/mk-project.c b/plugins/mk-project/mk-project.c
new file mode 100644
index 0000000..d3e48cc
--- /dev/null
+++ b/plugins/mk-project/mk-project.c
@@ -0,0 +1,1460 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* mk-project.c
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "mk-project.h"
+
+#include "mk-project-private.h"
+
+#include <libanjuta/interfaces/ianjuta-project.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include "mk-scanner.h"
+
+
+#define UNIMPLEMENTED G_STMT_START { g_warning (G_STRLOC": unimplemented"); } G_STMT_END
+
+/* Constant strings for parsing perl script error output */
+#define ERROR_PREFIX "ERROR("
+#define WARNING_PREFIX "WARNING("
+#define MESSAGE_DELIMITER ": "
+
+static const gchar *valid_makefiles[] = {"GNUmakefile", "makefile", "Makefile", NULL};
+
+/* convenient shortcut macro the get the MkpNode from a GNode */
+#define MKP_NODE_DATA(node) ((node) != NULL ? (AnjutaProjectNodeData *)((node)->data) : NULL)
+#define MKP_GROUP_DATA(node) ((node) != NULL ? (MkpGroupData *)((node)->data) : NULL)
+#define MKP_TARGET_DATA(node) ((node) != NULL ? (MkpTargetData *)((node)->data) : NULL)
+#define MKP_SOURCE_DATA(node) ((node) != NULL ? (MkpSourceData *)((node)->data) : NULL)
+
+
+struct _MkpVariable {
+ gchar *name;
+ AnjutaTokenType assign;
+ AnjutaToken *value;
+};
+
+typedef enum {
+ AM_GROUP_TOKEN_CONFIGURE,
+ AM_GROUP_TOKEN_SUBDIRS,
+ AM_GROUP_TOKEN_DIST_SUBDIRS,
+ AM_GROUP_TARGET,
+ AM_GROUP_TOKEN_LAST
+} MkpGroupTokenCategory;
+
+typedef struct _MkpGroupData MkpGroupData;
+
+struct _MkpGroupData {
+ AnjutaProjectGroupData base; /* Common node data */
+ gboolean dist_only; /* TRUE if the group is distributed but not built */
+ GFile *makefile; /* GFile corresponding to group makefile */
+ AnjutaTokenFile *tfile; /* Corresponding Makefile */
+ GList *tokens[AM_GROUP_TOKEN_LAST]; /* List of token used by this group */
+};
+
+typedef enum _MkpTargetFlag
+{
+ AM_TARGET_CHECK = 1 << 0,
+ AM_TARGET_NOINST = 1 << 1,
+ AM_TARGET_DIST = 1 << 2,
+ AM_TARGET_NODIST = 1 << 3,
+ AM_TARGET_NOBASE = 1 << 4,
+ AM_TARGET_NOTRANS = 1 << 5,
+ AM_TARGET_MAN = 1 << 6,
+ AM_TARGET_MAN_SECTION = 31 << 7
+} MkpTargetFlag;
+
+typedef struct _MkpTargetData MkpTargetData;
+
+struct _MkpTargetData {
+ AnjutaProjectTargetData base;
+ gchar *install;
+ gint flags;
+ GList* tokens;
+};
+
+typedef struct _MkpSourceData MkpSourceData;
+
+struct _MkpSourceData {
+ AnjutaProjectSourceData base;
+ AnjutaToken* token;
+};
+
+typedef struct _MkpTargetInformation MkpTargetInformation;
+
+struct _MkpTargetInformation {
+ AnjutaProjectTargetInformation base;
+ AnjutaTokenType token;
+ const gchar *prefix;
+ const gchar *install;
+};
+
+/* Target types
+ *---------------------------------------------------------------------------*/
+
+static MkpTargetInformation MkpTargetTypes[] = {
+ {{N_("Unknown"), ANJUTA_TARGET_UNKNOWN,
+ "text/plain"},
+ ANJUTA_TOKEN_NONE,
+ NULL,
+ NULL},
+
+ {{NULL, ANJUTA_TARGET_UNKNOWN,
+ NULL},
+ ANJUTA_TOKEN_NONE,
+ NULL,
+ NULL}
+};
+
+
+/* ----- Standard GObject types and variables ----- */
+
+enum {
+ PROP_0,
+ PROP_PROJECT_DIR
+};
+
+static GObject *parent_class;
+
+/* Helper functions
+ *---------------------------------------------------------------------------*/
+
+static void
+error_set (GError **error, gint code, const gchar *message)
+{
+ if (error != NULL) {
+ if (*error != NULL) {
+ gchar *tmp;
+
+ /* error already created, just change the code
+ * and prepend the string */
+ (*error)->code = code;
+ tmp = (*error)->message;
+ (*error)->message = g_strconcat (message, "\n\n", tmp, NULL);
+ g_free (tmp);
+
+ } else {
+ *error = g_error_new_literal (IANJUTA_PROJECT_ERROR,
+ code,
+ message);
+ }
+ }
+}
+
+/* Work even if file is not a descendant of parent */
+static gchar*
+get_relative_path (GFile *parent, GFile *file)
+{
+ gchar *relative;
+
+ relative = g_file_get_relative_path (parent, file);
+ if (relative == NULL)
+ {
+ if (g_file_equal (parent, file))
+ {
+ relative = g_strdup ("");
+ }
+ else
+ {
+ GFile *grand_parent = g_file_get_parent (parent);
+ gint level;
+ gchar *grand_relative;
+ gchar *ptr;
+ gsize len;
+
+
+ for (level = 1; !g_file_has_prefix (file, grand_parent); level++)
+ {
+ GFile *next = g_file_get_parent (grand_parent);
+
+ g_object_unref (grand_parent);
+ grand_parent = next;
+ }
+
+ grand_relative = g_file_get_relative_path (grand_parent, file);
+ g_object_unref (grand_parent);
+
+ len = strlen (grand_relative);
+ relative = g_new (gchar, len + level * 3 + 1);
+ ptr = relative;
+ for (; level; level--)
+ {
+ memcpy(ptr, ".." G_DIR_SEPARATOR_S, 3);
+ ptr += 3;
+ }
+ memcpy (ptr, grand_relative, len + 1);
+ g_free (grand_relative);
+ }
+ }
+
+ return relative;
+}
+
+static GFileType
+file_type (GFile *file, const gchar *filename)
+{
+ GFile *child;
+ GFileInfo *info;
+ GFileType type;
+
+ child = filename != NULL ? g_file_get_child (file, filename) : g_object_ref (file);
+
+ //g_message ("check file %s", g_file_get_path (child));
+
+ info = g_file_query_info (child,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info != NULL)
+ {
+ type = g_file_info_get_file_type (info);
+ g_object_unref (info);
+ }
+ else
+ {
+ type = G_FILE_TYPE_UNKNOWN;
+ }
+
+ g_object_unref (child);
+
+ return type;
+}
+
+/* Group objects
+ *---------------------------------------------------------------------------*/
+
+static void
+mkp_group_add_token (MkpGroup *node, AnjutaToken *token, MkpGroupTokenCategory category)
+{
+ MkpGroupData *group;
+
+ g_return_if_fail ((node != NULL) && (node->data != NULL));
+
+ group = MKP_GROUP_DATA (node);
+ group->tokens[category] = g_list_prepend (group->tokens[category], token);
+}
+
+static GList *
+mkp_group_get_token (MkpGroup *node, MkpGroupTokenCategory category)
+{
+ MkpGroupData *group;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ group = MKP_GROUP_DATA (node);
+ return group->tokens[category];
+}
+
+static AnjutaTokenFile*
+mkp_group_set_makefile (MkpGroup *node, GFile *makefile)
+{
+ MkpGroupData *group;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ group = MKP_GROUP_DATA (node);
+ if (group->makefile != NULL) g_object_unref (group->makefile);
+ if (group->tfile != NULL) anjuta_token_file_free (group->tfile);
+ if (makefile != NULL)
+ {
+ group->makefile = g_object_ref (makefile);
+ group->tfile = anjuta_token_file_new (makefile);
+ }
+ else
+ {
+ group->makefile = NULL;
+ group->tfile = NULL;
+ }
+
+ return group->tfile;
+}
+
+static MkpGroup*
+mkp_group_new (GFile *file)
+{
+ MkpGroupData *group = NULL;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ group = g_slice_new0(MkpGroupData);
+ group->base.node.type = ANJUTA_PROJECT_GROUP;
+ group->base.directory = g_object_ref (file);
+
+ return g_node_new (group);
+}
+
+static void
+mkp_group_free (MkpGroup *node)
+{
+ MkpGroupData *group = (MkpGroupData *)node->data;
+ gint i;
+
+ if (group->base.directory) g_object_unref (group->base.directory);
+ if (group->tfile) anjuta_token_file_free (group->tfile);
+ if (group->makefile) g_object_unref (group->makefile);
+ for (i = 0; i < AM_GROUP_TOKEN_LAST; i++)
+ {
+ if (group->tokens[i] != NULL) g_list_free (group->tokens[i]);
+ }
+ g_slice_free (MkpGroupData, group);
+
+ g_node_destroy (node);
+}
+
+/* Target objects
+ *---------------------------------------------------------------------------*/
+
+void
+mkp_target_add_token (MkpGroup *node, AnjutaToken *token)
+{
+ MkpTargetData *target;
+
+ g_return_if_fail ((node != NULL) && (node->data != NULL));
+
+ target = MKP_TARGET_DATA (node);
+ target->tokens = g_list_prepend (target->tokens, token);
+}
+
+static GList *
+mkp_target_get_token (MkpGroup *node)
+{
+ MkpTargetData *target;
+
+ g_return_val_if_fail ((node != NULL) && (node->data != NULL), NULL);
+
+ target = MKP_TARGET_DATA (node);
+ return target->tokens;
+}
+
+
+MkpTarget*
+mkp_target_new (const gchar *name, AnjutaProjectTargetType type)
+{
+ MkpTargetData *target = NULL;
+
+ target = g_slice_new0(MkpTargetData);
+ target->base.node.type = ANJUTA_PROJECT_TARGET;
+ target->base.name = g_strdup (name);
+ if (type == NULL) type = (AnjutaProjectTargetType)&MkpTargetTypes[0];
+ target->base.type = type;
+
+ return g_node_new (target);
+}
+
+void
+mkp_target_free (MkpTarget *node)
+{
+ MkpTargetData *target = MKP_TARGET_DATA (node);
+
+ g_free (target->base.name);
+ g_free (target->install);
+ g_slice_free (MkpTargetData, target);
+
+ g_node_destroy (node);
+}
+
+/* Source objects
+ *---------------------------------------------------------------------------*/
+
+MkpSource*
+mkp_source_new (GFile *file)
+{
+ MkpSourceData *source = NULL;
+
+ source = g_slice_new0(MkpSourceData);
+ source->base.node.type = ANJUTA_PROJECT_SOURCE;
+ source->base.file = g_object_ref (file);
+
+ return g_node_new (source);
+}
+
+static void
+mkp_source_free (MkpSource *node)
+{
+ MkpSourceData *source = MKP_SOURCE_DATA (node);
+
+ g_object_unref (source->base.file);
+ g_slice_free (MkpSourceData, source);
+
+ g_node_destroy (node);
+}
+
+/*
+ * File monitoring support --------------------------------
+ * FIXME: review these
+ */
+static void
+monitor_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer data)
+{
+ MkpProject *project = data;
+
+ g_return_if_fail (project != NULL && MKP_IS_PROJECT (project));
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ /* monitor will be removed here... is this safe? */
+ mkp_project_reload (project, NULL);
+ g_signal_emit_by_name (G_OBJECT (project), "project-updated");
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void
+monitor_add (MkpProject *project, GFile *file)
+{
+ GFileMonitor *monitor = NULL;
+
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (project->monitors != NULL);
+
+ if (file == NULL)
+ return;
+
+ monitor = g_hash_table_lookup (project->monitors, file);
+ if (!monitor) {
+ gboolean exists;
+
+ /* FIXME clarify if uri is uri, path or both */
+ exists = g_file_query_exists (file, NULL);
+
+ if (exists) {
+ monitor = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
+ if (monitor != NULL)
+ {
+ g_signal_connect (G_OBJECT (monitor),
+ "changed",
+ G_CALLBACK (monitor_cb),
+ project);
+ g_hash_table_insert (project->monitors,
+ g_object_ref (file),
+ monitor);
+ }
+ }
+ }
+}
+
+static void
+monitors_remove (MkpProject *project)
+{
+ g_return_if_fail (project != NULL);
+
+ if (project->monitors)
+ g_hash_table_destroy (project->monitors);
+ project->monitors = NULL;
+}
+
+static void
+group_hash_foreach_monitor (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ MkpGroup *group_node = value;
+ MkpProject *project = user_data;
+
+ monitor_add (project, MKP_GROUP_DATA(group_node)->base.directory);
+}
+
+static void
+monitors_setup (MkpProject *project)
+{
+ g_return_if_fail (project != NULL);
+
+ monitors_remove (project);
+
+ /* setup monitors hash */
+ project->monitors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+ (GDestroyNotify) g_file_monitor_cancel);
+
+ //monitor_add (project, anjuta_token_file_get_file (project->make_file));
+ if (project->groups)
+ g_hash_table_foreach (project->groups, group_hash_foreach_monitor, project);
+}
+
+
+/*
+ * ---------------- Data structures managment
+ */
+
+static void
+mkp_dump_node (GNode *g_node)
+{
+ gchar *name = NULL;
+
+ switch (MKP_NODE_DATA (g_node)->type) {
+ case ANJUTA_PROJECT_GROUP:
+ name = g_file_get_uri (MKP_GROUP_DATA (g_node)->base.directory);
+ DEBUG_PRINT ("GROUP: %s", name);
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ name = g_strdup (MKP_TARGET_DATA (g_node)->base.name);
+ DEBUG_PRINT ("TARGET: %s", name);
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ name = g_file_get_uri (MKP_SOURCE_DATA (g_node)->base.file);
+ DEBUG_PRINT ("SOURCE: %s", name);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ g_free (name);
+}
+
+static gboolean
+foreach_node_destroy (GNode *g_node,
+ gpointer data)
+{
+ switch (MKP_NODE_DATA (g_node)->type) {
+ case ANJUTA_PROJECT_GROUP:
+ //g_hash_table_remove (project->groups, g_file_get_uri (MKP_GROUP_NODE (g_node)->file));
+ mkp_group_free (g_node);
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ mkp_target_free (g_node);
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ //g_hash_table_remove (project->sources, MKP_NODE (g_node)->id);
+ mkp_source_free (g_node);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+
+ return FALSE;
+}
+
+static void
+project_node_destroy (MkpProject *project, GNode *g_node)
+{
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (MKP_IS_PROJECT (project));
+
+ if (g_node) {
+ /* free each node's data first */
+ g_node_traverse (g_node,
+ G_POST_ORDER, G_TRAVERSE_ALL, -1,
+ foreach_node_destroy, project);
+
+ /* now destroy the tree itself */
+ //g_node_destroy (g_node);
+ }
+}
+
+static void
+find_target (GNode *node, gpointer data)
+{
+ if (MKP_NODE_DATA (node)->type == ANJUTA_PROJECT_TARGET)
+ {
+ if (strcmp (MKP_TARGET_DATA (node)->base.name, *(gchar **)data) == 0)
+ {
+ /* Find target, return node value in pointer */
+ *(GNode **)data = node;
+
+ return;
+ }
+ }
+}
+
+static AnjutaToken*
+project_load_rule (MkpProject *project, AnjutaToken *rule, GNode *parent)
+{
+ AnjutaToken *arg;
+ AnjutaToken *prerequisite;
+
+ /* Search for prerequisite */
+ prerequisite = NULL;
+ for (arg = anjuta_token_list_first (rule); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ if (anjuta_token_get_type (arg) == MK_TOKEN_PREREQUISITE)
+ {
+ prerequisite = anjuta_token_list_next (arg);
+ }
+ }
+
+ for (arg = anjuta_token_list_first (rule); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ gchar *value;
+ gpointer find;
+ MkpTarget *target;
+
+ value = anjuta_token_evaluate (arg);
+
+ /* Check if target already exists */
+ find = value;
+ g_node_children_foreach (parent, G_TRAVERSE_ALL, find_target, &find);
+ if ((gchar *)find != value)
+ {
+ /* Find target */
+ target = (MkpTarget *)find;
+ }
+ else
+ {
+ /* Create target */
+ target = mkp_target_new (value, (AnjutaProjectTargetType)&MkpTargetTypes[0]);
+ mkp_target_add_token (target, arg);
+ g_node_append (parent, target);
+ }
+
+ g_free (value);
+
+ /* Add prerequisite */
+ for (arg = prerequisite; arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ MkpSource *source;
+ GFile *src_file;
+
+ value = anjuta_token_evaluate (arg);
+ src_file = g_file_get_child (project->root_file, value);
+ source = mkp_source_new (src_file);
+ g_object_unref (src_file);
+ g_node_append (target, source);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+remove_make_file (gpointer data, GObject *object, gboolean is_last_ref)
+{
+ if (is_last_ref)
+ {
+ MkpProject *project = (MkpProject *)data;
+ g_hash_table_remove (project->files, anjuta_token_file_get_file (ANJUTA_TOKEN_FILE (object)));
+ }
+}
+
+static MkpGroup*
+project_load_makefile (MkpProject *project, GFile *file, MkpGroup *parent, GError **error)
+{
+ MkpScanner *scanner;
+ AnjutaToken *rule_tok;
+ AnjutaToken *arg;
+ AnjutaTokenFile *tfile;
+ gboolean found;
+ gboolean ok;
+ GError *err = NULL;
+
+ /* Parse makefile */
+ DEBUG_PRINT ("Parse: %s", g_file_get_uri (file));
+ tfile = mkp_group_set_makefile (parent, file);
+ g_hash_table_insert (project->files, g_object_ref (file), g_object_ref (tfile));
+// g_object_add_toggle_ref (G_OBJECT (project->make_file), remove_make_file, project);
+ scanner = mkp_scanner_new (project);
+ ok = mkp_scanner_parse (scanner, tfile, &err);
+ mkp_scanner_free (scanner);
+ if (!ok)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED,
+ err == NULL ? _("Unable to parse make file") : err->message);
+ if (err != NULL) g_error_free (err);
+
+ return NULL;
+ }
+
+ /* Load target */
+ mkp_project_enumerate_targets (project, parent);
+
+ /*rule_tok = anjuta_token_new_static (MK_TOKEN_RULE, NULL);
+
+ arg = anjuta_token_file_first (tfile);
+ for (found = anjuta_token_match (rule_tok, ANJUTA_SEARCH_INTO, arg, &arg); found; found = anjuta_token_match (rule_tok, ANJUTA_SEARCH_INTO, anjuta_token_next_sibling (arg), &arg))
+ {
+ project_load_rule (project, arg, parent);
+ }*/
+
+ return parent;
+}
+
+/* Project access functions
+ *---------------------------------------------------------------------------*/
+
+MkpGroup *
+mkp_project_get_root (MkpProject *project)
+{
+ MkpGroup *g_node = NULL;
+
+ if (project->root_file != NULL)
+ {
+ gchar *id = g_file_get_uri (project->root_file);
+ g_node = (MkpGroup *)g_hash_table_lookup (project->groups, id);
+ g_free (id);
+ }
+
+ return g_node;
+}
+
+GList *
+mkp_project_list_variable (MkpProject *project)
+{
+ return g_hash_table_get_values (project->variables);
+}
+
+MkpVariable*
+mkp_project_get_variable (MkpProject *project, const gchar *name)
+{
+ MkpVariable *var;
+
+ var = (MkpVariable *)g_hash_table_lookup (project->groups, name);
+
+ return var;
+}
+
+MkpGroup *
+mkp_project_get_group (MkpProject *project, const gchar *id)
+{
+ return (MkpGroup *)g_hash_table_lookup (project->groups, id);
+}
+
+MkpTarget *
+mkp_project_get_target (MkpProject *project, const gchar *id)
+{
+ MkpTarget **buffer;
+ MkpTarget *target;
+ gsize dummy;
+
+ buffer = (MkpTarget **)g_base64_decode (id, &dummy);
+ target = *buffer;
+ g_free (buffer);
+
+ return target;
+}
+
+MkpSource *
+mkp_project_get_source (MkpProject *project, const gchar *id)
+{
+ MkpSource **buffer;
+ MkpSource *source;
+ gsize dummy;
+
+ buffer = (MkpSource **)g_base64_decode (id, &dummy);
+ source = *buffer;
+ g_free (buffer);
+
+ return source;
+}
+
+gchar *
+mkp_project_get_node_id (MkpProject *project, const gchar *path)
+{
+ GNode *node = NULL;
+
+ if (path != NULL)
+ {
+ for (; *path != '\0';)
+ {
+ gchar *end;
+ guint child = g_ascii_strtoull (path, &end, 10);
+
+ if (end == path)
+ {
+ /* error */
+ return NULL;
+ }
+
+ if (node == NULL)
+ {
+ if (child == 0) node = project->root_node;
+ }
+ else
+ {
+ node = g_node_nth_child (node, child);
+ }
+ if (node == NULL)
+ {
+ /* no node */
+ return NULL;
+ }
+
+ if (*end == '\0') break;
+ path = end + 1;
+ }
+ }
+
+ switch (MKP_NODE_DATA (node)->type)
+ {
+ case ANJUTA_PROJECT_GROUP:
+ return g_file_get_uri (MKP_GROUP_DATA (node)->base.directory);
+ case ANJUTA_PROJECT_TARGET:
+ case ANJUTA_PROJECT_SOURCE:
+ return g_base64_encode ((guchar *)&node, sizeof (node));
+ default:
+ return NULL;
+ }
+}
+
+gchar *
+mkp_project_get_uri (MkpProject *project)
+{
+ g_return_val_if_fail (project != NULL, NULL);
+
+ return project->root_file != NULL ? g_file_get_uri (project->root_file) : NULL;
+}
+
+GFile*
+mkp_project_get_file (MkpProject *project)
+{
+ g_return_val_if_fail (project != NULL, NULL);
+
+ return project->root_file;
+}
+
+GList *
+mkp_project_get_target_types (MkpProject *project, GError **error)
+{
+ MkpTargetInformation *targets = MkpTargetTypes;
+ GList *types = NULL;
+
+ while (targets->base.name != NULL)
+ {
+ types = g_list_prepend (types, targets);
+ targets++;
+ }
+ types = g_list_reverse (types);
+
+ return types;
+}
+
+/* Group access functions
+ *---------------------------------------------------------------------------*/
+
+GFile*
+mkp_group_get_directory (MkpGroup *group)
+{
+ return MKP_GROUP_DATA (group)->base.directory;
+}
+
+GFile*
+mkp_group_get_makefile (MkpGroup *group)
+{
+ return MKP_GROUP_DATA (group)->makefile;
+}
+
+gchar *
+mkp_group_get_id (MkpGroup *group)
+{
+ return g_file_get_uri (MKP_GROUP_DATA (group)->base.directory);
+}
+
+/* Target access functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+mkp_target_get_name (MkpTarget *target)
+{
+ return MKP_TARGET_DATA (target)->base.name;
+}
+
+AnjutaProjectTargetType
+mkp_target_get_type (MkpTarget *target)
+{
+ return MKP_TARGET_DATA (target)->base.type;
+}
+
+gchar *
+mkp_target_get_id (MkpTarget *target)
+{
+ return g_base64_encode ((guchar *)&target, sizeof (target));
+}
+
+/* Source access functions
+ *---------------------------------------------------------------------------*/
+
+gchar *
+mkp_source_get_id (MkpSource *source)
+{
+ return g_base64_encode ((guchar *)&source, sizeof (source));
+}
+
+GFile*
+mkp_source_get_file (MkpSource *source)
+{
+ return MKP_SOURCE_DATA (source)->base.file;
+}
+
+/* Variable access functions
+ *---------------------------------------------------------------------------*/
+
+const gchar *
+mkp_variable_get_name (MkpVariable *variable)
+{
+ return variable->name;
+}
+
+gchar *
+mkp_variable_evaluate (MkpVariable *variable, AnjutaProjectNode *context)
+{
+ return anjuta_token_evaluate (variable->value);
+}
+
+static MkpVariable*
+mkp_variable_new (gchar *name, AnjutaTokenType assign, AnjutaToken *value)
+{
+ MkpVariable *variable = NULL;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ variable = g_slice_new0(MkpVariable);
+ variable->name = g_strdup (name);
+ variable->assign = assign;
+ variable->value = value;
+
+ return variable;
+}
+
+static void
+mkp_variable_free (MkpVariable *variable)
+{
+ g_free (variable->name);
+
+ g_slice_free (MkpVariable, variable);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+static void
+mkp_project_token_evaluate_token (MkpProject *project, AnjutaToken *token, GString *value)
+{
+ if ((token != NULL) && (anjuta_token_get_length (token) != 0))
+ {
+ gint type = anjuta_token_get_type (token);
+ guint length;
+ const gchar *string;
+ gchar *name;
+ MkpVariable *var;
+
+ switch (type)
+ {
+ case ANJUTA_TOKEN_COMMENT:
+ case ANJUTA_TOKEN_OPEN_QUOTE:
+ case ANJUTA_TOKEN_CLOSE_QUOTE:
+ case ANJUTA_TOKEN_ESCAPE:
+ break;
+ case MK_TOKEN_VARIABLE:
+ length = anjuta_token_get_length (token);
+ string = anjuta_token_get_string (token);
+ if (string[1] == '(')
+ {
+ name = g_strndup (string + 2, length - 3);
+ }
+ else
+ {
+ name = g_strndup (string + 1, 1);
+ }
+ var = g_hash_table_lookup (project->variables, name);
+ g_free (name);
+ if (var != NULL)
+ {
+ name = mkp_variable_evaluate (var, NULL);
+ g_string_append (value, name);
+ g_free (name);
+ }
+ break;
+ default:
+ g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
+ }
+ }
+}
+
+static void
+mkp_project_token_evaluate_child (MkpProject *project, AnjutaToken *token, GString *value)
+{
+ AnjutaToken *child;
+
+ mkp_project_token_evaluate_token (project, token, value);
+
+ child = anjuta_token_next_child (token);
+ if (child) mkp_project_token_evaluate_child (project, child, value);
+
+ child = anjuta_token_next_sibling (token);
+ if (child) mkp_project_token_evaluate_child (project, child, value);
+}
+
+gchar *mkp_project_token_evaluate (MkpProject *project, AnjutaToken *token)
+{
+ GString *value = g_string_new (NULL);
+ gchar *str;
+
+ if (token != NULL)
+ {
+ AnjutaToken *child;
+
+ mkp_project_token_evaluate_token (project, token, value);
+
+ child = anjuta_token_next_child (token);
+ if (child != NULL) mkp_project_token_evaluate_child (project, child, value);
+ }
+
+ str = g_string_free (value, FALSE);
+ return *str == '\0' ? NULL : str;
+}
+
+gboolean
+mkp_project_reload (MkpProject *project, GError **error)
+{
+ GFile *root_file;
+ GFile *make_file;
+ const gchar **makefile;
+ MkpGroup *group;
+ gboolean ok = TRUE;
+
+ /* Unload current project */
+ root_file = g_object_ref (project->root_file);
+ mkp_project_unload (project);
+ project->root_file = root_file;
+ DEBUG_PRINT ("reload project %p root file %p", project, project->root_file);
+
+ /* shortcut hash tables */
+ project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
+ project->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, mkp_variable_free);
+
+ /* Initialize rules data */
+ mkp_project_init_rules (project);
+
+ /* Initialize list styles */
+ project->space_list = anjuta_token_style_new (NULL, " ", "\\n", NULL, 0);
+ project->arg_list = anjuta_token_style_new (NULL, ", ", ",\\n ", ")", 0);
+
+ /* Find make file */
+ for (makefile = valid_makefiles; *makefile != NULL; makefile++)
+ {
+ if (file_type (root_file, *makefile) == G_FILE_TYPE_REGULAR)
+ {
+ make_file = g_file_get_child (root_file, *makefile);
+ break;
+ }
+ }
+ if (make_file == NULL)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Project doesn't exist or invalid path"));
+
+ return FALSE;
+ }
+
+ /* Create group */
+ group = mkp_group_new (root_file);
+ g_hash_table_insert (project->groups, g_file_get_uri (root_file), group);
+ project->root_node = group;
+
+
+ /* Parse make file */
+ project_load_makefile (project, make_file, group, error);
+ g_object_unref (make_file);
+
+ monitors_setup (project);
+
+
+ return ok;
+}
+
+gboolean
+mkp_project_load (MkpProject *project,
+ GFile *directory,
+ GError **error)
+{
+ g_return_val_if_fail (directory != NULL, FALSE);
+
+ project->root_file = g_object_ref (directory);
+ if (!mkp_project_reload (project, error))
+ {
+ g_object_unref (project->root_file);
+ project->root_file = NULL;
+ }
+
+ return project->root_file != NULL;
+}
+
+void
+mkp_project_unload (MkpProject *project)
+{
+ monitors_remove (project);
+
+ /* project data */
+ project_node_destroy (project, project->root_node);
+ project->root_node = NULL;
+
+ if (project->root_file) g_object_unref (project->root_file);
+ project->root_file = NULL;
+
+ /* shortcut hash tables */
+ if (project->groups) g_hash_table_destroy (project->groups);
+ project->groups = NULL;
+ if (project->files) g_hash_table_destroy (project->files);
+ project->files = NULL;
+ if (project->variables) g_hash_table_destroy (project->variables);
+ project->variables = NULL;
+
+ mkp_project_free_rules (project);
+
+ /* List styles */
+ if (project->space_list) anjuta_token_style_free (project->space_list);
+ if (project->arg_list) anjuta_token_style_free (project->arg_list);
+}
+
+gint
+mkp_project_probe (GFile *directory,
+ GError **error)
+{
+ gboolean probe;
+ gboolean dir;
+
+ dir = (file_type (directory, NULL) == G_FILE_TYPE_DIRECTORY);
+ if (!dir)
+ {
+ g_set_error (error, IANJUTA_PROJECT_ERROR,
+ IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+ _("Project doesn't exist or invalid path"));
+ }
+
+ probe = dir;
+ if (probe)
+ {
+ const gchar **makefile;
+
+ /* Look for makefiles */
+ probe = FALSE;
+ for (makefile = valid_makefiles; *makefile != NULL; makefile++)
+ {
+ if (file_type (directory, *makefile) == G_FILE_TYPE_REGULAR)
+ {
+ probe = TRUE;
+ break;
+ }
+ }
+ }
+
+ return probe ? IANJUTA_PROJECT_PROBE_MAKE_FILES : 0;
+}
+
+void
+mkp_project_update_variable (MkpProject *project, AnjutaToken *variable)
+{
+ AnjutaToken *arg;
+ char *name = NULL;
+ MakeTokenType assign = 0;
+ AnjutaToken *value = NULL;
+
+ for (arg = anjuta_token_next_child (variable); arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ if (anjuta_token_get_type (arg) == ANJUTA_TOKEN_NAME)
+ {
+ name = g_strstrip (anjuta_token_evaluate (arg));
+ break;
+ }
+ }
+ for (; arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ switch (anjuta_token_get_type (arg))
+ {
+ case MK_TOKEN_EQUAL:
+ case MK_TOKEN_IMMEDIATE_EQUAL:
+ case MK_TOKEN_CONDITIONAL_EQUAL:
+ case MK_TOKEN_APPEND:
+ assign = anjuta_token_get_type (arg);
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ for (; arg != NULL; arg = anjuta_token_next_sibling (arg))
+ {
+ if (anjuta_token_get_type (arg) == ANJUTA_TOKEN_VALUE)
+ {
+ value = arg;
+ break;
+ }
+ }
+
+ if (assign != 0)
+ {
+ MkpVariable *var;
+
+ var = (MkpVariable *)g_hash_table_lookup (project->variables, name);
+ if (var != NULL)
+ {
+ var->assign = assign;
+ var->value = value;
+ }
+ else
+ {
+ var = mkp_variable_new (name, assign, value);
+ g_hash_table_insert (project->variables, var->name, var);
+ }
+
+ }
+
+ g_message ("update variable %s", name);
+
+ if (name) g_free (name);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+mkp_project_save (MkpProject *project, GError **error)
+{
+ gpointer key;
+ gpointer value;
+ GHashTableIter iter;
+
+ g_return_val_if_fail (project != NULL, FALSE);
+
+ g_hash_table_iter_init (&iter, project->files);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GError *error = NULL;
+ AnjutaTokenFile *tfile = (AnjutaTokenFile *)value;
+ ;
+ anjuta_token_file_save (tfile, &error);
+ }
+
+ return TRUE;
+}
+
+gboolean
+mkp_project_move (MkpProject *project, const gchar *path)
+{
+ GFile *old_root_file;
+ GFile *new_file;
+ gchar *relative;
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ AnjutaTokenFile *tfile;
+ GHashTable* old_hash;
+
+ /* Change project root directory */
+ old_root_file = project->root_file;
+ project->root_file = g_file_new_for_path (path);
+
+ /* Change project root directory in groups */
+ old_hash = project->groups;
+ project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_hash_table_iter_init (&iter, old_hash);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ MkpGroup *group = (MkpGroup *)value;
+
+ relative = get_relative_path (old_root_file, MKP_GROUP_DATA (group)->base.directory);
+ new_file = g_file_resolve_relative_path (project->root_file, relative);
+ g_free (relative);
+ g_object_unref (MKP_GROUP_DATA (group)->base.directory);
+ MKP_GROUP_DATA (group)->base.directory = new_file;
+
+ g_hash_table_insert (project->groups, g_file_get_uri (new_file), group);
+ }
+ g_hash_table_destroy (old_hash);
+
+ /* Change all files */
+ old_hash = project->files;
+ project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
+ g_hash_table_iter_init (&iter, old_hash);
+ while (g_hash_table_iter_next (&iter, &key, (gpointer *)&tfile))
+ {
+ relative = get_relative_path (old_root_file, anjuta_token_file_get_file (tfile));
+ new_file = g_file_resolve_relative_path (project->root_file, relative);
+ g_free (relative);
+ anjuta_token_file_move (tfile, new_file);
+
+ g_hash_table_insert (project->files, new_file, tfile);
+ g_object_unref (key);
+ }
+ g_hash_table_steal_all (old_hash);
+ g_hash_table_destroy (old_hash);
+
+ g_object_unref (old_root_file);
+
+ return TRUE;
+}
+
+MkpProject *
+mkp_project_new (void)
+{
+ return MKP_PROJECT (g_object_new (MKP_TYPE_PROJECT, NULL));
+}
+
+/* Implement IAnjutaProject
+ *---------------------------------------------------------------------------*/
+
+static AnjutaProjectGroup*
+iproject_add_group (IAnjutaProject *obj, AnjutaProjectGroup *parent, const gchar *name, GError **err)
+{
+ return NULL;
+}
+
+static AnjutaProjectSource*
+iproject_add_source (IAnjutaProject *obj, AnjutaProjectTarget *parent, GFile *file, GError **err)
+{
+ return NULL;
+}
+
+static AnjutaProjectTarget*
+iproject_add_target (IAnjutaProject *obj, AnjutaProjectGroup *parent, const gchar *name, AnjutaProjectTargetType type, GError **err)
+{
+ return NULL;
+}
+
+static GtkWidget*
+iproject_configure (IAnjutaProject *obj, GError **err)
+{
+ return NULL;
+}
+
+static guint
+iproject_get_capabilities (IAnjutaProject *obj, GError **err)
+{
+ return IANJUTA_PROJECT_CAN_ADD_NONE;
+}
+
+static GList*
+iproject_get_packages (IAnjutaProject *obj, GError **err)
+{
+ return NULL;
+}
+
+static AnjutaProjectGroup*
+iproject_get_root (IAnjutaProject *obj, GError **err)
+{
+ return mkp_project_get_root (MKP_PROJECT (obj));
+}
+
+static GList*
+iproject_get_target_types (IAnjutaProject *obj, GError **err)
+{
+ return mkp_project_get_target_types (MKP_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_load (IAnjutaProject *obj, GFile *file, GError **err)
+{
+ return mkp_project_load (MKP_PROJECT (obj), file, err);
+}
+
+static gboolean
+iproject_refresh (IAnjutaProject *obj, GError **err)
+{
+ return mkp_project_reload (MKP_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_remove_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+{
+ return TRUE;
+}
+
+static void
+iproject_iface_init(IAnjutaProjectIface* iface)
+{
+ iface->add_group = iproject_add_group;
+ iface->add_source = iproject_add_source;
+ iface->add_target = iproject_add_target;
+ iface->configure = iproject_configure;
+ iface->get_capabilities = iproject_get_capabilities;
+ iface->get_packages = iproject_get_packages;
+ iface->get_root = iproject_get_root;
+ iface->get_target_types = iproject_get_target_types;
+ iface->load = iproject_load;
+ iface->refresh = iproject_refresh;
+ iface->remove_node = iproject_remove_node;
+}
+
+/* GbfProject implementation
+ *---------------------------------------------------------------------------*/
+
+static void
+mkp_project_dispose (GObject *object)
+{
+ g_return_if_fail (MKP_IS_PROJECT (object));
+
+ mkp_project_unload (MKP_PROJECT (object));
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+mkp_project_instance_init (MkpProject *project)
+{
+ g_return_if_fail (project != NULL);
+ g_return_if_fail (MKP_IS_PROJECT (project));
+
+ /* project data */
+ project->root_file = NULL;
+ project->root_node = NULL;
+ project->property = NULL;
+ project->suffix = NULL;
+ project->rules = NULL;
+
+ project->space_list = NULL;
+ project->arg_list = NULL;
+}
+
+static void
+mkp_project_class_init (MkpProjectClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = mkp_project_dispose;
+}
+
+ANJUTA_TYPE_BEGIN(MkpProject, mkp_project, G_TYPE_OBJECT);
+ANJUTA_TYPE_ADD_INTERFACE(iproject, IANJUTA_TYPE_PROJECT);
+ANJUTA_TYPE_END;
+//GBF_BACKEND_BOILERPLATE (MkpProject, mkp_project);
diff --git a/plugins/mk-project/mk-project.h b/plugins/mk-project/mk-project.h
new file mode 100644
index 0000000..22c2fc0
--- /dev/null
+++ b/plugins/mk-project/mk-project.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* mk-project.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MK_PROJECT_H_
+#define _MK_PROJECT_H_
+
+#include <glib-object.h>
+
+#include <libanjuta/anjuta-project.h>
+#include <libanjuta/anjuta-token.h>
+#include <libanjuta/anjuta-token-file.h>
+#include <libanjuta/anjuta-token-style.h>
+
+G_BEGIN_DECLS
+
+#define YYSTYPE AnjutaToken*
+
+#define MKP_TYPE_PROJECT (mkp_project_get_type ())
+#define MKP_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MKP_TYPE_PROJECT, MkpProject))
+#define MKP_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MKP_TYPE_PROJECT, MkpProjectClass))
+#define MKP_IS_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MKP_TYPE_PROJECT))
+#define MKP_IS_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), MKP_TYPE_PROJECT))
+
+#define MKP_GROUP(obj) ((MkpGroup *)obj)
+#define MKP_TARGET(obj) ((MkpTarget *)obj)
+#define MKP_SOURCE(obj) ((MkpSource *)obj)
+
+typedef struct _MkpProject MkpProject;
+typedef struct _MkpProjectClass MkpProjectClass;
+
+struct _MkpProjectClass {
+ GObjectClass parent_class;
+};
+
+typedef AnjutaProjectGroup MkpGroup;
+typedef AnjutaProjectTarget MkpTarget;
+typedef AnjutaProjectSource MkpSource;
+typedef struct _MkpProperty MkpProperty;
+typedef struct _MkpVariable MkpVariable;
+typedef struct _MkpRule MkpRule;
+
+typedef enum {
+ MKP_PROPERTY_NAME = 0,
+ MKP_PROPERTY_VERSION,
+ MKP_PROPERTY_BUG_REPORT,
+ MKP_PROPERTY_TARNAME,
+ MKP_PROPERTY_URL
+} MkpPropertyType;
+
+
+GType mkp_project_get_type (void);
+MkpProject *mkp_project_new (void);
+
+
+gint mkp_project_probe (GFile *directory, GError **error);
+gboolean mkp_project_load (MkpProject *project, GFile *directory, GError **error);
+gboolean mkp_project_reload (MkpProject *project, GError **error);
+void mkp_project_unload (MkpProject *project);
+
+MkpGroup *mkp_project_get_root (MkpProject *project);
+MkpVariable *mkp_project_get_variable (MkpProject *project, const gchar *name);
+GList *mkp_project_list_variable (MkpProject *project);
+
+MkpGroup *mkp_project_get_group (MkpProject *project, const gchar *id);
+MkpTarget *mkp_project_get_target (MkpProject *project, const gchar *id);
+MkpSource *mkp_project_get_source (MkpProject *project, const gchar *id);
+
+gboolean mkp_project_move (MkpProject *project, const gchar *path);
+gboolean mkp_project_save (MkpProject *project, GError **error);
+
+gchar * mkp_project_get_uri (MkpProject *project);
+GFile* mkp_project_get_file (MkpProject *project);
+
+MkpGroup* mkp_project_add_group (MkpProject *project, MkpGroup *parent, const gchar *name, GError **error);
+void mkp_project_remove_group (MkpProject *project, MkpGroup *group, GError **error);
+
+MkpTarget* mkp_project_add_target (MkpProject *project, MkpGroup *parent, const gchar *name, const gchar *type, GError **error);
+void mkp_project_remove_target (MkpProject *project, MkpTarget *target, GError **error);
+
+MkpSource* mkp_project_add_source (MkpProject *project, MkpTarget *target, const gchar *uri, GError **error);
+void mkp_project_remove_source (MkpProject *project, MkpSource *source, GError **error);
+
+gchar * mkp_project_get_node_id (MkpProject *project, const gchar *path);
+
+GFile *mkp_group_get_directory (MkpGroup *group);
+GFile *mkp_group_get_makefile (MkpGroup *group);
+gchar *mkp_group_get_id (MkpGroup *group);
+
+const gchar *mkp_target_get_name (MkpTarget *target);
+AnjutaProjectTargetType amp_target_get_type (MkpTarget *target);
+gchar *mkp_target_get_id (MkpTarget *target);
+
+gchar *mkp_source_get_id (MkpSource *source);
+GFile *mkp_source_get_file (MkpSource *source);
+
+gchar *mkp_variable_evaluate (MkpVariable *variable, AnjutaProjectNode *context);
+const gchar* mkp_variable_get_name (MkpVariable *variable);
+
+G_END_DECLS
+
+#endif /* _MK_PROJECT_H_ */
diff --git a/plugins/gbf-mkfile/gbf-mkfile.plugin.in b/plugins/mk-project/mk-project.plugin.in
similarity index 78%
rename from plugins/gbf-mkfile/gbf-mkfile.plugin.in
rename to plugins/mk-project/mk-project.plugin.in
index d9aa4d5..543fc4c 100644
--- a/plugins/gbf-mkfile/gbf-mkfile.plugin.in
+++ b/plugins/mk-project/mk-project.plugin.in
@@ -1,8 +1,8 @@
[Anjuta Plugin]
_Name=Makefile backend
_Description=Makefile backend for project manager
-Location=gbf-mkfile:GbfMkfilePlugin
-Icon=gbf-mkfile-plugin-48.png
+Location=mk-project:MkpPlugin
+Icon=mk-project-plugin-48.png
Interfaces=IAnjutaProjectBackend
Dependencies=anjuta-project-manager:ProjectManagerPlugin
UserActivatable=no
diff --git a/plugins/mk-project/mk-project.ui b/plugins/mk-project/mk-project.ui
new file mode 100644
index 0000000..931f50b
--- /dev/null
+++ b/plugins/mk-project/mk-project.ui
@@ -0,0 +1,419 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="package_selection_dialog">
+ <property name="title" translatable="yes">Select package</property>
+ <property name="default_width">600</property>
+ <property name="default_height">500</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="pkg_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Select Package to add:</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancelbutton1">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okbutton1">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancelbutton1</action-widget>
+ <action-widget response="-3">okbutton1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkNotebook" id="top_level">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkTable" id="general_properties_table">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="n_rows">7</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="height_request">300</property>
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">5</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="add_module_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon-size">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add _module</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_package_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon-size">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add _Package</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_button">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTreeView" id="packages_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Packages</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="visible">True</property>
+ <property name="spacing">5</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="add_variable_button">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_variable_button">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">5</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="variables_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Variables</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/mk-project/mk-rule.c b/plugins/mk-project/mk-rule.c
new file mode 100644
index 0000000..39422ad
--- /dev/null
+++ b/plugins/mk-project/mk-rule.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* mk-rule.c
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "mk-rule.h"
+
+#include "mk-project-private.h"
+#include "mk-scanner.h"
+
+#include <string.h>
+
+/* Rule object
+ *---------------------------------------------------------------------------*/
+
+/* Maximum level of dependencies when searching for source files */
+#define MAX_DEPENDENCIES 16
+
+/* Rule object
+ *---------------------------------------------------------------------------*/
+
+static MkpRule*
+mkp_rule_new (gchar *name, AnjutaToken *token)
+{
+ MkpRule *rule = NULL;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ rule = g_slice_new0(MkpRule);
+ rule->name = g_strdup (name);
+ rule->rule = token;
+
+ return rule;
+}
+
+static void
+mkp_rule_free (MkpRule *rule)
+{
+ g_free (rule->name);
+ g_list_foreach (rule->prerequisite, (GFunc)g_free, NULL);
+ g_list_free (rule->prerequisite);
+
+ g_slice_free (MkpRule, rule);
+}
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+/* Find a source for target checking pattern rule. If no source is found,
+ * return target, else free target and return a newly allocated source name */
+
+gchar *
+mkp_project_find_source (MkpProject *project, gchar *target, AnjutaProjectGroup *parent, guint backtrack)
+{
+ GFile *child;
+ gboolean exist;
+ GHashTableIter iter;
+ gchar *key;
+ MkpRule *rule;
+
+ /* Check pattern rules */
+ if (backtrack < MAX_DEPENDENCIES)
+ {
+ for (g_hash_table_iter_init (&iter, project->rules); g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&rule);)
+ {
+ if (rule->pattern)
+ {
+ gchar *source;
+
+ if (rule->part == NULL)
+ {
+ /* simple suffix rule */
+ source = g_strconcat (target, rule->name, NULL);
+ }
+ else
+ {
+ /* double suffix rule */
+ if (strcmp (target + strlen (target) - strlen (rule->part), rule->part) == 0)
+ {
+ gchar *suffix;
+
+ source = g_strconcat (target, rule->name, NULL);
+ suffix = source + strlen (target) - strlen (rule->part);
+
+ memcpy (suffix, rule->name, rule->part - rule->name);
+ *(suffix + (rule->part - rule->name)) = '\0';
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ source = mkp_project_find_source (project, source, parent, backtrack + 1);
+
+ if (source != NULL)
+ {
+ g_free (target);
+
+ return source;
+ }
+ }
+ }
+ }
+
+ child = g_file_get_child (anjuta_project_group_get_directory (parent), target);
+ exist = g_file_query_exists (child, NULL);
+ g_message ("target =%s= filename =%s=", target, g_file_get_parse_name (child));
+ g_object_unref (child);
+
+ if (!exist)
+ {
+ g_free (target);
+ return NULL;
+ }
+ else
+ {
+ return target;
+ }
+}
+
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+void
+mkp_project_add_rule (MkpProject *project, AnjutaToken *token)
+{
+ AnjutaToken *targ;
+ AnjutaToken *dep;
+ AnjutaToken *arg;
+ gboolean double_colon = FALSE;
+
+ targ = anjuta_token_list_first (token);
+ arg = anjuta_token_list_next (targ);
+ if (anjuta_token_get_type (arg) == MK_TOKEN_DOUBLE_COLON) double_colon = TRUE;
+ dep = anjuta_token_list_next (arg);
+ for (arg = anjuta_token_list_first (targ); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ AnjutaToken *src;
+ gchar *target;
+ gboolean order = FALSE;
+ gboolean no_token = TRUE;
+ MkpRule *rule;
+
+ switch (anjuta_token_get_type (arg))
+ {
+ case MK_TOKEN__PHONY:
+ for (src = anjuta_token_list_first (dep); src != NULL; src = anjuta_token_list_next (src))
+ {
+ if (anjuta_token_get_type (src) != MK_TOKEN_ORDER)
+ {
+ target = mkp_project_token_evaluate (project, src);
+
+ rule = g_hash_table_lookup (project->rules, target);
+ if (rule == NULL)
+ {
+ rule = mkp_rule_new (target, NULL);
+ g_hash_table_insert (project->rules, rule->name, rule);
+ }
+ rule->phony = TRUE;
+
+ g_message (" with target %s", target);
+ if (target != NULL) g_free (target);
+ }
+ }
+ break;
+ case MK_TOKEN__SUFFIXES:
+ for (src = anjuta_token_list_first (dep); src != NULL; src = anjuta_token_list_next (src))
+ {
+ if (anjuta_token_get_type (src) != MK_TOKEN_ORDER)
+ {
+ gchar *suffix;
+
+ suffix = mkp_project_token_evaluate (project, src);
+ /* The pointer value must only be not NULL, it does not matter if it is
+ * invalid */
+ g_hash_table_replace (project->suffix, suffix, suffix);
+ g_message (" with suffix %s", suffix);
+ no_token = FALSE;
+ }
+ }
+ if (no_token == TRUE)
+ {
+ /* Clear all suffix */
+ g_hash_table_remove_all (project->suffix);
+ }
+ break;
+ case MK_TOKEN__DEFAULT:
+ case MK_TOKEN__PRECIOUS:
+ case MK_TOKEN__INTERMEDIATE:
+ case MK_TOKEN__SECONDARY:
+ case MK_TOKEN__SECONDEXPANSION:
+ case MK_TOKEN__DELETE_ON_ERROR:
+ case MK_TOKEN__IGNORE:
+ case MK_TOKEN__LOW_RESOLUTION_TIME:
+ case MK_TOKEN__SILENT:
+ case MK_TOKEN__EXPORT_ALL_VARIABLES:
+ case MK_TOKEN__NOTPARALLEL:
+ /* Do nothing with these targets, just ignore them */
+ break;
+ default:
+ target = g_strstrip (mkp_project_token_evaluate (project, arg));
+ if (*target == '\0') break;
+ g_message ("add rule =%s=", target);
+
+ rule = g_hash_table_lookup (project->rules, target);
+ if (rule == NULL)
+ {
+ rule = mkp_rule_new (target, token);
+ g_hash_table_insert (project->rules, rule->name, rule);
+ }
+ else
+ {
+ rule->rule = arg;
+ }
+
+ for (src = anjuta_token_list_first (dep); src != NULL; src = anjuta_token_list_next (src))
+ {
+ gchar *src_name = mkp_project_token_evaluate (project, src);
+
+ g_message (" with source %s", src_name);
+ if (anjuta_token_get_type (src) == MK_TOKEN_ORDER)
+ {
+ order = TRUE;
+ }
+ rule->prerequisite = g_list_prepend (rule->prerequisite, src_name);
+ }
+
+ if (target != NULL) g_free (target);
+ }
+ }
+}
+
+void
+mkp_project_enumerate_targets (MkpProject *project, AnjutaProjectGroup *parent)
+{
+ GHashTableIter iter;
+ gpointer key;
+ MkpRule *rule;
+
+ /* Check pattern rules */
+ for (g_hash_table_iter_init (&iter, project->rules); g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&rule);)
+ {
+ if (rule->phony) continue;
+
+ if (g_hash_table_lookup (project->suffix, rule->name))
+ {
+ /* Single suffix rule */
+ rule->pattern = TRUE;
+ rule->part = NULL;
+ }
+ else
+ {
+ GString *pattern = g_string_sized_new (16);
+ GList *suffix;
+ GList *src;
+
+ /* Check double suffix rule */
+ suffix = g_hash_table_get_keys (project->suffix);
+
+ for (src = g_list_first (suffix); src != NULL; src = g_list_next (src))
+ {
+ GList *obj;
+
+ for (obj = g_list_first (suffix); obj != NULL; obj = g_list_next (obj))
+ {
+ g_string_assign (pattern, src->data);
+ g_string_append (pattern, obj->data);
+
+ if (strcmp (pattern->str, rule->name) == 0)
+ {
+ rule->pattern = TRUE;
+ rule->part = rule->name + strlen (src->data);
+ break;
+ }
+ }
+ if (rule->pattern) break;
+ }
+
+ g_string_free (pattern, TRUE);
+ g_list_free (suffix);
+ }
+ }
+
+ /* Create new target */
+ for (g_hash_table_iter_init (&iter, project->rules); g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&rule);)
+ {
+ MkpTarget *target;
+ AnjutaToken *prerequisite;
+ AnjutaToken *arg;
+
+ g_message ("rule =%s=", rule->name);
+ if (rule->phony || rule->pattern) continue;
+
+ /* Create target */
+ target = mkp_target_new (rule->name, NULL);
+ mkp_target_add_token (target, rule->rule);
+ g_node_append (parent, target);
+
+ /* Search for prerequisite */
+ prerequisite = NULL;
+ for (arg = anjuta_token_list_first (rule->rule); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ if (anjuta_token_get_type (arg) == MK_TOKEN_PREREQUISITE)
+ {
+ prerequisite = arg;
+ break;
+ }
+ }
+
+ /* Add prerequisite */
+ for (arg = anjuta_token_list_first (prerequisite); arg != NULL; arg = anjuta_token_list_next (arg))
+ {
+ MkpSource *source;
+ GFile *src_file;
+ gchar *name;
+
+ name = g_strstrip (mkp_project_token_evaluate (project, arg));
+ name = mkp_project_find_source (project, name, parent, 0);
+
+ if (name != NULL)
+ {
+ src_file = g_file_get_child (project->root_file, name);
+ source = mkp_source_new (src_file);
+ g_object_unref (src_file);
+ g_node_append (target, source);
+
+ g_free (name);
+ }
+ }
+
+ }
+}
+
+void
+mkp_project_init_rules (MkpProject *project)
+{
+ project->rules = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)mkp_rule_free);
+ project->suffix = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+void
+mkp_project_free_rules (MkpProject *project)
+{
+ if (project->rules) g_hash_table_destroy (project->rules);
+ project->rules = NULL;
+ if (project->suffix) g_hash_table_destroy (project->suffix);
+ project->suffix = NULL;
+}
+
diff --git a/plugins/mk-project/mk-rule.h b/plugins/mk-project/mk-rule.h
new file mode 100644
index 0000000..e02db66
--- /dev/null
+++ b/plugins/mk-project/mk-rule.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* mk-rule.h
+ *
+ * Copyright (C) 2009 Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MK_RULE_H_
+#define _MK_RULE_H_
+
+#include <glib-object.h>
+
+#include "mk-project.h"
+
+
+G_BEGIN_DECLS
+
+void mkp_project_init_rules (MkpProject *project);
+void mkp_project_free_rules (MkpProject *project);
+void mkp_project_enumerate_targets (MkpProject *project, AnjutaProjectGroup *parent);
+
+G_END_DECLS
+
+#endif /* _MK_RULE_H_ */
diff --git a/plugins/mk-project/mk-scanner.h b/plugins/mk-project/mk-scanner.h
new file mode 100644
index 0000000..dd5ec57
--- /dev/null
+++ b/plugins/mk-project/mk-scanner.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * mk-scanner.h
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MK_SCANNER_H_
+#define _MK_SCANNER_H_
+
+#include "libanjuta/anjuta-token.h"
+#include "libanjuta/anjuta-token-file.h"
+#include "libanjuta/anjuta-token-style.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define YYSTYPE AnjutaToken*
+
+#ifndef _MK_PROJECT_H_
+typedef struct _MkpProject MkpProject;
+#endif
+
+typedef struct _MkpScanner MkpScanner;
+
+MkpScanner *mkp_scanner_new (MkpProject *project);
+void mkp_scanner_free (MkpScanner *scanner);
+
+gboolean mkp_scanner_parse (MkpScanner *scanner, AnjutaTokenFile *file, GError **error);
+
+void mkp_scanner_update_variable (MkpScanner *scanner, AnjutaToken *variable);
+void mkp_scanner_add_rule (MkpScanner *scanner, AnjutaToken *rule);
+
+const gchar* mkp_scanner_get_filename (MkpScanner *scanner);
+
+typedef enum
+{
+ MK_TOKEN_RULE = ANJUTA_TOKEN_USER,
+ MK_TOKEN_EQUAL,
+ MK_TOKEN_IMMEDIATE_EQUAL,
+ MK_TOKEN_CONDITIONAL_EQUAL,
+ MK_TOKEN_APPEND,
+ MK_TOKEN_TARGET,
+ MK_TOKEN_PREREQUISITE,
+ MK_TOKEN_ORDER_PREREQUISITE,
+ MK_TOKEN_ORDER,
+ MK_TOKEN_COLON,
+ MK_TOKEN_DOUBLE_COLON,
+ MK_TOKEN_VARIABLE,
+ MK_TOKEN__PHONY,
+ MK_TOKEN__SUFFIXES,
+ MK_TOKEN__DEFAULT,
+ MK_TOKEN__PRECIOUS,
+ MK_TOKEN__INTERMEDIATE,
+ MK_TOKEN__SECONDARY,
+ MK_TOKEN__SECONDEXPANSION,
+ MK_TOKEN__DELETE_ON_ERROR,
+ MK_TOKEN__IGNORE,
+ MK_TOKEN__LOW_RESOLUTION_TIME,
+ MK_TOKEN__SILENT,
+ MK_TOKEN__EXPORT_ALL_VARIABLES,
+ MK_TOKEN__NOTPARALLEL,
+} MakeTokenType;
+
+G_END_DECLS
+
+#endif
diff --git a/plugins/mk-project/mk-scanner.l b/plugins/mk-project/mk-scanner.l
new file mode 100644
index 0000000..972069d
--- /dev/null
+++ b/plugins/mk-project/mk-scanner.l
@@ -0,0 +1,294 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * mk-scanner.l
+ * Copyright (C) Sébastien Granjoux 2009 <seb sfo free fr>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <stdlib.h>
+#include <string.h>
+#include "mk-scanner.h"
+#include "mk-parser.h"
+
+#include "libanjuta/anjuta-debug.h"
+
+
+/* Eliminate warning */
+#define YY_NO_UNPUT 1
+
+#define YY_INPUT(buf,result,the_max_size) \
+ result = 0;
+
+#define YY_USER_ACTION mkp_update_location(yylloc, yytext, yyleng);
+
+#define YY_EXTRA_TYPE MkpScanner*
+
+//#define YY_USER_INIT {yy_flex_debug = 1;}
+
+static AnjutaToken* mkp_scanner_append_token (MkpScanner *scanner, gint token);
+static gint mkp_scanner_last_token (MkpScanner *scanner);
+static gint mkp_scanner_last_flags (MkpScanner *scanner);
+static void mkp_scanner_update_line_width (MkpScanner *scanner, YYLTYPE *loc);
+static void mkp_update_location (YYLTYPE *loc, const gchar *text, gint length);
+static int mkp_parse (yyscan_t scanner);
+
+void mkp_project_update_variable (MkpProject *project, AnjutaToken *variable);
+void mkp_project_add_rule (MkpProject *project, AnjutaToken *rule);
+
+
+#define RETURN(tok) *yylval = mkp_scanner_append_token (yyextra, tok); \
+ return tok
+
+%}
+
+%option reentrant stack noyywrap yylineno
+
+%option prefix="mkp_mk_yy"
+
+/* Necessary because autotools wrapper always looks for a file named "lex.yy.c",
+ * not "lex.mkp_yy.c"
+%option outfile="lex.yy.c"*/
+
+%option bison-bridge bison-locations
+
+%option never-interactive
+
+%option batch
+
+%option debug
+
+NAME [^ \t\n\r:#=$"'`&@\\]*
+
+%%
+
+\n { RETURN (EOL); }
+
+
+([ ]|\\\n)([ \t]|\\\n)* { RETURN (SPACE); }
+
+# { RETURN (HASH); }
+
+\t { RETURN (TAB); }
+
+\$\([^ \t\n\r:#=$)]+\) { RETURN (VARIABLE); }
+
+\$\{[^ \t\n\r:#=$}]+\} { RETURN (VARIABLE); }
+
+\$[^ \t\n\r\(\{] { RETURN (VARIABLE); }
+
+, { RETURN (COMMA); }
+
+: { RETURN (COLON); }
+
+:: { RETURN (DOUBLE_COLON); }
+
+; { RETURN (SEMI_COLON); }
+
+\| { RETURN (ORDER); }
+
+\= { RETURN (EQUAL); }
+
+:= { RETURN (IMMEDIATE_EQUAL); }
+
+\?= { RETURN (CONDITIONAL_EQUAL); }
+
+\+= { RETURN (APPEND); }
+
+\\[ ] { RETURN (CHARACTER); }
+
+\\: { RETURN (CHARACTER); }
+
+\\= { RETURN (CHARACTER); }
+
+\\# { RETURN (CHARACTER); }
+
+.PHONY { RETURN (_PHONY); }
+
+.SUFFIXES { RETURN (_SUFFIXES); }
+
+.DEFAULT { RETURN (_DEFAULT); }
+
+.PRECIOUS { RETURN (_PRECIOUS); }
+
+.INTERMEDIATE { RETURN (_INTERMEDIATE); }
+
+.SECONDARY { RETURN (_SECONDARY); }
+
+.SECONDEXPANSION { RETURN (_SECONDEXPANSION); }
+
+.DELETE_ON_ERROR { RETURN (_DELETE_ON_ERROR); }
+
+.IGNORE { RETURN (_IGNORE); }
+
+.LOW_RESOLUTION_TIME { RETURN (_LOW_RESOLUTION_TIME); }
+
+.SILENT { RETURN (_SILENT); }
+
+.EXPORT_ALL_VARIABLES { RETURN (_EXPORT_ALL_VARIABLES); }
+
+.NOTPARALLEL { RETURN (_NOTPARALLEL); }
+
+{NAME} { RETURN (NAME);}
+
+. { RETURN (CHARACTER); }
+
+%%
+
+struct _MkpScanner
+{
+ const gchar *pos;
+ yyscan_t scanner;
+ YY_BUFFER_STATE buffer;
+
+ AnjutaTokenFile *file;
+ gchar *filename;
+
+ MkpProject *project;
+
+ guint line_width;
+};
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static AnjutaToken*
+mkp_scanner_append_token (MkpScanner *scanner, gint token)
+{
+ AnjutaToken *frag;
+
+ frag = anjuta_token_new_fragment (token, scanner->pos, yyget_leng (scanner->scanner));
+ anjuta_token_file_append (scanner->file, frag);
+ scanner->pos += yyget_leng (scanner->scanner);
+ //anjuta_token_old_dump (frag);
+
+ return frag;
+}
+
+static void
+mkp_scanner_update_line_width (MkpScanner *scanner, YYLTYPE *loc)
+{
+ anjuta_token_file_update_line_width (scanner->file, loc->last_column);
+}
+
+void
+mkp_scanner_update_variable (MkpScanner *scanner, AnjutaToken *variable)
+{
+ mkp_project_update_variable (scanner->project, variable);
+}
+
+void
+mkp_scanner_add_rule (MkpScanner *scanner, AnjutaToken *rule)
+{
+ mkp_project_add_rule (scanner->project, rule);
+}
+
+static void
+mkp_update_location (YYLTYPE *loc, const gchar *text, gint length)
+{
+ const gchar *ptr;
+ const gchar *end = text + length;
+
+ loc->first_line = loc->last_line;
+ loc->first_column = loc->last_column + 1;
+
+ for (ptr = text; ptr != end; ptr++)
+ {
+ if (*ptr == '\n')
+ {
+ loc->last_column = 0;
+ loc->last_line++;
+ length -= (ptr + 1 - text);
+ }
+ }
+
+ loc->last_column += length;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+int
+mkp_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,MkpScanner *scanner)
+{
+ return mkp_mk_yylex (yylval_param, yylloc_param, scanner->scanner);
+}
+
+
+gboolean
+mkp_scanner_parse (MkpScanner *scanner, AnjutaTokenFile *file, GError **error)
+{
+ if (scanner->buffer != NULL) yy_delete_buffer (scanner->buffer, scanner->scanner);
+
+ scanner->file = file;
+ if (scanner->file== NULL) return FALSE;
+
+ scanner->pos = anjuta_token_file_get_content (scanner->file, error);
+ if (scanner->pos == NULL) return FALSE;
+
+ scanner->buffer = yy_scan_string (scanner->pos, scanner->scanner);
+
+ return mkp_yyparse (scanner) == 0;
+}
+
+guint
+mkp_scanner_get_line_width (MkpScanner *scanner)
+{
+ return scanner->line_width;
+}
+
+const gchar*
+mkp_scanner_get_filename (MkpScanner *scanner)
+{
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+ if (scanner->file) scanner->filename = g_file_get_path (anjuta_token_file_get_file (scanner->file));
+
+ return scanner->filename;
+}
+
+
+/* Constructor & Destructor
+ *---------------------------------------------------------------------------*/
+
+MkpScanner *
+mkp_scanner_new (MkpProject *project)
+{
+ MkpScanner *scanner;
+
+ scanner = g_new0 (MkpScanner, 1);
+
+ yylex_init(&scanner->scanner);
+ yyset_extra (scanner, scanner->scanner);
+
+ scanner->project = project;
+
+ return scanner;
+};
+
+void
+mkp_scanner_free (MkpScanner *scanner)
+{
+ g_return_if_fail (scanner != NULL);
+
+ if (scanner->buffer != NULL) yy_delete_buffer (scanner->buffer, scanner->scanner);
+ yylex_destroy(scanner->scanner);
+
+ g_free (scanner->filename);
+ scanner->filename = NULL;
+
+ g_free (scanner);
+}
diff --git a/plugins/gbf-mkfile/plugin.c b/plugins/mk-project/plugin.c
similarity index 77%
rename from plugins/gbf-mkfile/plugin.c
rename to plugins/mk-project/plugin.c
index 4d0d60f..f4db9b4 100644
--- a/plugins/gbf-mkfile/plugin.c
+++ b/plugins/mk-project/plugin.c
@@ -18,17 +18,16 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define DEBUG
#include <config.h>
#include <libanjuta/anjuta-debug.h>
#include <libanjuta/gbf-project.h>
#include <libanjuta/interfaces/ianjuta-project-backend.h>
#include "plugin.h"
-#include "gbf-mkfile-project.h"
+#include "mk-project.h"
-#define ICON_FILE "gbf-mkfile-plugin-48.png"
+#define ICON_FILE "mk-project-plugin-48.png"
/* AnjutaPlugin functions
*---------------------------------------------------------------------------*/
@@ -36,7 +35,7 @@
static gboolean
activate_plugin (AnjutaPlugin *plugin)
{
- DEBUG_PRINT ("GbfMkfilePlugin: Activating Gnome build makefile backend Plugin ...");
+ DEBUG_PRINT ("MkpPlugin: Activating Anjuta make backend Plugin ...");
return TRUE;
}
@@ -44,7 +43,7 @@ activate_plugin (AnjutaPlugin *plugin)
static gboolean
deactivate_plugin (AnjutaPlugin *plugin)
{
- DEBUG_PRINT ("GbfMkfilePlugin: Deactivating Gnome build makefile backend Plugin ...");
+ DEBUG_PRINT ("MkpPlugin: Deacctivating Anjuta make backend Plugin ...");
return TRUE;
}
@@ -52,20 +51,29 @@ deactivate_plugin (AnjutaPlugin *plugin)
/* IAnjutaProjectBackend implementation
*---------------------------------------------------------------------------*/
-static GbfProject*
+static IAnjutaProject*
iproject_backend_new_project (IAnjutaProjectBackend* backend, GError** err)
{
- GbfProject *project;
-
- project = gbf_mkfile_project_new ();
+ IAnjutaProject *project;
+ DEBUG_PRINT("create new mkp project");
+ project = (IAnjutaProject *)(g_object_new (MKP_TYPE_PROJECT, NULL));
return project;
}
+static gint
+iproject_backend_probe (IAnjutaProjectBackend* backend, GFile *directory, GError** err)
+{
+ DEBUG_PRINT("probe mkp project");
+
+ return mkp_project_probe (directory, err);
+}
+
static void
iproject_backend_iface_init(IAnjutaProjectBackendIface *iface)
{
iface->new_project = iproject_backend_new_project;
+ iface->probe = iproject_backend_probe;
}
/* GObject functions
@@ -75,7 +83,7 @@ iproject_backend_iface_init(IAnjutaProjectBackendIface *iface)
static gpointer parent_class;
static void
-gbf_mkfile_plugin_instance_init (GObject *obj)
+mkp_plugin_instance_init (GObject *obj)
{
}
@@ -96,7 +104,7 @@ finalize (GObject *obj)
}
static void
-gbf_mkfile_plugin_class_init (GObjectClass *klass)
+mkp_plugin_class_init (GObjectClass *klass)
{
AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
@@ -111,13 +119,8 @@ gbf_mkfile_plugin_class_init (GObjectClass *klass)
/* AnjutaPlugin declaration
*---------------------------------------------------------------------------*/
-ANJUTA_PLUGIN_BEGIN (GbfMkfilePlugin, gbf_mkfile_plugin);
+ANJUTA_PLUGIN_BEGIN (MkpPlugin, mkp_plugin);
ANJUTA_PLUGIN_ADD_INTERFACE (iproject_backend, IANJUTA_TYPE_PROJECT_BACKEND);
ANJUTA_PLUGIN_END;
-G_MODULE_EXPORT void
-anjuta_glue_register_components (GTypeModule *module)
-{
- gbf_mkfile_plugin_get_type (module);
- gbf_mkfile_project_get_type (module);
-}
+ANJUTA_SIMPLE_PLUGIN (MkpPlugin, mkp_plugin);
diff --git a/plugins/gbf-am/plugin.h b/plugins/mk-project/plugin.h
similarity index 56%
rename from plugins/gbf-am/plugin.h
rename to plugins/mk-project/plugin.h
index 100e980..0059cd0 100644
--- a/plugins/gbf-am/plugin.h
+++ b/plugins/mk-project/plugin.h
@@ -23,23 +23,23 @@
#include <libanjuta/anjuta-plugin.h>
-extern GType gbf_am_plugin_get_type (GTypeModule *module);
-#define GBF_TYPE_PLUGIN_AM (gbf_am_plugin_get_type (NULL))
-#define GBF_PLUGIN_AM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GBF_TYPE_PLUGIN_AM, GbfAmPlugin))
-#define GBF_PLUGIN_AM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GBF_TYPE_PLUGIN_AM, GbfAmPluginClass))
-#define GBF_IS_PLUGIN_AM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GBF_TYPE_PLUGIN_AM))
-#define GBF_IS_PLUGIN_AM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GBF_TYPE_PLUGIN_AM))
-#define GBF_PLUGIN_AM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GBF_TYPE_PLUGIN_AM, GbfAmPluginClass))
-
-typedef struct _GbfAmPlugin GbfAmPlugin;
-typedef struct _GbfAmPluginClass GbfAmPluginClass;
-
-struct _GbfAmPlugin
+extern GType amp_plugin_get_type (GTypeModule *module);
+#define ANJUTA_TYPE_PLUGIN_MKP (mkp_plugin_get_type (NULL))
+#define ANJUTA_PLUGIN_MKP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_TYPE_PLUGIN_MKP, MkpPlugin))
+#define ANJUTA_PLUGIN_MKP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_TYPE_PLUGIN_MKP, MkpPluginClass))
+#define ANJUTA_IS_PLUGIN_MKP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_TYPE_PLUGIN_MKP))
+#define ANJUTA_IS_PLUGIN_MKP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_TYPE_PLUGIN_MKP))
+#define ANJUTA_PLUGIN_MKP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_TYPE_PLUGIN_MKP, MkPluginClass))
+
+typedef struct _MkpPlugin MkpPlugin;
+typedef struct _MkpPluginClass MkpPluginClass;
+
+struct _MkpPlugin
{
AnjutaPlugin parent;
};
-struct _GbfAmPluginClass
+struct _MkpPluginClass
{
AnjutaPluginClass parent_class;
};
diff --git a/plugins/project-manager/gbf-project-model.c b/plugins/project-manager/gbf-project-model.c
index 5f63eb8..d9ede16 100644
--- a/plugins/project-manager/gbf-project-model.c
+++ b/plugins/project-manager/gbf-project-model.c
@@ -34,7 +34,7 @@
struct _GbfProjectModelPrivate {
- GbfProject *proj;
+ IAnjutaProject *proj;
gulong project_updated_handler;
GtkTreeRowReference *root_row;
@@ -57,7 +57,7 @@ static void gbf_project_model_drag_source_init (GtkTreeDragSourceIface *if
static void gbf_project_model_drag_dest_init (GtkTreeDragDestIface *iface);
static void load_project (GbfProjectModel *model,
- GbfProject *proj);
+ IAnjutaProject *proj);
static void insert_empty_node (GbfProjectModel *model);
static void unload_project (GbfProjectModel *model);
@@ -284,12 +284,12 @@ default_sort_func (GtkTreeModel *model,
/* special case: the order of shortcuts is
* user customizable */
for (l = GBF_PROJECT_MODEL (model)->priv->shortcuts; l; l = l->next) {
- if (!strcmp (l->data, data_a->id)) {
+ if (l->data == data_a->id) {
/* a comes first */
retval = -1;
break;
}
- else if (!strcmp (l->data, data_b->id)) {
+ else if (l->data == data_b->id) {
/* b comes first */
retval = 1;
break;
@@ -322,16 +322,14 @@ default_sort_func (GtkTreeModel *model,
static void
-add_source (GbfProjectModel *model,
- const gchar *source_id,
- GtkTreeIter *parent)
+add_source (GbfProjectModel *model,
+ AnjutaProjectSource *source,
+ GtkTreeIter *parent)
{
- GbfProjectTargetSource *source;
GtkTreeIter iter;
GbfTreeData *data;
- source = gbf_project_get_source (model->priv->proj, source_id, NULL);
- if (!source)
+ if ((!source) || (anjuta_project_node_get_type (source) != ANJUTA_PROJECT_SOURCE))
return;
data = gbf_tree_data_new_source (model->priv->proj, source);
@@ -340,31 +338,28 @@ add_source (GbfProjectModel *model,
GBF_PROJECT_MODEL_COLUMN_DATA, data,
-1);
gbf_tree_data_free (data);
-
- gbf_project_target_source_free (source);
}
static GtkTreePath *
-find_shortcut (GbfProjectModel *model, const gchar *target_id)
+find_shortcut (GbfProjectModel *model, const AnjutaProjectTarget *target)
{
GList *l;
gint i;
for (l = model->priv->shortcuts, i = 0; l; l = l->next, i++) {
- if (!strcmp (target_id, l->data))
+ if (target == l->data)
return gtk_tree_path_new_from_indices (i, -1);
}
return NULL;
}
static void
-remove_shortcut (GbfProjectModel *model, const gchar *target_id)
+remove_shortcut (GbfProjectModel *model, const AnjutaProjectTarget *target)
{
GList *l;
for (l = model->priv->shortcuts; l; l = l->next) {
- if (!strcmp (target_id, l->data)) {
- g_free (l->data);
+ if (target == l->data) {
model->priv->shortcuts = g_list_delete_link (
model->priv->shortcuts, l);
break;
@@ -374,18 +369,16 @@ remove_shortcut (GbfProjectModel *model, const gchar *target_id)
static void
add_target_shortcut (GbfProjectModel *model,
- const gchar *target_id,
+ AnjutaProjectTarget *target,
GtkTreePath *before_path)
{
- GList *l;
+ AnjutaProjectNode *node;
GtkTreeIter iter, sibling;
- GbfProjectTarget *target;
GtkTreePath *root_path, *old_path;
gint *path_indices, i;
GbfTreeData *data;
- target = gbf_project_get_target (model->priv->proj, target_id, NULL);
- if (!target)
+ if ((!target) || (anjuta_project_node_get_type (target) != ANJUTA_PROJECT_SOURCE))
return;
root_path = gtk_tree_row_reference_get_path (model->priv->root_row);
@@ -406,9 +399,9 @@ add_target_shortcut (GbfProjectModel *model,
i = path_indices [0];
/* remove the old shortcut to make sorting actually work */
- old_path = find_shortcut (model, target_id);
+ old_path = find_shortcut (model, target);
if (old_path) {
- remove_shortcut (model, target_id);
+ remove_shortcut (model, target);
if (gtk_tree_path_compare (old_path, before_path) < 0) {
/* adjust shortcut insert position if the old
* index was before the new site */
@@ -419,7 +412,7 @@ add_target_shortcut (GbfProjectModel *model,
/* add entry to the shortcut list */
model->priv->shortcuts = g_list_insert (model->priv->shortcuts,
- g_strdup (target->id), i);
+ target, i);
data = gbf_tree_data_new_target (model->priv->proj, target);
data->is_shortcut = TRUE;
@@ -430,25 +423,22 @@ add_target_shortcut (GbfProjectModel *model,
gbf_tree_data_free (data);
/* add sources */
- for (l = target->sources; l; l = l->next)
- add_source (model, l->data, &iter);
+ for (node = anjuta_project_node_first_child (target); node; node = anjuta_project_node_next_sibling (node))
+ add_source (model, node, &iter);
gtk_tree_path_free (root_path);
- gbf_project_target_free (target);
}
static void
-add_target (GbfProjectModel *model,
- const gchar *target_id,
- GtkTreeIter *parent)
+add_target (GbfProjectModel *model,
+ AnjutaProjectTarget *target,
+ GtkTreeIter *parent)
{
- GbfProjectTarget *target;
- GList *l;
+ AnjutaProjectNode *l;
GtkTreeIter iter;
GbfTreeData *data;
- target = gbf_project_get_target (model->priv->proj, target_id, NULL);
- if (!target)
+ if ((!target) || (anjuta_project_node_get_type (target) != ANJUTA_PROJECT_TARGET))
return;
data = gbf_tree_data_new_target (model->priv->proj, target);
@@ -459,39 +449,44 @@ add_target (GbfProjectModel *model,
gbf_tree_data_free (data);
/* add sources */
- for (l = target->sources; l; l = l->next)
- add_source (model, l->data, &iter);
+ for (l = anjuta_project_node_first_child (target); l; l = anjuta_project_node_next_sibling (l))
+ {
+ add_source (model, l, &iter);
+ }
/* add a shortcut to the target if the target's type is a primary */
/* FIXME: this shouldn't be here. We would rather provide a
* set of public functions to add/remove shortcuts to save
* this information in the project metadata (when that's
* implemented) */
- if (!strcmp (target->type, "program") ||
- !strcmp (target->type, "shared_lib") ||
- !strcmp (target->type, "static_lib") ||
- !strcmp (target->type, "java") ||
- !strcmp (target->type, "python")) {
- add_target_shortcut (model, target->id, NULL);
+ switch (anjuta_project_target_type_class (anjuta_project_target_get_type (target)))
+ {
+ case ANJUTA_TARGET_SHAREDLIB:
+ case ANJUTA_TARGET_STATICLIB:
+ case ANJUTA_TARGET_EXECUTABLE:
+ case ANJUTA_TARGET_PYTHON:
+ case ANJUTA_TARGET_JAVA:
+ add_target_shortcut (model, target, NULL);
+ break;
+ default:
+ break;
}
-
- gbf_project_target_free (target);
}
static void
-update_target (GbfProjectModel *model, const gchar *target_id, GtkTreeIter *iter)
+update_target (GbfProjectModel *model, AnjutaProjectTarget *target, GtkTreeIter *iter)
{
GtkTreeModel *tree_model;
- GbfProjectTarget *target;
GtkTreeIter child;
+ GList *sources;
GList *node;
tree_model = GTK_TREE_MODEL (model);
- target = gbf_project_get_target (model->priv->proj, target_id, NULL);
- if (!target)
+ if ((!target) || (anjuta_project_node_get_type (target) != ANJUTA_PROJECT_TARGET))
return;
/* update target data here */
+ sources = anjuta_project_node_all_child (target, ANJUTA_PROJECT_SOURCE);
/* walk the tree target */
if (gtk_tree_model_iter_children (tree_model, &child, iter)) {
@@ -505,10 +500,9 @@ update_target (GbfProjectModel *model, const gchar *target_id, GtkTreeIter *iter
/* find the iterating id in the target's sources */
if (data->id) {
- node = g_list_find_custom (target->sources,
- data->id, (GCompareFunc) strcmp);
+ node = g_list_find (sources, data->id);
if (node) {
- target->sources = g_list_delete_link (target->sources, node);
+ sources = g_list_delete_link (sources, node);
valid = gtk_tree_model_iter_next (tree_model, &child);
} else {
valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &child);
@@ -519,24 +513,22 @@ update_target (GbfProjectModel *model, const gchar *target_id, GtkTreeIter *iter
}
/* add the remaining sources */
- for (node = target->sources; node; node = node->next)
- add_source (model, node->data, iter);
-
- gbf_project_target_free (target);
+ for (node = sources; node; node = g_list_next (node))
+ {
+ add_source (model, (AnjutaProjectSource *)node->data, iter);
+ }
}
static void
-add_target_group (GbfProjectModel *model,
- const gchar *group_id,
- GtkTreeIter *parent)
+add_target_group (GbfProjectModel *model,
+ AnjutaProjectGroup *group,
+ GtkTreeIter *parent)
{
- GbfProjectGroup *group;
GtkTreeIter iter;
- GList *l;
+ AnjutaProjectNode *node;
GbfTreeData *data;
- group = gbf_project_get_group (model->priv->proj, group_id, NULL);
- if (!group)
+ if ((!group) || (anjuta_project_node_get_type (group) != ANJUTA_PROJECT_GROUP))
return;
data = gbf_tree_data_new_group (model->priv->proj, group);
@@ -557,28 +549,31 @@ add_target_group (GbfProjectModel *model,
}
/* add groups ... */
- for (l = group->groups; l; l = l->next)
- add_target_group (model, l->data, &iter);
-
+ for (node = anjuta_project_node_first_child (group); node; node = anjuta_project_node_next_sibling (node))
+ add_target_group (model, node, &iter);
+
/* ... and targets */
- for (l = group->targets; l; l = l->next)
- add_target (model, l->data, &iter);
-
- gbf_project_group_free (group);
+ for (node = anjuta_project_node_first_child (group); node; node = anjuta_project_node_next_sibling (node))
+ add_target (model, node, &iter);
}
static void
-update_group (GbfProjectModel *model, const gchar *group_id, GtkTreeIter *iter)
+update_group (GbfProjectModel *model, AnjutaProjectGroup *group, GtkTreeIter *iter)
{
GtkTreeModel *tree_model;
- GbfProjectGroup *group;
GtkTreeIter child;
GList *node;
-
+ GList *groups;
+ GList *targets;
+
+ if ((!group) || (anjuta_project_node_get_type (group) != ANJUTA_PROJECT_GROUP))
+ return;
+
tree_model = GTK_TREE_MODEL (model);
- group = gbf_project_get_group (model->priv->proj, group_id, NULL);
/* update group data. nothing to do here */
+ groups = anjuta_project_node_all_child (group, ANJUTA_PROJECT_GROUP);
+ targets = anjuta_project_node_all_child (group, ANJUTA_PROJECT_TARGET);
/* walk the tree group */
/* group can be NULL, but we iterate anyway to remove any
@@ -598,9 +593,8 @@ update_group (GbfProjectModel *model, const gchar *group_id, GtkTreeIter *iter)
if (data->type == GBF_TREE_NODE_GROUP) {
/* update recursively */
update_group (model, data->id, &child);
- if (group && (node = g_list_find_custom (group->groups, data->id,
- (GCompareFunc) strcmp))) {
- group->groups = g_list_delete_link (group->groups, node);
+ if (group && (node = g_list_find (groups, data->id))) {
+ groups = g_list_delete_link (groups, node);
} else {
remove_child = TRUE;
}
@@ -608,10 +602,8 @@ update_group (GbfProjectModel *model, const gchar *group_id, GtkTreeIter *iter)
} else if (data->type == GBF_TREE_NODE_TARGET) {
GtkTreePath *shortcut;
- if (group && (node = g_list_find_custom (group->targets,
- data->id,
- (GCompareFunc) strcmp))) {
- group->targets = g_list_delete_link (group->targets, node);
+ if (group && (node = g_list_find (targets, data->id))) {
+ targets = g_list_delete_link (targets, node);
/* update recursively */
update_target (model, data->id, &child);
} else {
@@ -646,34 +638,32 @@ update_group (GbfProjectModel *model, const gchar *group_id, GtkTreeIter *iter)
if (group) {
/* add the remaining targets and groups */
- for (node = group->groups; node; node = node->next)
+ for (node = groups; node; node = node->next)
add_target_group (model, node->data, iter);
- for (node = group->targets; node; node = node->next)
+ for (node = targets; node; node = node->next)
add_target (model, node->data, iter);
-
- gbf_project_group_free (group);
}
}
static void
-project_updated_cb (GbfProject *project, GbfProjectModel *model)
+project_updated_cb (IAnjutaProject *project, GbfProjectModel *model)
{
GtkTreePath *path;
GtkTreeIter iter;
path = gtk_tree_row_reference_get_path (model->priv->root_row);
if (path && gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
- update_group (model, "/", &iter);
+ update_group (model, ianjuta_project_get_root (project, NULL), &iter);
else
- add_target_group (model, "/", NULL);
+ add_target_group (model, ianjuta_project_get_root (project, NULL), NULL);
if (path)
gtk_tree_path_free (path);
}
static void
-load_project (GbfProjectModel *model, GbfProject *proj)
+load_project (GbfProjectModel *model, IAnjutaProject *proj)
{
model->priv->proj = proj;
g_object_ref (proj);
@@ -681,7 +671,7 @@ load_project (GbfProjectModel *model, GbfProject *proj)
/* to get rid of the empty node */
gtk_tree_store_clear (GTK_TREE_STORE (model));
- add_target_group (model, "/", NULL);
+ add_target_group (model, ianjuta_project_get_root (proj, NULL), NULL);
model->priv->project_updated_handler =
g_signal_connect (model->priv->proj, "project-updated",
@@ -723,10 +713,10 @@ unload_project (GbfProjectModel *model)
}
static gboolean
-recursive_find_id (GtkTreeModel *model,
- GtkTreeIter *iter,
- GbfTreeNodeType type,
- const gchar *id)
+recursive_find_id (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GbfTreeNodeType type,
+ AnjutaProjectNode *id)
{
GtkTreeIter tmp;
GbfTreeData *data;
@@ -739,7 +729,7 @@ recursive_find_id (GtkTreeModel *model,
gtk_tree_model_get (model, &tmp,
GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
- if (data->type == type && !strcmp (id, data->id)) {
+ if (id == data->id) {
*iter = tmp;
retval = TRUE;
}
@@ -758,10 +748,10 @@ recursive_find_id (GtkTreeModel *model,
}
gboolean
-gbf_project_model_find_id (GbfProjectModel *model,
- GtkTreeIter *iter,
- GbfTreeNodeType type,
- const gchar *id)
+gbf_project_model_find_id (GbfProjectModel *model,
+ GtkTreeIter *iter,
+ GbfTreeNodeType type,
+ AnjutaProjectNode *id)
{
GtkTreePath *root;
GtkTreeIter tmp_iter;
@@ -783,7 +773,7 @@ gbf_project_model_find_id (GbfProjectModel *model,
}
GbfProjectModel *
-gbf_project_model_new (GbfProject *project)
+gbf_project_model_new (IAnjutaProject *project)
{
return GBF_PROJECT_MODEL (g_object_new (GBF_TYPE_PROJECT_MODEL,
"project", project,
@@ -791,10 +781,10 @@ gbf_project_model_new (GbfProject *project)
}
void
-gbf_project_model_set_project (GbfProjectModel *model, GbfProject *project)
+gbf_project_model_set_project (GbfProjectModel *model, IAnjutaProject *project)
{
g_return_if_fail (model != NULL && GBF_IS_PROJECT_MODEL (model));
- g_return_if_fail (project == NULL || GBF_IS_PROJECT (project));
+ g_return_if_fail (project == NULL || IANJUTA_IS_PROJECT (project));
if (model->priv->proj)
unload_project (model);
@@ -803,7 +793,7 @@ gbf_project_model_set_project (GbfProjectModel *model, GbfProject *project)
load_project (model, project);
}
-GbfProject *
+IAnjutaProject *
gbf_project_model_get_project (GbfProjectModel *model)
{
g_return_val_if_fail (model != NULL && GBF_IS_PROJECT_MODEL (model), NULL);
diff --git a/plugins/project-manager/gbf-project-model.h b/plugins/project-manager/gbf-project-model.h
index 3129c2c..51484a8 100644
--- a/plugins/project-manager/gbf-project-model.h
+++ b/plugins/project-manager/gbf-project-model.h
@@ -25,7 +25,8 @@
#include <glib-object.h>
#include <gtk/gtk.h>
-#include <libanjuta/gbf-project.h>
+#include <libanjuta/interfaces/ianjuta-project.h>
+#include <libanjuta/anjuta-project.h>
#include "gbf-tree-data.h"
#define GBF_TYPE_PROJECT_MODEL (gbf_project_model_get_type ())
@@ -53,16 +54,16 @@ struct _GbfProjectModelClass {
};
GType gbf_project_model_get_type (void);
-GbfProjectModel *gbf_project_model_new (GbfProject *project);
+GbfProjectModel *gbf_project_model_new (IAnjutaProject *project);
-void gbf_project_model_set_project (GbfProjectModel *model,
- GbfProject *project);
-GbfProject *gbf_project_model_get_project (GbfProjectModel *model);
+void gbf_project_model_set_project (GbfProjectModel *model,
+ IAnjutaProject *project);
+IAnjutaProject *gbf_project_model_get_project (GbfProjectModel *model);
-GtkTreePath *gbf_project_model_get_project_root (GbfProjectModel *model);
-gboolean gbf_project_model_find_id (GbfProjectModel *model,
- GtkTreeIter *iter,
- GbfTreeNodeType type,
- const gchar *id);
+GtkTreePath *gbf_project_model_get_project_root (GbfProjectModel *model);
+gboolean gbf_project_model_find_id (GbfProjectModel *model,
+ GtkTreeIter *iter,
+ GbfTreeNodeType type,
+ AnjutaProjectNode *id);
#endif
diff --git a/plugins/project-manager/gbf-project-util.c b/plugins/project-manager/gbf-project-util.c
index c57d702..8cb178b 100644
--- a/plugins/project-manager/gbf-project-util.c
+++ b/plugins/project-manager/gbf-project-util.c
@@ -76,9 +76,9 @@ groups_filter_fn (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
}
static void
-setup_groups_treeview (GbfProjectModel *model,
- GtkWidget *view,
- const gchar *select_group)
+setup_groups_treeview (GbfProjectModel *model,
+ GtkWidget *view,
+ AnjutaProjectGroup *select_group)
{
GtkTreeModel *filter;
GtkTreePath *path;
@@ -163,19 +163,19 @@ entry_changed_cb (GtkEditable *editable, gpointer user_data)
g_free (text);
}
-gchar*
-gbf_project_util_new_group (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_group,
- const gchar *default_group_name_to_add)
+AnjutaProjectGroup*
+gbf_project_util_new_group (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectGroup *default_group,
+ const gchar *default_group_name_to_add)
{
GtkBuilder *gui;
GtkWidget *dialog, *group_name_entry, *ok_button;
GtkWidget *groups_view;
gint response;
- GbfProject *project;
+ IAnjutaProject *project;
gboolean finished = FALSE;
- gchar *new_group = NULL;
+ AnjutaProjectGroup *new_group = NULL;
g_return_val_if_fail (model != NULL, NULL);
@@ -219,19 +219,18 @@ gbf_project_util_new_group (GbfProjectModel *model,
{
GError *err = NULL;
GbfTreeData *data;
- gchar *parent_id = NULL, *name;
+ gchar *name;
+ AnjutaProjectGroup *parent_node;
name = gtk_editable_get_chars (
GTK_EDITABLE (group_name_entry), 0, -1);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (groups_view),
GBF_TREE_NODE_GROUP);
if (data) {
- gchar *new_group = NULL;
-
- parent_id = g_strdup (data->id);
+ parent_node = data->id;
gbf_tree_data_free (data);
- new_group = gbf_project_add_group (project, parent_id, name, &err);
+ new_group = ianjuta_project_add_group (project, parent_node, name, &err);
if (err) {
error_dialog (parent, _("Cannot add group"), "%s",
err->message);
@@ -239,7 +238,6 @@ gbf_project_util_new_group (GbfProjectModel *model,
} else {
finished = TRUE;
}
- g_free (parent_id);
} else {
error_dialog (parent, _("Cannot add group"),
"%s", _("No parent group selected"));
@@ -268,24 +266,24 @@ enum {
/* create a tree model with the target types */
static GtkListStore *
-build_types_store (GbfProject *project)
+build_types_store (IAnjutaProject *project)
{
GtkListStore *store;
GtkTreeIter iter;
- gchar **types;
- gint i;
-
- types = gbf_project_get_types (project);
+ GList *types;
+ GList *node;
+
+ types = ianjuta_project_get_target_types (project, NULL);
store = gtk_list_store_new (TARGET_TYPE_N_COLUMNS,
- G_TYPE_STRING,
+ G_TYPE_POINTER,
G_TYPE_STRING,
GDK_TYPE_PIXBUF);
- for (i = 0; types [i]; i++) {
+ for (node = g_list_first (types); node != NULL; node = g_list_next (node)) {
GdkPixbuf *pixbuf;
const gchar *name;
- name = gbf_project_name_for_type (project, types [i]);
+ name = anjuta_project_target_type_name ((AnjutaProjectTargetType)node->data);
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
GTK_STOCK_CONVERT,
ICON_SIZE,
@@ -294,7 +292,7 @@ build_types_store (GbfProject *project)
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
- TARGET_TYPE_TYPE, types [i],
+ TARGET_TYPE_TYPE, node->data,
TARGET_TYPE_NAME, name,
TARGET_TYPE_PIXBUF, pixbuf,
-1);
@@ -303,15 +301,15 @@ build_types_store (GbfProject *project)
g_object_unref (pixbuf);
}
- g_strfreev (types);
+ g_list_free (types);
return store;
}
-gchar*
+AnjutaProjectTarget*
gbf_project_util_new_target (GbfProjectModel *model,
GtkWindow *parent,
- const gchar *default_group,
+ AnjutaProjectGroup *default_group,
const gchar *default_target_name_to_add)
{
GtkBuilder *gui;
@@ -320,9 +318,9 @@ gbf_project_util_new_target (GbfProjectModel *model,
GtkListStore *types_store;
GtkCellRenderer *renderer;
gint response;
- GbfProject *project;
+ IAnjutaProject *project;
gboolean finished = FALSE;
- gchar *new_target = NULL;
+ AnjutaProjectTarget *new_target = NULL;
g_return_val_if_fail (model != NULL, NULL);
@@ -394,7 +392,9 @@ gbf_project_util_new_target (GbfProjectModel *model,
GError *err = NULL;
GbfTreeData *data;
GtkTreeIter iter;
- gchar *group_id = NULL, *name, *type = NULL;
+ AnjutaProjectGroup *group;
+ gchar *name;
+ AnjutaProjectTargetType type = NULL;
name = gtk_editable_get_chars (
GTK_EDITABLE (target_name_entry), 0, -1);
@@ -409,10 +409,10 @@ gbf_project_util_new_target (GbfProjectModel *model,
}
if (data && type) {
- group_id = g_strdup (data->id);
+ group = data->id;
gbf_tree_data_free (data);
- new_target = gbf_project_add_target (project, group_id, name, type, &err);
+ new_target = ianjuta_project_add_target (project, group, name, type, &err);
if (err) {
error_dialog (parent, _("Cannot add target"), "%s",
err->message);
@@ -420,8 +420,6 @@ gbf_project_util_new_target (GbfProjectModel *model,
} else {
finished = TRUE;
}
- g_free (group_id);
- g_free (type);
} else {
error_dialog (parent, _("Cannot add target"), "%s",
_("No group selected"));
@@ -461,10 +459,10 @@ targets_filter_fn (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
}
static void
-setup_targets_treeview (GbfProjectModel *model,
- GtkWidget *view,
- const gchar *select_target,
- const gchar *select_group)
+setup_targets_treeview (GbfProjectModel *model,
+ GtkWidget *view,
+ AnjutaProjectTarget *select_target,
+ AnjutaProjectGroup *select_group)
{
GtkTreeModel *filter;
GtkTreeIter iter, iter_filter;
@@ -590,12 +588,12 @@ on_row_changed(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpoint
gtk_widget_set_sensitive(button, FALSE);
}
-gchar*
-gbf_project_util_add_source (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_target,
- const gchar *default_group,
- const gchar *default_uri)
+AnjutaProjectSource*
+gbf_project_util_add_source (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectTarget *default_target,
+ AnjutaProjectGroup *default_group,
+ const gchar *default_uri)
{
GList* new_sources;
gchar* uri = NULL;
@@ -613,7 +611,7 @@ gbf_project_util_add_source (GbfProjectModel *model,
if (new_sources && g_list_length (new_sources))
{
- gchar* new_source = g_strdup (new_sources->data);
+ AnjutaProjectSource *new_source = new_sources->data;
g_list_foreach (new_sources, (GFunc) g_free, NULL);
g_list_free (new_sources);
return new_source;
@@ -623,18 +621,18 @@ gbf_project_util_add_source (GbfProjectModel *model,
}
GList*
-gbf_project_util_add_source_multi (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_target,
- const gchar *default_group,
- GList *uris_to_add)
+gbf_project_util_add_source_multi (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectTarget *default_target,
+ AnjutaProjectGroup *default_group,
+ GList *uris_to_add)
{
GtkBuilder *gui;
GtkWidget *dialog, *source_file_tree;
GtkWidget *ok_button, *browse_button;
GtkWidget *targets_view;
gint response;
- GbfProject *project;
+ IAnjutaProject *project;
gboolean finished = FALSE;
gchar *project_root;
GtkListStore* list;
@@ -724,7 +722,7 @@ gbf_project_util_add_source_multi (GbfProjectModel *model,
case GTK_RESPONSE_OK:
{
GbfTreeData *data;
- gchar *target_id = NULL;
+ AnjutaProjectTarget *target = NULL;
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (targets_view),
GBF_TREE_NODE_TARGET);
@@ -732,7 +730,7 @@ gbf_project_util_add_source_multi (GbfProjectModel *model,
GtkTreeIter iter;
GString *err_mesg = g_string_new (NULL);
- target_id = g_strdup (data->id);
+ target = data->id;
gbf_tree_data_free (data);
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list),
@@ -741,18 +739,22 @@ gbf_project_util_add_source_multi (GbfProjectModel *model,
do
{
GError *err = NULL;
- gchar* new_source;
- gchar* source_file;
+ AnjutaProjectSource* new_source;
+ gchar* uri;
+ GFile* source_file;
+
gtk_tree_model_get (GTK_TREE_MODEL(list), &iter,
- COLUMN_URI, &source_file, -1);
-
- new_source = gbf_project_add_source (project,
- target_id,
+ COLUMN_URI, &uri, -1);
+
+ source_file = g_file_new_for_uri (uri);
+ new_source = ianjuta_project_add_source (project,
+ target,
source_file,
&err);
+ g_object_unref (source_file);
if (err) {
gchar *str = g_strdup_printf ("%s: %s\n",
- source_file,
+ uri,
err->message);
g_string_append (err_mesg, str);
g_error_free (err);
@@ -762,12 +764,10 @@ gbf_project_util_add_source_multi (GbfProjectModel *model,
new_sources = g_list_append (new_sources,
new_source);
- g_free (source_file);
+ g_free (uri);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL(list),
&iter));
- g_free (target_id);
-
if (err_mesg->str && strlen (err_mesg->str) > 0) {
error_dialog (parent, _("Cannot add source files"),
"%s", err_mesg->str);
diff --git a/plugins/project-manager/gbf-project-util.h b/plugins/project-manager/gbf-project-util.h
index abc71e1..55f6a77 100644
--- a/plugins/project-manager/gbf-project-util.h
+++ b/plugins/project-manager/gbf-project-util.h
@@ -25,31 +25,32 @@
#include <glib.h>
#include <gtk/gtk.h>
+#include <libanjuta/anjuta-project.h>
#include "gbf-project-model.h"
G_BEGIN_DECLS
-gchar* gbf_project_util_new_group (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_group,
- const gchar *default_group_name_to_add);
-
-gchar* gbf_project_util_new_target (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_group,
- const gchar *default_target_name_to_add);
-
-gchar* gbf_project_util_add_source (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_target,
- const gchar *default_group,
- const gchar *default_uri_to_add);
-
-GList* gbf_project_util_add_source_multi (GbfProjectModel *model,
- GtkWindow *parent,
- const gchar *default_target,
- const gchar *default_group,
- GList *uris_to_add);
+AnjutaProjectGroup* gbf_project_util_new_group (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectGroup *default_group,
+ const gchar *default_group_name_to_add);
+
+AnjutaProjectTarget* gbf_project_util_new_target (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectGroup *default_group,
+ const gchar *default_target_name_to_add);
+
+AnjutaProjectSource* gbf_project_util_add_source (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectTarget *default_target,
+ AnjutaProjectGroup *default_group,
+ const gchar *default_uri_to_add);
+
+GList* gbf_project_util_add_source_multi (GbfProjectModel *model,
+ GtkWindow *parent,
+ AnjutaProjectTarget *default_target,
+ AnjutaProjectGroup *default_group,
+ GList *uris_to_add);
diff --git a/plugins/project-manager/gbf-project-view.c b/plugins/project-manager/gbf-project-view.c
index 2db6a70..e6c3ef3 100644
--- a/plugins/project-manager/gbf-project-view.c
+++ b/plugins/project-manager/gbf-project-view.c
@@ -309,8 +309,8 @@ gbf_project_view_class_init (GbfProjectViewClass *klass)
G_STRUCT_OFFSET (GbfProjectViewClass,
target_selected),
NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
signals [GROUP_SELECTED] =
g_signal_new ("group_selected",
GBF_TYPE_PROJECT_VIEW,
@@ -318,8 +318,8 @@ gbf_project_view_class_init (GbfProjectViewClass *klass)
G_STRUCT_OFFSET (GbfProjectViewClass,
group_selected),
NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
}
static void
diff --git a/plugins/project-manager/gbf-project-view.h b/plugins/project-manager/gbf-project-view.h
index db62a24..9688cda 100644
--- a/plugins/project-manager/gbf-project-view.h
+++ b/plugins/project-manager/gbf-project-view.h
@@ -24,6 +24,7 @@
#define _GBF_PROJECT_TREE_H_
#include <gtk/gtk.h>
+#include <libanjuta/anjuta-project.h>
#include "gbf-tree-data.h"
G_BEGIN_DECLS
@@ -51,10 +52,10 @@ struct _GbfProjectViewClass {
void (* uri_activated) (GbfProjectView *project_view,
const char *uri);
- void (* target_selected) (GbfProjectView *project_view,
- const gchar *target_id);
- void (* group_selected) (GbfProjectView *project_view,
- const gchar *group_id);
+ void (* target_selected) (GbfProjectView *project_view,
+ AnjutaProjectTarget *target);
+ void (* group_selected) (GbfProjectView *project_view,
+ AnjutaProjectGroup *group);
};
GType gbf_project_view_get_type (void);
diff --git a/plugins/project-manager/gbf-tree-data.c b/plugins/project-manager/gbf-tree-data.c
index 37ac2c8..c1f916a 100644
--- a/plugins/project-manager/gbf-tree-data.c
+++ b/plugins/project-manager/gbf-tree-data.c
@@ -53,60 +53,68 @@ gbf_tree_data_new_string (const gchar *string)
}
GbfTreeData *
-gbf_tree_data_new_group (GbfProject *project, const GbfProjectGroup *group)
+gbf_tree_data_new_group (IAnjutaProject *project, AnjutaProjectGroup *group)
{
GbfTreeData *node = g_new0 (GbfTreeData, 1);
-
+ GFileInfo *ginfo;
+
node->type = GBF_TREE_NODE_GROUP;
- node->name = g_strdup (group->name);
- node->id = g_strdup (group->id);
+ node->id = group;
+
+ ginfo = g_file_query_info (anjuta_project_group_get_directory (group),
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ if (ginfo)
+ {
+ node->name = g_strdup (g_file_info_get_display_name (ginfo));
+ g_object_unref(ginfo);
+ }
+ else
+ {
+ node->name = g_strdup ("?");
+ }
return node;
}
GbfTreeData *
-gbf_tree_data_new_target (GbfProject *project, const GbfProjectTarget *target)
+gbf_tree_data_new_target (IAnjutaProject *project, AnjutaProjectTarget *target)
{
GbfTreeData *node = g_new0 (GbfTreeData, 1);
node->type = GBF_TREE_NODE_TARGET;
- node->name = g_strdup (target->name);
- node->id = g_strdup (target->id);
- node->mime_type = g_strdup (gbf_project_mimetype_for_type (project, target->type));
+ node->id = target;
+
+ node->name = g_strdup (anjuta_project_target_get_name (target));
+ node->mime_type = g_strdup (anjuta_project_target_type_mime (anjuta_project_target_get_type (target)));
return node;
}
GbfTreeData *
-gbf_tree_data_new_source (GbfProject *project, const GbfProjectTargetSource *source)
+gbf_tree_data_new_source (IAnjutaProject *project, AnjutaProjectSource *source)
{
GbfTreeData *node = g_new0 (GbfTreeData, 1);
- GFile *file;
- GFileInfo *file_info;
+ GFileInfo *ginfo;
node->type = GBF_TREE_NODE_TARGET_SOURCE;
- node->id = g_strdup (source->id);
- node->uri = g_strdup (source->source_uri);
- node->name = NULL;
+ node->id = source;
- file = g_file_new_for_uri (source->source_uri);
- node->name = g_file_get_basename (file);
- if (g_file_query_exists (file, NULL))
+ node->uri = g_file_get_uri (anjuta_project_source_get_file (source));
+
+ ginfo = g_file_query_info (anjuta_project_source_get_file (source),
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ if (ginfo)
{
- file_info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
- G_FILE_QUERY_INFO_NONE,
- NULL, NULL);
- if (file_info)
- {
- node->name = g_strdup (g_file_info_get_display_name (file_info));
- }
+ node->name = g_strdup (g_file_info_get_display_name (ginfo));
+ g_object_unref(ginfo);
}
- g_object_unref (file);
-
- if (node->name == NULL)
+ else
{
- node->name = g_file_get_basename (file);
+ node->name = g_strdup ("?");
}
return node;
@@ -120,7 +128,7 @@ gbf_tree_data_copy (GbfTreeData *src)
node = g_new (GbfTreeData, 1);
node->type = src->type;
node->name = g_strdup (src->name);
- node->id = g_strdup (src->id);
+ node->id = src->id;
node->uri = g_strdup (src->uri);
node->is_shortcut = src->is_shortcut;
node->mime_type = g_strdup (src->mime_type);
@@ -133,7 +141,6 @@ gbf_tree_data_free (GbfTreeData *node)
{
if (node) {
g_free (node->name);
- g_free (node->id);
g_free (node->uri);
g_free (node->mime_type);
g_free (node);
diff --git a/plugins/project-manager/gbf-tree-data.h b/plugins/project-manager/gbf-tree-data.h
index 0c2075b..afbb09f 100644
--- a/plugins/project-manager/gbf-tree-data.h
+++ b/plugins/project-manager/gbf-tree-data.h
@@ -25,7 +25,8 @@
#define _GBF_TREE_DATA_H_
#include <glib-object.h>
-#include <libanjuta/gbf-project.h>
+#include <libanjuta/interfaces/ianjuta-project.h>
+#include <libanjuta/anjuta-project.h>
G_BEGIN_DECLS
@@ -42,24 +43,24 @@ typedef enum {
struct _GbfTreeData
{
- GbfTreeNodeType type;
- gchar *name;
- gchar *id;
- gchar *uri;
- gboolean is_shortcut;
- gchar *mime_type;
+ GbfTreeNodeType type;
+ gchar *name;
+ AnjutaProjectNode *id;
+ gchar *uri;
+ gboolean is_shortcut;
+ gchar *mime_type;
};
GType gbf_tree_data_get_type (void);
-GbfTreeData *gbf_tree_data_new_string (const gchar *string);
-GbfTreeData *gbf_tree_data_new_group (GbfProject *project,
- const GbfProjectGroup *group);
-GbfTreeData *gbf_tree_data_new_target (GbfProject *project,
- const GbfProjectTarget *target);
-GbfTreeData *gbf_tree_data_new_source (GbfProject *project,
- const GbfProjectTargetSource *source);
-GbfTreeData *gbf_tree_data_copy (GbfTreeData *data);
-void gbf_tree_data_free (GbfTreeData *data);
+GbfTreeData *gbf_tree_data_new_string (const gchar *string);
+GbfTreeData *gbf_tree_data_new_group (IAnjutaProject *project,
+ AnjutaProjectGroup *group);
+GbfTreeData *gbf_tree_data_new_target (IAnjutaProject *project,
+ AnjutaProjectTarget *target);
+GbfTreeData *gbf_tree_data_new_source (IAnjutaProject *project,
+ AnjutaProjectSource *source);
+GbfTreeData *gbf_tree_data_copy (GbfTreeData *data);
+void gbf_tree_data_free (GbfTreeData *data);
G_END_DECLS
diff --git a/plugins/project-manager/plugin.c b/plugins/project-manager/plugin.c
index 48492d2..1482116 100644
--- a/plugins/project-manager/plugin.c
+++ b/plugins/project-manager/plugin.c
@@ -27,9 +27,11 @@
#include <libanjuta/interfaces/ianjuta-file-manager.h>
#include <libanjuta/interfaces/ianjuta-builder.h>
#include <libanjuta/interfaces/ianjuta-project-backend.h>
+#include <libanjuta/interfaces/ianjuta-project.h>
#include <libanjuta/anjuta-profile-manager.h>
#include <libanjuta/anjuta-debug.h>
#include <libanjuta/anjuta-status.h>
+#include <libanjuta/anjuta-project.h>
#include "gbf-project-util.h"
@@ -53,7 +55,7 @@ typedef enum _PmPropertiesType
struct _PmPropertiesDialogInfo
{
PmPropertiesType type;
- const gchar* id;
+ AnjutaProjectNode* id;
GtkWidget* dialog;
};
@@ -266,7 +268,7 @@ update_operation_end (ProjectManagerPlugin *plugin, gboolean emit_signal)
{
GList *post_update_sources =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_SOURCE,
+ ANJUTA_PROJECT_SOURCE,
NULL);
update_operation_emit_signals (plugin, plugin->pre_update_sources,
post_update_sources);
@@ -280,7 +282,7 @@ update_operation_end (ProjectManagerPlugin *plugin, gboolean emit_signal)
{
GList *post_update_targets =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_TARGET,
+ ANJUTA_PROJECT_TARGET,
NULL);
update_operation_emit_signals (plugin, plugin->pre_update_targets,
post_update_targets);
@@ -294,7 +296,7 @@ update_operation_end (ProjectManagerPlugin *plugin, gboolean emit_signal)
{
GList *post_update_groups =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_GROUP,
+ ANJUTA_PROJECT_GROUP,
NULL);
update_operation_emit_signals (plugin, plugin->pre_update_groups,
post_update_groups);
@@ -331,15 +333,15 @@ update_operation_begin (ProjectManagerPlugin *plugin)
update_operation_end (plugin, FALSE);
plugin->pre_update_sources =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_SOURCE,
+ ANJUTA_PROJECT_SOURCE,
NULL);
plugin->pre_update_targets =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_TARGET,
+ ANJUTA_PROJECT_TARGET,
NULL);
plugin->pre_update_groups =
ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (plugin),
- IANJUTA_PROJECT_MANAGER_GROUP,
+ ANJUTA_PROJECT_GROUP,
NULL);
}
@@ -366,7 +368,7 @@ compare_properties_id (PmPropertiesDialogInfo *info, PmPropertiesDialogInfo *inf
return (info->type == info1->type) &&
((info1->id == NULL) ||
((info->id != NULL) &&
- (strcmp(info->id, info1->id) == 0))) ? 0 : 1;
+ (info->id == info1->id))) ? 0 : 1;
}
static void
@@ -395,7 +397,7 @@ on_properties_dialog_response (GtkDialog *win,
static void
project_manager_show_properties_dialog (ProjectManagerPlugin *plugin,
PmPropertiesType type,
- const gchar *id)
+ AnjutaProjectNode *id)
{
PmPropertiesDialogInfo info;
GList* prop;
@@ -421,16 +423,16 @@ project_manager_show_properties_dialog (ProjectManagerPlugin *plugin,
switch (type)
{
case PM_PROJECT_PROPERTIES:
- properties = gbf_project_configure (plugin->project, NULL);
+ properties = ianjuta_project_configure (plugin->project, NULL);
title = _("Project properties");
break;
case PM_TARGET_PROPERTIES:
- properties = gbf_project_configure_target (plugin->project,
+ properties = ianjuta_project_configure_node (plugin->project,
id, NULL);
title = _("Target properties");
break;
case PM_GROUP_PROPERTIES:
- properties = gbf_project_configure_group (plugin->project,
+ properties = ianjuta_project_configure_node (plugin->project,
id, NULL);
title = _("Group properties");
break;
@@ -478,7 +480,7 @@ on_refresh_idle (gpointer user_data)
anjuta_status_push (status, _("Refreshing symbol treeâ?¦"));
anjuta_status_busy_push (status);
- gbf_project_refresh (GBF_PROJECT (plugin->project), &err);
+ ianjuta_project_refresh (IANJUTA_PROJECT (plugin->project), &err);
if (err)
{
anjuta_util_dialog_error (get_plugin_parent_window (plugin),
@@ -587,8 +589,8 @@ static void
on_popup_add_group (GtkAction *action, ProjectManagerPlugin *plugin)
{
GbfTreeData *data;
- const gchar *selected_group;
- gchar *group_id;
+ AnjutaProjectGroup *selected_group;
+ AnjutaProjectGroup *new_group;
update_operation_begin (plugin);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
@@ -596,21 +598,20 @@ on_popup_add_group (GtkAction *action, ProjectManagerPlugin *plugin)
selected_group = NULL;
if (data)
selected_group = data->id;
- group_id = gbf_project_util_new_group (plugin->model,
+ new_group = gbf_project_util_new_group (plugin->model,
get_plugin_parent_window (plugin),
selected_group, NULL);
if (data)
gbf_tree_data_free (data);
update_operation_end (plugin, TRUE);
- g_free (group_id);
}
static void
on_popup_add_target (GtkAction *action, ProjectManagerPlugin *plugin)
{
GbfTreeData *data;
- const gchar *selected_group;
- gchar *target_id;
+ AnjutaProjectGroup *selected_group;
+ AnjutaProjectTarget *new_target;
update_operation_begin (plugin);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
@@ -618,21 +619,20 @@ on_popup_add_target (GtkAction *action, ProjectManagerPlugin *plugin)
selected_group = NULL;
if (data)
selected_group = data->id;
- target_id = gbf_project_util_new_target (plugin->model,
+ new_target = gbf_project_util_new_target (plugin->model,
get_plugin_parent_window (plugin),
selected_group, NULL);
if (data)
gbf_tree_data_free (data);
update_operation_end (plugin, TRUE);
- g_free (target_id);
}
static void
on_popup_add_source (GtkAction *action, ProjectManagerPlugin *plugin)
{
GbfTreeData *data;
- const gchar *selected_target;
- gchar *source_id;
+ AnjutaProjectTarget *selected_target;
+ AnjutaProjectSource *new_source;
update_operation_begin (plugin);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
@@ -640,13 +640,12 @@ on_popup_add_source (GtkAction *action, ProjectManagerPlugin *plugin)
selected_target = NULL;
if (data)
selected_target = data->id;
- source_id = gbf_project_util_add_source (plugin->model,
+ new_source = gbf_project_util_add_source (plugin->model,
get_plugin_parent_window (plugin),
selected_target, NULL, NULL);
if (data)
gbf_tree_data_free (data);
update_operation_end (plugin, TRUE);
- g_free (source_id);
}
static gboolean
@@ -706,20 +705,7 @@ on_popup_remove (GtkAction *action, ProjectManagerPlugin *plugin)
{
GError *err = NULL;
update_operation_begin (plugin);
- switch (data->type)
- {
- case GBF_TREE_NODE_GROUP:
- gbf_project_remove_group (plugin->project, data->id, &err);
- break;
- case GBF_TREE_NODE_TARGET:
- gbf_project_remove_target (plugin->project, data->id, &err);
- break;
- case GBF_TREE_NODE_TARGET_SOURCE:
- gbf_project_remove_source (plugin->project, data->id, &err);
- break;
- default:
- g_warning ("Should not reach here!!!");
- }
+ ianjuta_project_remove_node (plugin->project, data->id, &err);
update_operation_end (plugin, TRUE);
if (err)
{
@@ -759,21 +745,21 @@ on_popup_add_to_project (GtkAction *action, ProjectManagerPlugin *plugin)
filename = g_path_get_basename (plugin->fm_current_uri);
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
- gchar *group_id =
+ gchar *new_uri =
ianjuta_project_manager_add_group (IANJUTA_PROJECT_MANAGER (plugin),
filename, parent_directory,
NULL);
- g_free (group_id);
+ g_free (new_uri);
}
else
{
- gchar *source_id =
+ gchar *new_uri =
ianjuta_project_manager_add_source (IANJUTA_PROJECT_MANAGER
(plugin),
plugin->fm_current_uri,
parent_directory,
NULL);
- g_free(source_id);
+ g_free (new_uri);
}
g_object_unref (file_info);
g_free (filename);
@@ -893,10 +879,10 @@ update_ui (ProjectManagerPlugin *plugin)
AnjutaUI *ui;
gint j;
GtkAction *action;
- GbfProjectCapabilities caps = GBF_PROJECT_CAN_ADD_NONE;
+ IAnjutaProjectCapabilities caps = IANJUTA_PROJECT_CAN_ADD_NONE;
if (plugin->project)
- caps = gbf_project_get_capabilities (plugin->project, NULL);
+ caps = ianjuta_project_get_capabilities (plugin->project, NULL);
ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
for (j = 0; j < G_N_ELEMENTS (pm_actions); j++)
@@ -917,19 +903,19 @@ update_ui (ProjectManagerPlugin *plugin)
"ActionProjectAddGroup");
g_object_set (G_OBJECT (action), "sensitive",
((plugin->project != NULL) &&
- (caps & GBF_PROJECT_CAN_ADD_GROUP)), NULL);
+ (caps & IANJUTA_PROJECT_CAN_ADD_GROUP)), NULL);
action = anjuta_ui_get_action (ui, "ActionGroupProjectManager",
"ActionProjectAddTarget");
g_object_set (G_OBJECT (action), "sensitive",
((plugin->project != NULL) &&
- (caps & GBF_PROJECT_CAN_ADD_TARGET)), NULL);
+ (caps & IANJUTA_PROJECT_CAN_ADD_TARGET)), NULL);
action = anjuta_ui_get_action (ui, "ActionGroupProjectManager",
"ActionProjectAddSource");
g_object_set (G_OBJECT (action), "sensitive",
((plugin->project != NULL) &&
- (caps & GBF_PROJECT_CAN_ADD_SOURCE)), NULL);
+ (caps & IANJUTA_PROJECT_CAN_ADD_SOURCE)), NULL);
/* Popup menus */
for (j = 0; j < G_N_ELEMENTS (popup_actions); j++)
@@ -952,7 +938,7 @@ on_treeview_selection_changed (GtkTreeSelection *sel,
GtkAction *action;
GbfTreeData *data;
gchar *selected_uri;
- GbfProjectCapabilities caps = GBF_PROJECT_CAN_ADD_NONE;
+ IAnjutaProjectCapabilities caps = IANJUTA_PROJECT_CAN_ADD_NONE;
ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
/* Popup menu */
@@ -970,12 +956,12 @@ on_treeview_selection_changed (GtkTreeSelection *sel,
g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
if (plugin->project)
- caps = gbf_project_get_capabilities (plugin->project, NULL);
+ caps = ianjuta_project_get_capabilities (plugin->project, NULL);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
GBF_TREE_NODE_TARGET_SOURCE);
if (data && data->type == GBF_TREE_NODE_TARGET_SOURCE)
{
- if (caps & GBF_PROJECT_CAN_ADD_SOURCE)
+ if (caps & IANJUTA_PROJECT_CAN_ADD_SOURCE)
{
action = anjuta_ui_get_action (ui, "ActionGroupProjectManagerPopup",
"ActionPopupProjectAddSource");
@@ -993,7 +979,7 @@ on_treeview_selection_changed (GtkTreeSelection *sel,
GBF_TREE_NODE_TARGET);
if (data && data->type == GBF_TREE_NODE_TARGET)
{
- if (caps & GBF_PROJECT_CAN_ADD_SOURCE)
+ if (caps & IANJUTA_PROJECT_CAN_ADD_SOURCE)
{
action = anjuta_ui_get_action (ui, "ActionGroupProjectManagerPopup",
"ActionPopupProjectAddSource");
@@ -1011,13 +997,13 @@ on_treeview_selection_changed (GtkTreeSelection *sel,
GBF_TREE_NODE_GROUP);
if (data && data->type == GBF_TREE_NODE_GROUP)
{
- if (caps & GBF_PROJECT_CAN_ADD_GROUP)
+ if (caps & IANJUTA_PROJECT_CAN_ADD_GROUP)
{
action = anjuta_ui_get_action (ui, "ActionGroupProjectManagerPopup",
"ActionPopupProjectAddGroup");
g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
}
- if (caps & GBF_PROJECT_CAN_ADD_TARGET)
+ if (caps & IANJUTA_PROJECT_CAN_ADD_TARGET)
{
action = anjuta_ui_get_action (ui, "ActionGroupProjectManagerPopup",
"ActionPopupProjectAddTarget");
@@ -1183,15 +1169,18 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
AnjutaPluginManager *plugin_manager;
AnjutaStatus *status;
gchar *dirname;
+ GFile *dirfile;
gchar *basename;
const gchar *root_uri;
GError *error = NULL;
GList *descs = NULL;
GList *desc;
+ IAnjutaProjectBackend *backend;
root_uri = pm_plugin->project_root_uri;
dirname = anjuta_util_get_local_path_from_uri (root_uri);
+ dirfile = g_file_new_for_uri (root_uri);
g_return_if_fail (dirname != NULL);
@@ -1205,51 +1194,45 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
"Interfaces",
"IAnjutaProjectBackend",
NULL);
+ backend = NULL;
for (desc = g_list_first (descs); desc != NULL; desc = g_list_next (desc)) {
- AnjutaPluginDescription *backend;
- IAnjutaProjectBackend *plugin;
+ AnjutaPluginDescription *backend_desc;
gchar *location = NULL;
-
- backend = (AnjutaPluginDescription *)desc->data;
- anjuta_plugin_description_get_string (backend, "Anjuta Plugin", "Location", &location);
+ IAnjutaProjectBackend *plugin;
+
+ backend_desc = (AnjutaPluginDescription *)desc->data;
+ anjuta_plugin_description_get_string (backend_desc, "Anjuta Plugin", "Location", &location);
plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, location);
+ g_message ("search plugin %s", location);
g_free (location);
-
- pm_plugin->project = ianjuta_project_backend_new_project (plugin, NULL);
- if (pm_plugin->project)
+
+ if (ianjuta_project_backend_probe (plugin, dirfile, NULL))
{
- if (gbf_project_probe (pm_plugin->project, dirname, NULL))
- {
- /* Backend found */
- break;
- }
- g_object_unref (pm_plugin->project);
- pm_plugin->project = NULL;
- }
- /*
- if (!strcmp (backend->id, "gbf-am:GbfAmProject"))
+ /* Backend found */;
+ backend = plugin;
+ g_message ("Find backend");
break;
- */
- plugin = NULL;
+ }
}
g_list_free (descs);
- if (!pm_plugin->project)
+ if (!backend)
{
/* FIXME: Set err */
g_warning ("no backend available for this project\n");
g_free (dirname);
+ g_object_unref (dirfile);
return;
}
DEBUG_PRINT ("%s", "Creating new gbf project\n");
-
- /* pm_plugin->project = gbf_backend_new_project (backend->id); */
+ pm_plugin->project = ianjuta_project_backend_new_project (backend, NULL);
if (!pm_plugin->project)
{
/* FIXME: Set err */
g_warning ("project creation failed\n");
g_free (dirname);
+ g_object_unref (dirfile);
return;
}
@@ -1262,7 +1245,7 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
DEBUG_PRINT ("loading project %s\n\n", dirname);
/* FIXME: use the error parameter to determine if the project
* was loaded successfully */
- gbf_project_load (pm_plugin->project, dirname, &error);
+ ianjuta_project_load (pm_plugin->project, dirfile, &error);
anjuta_status_progress_tick (status, NULL, _("Created project viewâ?¦"));
@@ -1285,6 +1268,7 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
pm_plugin->project = NULL;
g_free (basename);
g_free (dirname);
+ g_object_unref (dirfile);
/* gtk_widget_destroy (progress_win); */
anjuta_status_pop (status);
anjuta_status_busy_pop (status);
@@ -1303,6 +1287,7 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
anjuta_status_busy_pop (status);
g_free (basename);
g_free (dirname);
+ g_object_unref (dirfile);
}
static void
@@ -1731,29 +1716,16 @@ uri_is_inside_project (ProjectManagerPlugin *plugin, const gchar *uri)
}
static gchar *
-get_element_uri_from_id (ProjectManagerPlugin *plugin, const gchar *id, const gchar *root)
+get_element_uri_from_id (ProjectManagerPlugin *plugin, AnjutaProjectNode *id, const gchar *root)
{
- gchar *path, *ptr;
- gchar *uri;
const gchar *project_root = NULL;
+ GFile *file = NULL;
+ GFile *target_file = NULL;
+ gchar *uri;
if (!id)
return NULL;
- path = g_strdup (id);
- ptr = strrchr (path, ':');
- if (ptr)
- {
- *ptr = '\0';
- if (ptr[1] == '/')
- {
- /* ID is source ID, extract source uri */
- uri = strrchr (path, ':'); /* keep uri scheme */
- *ptr = ':';
- return g_strdup (uri+1);
- }
- }
-
anjuta_shell_get (ANJUTA_PLUGIN (plugin)->shell,
root, G_TYPE_STRING,
&project_root, NULL);
@@ -1766,9 +1738,46 @@ get_element_uri_from_id (ProjectManagerPlugin *plugin, const gchar *id, const gc
&project_root,
NULL);
}
- uri = g_build_filename (project_root, path, NULL);
- /* DEBUG_PRINT ("Converting id: %s to %s", id, uri); */
- g_free (path);
+
+ switch (anjuta_project_node_get_type (id))
+ {
+ case ANJUTA_PROJECT_GROUP:
+ file = anjuta_project_group_get_directory (id);
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ file = anjuta_project_group_get_directory (anjuta_project_node_parent (id));
+ target_file = g_file_get_child (file, anjuta_project_target_get_name (id));
+ file = target_file;
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ file = anjuta_project_source_get_file (id);
+ break;
+ default:
+ file = NULL;
+ }
+
+ if ((file != NULL) && (project_root != NULL))
+ {
+ gchar *rel_path;
+
+ rel_path = g_file_get_relative_path (anjuta_project_group_get_directory (ianjuta_project_get_root (plugin->project, NULL)), file);
+
+ if (rel_path)
+ {
+ GFile *node_file = NULL;
+ GFile *root_file = NULL;
+ root_file = g_file_new_for_uri (project_root);
+ node_file = g_file_get_child (root_file, rel_path);
+ g_object_unref (root_file);
+
+ uri = g_file_get_uri (node_file);
+ g_object_unref (node_file);
+ g_free (rel_path);
+ }
+ }
+
+ if (target_file != NULL) g_object_unref (target_file);
+
return uri;
}
@@ -1808,293 +1817,199 @@ get_element_relative_path (ProjectManagerPlugin *plugin, const gchar *uri, const
return NULL;
}
-static GbfProjectTarget*
-get_target_from_uri (ProjectManagerPlugin *plugin, const gchar *uri)
+static AnjutaProjectNode*
+get_node_from_file (AnjutaProjectNode *parent, GFile *file)
{
- GbfProjectTarget *data;
- const gchar *rel_path;
- gchar *test_id;
-
- rel_path = get_element_relative_path (plugin, uri, IANJUTA_BUILDER_ROOT_URI);
-
- if (!rel_path)
- return NULL;
-
- /* FIXME: More target types should be handled */
- /* Test for shared lib */
- test_id = g_strconcat (rel_path, ":shared_lib", NULL);
- data = gbf_project_get_target (GBF_PROJECT (plugin->project),
- test_id, NULL);
- g_free (test_id);
-
- if (!data)
- {
- /* Test for static lib */
- test_id = g_strconcat (rel_path, ":static_lib", NULL);
- data = gbf_project_get_target (GBF_PROJECT (plugin->project),
- test_id, NULL);
- g_free (test_id);
- }
- if (!data)
+ AnjutaProjectNode *node;
+ GFile *target_file = NULL;
+
+ for (node = anjuta_project_node_first_child (parent); node != NULL; node = anjuta_project_node_next_sibling (node))
{
- /* Test for program */
- test_id = g_strconcat (rel_path, ":program", NULL);
- data = gbf_project_get_target (GBF_PROJECT (plugin->project),
- test_id, NULL);
- g_free (test_id);
+ switch (anjuta_project_node_get_type (node))
+ {
+ case ANJUTA_PROJECT_GROUP:
+ if (g_file_equal (anjuta_project_group_get_directory (node), file))
+ {
+ return node;
+ }
+ else
+ {
+ return get_node_from_file (node, file);
+ }
+ break;
+ case ANJUTA_PROJECT_TARGET:
+ target_file = g_file_get_child (anjuta_project_group_get_directory (parent), anjuta_project_target_get_name (node));
+ if (g_file_equal (target_file, file))
+ {
+ g_object_unref (target_file);
+ return node;
+ }
+ g_object_unref (target_file);
+ break;
+ case ANJUTA_PROJECT_SOURCE:
+ if (g_file_equal (anjuta_project_source_get_file (node), file))
+ {
+ return node;
+ }
+ break;
+ default:
+ break;
+ }
}
- return data;
+
+ return NULL;
}
-static gchar *
+static AnjutaProjectNode*
get_element_id_from_uri (ProjectManagerPlugin *plugin, const gchar *uri)
{
- GbfProjectTarget *target;
- gchar *id;
+ AnjutaProjectNode *node;
+ GFile *file;
if (!uri_is_inside_project (plugin, uri))
return NULL;
-
- target = get_target_from_uri (plugin, uri);
- if (target)
+
+ file = g_file_new_for_uri (uri);
+ node = ianjuta_project_get_root (plugin->project, NULL);
+ if (g_file_equal (anjuta_project_group_get_directory (node), file))
{
- id = g_strdup (target->id);
- gbf_project_target_free (target);
+ return node;
}
- else if (get_uri_vfs_type (uri) | G_FILE_TYPE_DIRECTORY)
+ else
{
- id = g_strconcat (get_element_relative_path (plugin, uri, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI), "/", NULL);
+ return get_node_from_file (node, file);
+ }
+}
+
+static AnjutaProjectTarget*
+get_target_from_uri (ProjectManagerPlugin *plugin, const gchar *uri)
+{
+ AnjutaProjectNode *node;
+
+ node = get_element_id_from_uri (plugin, uri);
+
+ if (anjuta_project_node_get_type (node) == ANJUTA_PROJECT_TARGET)
+ {
+ return (AnjutaProjectTarget *)node;
}
else
{
- id = strdup (get_element_relative_path (plugin, uri, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI));
+ return NULL;
}
- return id;
}
-static IAnjutaProjectManagerElementType
+static AnjutaProjectNodeType
iproject_manager_get_element_type (IAnjutaProjectManager *project_manager,
const gchar *element_uri,
GError **err)
{
- GFileType ftype;
+ AnjutaProjectNode *node;
ProjectManagerPlugin *plugin;
-
+
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager),
- IANJUTA_PROJECT_MANAGER_UNKNOWN);
+ ANJUTA_PROJECT_UNKNOWN);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project),
- IANJUTA_PROJECT_MANAGER_UNKNOWN);
- g_return_val_if_fail (uri_is_inside_project (plugin, element_uri),
- IANJUTA_PROJECT_MANAGER_UNKNOWN);
-
- ftype = get_uri_vfs_type (element_uri);
- if (ftype | G_FILE_TYPE_DIRECTORY)
- {
- return IANJUTA_PROJECT_MANAGER_GROUP;
- }
- else if (ianjuta_project_manager_get_target_type (project_manager,
- element_uri, NULL) !=
- IANJUTA_PROJECT_MANAGER_TARGET_UNKNOWN)
- {
- return IANJUTA_PROJECT_MANAGER_TARGET;
- }
- else if (ftype | G_FILE_TYPE_REGULAR)
- {
- return IANJUTA_PROJECT_MANAGER_SOURCE;
- }
- return IANJUTA_PROJECT_MANAGER_UNKNOWN;
+
+ node = get_element_id_from_uri (plugin, element_uri);
+
+ return node == NULL ? ANJUTA_PROJECT_UNKNOWN : anjuta_project_node_get_type (node);
}
static GList*
iproject_manager_get_elements (IAnjutaProjectManager *project_manager,
- IAnjutaProjectManagerElementType element_type,
+ AnjutaProjectNodeType element_type,
GError **err)
{
- GList *elements;
ProjectManagerPlugin *plugin;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), NULL);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
-
- elements = NULL;
- switch (element_type)
- {
- case IANJUTA_PROJECT_MANAGER_SOURCE:
- {
- GList *sources, *node;
- GbfProjectTargetSource *source;
- sources = gbf_project_get_all_sources (plugin->project, NULL);
- node = sources;
- while (node)
- {
- source = gbf_project_get_source (plugin->project,
- (const gchar *) node->data,
- NULL);
- if (source)
- elements = g_list_prepend (elements,
- g_strdup (source->source_uri));
- gbf_project_target_source_free (source);
- g_free (node->data);
- node = node->next;
- }
- g_list_free (sources);
- break;
- }
- case IANJUTA_PROJECT_MANAGER_TARGET:
- {
- GList *targets, *node;
- targets = gbf_project_get_all_targets (plugin->project, NULL);
- node = targets;
- while (node)
- {
- elements = g_list_prepend (elements,
- get_element_uri_from_id (plugin,
- (const gchar *)node->data,
- IANJUTA_BUILDER_ROOT_URI));
- g_free (node->data);
- node = node->next;
- }
- g_list_free (targets);
- break;
- }
- case IANJUTA_PROJECT_MANAGER_GROUP:
- {
- GList *groups, *node;
- groups = gbf_project_get_all_groups (plugin->project, NULL);
- node = groups;
- while (node)
- {
- elements = g_list_prepend (elements,
- get_element_uri_from_id (plugin,
- (const gchar *)node->data,
- IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI));
- g_free (node->data);
- node = node->next;
- }
- g_list_free (groups);
- break;
- }
- default:
- elements = NULL;
- }
- return g_list_reverse (elements);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
+
+ return anjuta_project_node_all (ianjuta_project_get_root (plugin->project, NULL), element_type);
}
-static IAnjutaProjectManagerTargetType
+static AnjutaProjectTargetClass
iproject_manager_get_target_type (IAnjutaProjectManager *project_manager,
const gchar *target_uri,
GError **err)
{
- IAnjutaProjectManagerElementType element_type;
- IAnjutaProjectManagerTargetType target_type;
ProjectManagerPlugin *plugin;
- GbfProjectTarget *data;
+ AnjutaProjectTarget *target;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager),
- IANJUTA_PROJECT_MANAGER_TARGET_UNKNOWN);
+ ANJUTA_TARGET_UNKNOWN);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project),
- IANJUTA_PROJECT_MANAGER_TARGET_UNKNOWN);
-
- element_type = ianjuta_project_manager_get_element_type (project_manager,
- target_uri, NULL);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project),
+ ANJUTA_TARGET_UNKNOWN);
g_return_val_if_fail (uri_is_inside_project (plugin, target_uri),
- IANJUTA_PROJECT_MANAGER_TARGET_UNKNOWN);
-
- data = get_target_from_uri (plugin, target_uri);
+ ANJUTA_TARGET_UNKNOWN);
- if (data && data->type && strcmp (data->type, "shared_lib") == 0)
- {
- target_type = IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB;
- }
- else if (data && data->type && strcmp (data->type, "static_lib") == 0)
- {
- target_type = IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB;
- }
- else if (data && data->type && strcmp (data->type, "program") == 0)
+ target = get_target_from_uri (plugin, target_uri);
+
+ if (target != NULL)
{
- target_type = IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB;
+ AnjutaProjectTargetType type = anjuta_project_target_get_type (target);
+
+ return anjuta_project_target_type_class (type);
}
else
{
- target_type = IANJUTA_PROJECT_MANAGER_TARGET_UNKNOWN;
+ return ANJUTA_TARGET_UNKNOWN;
}
- if (data)
- gbf_project_target_free (data);
- return target_type;
}
static GList*
iproject_manager_get_targets (IAnjutaProjectManager *project_manager,
- IAnjutaProjectManagerTargetType target_type,
+ AnjutaProjectTargetClass target_type,
GError **err)
{
GList *targets, *node;
- const gchar *target_id;
- GList *elements;
ProjectManagerPlugin *plugin;
- GList *target_types = NULL;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), NULL);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
-
- switch (target_type)
- {
- case IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB:
- target_types = g_list_append(target_types, "shared_lib");
- break;
- case IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB:
- target_types = g_list_append(target_types, "static_lib");
- break;
- case IANJUTA_PROJECT_MANAGER_TARGET_EXECUTABLE:
- target_types = g_list_append(target_types, "program");
- target_types = g_list_append(target_types, "script");
- break;
- default:
- /* FIXME: there are some more target types */
- g_warning ("Unsupported target type");
- return NULL;
- }
-
- elements = NULL;
- targets = gbf_project_get_all_targets (plugin->project, NULL);
- node = targets;
- while (node)
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
+
+ /* Get all targets */
+ targets = anjuta_project_node_all (ianjuta_project_get_root (plugin->project, NULL), ANJUTA_PROJECT_TARGET);
+
+ /* Remove all targets not in specified class */
+ for (node = g_list_first (targets); node != NULL;)
{
- const gchar *t_type;
-
- target_id = (const gchar*) node->data;
-
- t_type = strrchr (target_id, ':');
- if (t_type && strlen (t_type) > 2)
+ AnjutaProjectTargetType type;
+
+ type = anjuta_project_target_get_type (node->data);
+ if (anjuta_project_target_type_class (type) != target_type)
{
- GList* type_node;
- t_type++;
- for (type_node = target_types; type_node != NULL;
- type_node = type_node->next)
- {
- if (strcmp (t_type, type_node->data) == 0)
- {
- gchar *target_uri = get_element_uri_from_id (plugin,
- target_id,
- IANJUTA_BUILDER_ROOT_URI);
- elements = g_list_prepend (elements, target_uri);
- }
- }
+ GList *next = g_list_next (node);
+ targets = g_list_delete_link (targets, node);
+ node = next;
+ }
+ else
+ {
+ node = g_list_next (node);
}
- g_free (node->data);
- node = node->next;
}
- g_list_free (targets);
- return g_list_reverse (elements);
+
+ /* Replace all targets by their corresponding URI */
+ for (node = g_list_first (targets); node != NULL; node = g_list_next (node))
+ {
+ AnjutaProjectTarget *target = (AnjutaProjectTarget *)node->data;
+ AnjutaProjectGroup *parent = anjuta_project_node_parent (target);
+ GFile *file;
+
+ file = g_file_get_child (anjuta_project_group_get_directory (parent), anjuta_project_target_get_name (target));
+ node->data = g_file_get_uri (file);
+ g_object_unref (file);
+ }
+
+ return targets;
}
static gchar*
@@ -2102,13 +2017,13 @@ iproject_manager_get_parent (IAnjutaProjectManager *project_manager,
const gchar *element_uri,
GError **err)
{
- IAnjutaProjectManagerElementType type;
+ AnjutaProjectNodeType type;
ProjectManagerPlugin *plugin;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), NULL);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
type = ianjuta_project_manager_get_element_type (project_manager,
element_uri, NULL);
@@ -2126,7 +2041,7 @@ iproject_manager_get_children (IAnjutaProjectManager *project_manager,
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), NULL);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
/* FIXME: */
return NULL;
}
@@ -2144,7 +2059,7 @@ iproject_manager_get_selected (IAnjutaProjectManager *project_manager,
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
if (plugin->project == NULL) return NULL;
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
GBF_TREE_NODE_TARGET_SOURCE);
@@ -2162,7 +2077,7 @@ iproject_manager_get_selected (IAnjutaProjectManager *project_manager,
GBF_TREE_NODE_TARGET);
if (data && data->type == GBF_TREE_NODE_TARGET)
{
- uri = get_element_uri_from_id (plugin, data->id, IANJUTA_BUILDER_ROOT_URI);
+ uri = get_element_uri_from_id (plugin, (AnjutaProjectNode *)data->id, IANJUTA_BUILDER_ROOT_URI);
gbf_tree_data_free (data);
return uri;
}
@@ -2185,79 +2100,94 @@ iproject_manager_get_selected (IAnjutaProjectManager *project_manager,
return NULL;
}
-static gchar *
+static gchar*
iproject_manager_get_selected_id (IAnjutaProjectManager *project_manager,
- IAnjutaProjectManagerElementType element_type,
+ AnjutaProjectNodeType element_type,
GError **err)
{
GbfTreeData *data;
ProjectManagerPlugin *plugin;
- gchar *id = NULL;
+ AnjutaProjectNode *node = NULL;
+ gchar *uri;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), NULL);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), NULL);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), NULL);
- if (element_type == IANJUTA_PROJECT_MANAGER_UNKNOWN ||
- element_type == IANJUTA_PROJECT_MANAGER_SOURCE)
+ if (element_type == ANJUTA_PROJECT_UNKNOWN ||
+ element_type == ANJUTA_PROJECT_SOURCE)
{
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
GBF_TREE_NODE_TARGET_SOURCE);
if (data && data->type == GBF_TREE_NODE_TARGET_SOURCE)
- id = g_strdup (data->id);
+ node = data->id;
if (data)
gbf_tree_data_free (data);
- if (id)
- return id;
+ if (node)
+ {
+ uri = get_element_uri_from_id (plugin, node, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
+ return uri;
+ }
}
- if (element_type == IANJUTA_PROJECT_MANAGER_UNKNOWN ||
- element_type == IANJUTA_PROJECT_MANAGER_TARGET)
+ if (element_type == ANJUTA_PROJECT_UNKNOWN ||
+ element_type == ANJUTA_PROJECT_TARGET)
{
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
GBF_TREE_NODE_TARGET);
if (data && data->type == GBF_TREE_NODE_TARGET)
- id = g_strdup (data->id);
+ node = data->id;
if (data)
gbf_tree_data_free (data);
- if (id)
- return id;
+ if (node)
+ {
+ uri = get_element_uri_from_id (plugin, node, IANJUTA_BUILDER_ROOT_URI);
+ return uri;
+ }
}
- if (element_type == IANJUTA_PROJECT_MANAGER_UNKNOWN ||
- element_type == IANJUTA_PROJECT_MANAGER_GROUP)
+ if (element_type == ANJUTA_PROJECT_UNKNOWN ||
+ element_type == ANJUTA_PROJECT_GROUP)
{
data = gbf_project_view_find_selected (GBF_PROJECT_VIEW (plugin->view),
GBF_TREE_NODE_GROUP);
if (data && data->type == GBF_TREE_NODE_GROUP)
- id = g_strdup (data->id);
+ node = data->id;
if (data)
gbf_tree_data_free (data);
- if (id)
- return id;
+ if (node)
+ {
+ uri = get_element_uri_from_id (plugin, node, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
+ return uri;
+ }
}
- return id;
+ if (node)
+ {
+ uri = get_element_uri_from_id (plugin, node, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
+ return uri;
+ }
+ return NULL;
}
-static IAnjutaProjectManagerCapabilities
+static IAnjutaProjectCapabilities
iproject_manager_get_capabilities (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager),
- IANJUTA_PROJECT_MANAGER_CAN_ADD_NONE);
+ IANJUTA_PROJECT_CAN_ADD_NONE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- return gbf_project_get_capabilities (plugin->project, NULL);
+ return ianjuta_project_get_capabilities (plugin->project, NULL);
}
static gchar*
@@ -2267,20 +2197,20 @@ iproject_manager_add_source (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
- IAnjutaProjectManagerElementType default_location_type;
- gchar *location_id = NULL;
- gchar* source_id;
+ AnjutaProjectNodeType default_location_type;
+ AnjutaProjectNode *location_id = NULL;
+ AnjutaProjectSource *source_id;
gchar* source_uri;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), FALSE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), FALSE);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), FALSE);
update_operation_begin (plugin);
if (default_location_uri == NULL)
{
- default_location_type = IANJUTA_PROJECT_MANAGER_UNKNOWN;
+ default_location_type = ANJUTA_PROJECT_UNKNOWN;
}
else
{
@@ -2289,14 +2219,14 @@ iproject_manager_add_source (IAnjutaProjectManager *project_manager,
default_location_uri, NULL);
location_id = get_element_id_from_uri (plugin, default_location_uri);
}
- if (default_location_type == IANJUTA_PROJECT_MANAGER_GROUP)
+ if (default_location_type == ANJUTA_PROJECT_GROUP)
{
source_id = gbf_project_util_add_source (plugin->model,
get_plugin_parent_window (plugin),
NULL, location_id,
source_uri_to_add);
}
- else if (default_location_type == IANJUTA_PROJECT_MANAGER_TARGET)
+ else if (default_location_type == ANJUTA_PROJECT_TARGET)
{
source_id = gbf_project_util_add_source (plugin->model,
get_plugin_parent_window (plugin),
@@ -2313,7 +2243,6 @@ iproject_manager_add_source (IAnjutaProjectManager *project_manager,
update_operation_end (plugin, TRUE);
source_uri = get_element_uri_from_id(plugin, source_id, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
- g_free(source_id);
return source_uri;
}
@@ -2325,21 +2254,26 @@ iproject_manager_add_source_quiet (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
- gchar* source_id;
+ AnjutaProjectSource *source_id;
+ GFile *source_file;
+ AnjutaProjectTarget *target;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), FALSE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), FALSE);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), FALSE);
+ target = get_element_id_from_uri (plugin, location_uri);
+ source_file = g_file_new_for_uri (source_uri_to_add);
update_operation_begin (plugin);
- source_id = gbf_project_add_source (plugin->project,
- source_uri_to_add,
- location_uri,
+ source_id = ianjuta_project_add_source (plugin->project,
+ target,
+ source_file,
err);
update_operation_end (plugin, TRUE);
+ g_object_unref (source_file);
- return source_id;
+ return get_element_uri_from_id (plugin, source_id, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
}
static GList*
@@ -2349,20 +2283,20 @@ iproject_manager_add_source_multi (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
- IAnjutaProjectManagerElementType default_location_type;
- gchar *location_id = NULL;
+ AnjutaProjectNodeType default_location_type;
+ AnjutaProjectNode *location_id = NULL;
GList* source_ids;
GList* source_uris = NULL;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), FALSE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), FALSE);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), FALSE);
update_operation_begin (plugin);
if (default_location_uri == NULL)
{
- default_location_type = IANJUTA_PROJECT_MANAGER_UNKNOWN;
+ default_location_type = ANJUTA_PROJECT_UNKNOWN;
}
else
{
@@ -2371,14 +2305,14 @@ iproject_manager_add_source_multi (IAnjutaProjectManager *project_manager,
default_location_uri, NULL);
location_id = get_element_id_from_uri (plugin, default_location_uri);
}
- if (default_location_type == IANJUTA_PROJECT_MANAGER_GROUP)
+ if (default_location_type == ANJUTA_PROJECT_GROUP)
{
source_ids = gbf_project_util_add_source_multi (plugin->model,
get_plugin_parent_window (plugin),
NULL, location_id,
source_add_uris);
}
- else if (default_location_type == IANJUTA_PROJECT_MANAGER_TARGET)
+ else if (default_location_type == ANJUTA_PROJECT_TARGET)
{
source_ids =
gbf_project_util_add_source_multi (plugin->model,
@@ -2416,13 +2350,15 @@ iproject_manager_add_target (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
- gchar *default_group_id, *target_id, *target_uri = NULL;
+ gchar *target_uri = NULL;
+ AnjutaProjectTarget *target_id;
+ AnjutaProjectGroup *default_group_id;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), FALSE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), FALSE);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), FALSE);
default_group_id = get_element_id_from_uri (plugin, default_group_uri);
@@ -2434,7 +2370,6 @@ iproject_manager_add_target (IAnjutaProjectManager *project_manager,
update_operation_end (plugin, TRUE);
target_uri = get_element_uri_from_id (plugin, target_id, IANJUTA_BUILDER_ROOT_URI);
g_free (target_id);
- g_free (default_group_id);
return target_uri;
}
@@ -2445,13 +2380,14 @@ iproject_manager_add_group (IAnjutaProjectManager *project_manager,
GError **err)
{
ProjectManagerPlugin *plugin;
- gchar *group_id, *group_uri = NULL;
- gchar *default_group_id;
+ gchar *group_uri = NULL;
+ AnjutaProjectGroup *group_id;
+ AnjutaProjectGroup *default_group_id;
g_return_val_if_fail (ANJUTA_IS_PLUGIN (project_manager), FALSE);
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- g_return_val_if_fail (GBF_IS_PROJECT (plugin->project), FALSE);
+ g_return_val_if_fail (IANJUTA_IS_PROJECT (plugin->project), FALSE);
default_group_id = get_element_id_from_uri (plugin, default_group_uri);
@@ -2463,7 +2399,7 @@ iproject_manager_add_group (IAnjutaProjectManager *project_manager,
update_operation_end (plugin, TRUE);
group_uri = get_element_uri_from_id (plugin, group_id, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI);
g_free (group_id);
- g_free (default_group_id);
+
return group_uri;
}
@@ -2474,32 +2410,20 @@ iproject_manager_is_open (IAnjutaProjectManager *project_manager, GError **err)
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
- return GBF_IS_PROJECT (plugin->project);
+ return IANJUTA_IS_PROJECT (plugin->project);
}
static GList*
iproject_manager_get_packages (IAnjutaProjectManager *project_manager, GError **err)
{
ProjectManagerPlugin *plugin;
- GList *modules = NULL;
- GList *packages = NULL;
- GList* node;
plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (G_OBJECT (project_manager));
/* Check if a current project is opened */
if (plugin->project == NULL) return NULL;
-
- modules = gbf_project_get_config_modules (plugin->project, NULL);
- for (node = modules; node != NULL; node = g_list_next (node))
- {
- GList* mod_pkgs = gbf_project_get_config_packages (plugin->project,
- node->data, NULL);
- packages = g_list_concat (packages, mod_pkgs);
- }
- g_list_foreach (modules, (GFunc)g_free, NULL);
- g_list_free (modules);
- return packages;
+
+ return ianjuta_project_get_packages (plugin->project, NULL);
}
static void
diff --git a/plugins/project-manager/plugin.h b/plugins/project-manager/plugin.h
index 7490a02..1e58763 100644
--- a/plugins/project-manager/plugin.h
+++ b/plugins/project-manager/plugin.h
@@ -22,7 +22,8 @@
#define _PROJECT_MANAGER_PLUGIN_H_
#include <libanjuta/anjuta-plugin.h>
-#include <libanjuta/gbf-project.h>
+#include <libanjuta/anjuta-project.h>
+#include <libanjuta/interfaces/ianjuta-project.h>
#include "gbf-project-model.h"
#include "gbf-project-view.h"
@@ -42,7 +43,7 @@ struct _ProjectManagerPlugin{
AnjutaUI *ui;
AnjutaPreferences *prefs;
- GbfProject *project;
+ IAnjutaProject *project;
GtkWidget *view;
GbfProjectModel *model;
GtkWidget *scrolledwindow;
diff --git a/plugins/run-program/parameters.c b/plugins/run-program/parameters.c
index 2f7c6d9..9a31567 100644
--- a/plugins/run-program/parameters.c
+++ b/plugins/run-program/parameters.c
@@ -677,7 +677,7 @@ run_dialog_init (RunDialog *dlg, RunProgramPlugin *plugin)
if (pm != NULL)
{
exec_targets = ianjuta_project_manager_get_targets (pm,
- IANJUTA_PROJECT_MANAGER_TARGET_EXECUTABLE,
+ ANJUTA_TARGET_EXECUTABLE,
NULL);
}
if (exec_targets != NULL)
diff --git a/plugins/search/search-replace_backend.c b/plugins/search/search-replace_backend.c
index 8b1fa17..b67fbeb 100644
--- a/plugins/search/search-replace_backend.c
+++ b/plugins/search/search-replace_backend.c
@@ -300,7 +300,7 @@ get_project_file_list(void)
IAnjutaProjectManager , NULL);
list = ianjuta_project_manager_get_elements (prjman,
- IANJUTA_PROJECT_MANAGER_SOURCE,
+ ANJUTA_PROJECT_SOURCE,
NULL);
if (list)
{
diff --git a/plugins/symbol-db/plugin.c b/plugins/symbol-db/plugin.c
index 87666a8..fe8d105 100644
--- a/plugins/symbol-db/plugin.c
+++ b/plugins/symbol-db/plugin.c
@@ -1413,7 +1413,7 @@ do_import_project_sources (AnjutaPlugin *plugin, IAnjutaProjectManager *pm,
sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
prj_elements_list = ianjuta_project_manager_get_elements (pm,
- IANJUTA_PROJECT_MANAGER_SOURCE,
+ ANJUTA_PROJECT_SOURCE,
NULL);
if (prj_elements_list == NULL)
@@ -1579,7 +1579,7 @@ do_check_offline_files_changed (SymbolDBPlugin *sdb_plugin)
IAnjutaProjectManager, NULL);
prj_elements_list = ianjuta_project_manager_get_elements (pm,
- IANJUTA_PROJECT_MANAGER_SOURCE,
+ ANJUTA_PROJECT_SOURCE,
NULL);
/* fill an hash table with all the items of the list just taken.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]