1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
4 * Copyright (C) 2009 Sébastien Granjoux
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
27 #include "am-project.h"
29 #include "am-project-private.h"
31 #include "amp-module.h"
32 #include "amp-package.h"
33 #include "amp-group.h"
34 #include "amp-target.h"
35 #include "amp-source.h"
36 #include "amp-object.h"
37 #include "command-queue.h"
39 #include <libanjuta/interfaces/ianjuta-project.h>
40 #include <libanjuta/anjuta-debug.h>
41 #include <libanjuta/anjuta-utils.h>
42 #include <libanjuta/anjuta-pkg-config.h>
50 #include <sys/types.h>
52 #include <glib/gi18n.h>
56 #include "ac-scanner.h"
57 #include "ac-writer.h"
58 #include "am-scanner.h"
59 #include "am-writer.h"
60 //#include "am-config.h"
61 #include "am-properties.h"
64 #define UNIMPLEMENTED G_STMT_START { g_warning (G_STRLOC": unimplemented"); } G_STMT_END
66 /* Constant strings for parsing perl script error output */
67 #define ERROR_PREFIX "ERROR("
68 #define WARNING_PREFIX "WARNING("
69 #define MESSAGE_DELIMITER ": "
71 const gchar
*valid_am_makefiles
[] = {"GNUmakefile.am", "makefile.am", "Makefile.am", NULL
};
74 #define STR_REPLACE(target, source) \
75 { g_free (target); target = source == NULL ? NULL : g_strdup (source);}
78 typedef struct _AmpConfigFile AmpConfigFile
;
80 struct _AmpConfigFile
{
86 *---------------------------------------------------------------------------*/
88 static AmpNodeInfo AmpNodeInformations
[] = {
89 {{ANJUTA_PROJECT_GROUP
| ANJUTA_PROJECT_ROOT_GROUP
,
92 "autotools-project-root-edit"},
97 {{ANJUTA_PROJECT_GROUP
,
100 "autotools-project-folder-edit"},
105 {{ANJUTA_PROJECT_SOURCE
,
113 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_UNKNOWN
| ANJUTA_PROJECT_READ_ONLY
,
114 /* Translator: Unknown here is a target type, if not unknown it can
115 * be a program or a shared library by example */
118 "autotools-project-target-edit"},
123 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_SHAREDLIB
,
124 N_("Shared Library (Libtool)"),
125 "application/x-sharedlib",
126 "autotools-project-target-edit"},
127 AM_TOKEN__LTLIBRARIES
,
131 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_LT_MODULE
,
132 N_("Module (Libtool)"),
133 "application/x-sharedlib",
134 "autotools-project-target-edit"},
135 AM_TOKEN__LTLIBRARIES
,
139 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_STATICLIB
,
140 N_("Static Library (Libtool)"),
141 "application/x-archive",
142 "autotools-project-target-edit"},
147 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_PROGRAM
| ANJUTA_PROJECT_EXECUTABLE
,
149 "application/x-executable",
150 "autotools-project-target-edit"},
155 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PYTHON
,
157 "application/x-python",
158 "autotools-project-target-edit"},
163 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_JAVA
,
165 "application/x-java",
166 "autotools-project-target-edit"},
171 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_LISP
,
174 "autotools-project-target-edit"},
179 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_HEADER
,
182 "autotools-project-target-edit"},
187 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_MAN
,
188 N_("Man Documentation"),
190 "autotools-project-target-edit"},
195 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_INFO
,
196 N_("Info Documentation"),
197 "application/x-tex-info",
198 "autotools-project-target-edit"},
203 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_DATA
,
204 N_("Miscellaneous Data"),
205 "application/octet-stream",
206 "autotools-project-target-edit"},
211 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_SCRIPT
,
213 "text/x-shellscript",
214 "autotools-project-target-edit"},
219 {{ANJUTA_PROJECT_MODULE
,
227 {{ANJUTA_PROJECT_PACKAGE
,
235 {{ANJUTA_PROJECT_UNKNOWN
,
245 *---------------------------------------------------------------------------*/
247 static void iproject_iface_init(IAnjutaProjectIface
* iface
);
249 G_DEFINE_DYNAMIC_TYPE_EXTENDED (AmpProject
,
253 G_IMPLEMENT_INTERFACE_DYNAMIC (IANJUTA_TYPE_PROJECT
,
254 iproject_iface_init
));
259 *---------------------------------------------------------------------------*/
262 /* ----- Standard GObject types and variables ----- */
269 static GObject
*parent_class
;
272 *---------------------------------------------------------------------------*/
274 /* Work even if file is not a descendant of parent */
276 get_relative_path (GFile
*parent
, GFile
*file
)
280 relative
= g_file_get_relative_path (parent
, file
);
281 if (relative
== NULL
)
283 if (g_file_equal (parent
, file
))
285 relative
= g_strdup (".");
289 GFile
*grand_parent
= g_file_get_parent (parent
);
291 gchar
*grand_relative
;
296 for (level
= 1; !g_file_has_prefix (file
, grand_parent
); level
++)
298 GFile
*next
= g_file_get_parent (grand_parent
);
300 g_object_unref (grand_parent
);
304 grand_relative
= g_file_get_relative_path (grand_parent
, file
);
305 g_object_unref (grand_parent
);
307 len
= strlen (grand_relative
);
308 relative
= g_new (gchar
, len
+ level
* 3 + 1);
310 for (; level
; level
--)
312 memcpy(ptr
, ".." G_DIR_SEPARATOR_S
, 3);
315 memcpy (ptr
, grand_relative
, len
+ 1);
316 g_free (grand_relative
);
324 file_type (GFile
*file
, const gchar
*filename
)
330 child
= filename
!= NULL
? g_file_get_child (file
, filename
) : g_object_ref (file
);
332 info
= g_file_query_info (child
,
333 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
334 G_FILE_QUERY_INFO_NONE
,
339 type
= g_file_info_get_file_type (info
);
340 g_object_unref (info
);
344 type
= G_FILE_TYPE_UNKNOWN
;
347 g_object_unref (child
);
352 /* Automake parsing function
353 *---------------------------------------------------------------------------*/
355 /* Remove invalid character according to automake rules */
357 canonicalize_automake_variable (const gchar
*name
)
359 gchar
*canon_name
= g_strdup (name
);
362 for (ptr
= canon_name
; *ptr
!= '\0'; ptr
++)
364 if (!g_ascii_isalnum (*ptr
) && (*ptr
!= '@'))
374 split_automake_variable (gchar
*name
, gint
*flags
, gchar
**module
, gchar
**primary
)
376 gboolean res
= FALSE
;
378 GMatchInfo
*match_info
;
382 regex
= g_regex_new ("(nobase_|notrans_)?"
384 "(noinst_|check_|man_|man[0-9al]_)?"
388 G_REGEX_MATCH_ANCHORED
,
391 if (!g_regex_match (regex
, name
, G_REGEX_MATCH_ANCHORED
, &match_info
))
397 g_match_info_fetch_pos (match_info
, 1, &start_pos
, &end_pos
);
400 if (*(name
+ start_pos
+ 2) == 'b') *flags
|= AM_TARGET_NOBASE
;
401 if (*(name
+ start_pos
+ 2) == 't') *flags
|= AM_TARGET_NOTRANS
;
404 g_match_info_fetch_pos (match_info
, 2, &start_pos
, &end_pos
);
407 if (*(name
+ start_pos
) == 'd') *flags
|= AM_TARGET_DIST
;
408 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NODIST
;
411 g_match_info_fetch_pos (match_info
, 3, &start_pos
, &end_pos
);
414 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NOINST
;
415 if (*(name
+ start_pos
) == 'c') *flags
|= AM_TARGET_CHECK
;
416 if (*(name
+ start_pos
) == 'm')
418 gchar section
= *(name
+ end_pos
- 1);
419 *flags
|= AM_TARGET_MAN
;
420 if (section
!= 'n') *flags
|= (section
& 0x1F) << 7;
427 g_match_info_fetch_pos (match_info
, 4, &start_pos
, &end_pos
);
430 *module
= name
+ start_pos
;
431 *(name
+ end_pos
- 1) = '\0';
441 g_match_info_fetch_pos (match_info
, 5, &start_pos
, &end_pos
);
444 *primary
= name
+ start_pos
;
455 g_match_info_unref (match_info
);
456 g_regex_unref (regex
);
462 ac_init_default_tarname (const gchar
*name
)
466 if (name
== NULL
) return NULL
;
468 /* Remove GNU prefix */
469 if (strncmp (name
, "GNU ", 4) == 0) name
+= 4;
471 tarname
= g_ascii_strdown (name
, -1);
472 g_strcanon (tarname
, "abcdefghijklmnopqrstuvwxyz0123456789", '-');
477 /* Config file objects
478 *---------------------------------------------------------------------------*/
480 static AmpConfigFile
*
481 amp_config_file_new (const gchar
*pathname
, GFile
*project_root
, AnjutaToken
*token
)
483 AmpConfigFile
*config
;
485 g_return_val_if_fail ((pathname
!= NULL
) && (project_root
!= NULL
), NULL
);
487 config
= g_slice_new0(AmpConfigFile
);
488 config
->file
= g_file_resolve_relative_path (project_root
, pathname
);
489 config
->token
= token
;
495 amp_config_file_free (AmpConfigFile
*config
)
499 g_object_unref (config
->file
);
500 g_slice_free (AmpConfigFile
, config
);
505 amp_project_clear (AmpProject
*project
)
507 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
508 project
->configure_file
= NULL
;
509 if (project
->configure_token
) anjuta_token_free (project
->configure_token
);
510 project
->configure_token
= NULL
;
514 on_project_monitor_changed (GFileMonitor
*monitor
,
517 GFileMonitorEvent event_type
,
520 AmpProject
*project
= AMP_PROJECT (data
);
522 switch (event_type
) {
523 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
:
524 case G_FILE_MONITOR_EVENT_CHANGED
:
525 case G_FILE_MONITOR_EVENT_DELETED
:
526 /* project can be NULL, if the node is dummy node because the
527 * original one is reloaded. */
528 g_signal_emit_by_name (G_OBJECT (project
), "file-changed", data
);
536 amp_project_set_configure (AmpProject
*project
, GFile
*configure
)
538 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
539 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
540 if (project
->monitor
) g_object_unref (project
->monitor
);
541 if (configure
!= NULL
)
543 project
->configure_file
= anjuta_token_file_new (configure
);
544 project
->configure
= g_object_ref (configure
);
546 project
->monitor
= g_file_monitor_file (configure
,
550 if (project
->monitor
!= NULL
)
552 g_signal_connect (G_OBJECT (project
->monitor
),
554 G_CALLBACK (on_project_monitor_changed
),
560 project
->configure_file
= NULL
;
561 project
->configure
= NULL
;
562 project
->monitor
= NULL
;
565 return project
->configure_file
;
569 amp_project_update_configure (AmpProject
*project
, AnjutaToken
*token
)
571 return anjuta_token_file_update (project
->configure_file
, token
);
575 amp_project_get_configure_token (AmpProject
*project
)
577 return project
->configure_token
;
581 amp_project_get_config_token (AmpProject
*project
, GFile
*file
)
583 AmpConfigFile
*config
;
585 config
= g_hash_table_lookup (project
->configs
, file
);
587 return config
!= NULL
? config
->token
: NULL
;
591 remove_config_file (gpointer data
, GObject
*object
)
593 AmpProject
*project
= (AmpProject
*)data
;
595 g_return_if_fail (project
->files
!= NULL
);
597 project
->files
= g_list_remove (project
->files
, object
);
601 amp_project_update_root (AmpProject
*project
, AmpProject
*new_project
)
605 AnjutaTokenStyle
*style
;
607 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
608 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
609 if (project
->monitor
) g_object_unref (project
->monitor
);
611 project
->configure
= new_project
->configure
;
612 if (project
->configure
!= NULL
)
614 project
->monitor
= g_file_monitor_file (project
->configure
,
618 if (project
->monitor
!= NULL
)
620 g_signal_connect (G_OBJECT (project
->monitor
),
622 G_CALLBACK (on_project_monitor_changed
),
628 project
->monitor
= NULL
;
630 new_project
->configure
= NULL
;
631 project
->configure_file
= new_project
->configure_file
;
632 new_project
->configure_file
= NULL
;
633 project
->configure_token
= new_project
->configure_token
;
634 new_project
->configure_token
= NULL
;
636 hash
= project
->groups
;
637 project
->groups
= new_project
->groups
;
638 new_project
->groups
= hash
;
640 list
= project
->files
;
641 project
->files
= new_project
->files
;
642 new_project
->files
= list
;
644 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
646 GObject
*tfile
= (GObject
*)list
->data
;
648 g_object_weak_unref (tfile
, remove_config_file
, new_project
);
649 g_object_weak_ref (tfile
, remove_config_file
, project
);
651 for (list
= new_project
->files
; list
!= NULL
; list
= g_list_next (list
))
653 GObject
*tfile
= (GObject
*)list
->data
;
655 g_object_weak_unref (tfile
, remove_config_file
, project
);
656 g_object_weak_ref (tfile
, remove_config_file
, new_project
);
659 hash
= project
->configs
;
660 project
->configs
= new_project
->configs
;
661 new_project
->configs
= hash
;
664 style
= project
->ac_space_list
;
665 project
->ac_space_list
= new_project
->ac_space_list
;
666 new_project
->ac_space_list
= style
;
668 style
= project
->am_space_list
;
669 project
->am_space_list
= new_project
->am_space_list
;
670 new_project
->am_space_list
= style
;
672 style
= project
->arg_list
;
673 project
->arg_list
= new_project
->arg_list
;
674 new_project
->arg_list
= style
;
676 AMP_NODE_CLASS (parent_class
)->update (AMP_NODE (project
), AMP_NODE (new_project
));
681 *---------------------------------------------------------------------------*/
684 find_target (AnjutaProjectNode
*node
, gpointer data
)
686 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
688 if (strcmp (anjuta_project_node_get_name (node
), *(gchar
**)data
) == 0)
690 /* Find target, return node value in pointer */
691 *(AnjutaProjectNode
**)data
= node
;
701 find_canonical_target (AnjutaProjectNode
*node
, gpointer data
)
703 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
705 gchar
*canon_name
= canonicalize_automake_variable (anjuta_project_node_get_name (node
));
706 DEBUG_PRINT ("compare canon %s vs %s node %p", canon_name
, *(gchar
**)data
, node
);
707 if (strcmp (canon_name
, *(gchar
**)data
) == 0)
709 /* Find target, return node value in pointer */
710 *(AnjutaProjectNode
**)data
= node
;
722 * ---------------- Data structures managment
726 amp_project_load_properties (AmpProject
*project
, AnjutaToken
*macro
, AnjutaToken
*args
)
729 gint type
= anjuta_token_get_type (macro
);
731 for (item
= anjuta_project_node_get_properties_info (ANJUTA_PROJECT_NODE (project
)); item
!= NULL
; item
= g_list_next (item
))
733 AmpPropertyInfo
*info
= (AmpPropertyInfo
*)item
->data
;
735 if ((info
->token_type
== type
) && (info
->flags
& AM_PROPERTY_IN_CONFIGURE
))
737 AnjutaProjectProperty
*new_prop
;
739 new_prop
= anjuta_project_node_get_property (ANJUTA_PROJECT_NODE (project
), info
->base
.id
);
740 if ((new_prop
!= NULL
) && (new_prop
->info
->default_value
!= new_prop
))
742 anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (project
), new_prop
);
743 amp_property_free (new_prop
);
745 new_prop
= amp_property_new (NULL
, info
->token_type
, info
->position
, NULL
, args
);
747 if (info
->position
>= 0)
749 /* Each parameter correspond to a different property */
752 arg
= anjuta_token_nth_word (args
, info
->position
);
753 g_free (new_prop
->value
);
754 new_prop
->value
= anjuta_token_evaluate_name (arg
);
758 /* Property value is whole argument */
761 new_prop
->value
= g_strdup(" ");
767 arg
= anjuta_token_nth_word (args
, 0);
768 new_prop
->value
= anjuta_token_evaluate_name (arg
);
769 if (new_prop
->value
== NULL
) new_prop
->value
= g_strdup(" ");
772 amp_node_property_add (ANJUTA_PROJECT_NODE (project
), new_prop
);
778 amp_project_load_module (AmpProject
*project
, AnjutaToken
*module_token
)
780 AmpAcScanner
*scanner
= NULL
;
782 if (module_token
!= NULL
)
788 AmpModuleNode
*module
;
789 AmpPackageNode
*package
;
793 arg
= anjuta_token_first_item (module_token
);
794 value
= anjuta_token_evaluate (arg
);
795 module
= amp_module_node_new (value
);
796 amp_module_node_add_token (module
, module_token
);
797 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), ANJUTA_PROJECT_NODE (module
));
800 arg
= anjuta_token_next_word (arg
);
803 scanner
= amp_ac_scanner_new (project
);
804 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
805 anjuta_token_free_children (arg
);
806 list
= anjuta_token_delete_parent (list
);
807 anjuta_token_prepend_items (arg
, list
);
808 amp_ac_scanner_free (scanner
);
813 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
815 value
= anjuta_token_evaluate (item
);
816 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
823 if ((package
!= NULL
) && (compare
!= NULL
))
825 amp_package_node_set_version (package
, compare
, value
);
831 else if ((package
!= NULL
) && (anjuta_token_get_type (item
) == ANJUTA_TOKEN_OPERATOR
))
837 package
= amp_package_node_new (value
);
838 amp_package_node_add_token (package
, item
);
839 anjuta_project_node_append (ANJUTA_PROJECT_NODE (module
), ANJUTA_PROJECT_NODE (package
));
840 anjuta_project_node_set_state (ANJUTA_PROJECT_NODE (package
), ANJUTA_PROJECT_INCOMPLETE
);
849 amp_project_load_config (AmpProject
*project
, AnjutaToken
*arg_list
)
851 AmpAcScanner
*scanner
= NULL
;
853 if (arg_list
!= NULL
)
860 scanner
= amp_ac_scanner_new (project
);
862 arg
= anjuta_token_first_word (arg_list
);
863 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
864 anjuta_token_free_children (arg
);
865 list
= anjuta_token_delete_parent (list
);
866 amp_ac_scanner_free (scanner
);
868 /* list can be NULL is there is no argument to AC_OUTPUT or AC_CONFIG_FILES */
871 anjuta_token_prepend_items (arg
, list
);
872 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
877 value
= anjuta_token_evaluate (item
);
878 if (value
== NULL
) continue;
880 cfg
= amp_config_file_new (value
, anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)), item
);
881 g_hash_table_replace (project
->configs
, cfg
->file
, cfg
);
889 project_load_target (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
892 gchar
*install
= NULL
;
895 AmpNodeInfo
*info
= AmpNodeInformations
;
897 while (info
->base
.type
!= 0)
899 if (anjuta_token_get_type (variable
) == info
->token
)
906 value
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
907 split_automake_variable (value
, &flags
, &install
, NULL
);
909 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
911 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
915 AmpTargetNode
*target
;
916 AmpTargetNode
*orphan
;
920 value
= anjuta_token_evaluate (arg
);
922 /* This happens for variable token which are considered as value */
923 if (value
== NULL
) continue;
924 canon_id
= canonicalize_automake_variable (value
);
926 /* Check if target already exists */
928 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
929 if ((gchar
*)find
!= value
)
938 target
= amp_target_node_new (value
, info
->base
.type
, install
, flags
);
941 amp_target_node_add_token (target
, ANJUTA_TOKEN_ARGUMENT
, arg
);
942 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
943 DEBUG_PRINT ("create target %p name %s", target
, value
);
945 /* Check if there are sources or properties availables */
946 if (g_hash_table_lookup_extended (orphan_properties
, canon_id
, (gpointer
*)&orig_key
, (gpointer
*)&orphan
))
948 AnjutaTokenType type
;
950 AnjutaProjectNode
*child
;
952 g_hash_table_steal (orphan_properties
, canon_id
);
955 for (type
= amp_target_node_get_first_token_type (orphan
); type
!= 0; type
= amp_target_node_get_next_token_type (orphan
, type
))
958 tokens
= amp_target_node_get_token (orphan
, type
);
960 for (tokens
= g_list_first (tokens
); tokens
!= NULL
; tokens
= g_list_next (tokens
))
962 AnjutaToken
*token
= (AnjutaToken
*)tokens
->data
;
964 amp_target_node_add_token (target
, type
, token
);
968 /* Copy all properties */
969 while ((properties
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
971 AnjutaProjectProperty
*prop
;
973 prop
= (AnjutaProjectProperty
*)anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (orphan
), (AnjutaProjectProperty
*)properties
->data
);
974 amp_node_property_add ((AnjutaProjectNode
*)target
, prop
);
977 /* Copy all sources */
978 while ((child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
980 anjuta_project_node_remove (child
);
981 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), child
);
982 g_object_unref (child
);
984 amp_target_changed (target
);
986 amp_target_node_free (orphan
);
989 /* Set target properties */
990 if (flags
& AM_TARGET_NOBASE
)
991 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
992 if (flags
& AM_TARGET_NOTRANS
)
993 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
994 if (flags
& AM_TARGET_DIST
)
995 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
996 if (flags
& AM_TARGET_NODIST
)
997 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
998 if (flags
& AM_TARGET_NOINST
)
1000 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1002 else if (install
!= NULL
)
1004 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1005 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1009 if (flags
& AM_TARGET_CHECK
)
1010 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, "1", arg
);
1011 if (flags
& AM_TARGET_MAN
)
1013 gchar section
[] = "0";
1015 section
[0] += (flags
>> 7) & 0x1F;
1016 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, section
, arg
);
1029 project_load_sources (AmpProject
*project
, AnjutaProjectNode
*group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1032 GFile
*group_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (group
)));
1033 gchar
*target_id
= NULL
;
1035 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1038 gchar
*end
= strrchr (target_id
, '_');
1048 AnjutaProjectNode
*target
;
1051 DEBUG_PRINT ("search for canonical %s", target_id
);
1052 anjuta_project_node_children_traverse (group
, find_canonical_target
, &find
);
1053 target
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1055 /* Get orphan buffer if there is no target */
1060 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&target
))
1062 g_hash_table_steal (orphan_properties
, target_id
);
1067 target
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1069 g_hash_table_insert (orphan_properties
, target_id
, target
);
1075 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__SOURCES
, variable
);
1077 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1080 AnjutaProjectNode
*source
;
1081 AnjutaProjectNode
*parent
= target
;
1083 GFileInfo
* file_info
;
1085 value
= anjuta_token_evaluate (arg
);
1086 if (value
== NULL
) continue;
1088 src_file
= g_file_get_child (group_file
, value
);
1089 if (project
->lang_manager
!= NULL
)
1091 file_info
= g_file_query_info (src_file
,
1092 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
1093 G_FILE_QUERY_INFO_NONE
,
1098 gint id
= ianjuta_language_get_from_mime_type (project
->lang_manager
,
1099 g_file_info_get_content_type (file_info
),
1103 const gchar
*obj_ext
= ianjuta_language_get_make_target (project
->lang_manager
, id
, NULL
);
1104 if (obj_ext
!= NULL
)
1106 /* Create object node */
1111 AnjutaProjectNode
*object
;
1113 ext
= strrchr (value
, '.');
1114 if ((ext
!= NULL
) && (ext
!= value
)) *ext
= '\0';
1115 object_name
= g_strconcat (value
, obj_ext
, NULL
);
1116 basename
= g_path_get_basename (object_name
);
1117 obj_file
= g_file_get_child (group_file
, basename
);
1119 g_free (object_name
);
1120 object
= amp_object_node_new (obj_file
, ANJUTA_PROJECT_PROJECT
);
1121 g_object_unref (obj_file
);
1122 anjuta_project_node_append (parent
, object
);
1126 g_object_unref (file_info
);
1131 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
);
1132 g_object_unref (src_file
);
1135 amp_source_node_add_token (AMP_SOURCE_NODE (source
), arg
);
1137 DEBUG_PRINT ("add target child %p", target
);
1138 /* Add as target child */
1139 anjuta_project_node_append (parent
, source
);
1144 amp_target_changed (AMP_TARGET_NODE (target
));
1147 g_object_unref (group_file
);
1153 project_load_data (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
, gint data_flags
)
1155 gchar
*install
= NULL
;
1156 AmpTargetNode
*target
;
1160 AmpNodeInfo
*info
= AmpNodeInformations
;
1164 while (info
->base
.name
!= NULL
)
1166 if (anjuta_token_get_type (variable
) == info
->token
)
1173 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1174 split_automake_variable (target_id
, &flags
, &install
, NULL
);
1176 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
1178 /* Check if target already exists */
1180 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
1181 if ((gchar
*)find
== target_id
)
1184 target
= amp_target_node_new (target_id
, info
->base
.type
, install
, flags
);
1187 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
1188 DEBUG_PRINT ("create target %p name %s", target
, target_id
);
1193 target
= AMP_TARGET_NODE (find
);
1198 GFile
*parent_file
= g_object_ref (anjuta_project_node_get_file (parent
));
1200 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__DATA
, variable
);
1202 list
= anjuta_token_last_item (variable
);
1203 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1206 AnjutaProjectNode
*source
;
1209 value
= anjuta_token_evaluate (arg
);
1210 if (value
== NULL
) continue;
1213 src_file
= g_file_get_child (parent_file
, value
);
1214 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
| data_flags
);
1215 g_object_unref (src_file
);
1218 amp_source_node_add_token (AMP_SOURCE_NODE(source
), arg
);
1220 /* Add as target child */
1221 DEBUG_PRINT ("add target child %p", target
);
1222 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), source
);
1227 g_object_unref (parent_file
);
1229 /* Set target properties */
1230 if (flags
& AM_TARGET_NOBASE
)
1231 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
1232 if (flags
& AM_TARGET_NOTRANS
)
1233 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
1234 if (flags
& AM_TARGET_DIST
)
1235 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
1236 if (flags
& AM_TARGET_NODIST
)
1237 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
1238 if (flags
& AM_TARGET_NOINST
)
1240 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1242 else if (install
!= NULL
)
1244 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1245 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1255 project_load_target_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1257 gchar
*target_id
= NULL
;
1259 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1262 gchar
*end
= strrchr (target_id
, '_');
1273 AnjutaProjectProperty
*prop
;
1275 AnjutaTokenType type
;
1278 DEBUG_PRINT ("search for canonical %s", target_id
);
1279 anjuta_project_node_children_traverse (parent
, find_canonical_target
, &find
);
1280 parent
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1282 /* Create property */
1283 list
= anjuta_token_last_item (variable
);
1284 type
= anjuta_token_get_type (variable
);
1285 value
= anjuta_token_evaluate_name (list
);
1286 prop
= amp_property_new (NULL
, type
, 0, value
, list
);
1290 /* Add property to non existing target, create a dummy target */
1293 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&parent
))
1295 /* Dummy target already created */
1296 g_hash_table_steal (orphan_properties
, target_id
);
1301 /* Create dummy target */
1302 parent
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1304 g_hash_table_insert (orphan_properties
, target_id
, parent
);
1312 /* Add property to target */
1313 amp_node_property_add (parent
, prop
);
1314 amp_target_node_add_token (AMP_TARGET_NODE (parent
), type
, variable
);
1315 amp_target_changed (AMP_TARGET_NODE (parent
));
1322 project_load_group_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
)
1326 AnjutaProjectProperty
*prop
;
1329 /* Create property */
1330 list
= anjuta_token_last_item (variable
);
1331 name
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1332 value
= anjuta_token_evaluate_name (list
);
1334 prop
= amp_property_new (name
, anjuta_token_get_type (variable
), 0, value
, list
);
1336 amp_node_property_add (parent
, prop
);
1345 find_group (AnjutaProjectNode
*node
, gpointer data
)
1347 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1349 if (g_file_equal (anjuta_project_node_get_file (node
), (GFile
*)data
))
1351 /* Find group, return node value in pointer */
1360 project_load_subdirs (AmpProject
*project
, AnjutaToken
*list
, AnjutaProjectNode
*parent
, gboolean dist_only
)
1364 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1368 value
= anjuta_token_evaluate (arg
);
1369 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
1371 /* Skip ., it is a special case, used to defined build order */
1372 if (strcmp (value
, ".") != 0)
1375 AmpGroupNode
*group
;
1377 subdir
= g_file_resolve_relative_path (anjuta_project_node_get_file (parent
), value
);
1379 /* Look for already existing group */
1380 group
= AMP_GROUP_NODE (anjuta_project_node_children_traverse (parent
, find_group
, subdir
));
1384 /* Already existing group, mark for built if needed */
1385 if (!dist_only
) amp_group_node_set_dist_only (group
, FALSE
);
1389 /* Create new group */
1390 group
= amp_group_node_new (subdir
, value
, dist_only
);
1392 /* Group can be NULL if the name is not valid */
1395 g_hash_table_insert (project
->groups
, g_file_get_uri (subdir
), group
);
1396 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (group
));
1398 amp_node_load (AMP_NODE (group
), NULL
, project
, NULL
);
1401 if (group
) amp_group_node_add_token (group
, arg
, dist_only
? AM_GROUP_TOKEN_DIST_SUBDIRS
: AM_GROUP_TOKEN_SUBDIRS
);
1402 g_object_unref (subdir
);
1409 amp_project_set_am_variable (AmpProject
* project
, AmpGroupNode
* group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1413 switch (anjuta_token_get_type (variable
))
1415 case AM_TOKEN_SUBDIRS
:
1416 list
= anjuta_token_last_item (variable
);
1417 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), FALSE
);
1419 case AM_TOKEN_DIST_SUBDIRS
:
1420 list
= anjuta_token_last_item (variable
);
1421 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), TRUE
);
1423 case AM_TOKEN__DATA
:
1424 case AM_TOKEN__HEADERS
:
1425 case AM_TOKEN__LISP
:
1426 case AM_TOKEN__MANS
:
1427 case AM_TOKEN__PYTHON
:
1428 case AM_TOKEN__JAVA
:
1429 case AM_TOKEN__TEXINFOS
:
1430 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, 0);
1432 case AM_TOKEN__SCRIPTS
:
1433 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, ANJUTA_PROJECT_EXECUTABLE
);
1435 case AM_TOKEN__LIBRARIES
:
1436 case AM_TOKEN__LTLIBRARIES
:
1437 case AM_TOKEN__PROGRAMS
:
1438 project_load_target (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1440 case AM_TOKEN__SOURCES
:
1441 project_load_sources (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1444 case AM_TOKEN__LDFLAGS
:
1445 case AM_TOKEN__CPPFLAGS
:
1446 case AM_TOKEN__CFLAGS
:
1447 case AM_TOKEN__CXXFLAGS
:
1448 case AM_TOKEN__JAVACFLAGS
:
1449 case AM_TOKEN__VALAFLAGS
:
1450 case AM_TOKEN__FCFLAGS
:
1451 case AM_TOKEN__OBJCFLAGS
:
1452 case AM_TOKEN__LFLAGS
:
1453 case AM_TOKEN__YFLAGS
:
1454 project_load_group_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
);
1456 case AM_TOKEN_TARGET_LDFLAGS
:
1457 case AM_TOKEN_TARGET_CPPFLAGS
:
1458 case AM_TOKEN_TARGET_CFLAGS
:
1459 case AM_TOKEN_TARGET_CXXFLAGS
:
1460 case AM_TOKEN_TARGET_JAVACFLAGS
:
1461 case AM_TOKEN_TARGET_VALAFLAGS
:
1462 case AM_TOKEN_TARGET_FCFLAGS
:
1463 case AM_TOKEN_TARGET_OBJCFLAGS
:
1464 case AM_TOKEN_TARGET_LFLAGS
:
1465 case AM_TOKEN_TARGET_YFLAGS
:
1466 case AM_TOKEN_TARGET_DEPENDENCIES
:
1467 case AM_TOKEN_TARGET_LIBADD
:
1468 case AM_TOKEN_TARGET_LDADD
:
1469 project_load_target_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1475 /* Keep the autotools variable as a normal variable too */
1476 amp_group_node_update_variable (group
, variable
);
1480 *---------------------------------------------------------------------------*/
1483 amp_project_compare_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1490 name1
= anjuta_project_node_get_name (old_node
);
1491 name2
= anjuta_project_node_get_name (new_node
);
1492 file1
= anjuta_project_node_get_file (old_node
);
1493 file2
= anjuta_project_node_get_file (new_node
);
1495 return (anjuta_project_node_get_full_type (old_node
) == anjuta_project_node_get_full_type (new_node
))
1496 && ((name1
== NULL
) || (name2
== NULL
) || (strcmp (name1
, name2
) == 0))
1497 && ((file1
== NULL
) || (file2
== NULL
) || g_file_equal (file1
, file2
)) ? 0 : 1;
1501 amp_project_map_children (GHashTable
*map
, AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1503 GList
*children
= NULL
;
1505 if (new_node
!= NULL
)
1507 for (new_node
= anjuta_project_node_first_child (new_node
); new_node
!= NULL
; new_node
= anjuta_project_node_next_sibling (new_node
))
1509 children
= g_list_prepend (children
, new_node
);
1511 children
= g_list_reverse (children
);
1514 for (old_node
= anjuta_project_node_first_child (old_node
); old_node
!= NULL
; old_node
= anjuta_project_node_next_sibling (old_node
))
1518 same
= g_list_find_custom (children
, old_node
, (GCompareFunc
)amp_project_compare_node
);
1522 /* Add new to old node mapping */
1523 g_hash_table_insert (map
, (AnjutaProjectNode
*)same
->data
, old_node
);
1525 amp_project_map_children (map
, old_node
, (AnjutaProjectNode
*)same
->data
);
1526 children
= g_list_delete_link (children
, same
);
1530 /* Keep old_node to be deleted in the hash table as a key with a NULL
1532 g_hash_table_insert (map
, old_node
, NULL
);
1536 /* Add remaining node in hash table */
1537 for (; children
!= NULL
; children
= g_list_delete_link (children
, children
))
1539 /* Keep new node without a corresponding old node as a key and a identical
1541 g_hash_table_insert (map
, children
->data
, children
->data
);
1545 /* Find the correspondance between the new loaded node (new_node) and the
1546 * original node currently in the tree (old_node) */
1548 amp_project_map_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1552 map
= g_hash_table_new (g_direct_hash
, NULL
);
1554 g_hash_table_insert (map
, new_node
, old_node
);
1556 amp_project_map_children (map
, old_node
, new_node
);
1563 amp_project_update_node (AnjutaProjectNode
*key
, AnjutaProjectNode
*value
, GHashTable
*map
)
1565 AnjutaProjectNode
*old_node
= NULL
; /* The node that will be deleted */
1569 /* if value is NULL, delete the old node which is the key */
1574 AnjutaProjectNode
*node
= value
; /* The node that we keep in the tree */
1575 AnjutaProjectNode
*new_node
= key
; /* The node with the new data */
1577 if (new_node
&& new_node
!= node
)
1581 amp_node_update (AMP_NODE (node
), AMP_NODE (new_node
));
1583 /* Swap custom properties */
1584 properties
= node
->properties
;
1585 node
->properties
= new_node
->properties
;
1586 new_node
->properties
= properties
;
1588 if (new_node
->parent
== NULL
)
1590 /* This is the top loaded node, update only the children */
1591 node
->children
= new_node
->children
;
1595 /* Other node update all pointers */
1596 node
->parent
= new_node
->parent
;
1597 node
->children
= new_node
->children
;
1598 node
->next
= new_node
->next
;
1599 node
->prev
= new_node
->prev
;
1602 /* Destroy node with data */
1603 old_node
= new_node
;
1606 /* Update links, using original node address if they stay in the tree */
1607 new_node
= g_hash_table_lookup (map
, node
->parent
);
1608 if (new_node
!= NULL
) node
->parent
= new_node
;
1609 new_node
= g_hash_table_lookup (map
, node
->children
);
1610 if (new_node
!= NULL
) node
->children
= new_node
;
1611 new_node
= g_hash_table_lookup (map
, node
->next
);
1612 if (new_node
!= NULL
) node
->next
= new_node
;
1613 new_node
= g_hash_table_lookup (map
, node
->prev
);
1614 if (new_node
!= NULL
) node
->prev
= new_node
;
1618 /* Unlink old node and free it */
1619 if (old_node
!= NULL
)
1621 old_node
->parent
= NULL
;
1622 old_node
->children
= NULL
;
1623 old_node
->next
= NULL
;
1624 old_node
->prev
= NULL
;
1625 g_object_unref (old_node
);
1630 *---------------------------------------------------------------------------*/
1632 AnjutaProjectNodeInfo
*
1633 amp_project_get_type_info (AmpProject
*project
, AnjutaProjectNodeType type
)
1637 for (info
= AmpNodeInformations
; info
->base
.type
!= type
; info
++)
1639 if ((info
->base
.type
== type
) || (info
->base
.type
== 0)) break;
1642 return (AnjutaProjectNodeInfo
*)info
;
1646 amp_project_load_root (AmpProject
*project
, GError
**error
)
1648 AmpAcScanner
*scanner
;
1651 GFile
*configure_file
;
1652 AnjutaTokenFile
*configure_token_file
;
1653 AnjutaProjectNode
*source
;
1656 root_file
= anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
1657 DEBUG_PRINT ("reload project %p root file %p", project
, root_file
);
1659 /* Unload current project */
1660 amp_project_unload (project
);
1662 /* Initialize list styles */
1663 project
->ac_space_list
= anjuta_token_style_new (NULL
, " ", "\n", NULL
, 0);
1664 project
->am_space_list
= anjuta_token_style_new (NULL
, " ", " \\\n\t", NULL
, 0);
1665 project
->arg_list
= anjuta_token_style_new (NULL
, ", ", ", ", ")", 0);
1667 /* Find configure file */
1668 if (file_type (root_file
, "configure.ac") == G_FILE_TYPE_REGULAR
)
1670 configure_file
= g_file_get_child (root_file
, "configure.ac");
1672 else if (file_type (root_file
, "configure.in") == G_FILE_TYPE_REGULAR
)
1674 configure_file
= g_file_get_child (root_file
, "configure.in");
1678 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1679 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1680 _("Project doesn't exist or invalid path"));
1685 /* Parse configure */
1686 configure_token_file
= amp_project_set_configure (project
, configure_file
);
1687 amp_project_add_file (project
, configure_file
, configure_token_file
);
1688 source
= amp_source_node_new (configure_file
, ANJUTA_PROJECT_PROJECT
| ANJUTA_PROJECT_FRAME
| ANJUTA_PROJECT_READ_ONLY
);
1689 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), source
);
1690 arg
= anjuta_token_file_load (configure_token_file
, NULL
);
1691 g_hash_table_remove_all (project
->ac_variables
);
1692 scanner
= amp_ac_scanner_new (project
);
1693 project
->configure_token
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, 0, configure_file
, &err
);
1694 amp_ac_scanner_free (scanner
);
1696 if (project
->configure_token
== NULL
)
1700 g_set_error_literal (error
, IANJUTA_PROJECT_ERROR
,
1701 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1707 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1708 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1710 _("Unable to parse project file"));
1716 /* Load all makefiles recursively */
1717 if (!AMP_NODE_CLASS (parent_class
)->load (AMP_NODE (project
), NULL
, project
, NULL
))
1719 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1720 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1721 _("Project doesn't exist or has an invalid path"));
1730 amp_project_unload (AmpProject
*project
)
1733 amp_project_clear (project
);
1735 /* shortcut hash tables */
1736 if (project
->groups
) g_hash_table_remove_all (project
->groups
);
1737 if (project
->files
!= NULL
)
1741 for (list
= project
->files
; list
!= NULL
; list
= g_list_delete_link (list
, list
))
1743 g_object_weak_unref (G_OBJECT (list
->data
), remove_config_file
, project
);
1745 project
->files
= NULL
;
1747 if (project
->configs
) g_hash_table_remove_all (project
->configs
);
1750 if (project
->am_space_list
) anjuta_token_style_free (project
->am_space_list
);
1751 if (project
->ac_space_list
) anjuta_token_style_free (project
->ac_space_list
);
1752 if (project
->arg_list
) anjuta_token_style_free (project
->arg_list
);
1756 amp_project_is_loaded (AmpProject
*project
)
1758 return project
->loading
== 0;
1762 amp_project_probe (GFile
*file
,
1768 dir
= (file_type (file
, NULL
) == G_FILE_TYPE_DIRECTORY
);
1771 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1772 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1773 _("Project doesn't exist or invalid path"));
1779 const gchar
**makefile
;
1781 /* Look for makefiles */
1783 for (makefile
= valid_am_makefiles
; *makefile
!= NULL
; makefile
++)
1785 if (file_type (file
, *makefile
) == G_FILE_TYPE_REGULAR
)
1794 probe
= ((file_type (file
, "configure.ac") == G_FILE_TYPE_REGULAR
) ||
1795 (file_type (file
, "configure.in") == G_FILE_TYPE_REGULAR
));
1799 return probe
? IANJUTA_PROJECT_PROBE_PROJECT_FILES
: 0;
1803 amp_project_get_token_location (AmpProject
*project
, AnjutaTokenFileLocation
*location
, AnjutaToken
*token
)
1807 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1809 if (anjuta_token_file_get_token_location ((AnjutaTokenFile
*)list
->data
, location
, token
))
1819 amp_project_remove_group (AmpProject
*project
,
1820 AmpGroupNode
*group
,
1825 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (group
)) != ANJUTA_PROJECT_GROUP
) return;
1827 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_CONFIGURE
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1829 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1831 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1833 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1835 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_DIST_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1837 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1840 amp_group_node_free (group
);
1844 amp_project_remove_source (AmpProject
*project
,
1845 AmpSourceNode
*source
,
1848 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (source
)) != ANJUTA_PROJECT_SOURCE
) return;
1850 anjuta_token_remove_word (amp_source_node_get_token (source
));
1852 amp_source_node_free (source
);
1856 amp_project_get_node_info (AmpProject
*project
, GError
**error
)
1858 static GList
*info_list
= NULL
;
1860 if (info_list
== NULL
)
1864 for (node
= AmpNodeInformations
; node
->base
.type
!= 0; node
++)
1866 info_list
= g_list_prepend (info_list
, node
);
1869 info_list
= g_list_reverse (info_list
);
1876 *---------------------------------------------------------------------------*/
1878 typedef struct _AmpMovePacket
{
1879 AmpProject
*project
;
1880 GFile
*old_root_file
;
1881 GFile
*new_root_file
;
1885 foreach_node_move (AnjutaProjectNode
*g_node
, gpointer data
)
1887 AmpProject
*project
= ((AmpMovePacket
*)data
)->project
;
1888 GFile
*old_root_file
= ((AmpMovePacket
*)data
)->old_root_file
;
1889 GFile
*new_root_file
= ((AmpMovePacket
*)data
)->new_root_file
;
1893 switch (anjuta_project_node_get_node_type (g_node
))
1895 case ANJUTA_PROJECT_GROUP
:
1896 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1897 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1899 amp_group_node_set_file (AMP_GROUP_NODE (g_node
), new_file
);
1900 g_object_unref (new_file
);
1902 g_hash_table_insert (project
->groups
, g_file_get_uri (new_file
), g_node
);
1904 case ANJUTA_PROJECT_SOURCE
:
1905 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1906 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1908 amp_source_node_set_file (AMP_SOURCE_NODE (g_node
), new_file
);
1909 g_object_unref (new_file
);
1917 amp_project_move (AmpProject
*project
, const gchar
*path
)
1924 GHashTable
* old_hash
;
1925 GHashTableIter iter
;
1926 AmpMovePacket packet
= {project
, NULL
};
1928 /* Change project root directory */
1929 packet
.old_root_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
1930 packet
.new_root_file
= g_file_new_for_path (path
);
1932 /* Change project root directory in groups */
1933 old_hash
= project
->groups
;
1934 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
1935 anjuta_project_node_foreach (ANJUTA_PROJECT_NODE (project
), G_POST_ORDER
, foreach_node_move
, &packet
);
1936 g_hash_table_destroy (old_hash
);
1938 /* Change all files */
1939 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1941 AnjutaTokenFile
*tfile
= (AnjutaTokenFile
*)list
->data
;
1943 relative
= get_relative_path (packet
.old_root_file
, anjuta_token_file_get_file (tfile
));
1944 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1946 anjuta_token_file_move (tfile
, new_file
);
1949 /* Change all configs */
1950 old_hash
= project
->configs
;
1951 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
1952 g_hash_table_iter_init (&iter
, old_hash
);
1953 while (g_hash_table_iter_next (&iter
, &key
, (gpointer
*)&cfg
))
1955 relative
= get_relative_path (packet
.old_root_file
, cfg
->file
);
1956 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1958 g_object_unref (cfg
->file
);
1959 cfg
->file
= new_file
;
1961 g_hash_table_insert (project
->configs
, new_file
, cfg
);
1963 g_hash_table_steal_all (old_hash
);
1964 g_hash_table_destroy (old_hash
);
1966 g_object_unref (packet
.old_root_file
);
1967 g_object_unref (packet
.new_root_file
);
1972 /* Dump file content of corresponding node */
1974 amp_project_dump (AmpProject
*project
, AnjutaProjectNode
*node
, AmpFileType type
)
1976 gboolean ok
= FALSE
;
1978 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1983 anjuta_token_dump (amp_group_node_get_makefile_token (AMP_GROUP_NODE (node
)));
1985 case DUMP_CONFIGURE
:
1986 anjuta_token_dump (AMP_PROJECT (node
)->configure_token
);
1998 amp_project_new (GFile
*file
, IAnjutaLanguage
*language
, GError
**error
)
2000 AmpProject
*project
;
2003 project
= AMP_PROJECT (g_object_new (AMP_TYPE_PROJECT
, NULL
));
2004 new_file
= g_file_dup (file
);
2005 amp_root_node_set_file (AMP_ROOT_NODE (project
), new_file
);
2006 g_object_unref (new_file
);
2008 project
->lang_manager
= (language
!= NULL
) ? g_object_ref (language
) : NULL
;
2013 /* Project access functions
2014 *---------------------------------------------------------------------------*/
2017 amp_project_get_root (AmpProject
*project
)
2019 return AMP_PROJECT (project
);
2023 amp_project_get_group (AmpProject
*project
, const gchar
*id
)
2025 return (AmpGroupNode
*)g_hash_table_lookup (project
->groups
, id
);
2029 amp_project_get_target (AmpProject
*project
, const gchar
*id
)
2031 AmpTargetNode
**buffer
;
2032 AmpTargetNode
*target
;
2035 buffer
= (AmpTargetNode
**)g_base64_decode (id
, &dummy
);
2043 amp_project_get_source (AmpProject
*project
, const gchar
*id
)
2045 AmpSourceNode
**buffer
;
2046 AmpSourceNode
*source
;
2049 buffer
= (AmpSourceNode
**)g_base64_decode (id
, &dummy
);
2057 amp_project_get_uri (AmpProject
*project
)
2059 g_return_val_if_fail (project
!= NULL
, NULL
);
2061 return g_file_get_uri (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
2065 amp_project_get_file (AmpProject
*project
)
2067 g_return_val_if_fail (project
!= NULL
, NULL
);
2069 return anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
2073 amp_project_add_file (AmpProject
*project
, GFile
*file
, AnjutaTokenFile
* token
)
2075 project
->files
= g_list_prepend (project
->files
, token
);
2076 g_object_weak_ref (G_OBJECT (token
), remove_config_file
, project
);
2080 amp_project_add_subst_variable (AmpProject
*project
, const gchar
*name
, AnjutaToken
*value
)
2082 g_hash_table_insert (project
->ac_variables
, (gchar
*)name
, value
);
2086 amp_project_get_subst_variable_token (AmpProject
*project
, const gchar
*name
)
2088 return g_hash_table_lookup (project
->ac_variables
, name
);
2093 amp_project_is_busy (AmpProject
*project
)
2095 if (project
->queue
== NULL
) return FALSE
;
2097 return pm_command_queue_is_busy (project
->queue
);
2101 *---------------------------------------------------------------------------*/
2104 amp_load_setup (PmJob
*job
)
2106 //anjuta_project_node_check (job->node);
2107 pm_job_set_parent (job
, anjuta_project_node_parent (job
->node
));
2108 job
->proxy
= ANJUTA_PROJECT_NODE (amp_node_copy (AMP_NODE (job
->node
)));
2114 amp_load_work (PmJob
*job
)
2116 return amp_node_load (AMP_NODE (job
->proxy
), AMP_NODE (job
->parent
), AMP_PROJECT (job
->user_data
), &job
->error
);
2120 amp_load_complete (PmJob
*job
)
2123 //static GTimer *timer = NULL;
2125 g_return_val_if_fail (job
->proxy
!= NULL
, FALSE
);
2127 //anjuta_project_node_check (job->node);
2128 /*if (timer == NULL)
2130 timer = g_timer_new ();
2134 g_timer_continue (timer);
2136 map
= amp_project_map_node (job
->node
, job
->proxy
);
2137 g_object_ref (job
->proxy
);
2139 job
->proxy
->parent
= NULL
; // Mark loaded top node
2140 g_hash_table_foreach (map
, (GHFunc
)amp_project_update_node
, map
);
2141 //anjuta_project_node_check (job->node);
2142 g_hash_table_destroy (map
);
2143 g_object_unref (job
->proxy
);
2145 AMP_PROJECT (job
->user_data
)->loading
--;
2146 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-loaded", job
->node
, job
->error
);
2147 //g_timer_stop (timer);
2148 //g_message ("amp_load_complete completed in %g", g_timer_elapsed (timer, NULL));
2153 static PmCommandWork amp_load_job
= {amp_load_setup
, amp_load_work
, amp_load_complete
};
2156 amp_save_setup (PmJob
*job
)
2162 amp_save_work (PmJob
*job
)
2164 /* It is difficult to save only a particular node, so the whole project is saved */
2165 amp_node_save (AMP_NODE (job
->user_data
), NULL
, AMP_PROJECT (job
->user_data
), &job
->error
);
2171 amp_save_complete (PmJob
*job
)
2173 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-saved", job
->node
, job
->error
);
2178 static PmCommandWork amp_save_job
= {amp_save_setup
, amp_save_work
, amp_save_complete
};
2181 amp_add_before_setup (PmJob
*job
)
2183 /* If add is called to add the root group, the node is already existing */
2184 if (job
->parent
!= job
->node
)
2185 anjuta_project_node_insert_before (job
->parent
, job
->sibling
, job
->node
);
2191 amp_add_after_setup (PmJob
*job
)
2193 /* If add is called to add the root group, the node is already existing */
2194 if (job
->parent
!= job
->node
)
2195 anjuta_project_node_insert_after (job
->parent
, job
->sibling
, job
->node
);
2201 amp_add_work (PmJob
*job
)
2203 AmpNode
*parent
= AMP_NODE (job
->parent
);
2206 ok
= amp_node_write (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2207 /* Add new node properties if existing */
2212 for (item
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (job
->node
)); item
!= NULL
; item
= g_list_next (item
))
2214 AnjutaProjectProperty
*property
= (AnjutaProjectProperty
*)item
->data
;
2217 flags
= ((AmpPropertyInfo
*)property
->info
)->flags
;
2218 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2220 ok
= ok
&& amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), property
);
2222 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2224 if (((AnjutaProjectPropertyInfo
*)property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2226 ok
= ok
&& amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, property
);
2236 amp_add_complete (PmJob
*job
)
2238 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2243 static PmCommandWork amp_add_before_job
= {amp_add_before_setup
, amp_add_work
, amp_add_complete
};
2244 static PmCommandWork amp_add_after_job
= {amp_add_after_setup
, amp_add_work
, amp_add_complete
};
2248 amp_remove_setup (PmJob
*job
)
2250 AnjutaProjectNode
*parent
;
2252 parent
= anjuta_project_node_parent (job
->node
);
2253 if (parent
== NULL
) parent
= job
->node
;
2254 pm_job_set_parent (job
, parent
);
2255 anjuta_project_node_set_state (job
->node
, ANJUTA_PROJECT_REMOVED
);
2261 amp_remove_work (PmJob
*job
)
2263 AmpNode
*parent
= AMP_NODE (job
->parent
);
2266 ok
= amp_node_erase (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2272 amp_remove_complete (PmJob
*job
)
2274 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2279 static PmCommandWork amp_remove_job
= {amp_remove_setup
, amp_remove_work
, amp_remove_complete
};
2282 amp_set_property_setup (PmJob
*job
)
2288 amp_set_property_work (PmJob
*job
)
2292 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2294 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2296 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2298 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2300 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2302 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2310 amp_set_property_complete (PmJob
*job
)
2312 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2317 static PmCommandWork amp_set_property_job
= {amp_set_property_setup
, amp_set_property_work
, amp_set_property_complete
};
2320 amp_remove_property_setup (PmJob
*job
)
2326 amp_remove_property_work (PmJob
*job
)
2330 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2332 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2334 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2336 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2338 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2340 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2348 amp_remove_property_complete (PmJob
*job
)
2350 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2355 static PmCommandWork amp_remove_property_job
= {amp_remove_property_setup
, amp_remove_property_work
, amp_remove_property_complete
};
2357 /* Implement IAnjutaProject
2358 *---------------------------------------------------------------------------*/
2361 iproject_load_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2365 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2366 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2368 AMP_PROJECT (obj
)->loading
++;
2369 load_job
= pm_job_new (&_load_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2371 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, load_job
);
2377 iproject_save_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2381 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2382 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2384 save_job
= pm_job_new (&_save_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2385 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, save_job
);
2390 static AnjutaProjectNode
*
2391 iproject_add_node_before (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2393 AnjutaProjectNode
*node
;
2396 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2398 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2401 add_job
= pm_job_new (&_add_before_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2402 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2408 static AnjutaProjectNode
*
2409 iproject_add_node_after (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2411 AnjutaProjectNode
*node
;
2414 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2416 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2419 add_job
= pm_job_new (&_add_after_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2420 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2427 iproject_remove_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
2431 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2433 remove_job
= pm_job_new (&_remove_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2434 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_job
);
2439 static AnjutaProjectProperty
*
2440 iproject_set_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, const gchar
*value
, GError
**error
)
2442 AnjutaProjectProperty
*new_prop
;
2443 PmJob
*set_property_job
;
2445 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2447 new_prop
= name
== NULL
? amp_node_property_set (node
, id
, value
) : amp_node_map_property_set (node
, id
, name
, value
);
2448 set_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2449 set_property_job
->property
= new_prop
;
2450 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, set_property_job
);
2456 iproject_remove_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, GError
**error
)
2458 AnjutaProjectProperty
*new_prop
;
2459 PmJob
*remove_property_job
;
2461 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2464 new_prop
= amp_node_map_property_set (node
, id
, name
, NULL
);
2465 remove_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2466 remove_property_job
->property
= new_prop
;
2467 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_property_job
);
2472 static AnjutaProjectNode
*
2473 iproject_get_root (IAnjutaProject
*obj
, GError
**err
)
2475 return ANJUTA_PROJECT_NODE (obj
);
2479 iproject_get_node_info (IAnjutaProject
*obj
, GError
**err
)
2481 return amp_project_get_node_info (AMP_PROJECT (obj
), err
);
2485 iproject_is_loaded (IAnjutaProject
*obj
, GError
**err
)
2487 return amp_project_is_loaded (AMP_PROJECT (obj
));
2491 iproject_iface_init(IAnjutaProjectIface
* iface
)
2493 iface
->load_node
= iproject_load_node
;
2494 iface
->save_node
= iproject_save_node
;
2495 iface
->add_node_before
= iproject_add_node_before
;
2496 iface
->add_node_after
= iproject_add_node_after
;
2497 iface
->remove_node
= iproject_remove_node
;
2498 iface
->set_property
= iproject_set_property
;
2499 iface
->remove_property
= iproject_remove_property
;
2500 iface
->get_root
= iproject_get_root
;
2501 iface
->get_node_info
= iproject_get_node_info
;
2502 iface
->is_loaded
= iproject_is_loaded
;
2505 /* AmpNode implementation
2506 *---------------------------------------------------------------------------*/
2509 amp_project_load (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2511 return amp_project_load_root (AMP_PROJECT (root
), error
);
2515 amp_project_save (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2517 AnjutaTokenFile
*tfile
;
2518 AnjutaProjectNode
*child
;
2521 tfile
= AMP_PROJECT (root
)->configure_file
;
2522 if (anjuta_token_file_is_dirty (tfile
))
2524 if (!anjuta_token_file_save (tfile
, error
)) return FALSE
;
2527 if (!AMP_NODE_CLASS (parent_class
)->save (root
, parent
, project
, error
))
2532 /* Save all children */
2533 for (child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (root
)); child
!= NULL
; child
= anjuta_project_node_next_sibling (child
))
2535 if (!amp_node_save (AMP_NODE (child
), root
, project
, error
)) return FALSE
;
2543 amp_project_update (AmpNode
*node
, AmpNode
*new_node
)
2545 amp_project_update_root (AMP_PROJECT (node
), AMP_PROJECT (new_node
));
2551 amp_project_copy (AmpNode
*old_node
)
2555 new_node
= AMP_NODE_CLASS (amp_project_parent_class
)->copy (old_node
);
2556 ((AmpProject
*)new_node
)->lang_manager
= (((AmpProject
*)old_node
)->lang_manager
!= NULL
) ? g_object_ref (((AmpProject
*)old_node
)->lang_manager
) : NULL
;
2562 /* GObject implementation
2563 *---------------------------------------------------------------------------*/
2566 amp_project_dispose (GObject
*object
)
2568 AmpProject
*project
;
2570 g_return_if_fail (AMP_IS_PROJECT (object
));
2572 project
= AMP_PROJECT (object
);
2573 amp_project_unload (project
);
2575 amp_project_clear (project
);
2577 if (project
->groups
) g_hash_table_destroy (project
->groups
);
2578 project
->groups
= NULL
;
2579 if (project
->configs
) g_hash_table_destroy (project
->configs
);
2580 project
->configs
= NULL
;
2581 if (project
->ac_variables
) g_hash_table_destroy (project
->ac_variables
);
2582 project
->ac_variables
= NULL
;
2584 if (project
->queue
) pm_command_queue_free (project
->queue
);
2585 project
->queue
= NULL
;
2587 if (project
->monitor
) g_object_unref (project
->monitor
);
2588 project
->monitor
= NULL
;
2590 if (project
->lang_manager
) g_object_unref (project
->lang_manager
);
2591 project
->lang_manager
= NULL
;
2593 G_OBJECT_CLASS (parent_class
)->dispose (object
);
2597 amp_project_init (AmpProject
*project
)
2599 g_return_if_fail (project
!= NULL
);
2600 g_return_if_fail (AMP_IS_PROJECT (project
));
2603 project
->configure_file
= NULL
;
2604 project
->configure_token
= NULL
;
2607 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
2608 project
->files
= NULL
;
2609 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
2610 project
->ac_variables
= g_hash_table_new_full (g_str_hash
, g_str_equal
, (GDestroyNotify
)g_free
, NULL
);
2613 project
->am_space_list
= NULL
;
2614 project
->ac_space_list
= NULL
;
2615 project
->arg_list
= NULL
;
2617 project
->queue
= NULL
;
2618 project
->loading
= 0;
2622 amp_project_class_init (AmpProjectClass
*klass
)
2624 GObjectClass
*object_class
;
2625 AmpNodeClass
*node_class
;
2627 parent_class
= g_type_class_peek_parent (klass
);
2629 object_class
= G_OBJECT_CLASS (klass
);
2630 object_class
->dispose
= amp_project_dispose
;
2632 node_class
= AMP_NODE_CLASS (klass
);
2633 node_class
->load
= amp_project_load
;
2634 node_class
->save
= amp_project_save
;
2635 node_class
->update
= amp_project_update
;
2636 node_class
->copy
= amp_project_copy
;
2640 amp_project_class_finalize (AmpProjectClass
*klass
)
2645 amp_project_register (GTypeModule
*module
)
2647 amp_node_register (module
);
2648 amp_project_register_type (module
);