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
)
282 g_warning("get_relative_path for a NULL file");
286 relative
= g_file_get_relative_path (parent
, file
);
287 if (relative
== NULL
)
289 if (g_file_equal (parent
, file
))
291 relative
= g_strdup (".");
295 GFile
*grand_parent
= g_file_get_parent (parent
);
297 gchar
*grand_relative
;
302 for (level
= 1; !g_file_has_prefix (file
, grand_parent
); level
++)
304 GFile
*next
= g_file_get_parent (grand_parent
);
306 g_object_unref (grand_parent
);
310 grand_relative
= g_file_get_relative_path (grand_parent
, file
);
311 g_object_unref (grand_parent
);
313 len
= strlen (grand_relative
);
314 relative
= g_new (gchar
, len
+ level
* 3 + 1);
316 for (; level
; level
--)
318 memcpy(ptr
, ".." G_DIR_SEPARATOR_S
, 3);
321 memcpy (ptr
, grand_relative
, len
+ 1);
322 g_free (grand_relative
);
330 file_type (GFile
*file
, const gchar
*filename
)
336 child
= filename
!= NULL
? g_file_get_child (file
, filename
) : g_object_ref (file
);
338 info
= g_file_query_info (child
,
339 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
340 G_FILE_QUERY_INFO_NONE
,
345 type
= g_file_info_get_file_type (info
);
346 g_object_unref (info
);
350 type
= G_FILE_TYPE_UNKNOWN
;
353 g_object_unref (child
);
358 /* Automake parsing function
359 *---------------------------------------------------------------------------*/
361 /* Remove invalid character according to automake rules */
363 canonicalize_automake_variable (const gchar
*name
)
365 gchar
*canon_name
= g_strdup (name
);
368 for (ptr
= canon_name
; *ptr
!= '\0'; ptr
++)
370 if (!g_ascii_isalnum (*ptr
) && (*ptr
!= '@'))
380 split_automake_variable (gchar
*name
, gint
*flags
, gchar
**module
, gchar
**primary
)
382 gboolean res
= FALSE
;
384 GMatchInfo
*match_info
;
388 regex
= g_regex_new ("(nobase_|notrans_)?"
390 "(noinst_|check_|man_|man[0-9al]_)?"
394 G_REGEX_MATCH_ANCHORED
,
397 if (!g_regex_match (regex
, name
, G_REGEX_MATCH_ANCHORED
, &match_info
))
403 g_match_info_fetch_pos (match_info
, 1, &start_pos
, &end_pos
);
406 if (*(name
+ start_pos
+ 2) == 'b') *flags
|= AM_TARGET_NOBASE
;
407 if (*(name
+ start_pos
+ 2) == 't') *flags
|= AM_TARGET_NOTRANS
;
410 g_match_info_fetch_pos (match_info
, 2, &start_pos
, &end_pos
);
413 if (*(name
+ start_pos
) == 'd') *flags
|= AM_TARGET_DIST
;
414 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NODIST
;
417 g_match_info_fetch_pos (match_info
, 3, &start_pos
, &end_pos
);
420 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NOINST
;
421 if (*(name
+ start_pos
) == 'c') *flags
|= AM_TARGET_CHECK
;
422 if (*(name
+ start_pos
) == 'm')
424 gchar section
= *(name
+ end_pos
- 1);
425 *flags
|= AM_TARGET_MAN
;
426 if (section
!= 'n') *flags
|= (section
& 0x1F) << 7;
433 g_match_info_fetch_pos (match_info
, 4, &start_pos
, &end_pos
);
436 *module
= name
+ start_pos
;
437 *(name
+ end_pos
- 1) = '\0';
447 g_match_info_fetch_pos (match_info
, 5, &start_pos
, &end_pos
);
450 *primary
= name
+ start_pos
;
461 g_match_info_unref (match_info
);
462 g_regex_unref (regex
);
468 ac_init_default_tarname (const gchar
*name
)
472 if (name
== NULL
) return NULL
;
474 /* Remove GNU prefix */
475 if (strncmp (name
, "GNU ", 4) == 0) name
+= 4;
477 tarname
= g_ascii_strdown (name
, -1);
478 g_strcanon (tarname
, "abcdefghijklmnopqrstuvwxyz0123456789", '-');
483 /* Config file objects
484 *---------------------------------------------------------------------------*/
486 static AmpConfigFile
*
487 amp_config_file_new (const gchar
*pathname
, GFile
*project_root
, AnjutaToken
*token
)
489 AmpConfigFile
*config
;
491 g_return_val_if_fail ((pathname
!= NULL
) && (project_root
!= NULL
), NULL
);
493 config
= g_slice_new0(AmpConfigFile
);
494 config
->file
= g_file_resolve_relative_path (project_root
, pathname
);
495 config
->token
= token
;
501 amp_config_file_free (AmpConfigFile
*config
)
505 g_object_unref (config
->file
);
506 g_slice_free (AmpConfigFile
, config
);
511 amp_project_clear (AmpProject
*project
)
513 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
514 project
->configure_file
= NULL
;
515 if (project
->configure_token
) anjuta_token_free (project
->configure_token
);
516 project
->configure_token
= NULL
;
520 on_project_monitor_changed (GFileMonitor
*monitor
,
523 GFileMonitorEvent event_type
,
526 AmpProject
*project
= AMP_PROJECT (data
);
528 switch (event_type
) {
529 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
:
530 case G_FILE_MONITOR_EVENT_CHANGED
:
531 case G_FILE_MONITOR_EVENT_DELETED
:
532 /* project can be NULL, if the node is dummy node because the
533 * original one is reloaded. */
534 g_signal_emit_by_name (G_OBJECT (project
), "file-changed", data
);
542 amp_project_set_configure (AmpProject
*project
, GFile
*configure
)
544 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
545 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
546 if (project
->monitor
) g_object_unref (project
->monitor
);
547 if (configure
!= NULL
)
549 project
->configure_file
= anjuta_token_file_new (configure
);
550 project
->configure
= g_object_ref (configure
);
552 project
->monitor
= g_file_monitor_file (configure
,
556 if (project
->monitor
!= NULL
)
558 g_signal_connect (G_OBJECT (project
->monitor
),
560 G_CALLBACK (on_project_monitor_changed
),
566 project
->configure_file
= NULL
;
567 project
->configure
= NULL
;
568 project
->monitor
= NULL
;
571 return project
->configure_file
;
575 amp_project_update_configure (AmpProject
*project
, AnjutaToken
*token
)
577 return anjuta_token_file_update (project
->configure_file
, token
);
581 amp_project_get_configure_token (AmpProject
*project
)
583 return project
->configure_token
;
587 amp_project_get_config_token (AmpProject
*project
, GFile
*file
)
589 AmpConfigFile
*config
;
591 config
= g_hash_table_lookup (project
->configs
, file
);
593 return config
!= NULL
? config
->token
: NULL
;
597 remove_config_file (gpointer data
, GObject
*object
)
599 AmpProject
*project
= (AmpProject
*)data
;
601 g_return_if_fail (project
->files
!= NULL
);
603 project
->files
= g_list_remove (project
->files
, object
);
607 amp_project_update_root (AmpProject
*project
, AmpProject
*new_project
)
611 AnjutaTokenStyle
*style
;
613 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
614 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
615 if (project
->monitor
) g_object_unref (project
->monitor
);
617 project
->configure
= new_project
->configure
;
618 if (project
->configure
!= NULL
)
620 project
->monitor
= g_file_monitor_file (project
->configure
,
624 if (project
->monitor
!= NULL
)
626 g_signal_connect (G_OBJECT (project
->monitor
),
628 G_CALLBACK (on_project_monitor_changed
),
634 project
->monitor
= NULL
;
636 new_project
->configure
= NULL
;
637 project
->configure_file
= new_project
->configure_file
;
638 new_project
->configure_file
= NULL
;
639 project
->configure_token
= new_project
->configure_token
;
640 new_project
->configure_token
= NULL
;
642 hash
= project
->groups
;
643 project
->groups
= new_project
->groups
;
644 new_project
->groups
= hash
;
646 list
= project
->files
;
647 project
->files
= new_project
->files
;
648 new_project
->files
= list
;
650 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
652 GObject
*tfile
= (GObject
*)list
->data
;
654 g_object_weak_unref (tfile
, remove_config_file
, new_project
);
655 g_object_weak_ref (tfile
, remove_config_file
, project
);
657 for (list
= new_project
->files
; list
!= NULL
; list
= g_list_next (list
))
659 GObject
*tfile
= (GObject
*)list
->data
;
661 g_object_weak_unref (tfile
, remove_config_file
, project
);
662 g_object_weak_ref (tfile
, remove_config_file
, new_project
);
665 hash
= project
->configs
;
666 project
->configs
= new_project
->configs
;
667 new_project
->configs
= hash
;
670 style
= project
->ac_space_list
;
671 project
->ac_space_list
= new_project
->ac_space_list
;
672 new_project
->ac_space_list
= style
;
674 style
= project
->am_space_list
;
675 project
->am_space_list
= new_project
->am_space_list
;
676 new_project
->am_space_list
= style
;
678 style
= project
->arg_list
;
679 project
->arg_list
= new_project
->arg_list
;
680 new_project
->arg_list
= style
;
682 AMP_NODE_CLASS (parent_class
)->update (AMP_NODE (project
), AMP_NODE (new_project
));
687 *---------------------------------------------------------------------------*/
690 find_target (AnjutaProjectNode
*node
, gpointer data
)
692 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
694 if (strcmp (anjuta_project_node_get_name (node
), *(gchar
**)data
) == 0)
696 /* Find target, return node value in pointer */
697 *(AnjutaProjectNode
**)data
= node
;
707 find_canonical_target (AnjutaProjectNode
*node
, gpointer data
)
709 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
711 gchar
*canon_name
= canonicalize_automake_variable (anjuta_project_node_get_name (node
));
712 DEBUG_PRINT ("compare canon %s vs %s node %p", canon_name
, *(gchar
**)data
, node
);
713 if (strcmp (canon_name
, *(gchar
**)data
) == 0)
715 /* Find target, return node value in pointer */
716 *(AnjutaProjectNode
**)data
= node
;
728 * ---------------- Data structures managment
732 amp_project_load_properties (AmpProject
*project
, AnjutaToken
*macro
, AnjutaToken
*args
)
735 gint type
= anjuta_token_get_type (macro
);
737 for (item
= anjuta_project_node_get_properties_info (ANJUTA_PROJECT_NODE (project
)); item
!= NULL
; item
= g_list_next (item
))
739 AmpPropertyInfo
*info
= (AmpPropertyInfo
*)item
->data
;
741 if ((info
->token_type
== type
) && (info
->flags
& AM_PROPERTY_IN_CONFIGURE
))
743 AnjutaProjectProperty
*new_prop
;
745 new_prop
= anjuta_project_node_get_property (ANJUTA_PROJECT_NODE (project
), info
->base
.id
);
746 if ((new_prop
!= NULL
) && (new_prop
->info
->default_value
!= new_prop
))
748 anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (project
), new_prop
);
749 amp_property_free (new_prop
);
751 new_prop
= amp_property_new (NULL
, info
->token_type
, info
->position
, NULL
, args
);
753 if (info
->position
>= 0)
755 /* Each parameter correspond to a different property */
758 arg
= anjuta_token_nth_word (args
, info
->position
);
759 g_free (new_prop
->value
);
760 new_prop
->value
= anjuta_token_evaluate_name (arg
);
764 /* Property value is whole argument */
767 new_prop
->value
= g_strdup(" ");
773 arg
= anjuta_token_nth_word (args
, 0);
774 new_prop
->value
= anjuta_token_evaluate_name (arg
);
775 if (new_prop
->value
== NULL
) new_prop
->value
= g_strdup(" ");
778 amp_node_property_add (ANJUTA_PROJECT_NODE (project
), new_prop
);
784 amp_project_load_module (AmpProject
*project
, AnjutaToken
*module_token
)
786 AmpAcScanner
*scanner
= NULL
;
788 if (module_token
!= NULL
)
794 AmpModuleNode
*module
;
795 AmpPackageNode
*package
;
799 arg
= anjuta_token_first_item (module_token
);
800 value
= anjuta_token_evaluate (arg
);
801 module
= amp_module_node_new (value
);
802 amp_module_node_add_token (module
, module_token
);
803 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), ANJUTA_PROJECT_NODE (module
));
806 arg
= anjuta_token_next_word (arg
);
809 scanner
= amp_ac_scanner_new (project
);
810 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
811 anjuta_token_free_children (arg
);
812 list
= anjuta_token_delete_parent (list
);
813 anjuta_token_prepend_items (arg
, list
);
814 amp_ac_scanner_free (scanner
);
819 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
821 value
= anjuta_token_evaluate (item
);
822 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
829 if ((package
!= NULL
) && (compare
!= NULL
))
831 amp_package_node_set_version (package
, compare
, value
);
837 else if ((package
!= NULL
) && (anjuta_token_get_type (item
) == ANJUTA_TOKEN_OPERATOR
))
843 package
= amp_package_node_new (value
);
844 amp_package_node_add_token (package
, item
);
845 anjuta_project_node_append (ANJUTA_PROJECT_NODE (module
), ANJUTA_PROJECT_NODE (package
));
846 anjuta_project_node_set_state (ANJUTA_PROJECT_NODE (package
), ANJUTA_PROJECT_INCOMPLETE
);
855 amp_project_load_config (AmpProject
*project
, AnjutaToken
*arg_list
)
857 AmpAcScanner
*scanner
= NULL
;
859 if (arg_list
!= NULL
)
866 scanner
= amp_ac_scanner_new (project
);
868 arg
= anjuta_token_first_word (arg_list
);
869 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
870 anjuta_token_free_children (arg
);
871 list
= anjuta_token_delete_parent (list
);
872 amp_ac_scanner_free (scanner
);
874 /* list can be NULL is there is no argument to AC_OUTPUT or AC_CONFIG_FILES */
877 anjuta_token_prepend_items (arg
, list
);
878 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
883 value
= anjuta_token_evaluate (item
);
884 if (value
== NULL
) continue;
886 cfg
= amp_config_file_new (value
, anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)), item
);
887 g_hash_table_replace (project
->configs
, cfg
->file
, cfg
);
895 project_load_target (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
898 gchar
*install
= NULL
;
901 AmpNodeInfo
*info
= AmpNodeInformations
;
903 while (info
->base
.type
!= 0)
905 if (anjuta_token_get_type (variable
) == info
->token
)
912 value
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
913 split_automake_variable (value
, &flags
, &install
, NULL
);
915 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
917 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
921 AmpTargetNode
*target
;
922 AmpTargetNode
*orphan
;
926 value
= anjuta_token_evaluate (arg
);
928 /* This happens for variable token which are considered as value */
929 if (value
== NULL
) continue;
930 canon_id
= canonicalize_automake_variable (value
);
932 /* Check if target already exists */
934 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
935 if ((gchar
*)find
!= value
)
944 target
= amp_target_node_new (value
, info
->base
.type
, install
, flags
);
947 amp_target_node_add_token (target
, ANJUTA_TOKEN_ARGUMENT
, arg
);
948 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
949 DEBUG_PRINT ("create target %p name %s", target
, value
);
951 /* Check if there are sources or properties availables */
952 if (g_hash_table_lookup_extended (orphan_properties
, canon_id
, (gpointer
*)&orig_key
, (gpointer
*)&orphan
))
954 AnjutaTokenType type
;
956 AnjutaProjectNode
*child
;
958 g_hash_table_steal (orphan_properties
, canon_id
);
961 for (type
= amp_target_node_get_first_token_type (orphan
); type
!= 0; type
= amp_target_node_get_next_token_type (orphan
, type
))
964 tokens
= amp_target_node_get_token (orphan
, type
);
966 for (tokens
= g_list_first (tokens
); tokens
!= NULL
; tokens
= g_list_next (tokens
))
968 AnjutaToken
*token
= (AnjutaToken
*)tokens
->data
;
970 amp_target_node_add_token (target
, type
, token
);
974 /* Copy all properties */
975 while ((properties
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
977 AnjutaProjectProperty
*prop
;
979 prop
= (AnjutaProjectProperty
*)anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (orphan
), (AnjutaProjectProperty
*)properties
->data
);
980 amp_node_property_add ((AnjutaProjectNode
*)target
, prop
);
983 /* Copy all sources */
984 while ((child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
986 anjuta_project_node_remove (child
);
987 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), child
);
988 g_object_unref (child
);
990 amp_target_changed (target
);
992 amp_target_node_free (orphan
);
995 /* Set target properties */
996 if (flags
& AM_TARGET_NOBASE
)
997 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
998 if (flags
& AM_TARGET_NOTRANS
)
999 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
1000 if (flags
& AM_TARGET_DIST
)
1001 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
1002 if (flags
& AM_TARGET_NODIST
)
1003 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
1004 if (flags
& AM_TARGET_NOINST
)
1006 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1008 else if (install
!= NULL
)
1010 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1011 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1015 if (flags
& AM_TARGET_CHECK
)
1016 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, "1", arg
);
1017 if (flags
& AM_TARGET_MAN
)
1019 gchar section
[] = "0";
1021 section
[0] += (flags
>> 7) & 0x1F;
1022 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, section
, arg
);
1035 project_load_sources (AmpProject
*project
, AnjutaProjectNode
*group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1038 GFile
*group_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (group
)));
1039 gchar
*target_id
= NULL
;
1041 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1044 gchar
*end
= strrchr (target_id
, '_');
1054 AnjutaProjectNode
*target
;
1057 DEBUG_PRINT ("search for canonical %s", target_id
);
1058 anjuta_project_node_children_traverse (group
, find_canonical_target
, &find
);
1059 target
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1061 /* Get orphan buffer if there is no target */
1066 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&target
))
1068 g_hash_table_steal (orphan_properties
, target_id
);
1073 target
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1075 g_hash_table_insert (orphan_properties
, target_id
, target
);
1081 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__SOURCES
, variable
);
1083 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1086 AnjutaProjectNode
*source
;
1087 AnjutaProjectNode
*parent
= target
;
1089 GFileInfo
* file_info
;
1091 value
= anjuta_token_evaluate (arg
);
1092 if (value
== NULL
) continue;
1094 src_file
= g_file_get_child (group_file
, value
);
1095 if (project
->lang_manager
!= NULL
)
1097 file_info
= g_file_query_info (src_file
,
1098 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
1099 G_FILE_QUERY_INFO_NONE
,
1104 gint id
= ianjuta_language_get_from_mime_type (project
->lang_manager
,
1105 g_file_info_get_content_type (file_info
),
1109 const gchar
*obj_ext
= ianjuta_language_get_make_target (project
->lang_manager
, id
, NULL
);
1110 if (obj_ext
!= NULL
)
1112 /* Create object node */
1117 AnjutaProjectNode
*object
;
1119 ext
= strrchr (value
, '.');
1120 if ((ext
!= NULL
) && (ext
!= value
)) *ext
= '\0';
1121 object_name
= g_strconcat (value
, obj_ext
, NULL
);
1122 basename
= g_path_get_basename (object_name
);
1123 obj_file
= g_file_get_child (group_file
, basename
);
1125 g_free (object_name
);
1126 object
= amp_object_node_new (obj_file
, ANJUTA_PROJECT_PROJECT
);
1127 g_object_unref (obj_file
);
1128 anjuta_project_node_append (parent
, object
);
1132 g_object_unref (file_info
);
1137 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
);
1138 g_object_unref (src_file
);
1141 amp_source_node_add_token (AMP_SOURCE_NODE (source
), arg
);
1143 DEBUG_PRINT ("add target child %p", target
);
1144 /* Add as target child */
1145 anjuta_project_node_append (parent
, source
);
1150 amp_target_changed (AMP_TARGET_NODE (target
));
1153 g_object_unref (group_file
);
1159 project_load_data (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
, gint data_flags
)
1161 gchar
*install
= NULL
;
1162 AmpTargetNode
*target
;
1166 AmpNodeInfo
*info
= AmpNodeInformations
;
1170 while (info
->base
.name
!= NULL
)
1172 if (anjuta_token_get_type (variable
) == info
->token
)
1179 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1180 split_automake_variable (target_id
, &flags
, &install
, NULL
);
1182 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
1184 /* Check if target already exists */
1186 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
1187 if ((gchar
*)find
== target_id
)
1190 target
= amp_target_node_new (target_id
, info
->base
.type
, install
, flags
);
1193 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
1194 DEBUG_PRINT ("create target %p name %s", target
, target_id
);
1199 target
= AMP_TARGET_NODE (find
);
1204 GFile
*parent_file
= g_object_ref (anjuta_project_node_get_file (parent
));
1206 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__DATA
, variable
);
1208 list
= anjuta_token_last_item (variable
);
1209 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1212 AnjutaProjectNode
*source
;
1215 value
= anjuta_token_evaluate (arg
);
1216 if (value
== NULL
) continue;
1219 src_file
= g_file_get_child (parent_file
, value
);
1220 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
| data_flags
);
1221 g_object_unref (src_file
);
1224 amp_source_node_add_token (AMP_SOURCE_NODE(source
), arg
);
1226 /* Add as target child */
1227 DEBUG_PRINT ("add target child %p", target
);
1228 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), source
);
1233 g_object_unref (parent_file
);
1235 /* Set target properties */
1236 if (flags
& AM_TARGET_NOBASE
)
1237 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
1238 if (flags
& AM_TARGET_NOTRANS
)
1239 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
1240 if (flags
& AM_TARGET_DIST
)
1241 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
1242 if (flags
& AM_TARGET_NODIST
)
1243 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
1244 if (flags
& AM_TARGET_NOINST
)
1246 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1248 else if (install
!= NULL
)
1250 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1251 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1261 project_load_target_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1263 gchar
*target_id
= NULL
;
1265 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1268 gchar
*end
= strrchr (target_id
, '_');
1279 AnjutaProjectProperty
*prop
;
1281 AnjutaTokenType type
;
1284 DEBUG_PRINT ("search for canonical %s", target_id
);
1285 anjuta_project_node_children_traverse (parent
, find_canonical_target
, &find
);
1286 parent
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1288 /* Create property */
1289 list
= anjuta_token_last_item (variable
);
1290 type
= anjuta_token_get_type (variable
);
1291 value
= anjuta_token_evaluate_name (list
);
1292 prop
= amp_property_new (NULL
, type
, 0, value
, list
);
1296 /* Add property to non existing target, create a dummy target */
1299 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&parent
))
1301 /* Dummy target already created */
1302 g_hash_table_steal (orphan_properties
, target_id
);
1307 /* Create dummy target */
1308 parent
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1310 g_hash_table_insert (orphan_properties
, target_id
, parent
);
1318 /* Add property to target */
1319 amp_node_property_add (parent
, prop
);
1320 amp_target_node_add_token (AMP_TARGET_NODE (parent
), type
, variable
);
1321 amp_target_changed (AMP_TARGET_NODE (parent
));
1328 project_load_group_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
)
1332 AnjutaProjectProperty
*prop
;
1335 /* Create property */
1336 list
= anjuta_token_last_item (variable
);
1337 name
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1338 value
= anjuta_token_evaluate_name (list
);
1340 prop
= amp_property_new (name
, anjuta_token_get_type (variable
), 0, value
, list
);
1342 amp_node_property_add (parent
, prop
);
1351 find_group (AnjutaProjectNode
*node
, gpointer data
)
1353 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1355 if (g_file_equal (anjuta_project_node_get_file (node
), (GFile
*)data
))
1357 /* Find group, return node value in pointer */
1366 project_load_subdirs (AmpProject
*project
, AnjutaToken
*list
, AnjutaProjectNode
*parent
, gboolean dist_only
)
1370 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1374 value
= anjuta_token_evaluate (arg
);
1375 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
1377 /* Skip ., it is a special case, used to defined build order */
1378 if (strcmp (value
, ".") != 0)
1381 AmpGroupNode
*group
;
1383 subdir
= g_file_resolve_relative_path (anjuta_project_node_get_file (parent
), value
);
1385 /* Look for already existing group */
1386 group
= AMP_GROUP_NODE (anjuta_project_node_children_traverse (parent
, find_group
, subdir
));
1390 /* Already existing group, mark for built if needed */
1391 if (!dist_only
) amp_group_node_set_dist_only (group
, FALSE
);
1395 /* Create new group */
1396 group
= amp_group_node_new (subdir
, value
, dist_only
);
1398 /* Group can be NULL if the name is not valid */
1401 g_hash_table_insert (project
->groups
, g_file_get_uri (subdir
), group
);
1402 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (group
));
1404 amp_node_load (AMP_NODE (group
), NULL
, project
, NULL
);
1407 if (group
) amp_group_node_add_token (group
, arg
, dist_only
? AM_GROUP_TOKEN_DIST_SUBDIRS
: AM_GROUP_TOKEN_SUBDIRS
);
1408 g_object_unref (subdir
);
1415 amp_project_set_am_variable (AmpProject
* project
, AmpGroupNode
* group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1419 switch (anjuta_token_get_type (variable
))
1421 case AM_TOKEN_SUBDIRS
:
1422 list
= anjuta_token_last_item (variable
);
1423 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), FALSE
);
1425 case AM_TOKEN_DIST_SUBDIRS
:
1426 list
= anjuta_token_last_item (variable
);
1427 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), TRUE
);
1429 case AM_TOKEN__DATA
:
1430 case AM_TOKEN__HEADERS
:
1431 case AM_TOKEN__LISP
:
1432 case AM_TOKEN__MANS
:
1433 case AM_TOKEN__PYTHON
:
1434 case AM_TOKEN__JAVA
:
1435 case AM_TOKEN__TEXINFOS
:
1436 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, 0);
1438 case AM_TOKEN__SCRIPTS
:
1439 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, ANJUTA_PROJECT_EXECUTABLE
);
1441 case AM_TOKEN__LIBRARIES
:
1442 case AM_TOKEN__LTLIBRARIES
:
1443 case AM_TOKEN__PROGRAMS
:
1444 project_load_target (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1446 case AM_TOKEN__SOURCES
:
1447 project_load_sources (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1450 case AM_TOKEN__LDFLAGS
:
1451 case AM_TOKEN__CPPFLAGS
:
1452 case AM_TOKEN__CFLAGS
:
1453 case AM_TOKEN__CXXFLAGS
:
1454 case AM_TOKEN__JAVACFLAGS
:
1455 case AM_TOKEN__VALAFLAGS
:
1456 case AM_TOKEN__FCFLAGS
:
1457 case AM_TOKEN__OBJCFLAGS
:
1458 case AM_TOKEN__LFLAGS
:
1459 case AM_TOKEN__YFLAGS
:
1460 project_load_group_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
);
1462 case AM_TOKEN_TARGET_LDFLAGS
:
1463 case AM_TOKEN_TARGET_CPPFLAGS
:
1464 case AM_TOKEN_TARGET_CFLAGS
:
1465 case AM_TOKEN_TARGET_CXXFLAGS
:
1466 case AM_TOKEN_TARGET_JAVACFLAGS
:
1467 case AM_TOKEN_TARGET_VALAFLAGS
:
1468 case AM_TOKEN_TARGET_FCFLAGS
:
1469 case AM_TOKEN_TARGET_OBJCFLAGS
:
1470 case AM_TOKEN_TARGET_LFLAGS
:
1471 case AM_TOKEN_TARGET_YFLAGS
:
1472 case AM_TOKEN_TARGET_DEPENDENCIES
:
1473 case AM_TOKEN_TARGET_LIBADD
:
1474 case AM_TOKEN_TARGET_LDADD
:
1475 project_load_target_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1481 /* Keep the autotools variable as a normal variable too */
1482 amp_group_node_update_variable (group
, variable
);
1486 *---------------------------------------------------------------------------*/
1489 amp_project_compare_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1496 name1
= anjuta_project_node_get_name (old_node
);
1497 name2
= anjuta_project_node_get_name (new_node
);
1498 file1
= anjuta_project_node_get_file (old_node
);
1499 file2
= anjuta_project_node_get_file (new_node
);
1501 return (anjuta_project_node_get_full_type (old_node
) == anjuta_project_node_get_full_type (new_node
))
1502 && ((name1
== NULL
) || (name2
== NULL
) || (strcmp (name1
, name2
) == 0))
1503 && ((file1
== NULL
) || (file2
== NULL
) || g_file_equal (file1
, file2
)) ? 0 : 1;
1507 amp_project_map_children (GHashTable
*map
, AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1509 GList
*children
= NULL
;
1511 if (new_node
!= NULL
)
1513 for (new_node
= anjuta_project_node_first_child (new_node
); new_node
!= NULL
; new_node
= anjuta_project_node_next_sibling (new_node
))
1515 children
= g_list_prepend (children
, new_node
);
1517 children
= g_list_reverse (children
);
1520 for (old_node
= anjuta_project_node_first_child (old_node
); old_node
!= NULL
; old_node
= anjuta_project_node_next_sibling (old_node
))
1524 same
= g_list_find_custom (children
, old_node
, (GCompareFunc
)amp_project_compare_node
);
1528 /* Add new to old node mapping */
1529 g_hash_table_insert (map
, (AnjutaProjectNode
*)same
->data
, old_node
);
1531 amp_project_map_children (map
, old_node
, (AnjutaProjectNode
*)same
->data
);
1532 children
= g_list_delete_link (children
, same
);
1536 /* Keep old_node to be deleted in the hash table as a key with a NULL
1538 g_hash_table_insert (map
, old_node
, NULL
);
1542 /* Add remaining node in hash table */
1543 for (; children
!= NULL
; children
= g_list_delete_link (children
, children
))
1545 /* Keep new node without a corresponding old node as a key and a identical
1547 g_hash_table_insert (map
, children
->data
, children
->data
);
1551 /* Find the correspondance between the new loaded node (new_node) and the
1552 * original node currently in the tree (old_node) */
1554 amp_project_map_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1558 map
= g_hash_table_new (g_direct_hash
, NULL
);
1560 g_hash_table_insert (map
, new_node
, old_node
);
1562 amp_project_map_children (map
, old_node
, new_node
);
1569 amp_project_update_node (AnjutaProjectNode
*key
, AnjutaProjectNode
*value
, GHashTable
*map
)
1571 AnjutaProjectNode
*old_node
= NULL
; /* The node that will be deleted */
1575 /* if value is NULL, delete the old node which is the key */
1580 AnjutaProjectNode
*node
= value
; /* The node that we keep in the tree */
1581 AnjutaProjectNode
*new_node
= key
; /* The node with the new data */
1583 if (new_node
&& new_node
!= node
)
1587 amp_node_update (AMP_NODE (node
), AMP_NODE (new_node
));
1589 /* Swap custom properties */
1590 properties
= node
->properties
;
1591 node
->properties
= new_node
->properties
;
1592 new_node
->properties
= properties
;
1594 if (new_node
->parent
== NULL
)
1596 /* This is the top loaded node, update only the children */
1597 node
->children
= new_node
->children
;
1601 /* Other node update all pointers */
1602 node
->parent
= new_node
->parent
;
1603 node
->children
= new_node
->children
;
1604 node
->next
= new_node
->next
;
1605 node
->prev
= new_node
->prev
;
1608 /* Destroy node with data */
1609 old_node
= new_node
;
1612 /* Update links, using original node address if they stay in the tree */
1613 new_node
= g_hash_table_lookup (map
, node
->parent
);
1614 if (new_node
!= NULL
) node
->parent
= new_node
;
1615 new_node
= g_hash_table_lookup (map
, node
->children
);
1616 if (new_node
!= NULL
) node
->children
= new_node
;
1617 new_node
= g_hash_table_lookup (map
, node
->next
);
1618 if (new_node
!= NULL
) node
->next
= new_node
;
1619 new_node
= g_hash_table_lookup (map
, node
->prev
);
1620 if (new_node
!= NULL
) node
->prev
= new_node
;
1624 /* Unlink old node and free it */
1625 if (old_node
!= NULL
)
1627 old_node
->parent
= NULL
;
1628 old_node
->children
= NULL
;
1629 old_node
->next
= NULL
;
1630 old_node
->prev
= NULL
;
1631 g_object_unref (old_node
);
1636 *---------------------------------------------------------------------------*/
1638 AnjutaProjectNodeInfo
*
1639 amp_project_get_type_info (AmpProject
*project
, AnjutaProjectNodeType type
)
1643 for (info
= AmpNodeInformations
; info
->base
.type
!= type
; info
++)
1645 if ((info
->base
.type
== type
) || (info
->base
.type
== 0)) break;
1648 return (AnjutaProjectNodeInfo
*)info
;
1652 amp_project_load_root (AmpProject
*project
, GError
**error
)
1654 AmpAcScanner
*scanner
;
1657 GFile
*configure_file
;
1658 AnjutaTokenFile
*configure_token_file
;
1659 AnjutaProjectNode
*source
;
1662 root_file
= anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
1663 DEBUG_PRINT ("reload project %p root file %p", project
, root_file
);
1665 /* Unload current project */
1666 amp_project_unload (project
);
1668 /* Initialize list styles */
1669 project
->ac_space_list
= anjuta_token_style_new (NULL
, " ", "\n", NULL
, 0);
1670 project
->am_space_list
= anjuta_token_style_new (NULL
, " ", " \\\n\t", NULL
, 0);
1671 project
->arg_list
= anjuta_token_style_new (NULL
, ", ", ", ", ")", 0);
1673 /* Find configure file */
1674 if (file_type (root_file
, "configure.ac") == G_FILE_TYPE_REGULAR
)
1676 configure_file
= g_file_get_child (root_file
, "configure.ac");
1678 else if (file_type (root_file
, "configure.in") == G_FILE_TYPE_REGULAR
)
1680 configure_file
= g_file_get_child (root_file
, "configure.in");
1684 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1685 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1686 _("Project doesn't exist or invalid path"));
1691 /* Parse configure */
1692 configure_token_file
= amp_project_set_configure (project
, configure_file
);
1693 amp_project_add_file (project
, configure_file
, configure_token_file
);
1694 source
= amp_source_node_new (configure_file
, ANJUTA_PROJECT_PROJECT
| ANJUTA_PROJECT_FRAME
| ANJUTA_PROJECT_READ_ONLY
);
1695 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), source
);
1696 arg
= anjuta_token_file_load (configure_token_file
, NULL
);
1697 g_hash_table_remove_all (project
->ac_variables
);
1698 scanner
= amp_ac_scanner_new (project
);
1699 project
->configure_token
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, 0, configure_file
, &err
);
1700 amp_ac_scanner_free (scanner
);
1702 if (project
->configure_token
== NULL
)
1706 g_set_error_literal (error
, IANJUTA_PROJECT_ERROR
,
1707 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1713 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1714 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1716 _("Unable to parse project file"));
1722 /* Load all makefiles recursively */
1723 if (!AMP_NODE_CLASS (parent_class
)->load (AMP_NODE (project
), NULL
, project
, NULL
))
1725 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1726 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1727 _("Project doesn't exist or has an invalid path"));
1736 amp_project_unload (AmpProject
*project
)
1739 amp_project_clear (project
);
1741 /* shortcut hash tables */
1742 if (project
->groups
) g_hash_table_remove_all (project
->groups
);
1743 if (project
->files
!= NULL
)
1747 for (list
= project
->files
; list
!= NULL
; list
= g_list_delete_link (list
, list
))
1749 g_object_weak_unref (G_OBJECT (list
->data
), remove_config_file
, project
);
1751 project
->files
= NULL
;
1753 if (project
->configs
) g_hash_table_remove_all (project
->configs
);
1756 if (project
->am_space_list
) anjuta_token_style_free (project
->am_space_list
);
1757 if (project
->ac_space_list
) anjuta_token_style_free (project
->ac_space_list
);
1758 if (project
->arg_list
) anjuta_token_style_free (project
->arg_list
);
1762 amp_project_is_loaded (AmpProject
*project
)
1764 return project
->loading
== 0;
1768 amp_project_probe (GFile
*file
,
1774 dir
= (file_type (file
, NULL
) == G_FILE_TYPE_DIRECTORY
);
1777 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1778 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1779 _("Project doesn't exist or invalid path"));
1785 const gchar
**makefile
;
1787 /* Look for makefiles */
1789 for (makefile
= valid_am_makefiles
; *makefile
!= NULL
; makefile
++)
1791 if (file_type (file
, *makefile
) == G_FILE_TYPE_REGULAR
)
1800 probe
= ((file_type (file
, "configure.ac") == G_FILE_TYPE_REGULAR
) ||
1801 (file_type (file
, "configure.in") == G_FILE_TYPE_REGULAR
));
1805 return probe
? IANJUTA_PROJECT_PROBE_PROJECT_FILES
: 0;
1809 amp_project_get_token_location (AmpProject
*project
, AnjutaTokenFileLocation
*location
, AnjutaToken
*token
)
1813 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1815 if (anjuta_token_file_get_token_location ((AnjutaTokenFile
*)list
->data
, location
, token
))
1825 amp_project_remove_group (AmpProject
*project
,
1826 AmpGroupNode
*group
,
1831 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (group
)) != ANJUTA_PROJECT_GROUP
) return;
1833 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_CONFIGURE
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1835 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1837 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1839 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1841 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_DIST_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1843 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1846 amp_group_node_free (group
);
1850 amp_project_remove_source (AmpProject
*project
,
1851 AmpSourceNode
*source
,
1854 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (source
)) != ANJUTA_PROJECT_SOURCE
) return;
1856 anjuta_token_remove_word (amp_source_node_get_token (source
));
1858 amp_source_node_free (source
);
1862 amp_project_get_node_info (AmpProject
*project
, GError
**error
)
1864 static GList
*info_list
= NULL
;
1866 if (info_list
== NULL
)
1870 for (node
= AmpNodeInformations
; node
->base
.type
!= 0; node
++)
1872 info_list
= g_list_prepend (info_list
, node
);
1875 info_list
= g_list_reverse (info_list
);
1882 *---------------------------------------------------------------------------*/
1884 typedef struct _AmpMovePacket
{
1885 AmpProject
*project
;
1886 GFile
*old_root_file
;
1887 GFile
*new_root_file
;
1891 foreach_node_move (AnjutaProjectNode
*g_node
, gpointer data
)
1893 AmpProject
*project
= ((AmpMovePacket
*)data
)->project
;
1894 GFile
*old_root_file
= ((AmpMovePacket
*)data
)->old_root_file
;
1895 GFile
*new_root_file
= ((AmpMovePacket
*)data
)->new_root_file
;
1899 switch (anjuta_project_node_get_node_type (g_node
))
1901 case ANJUTA_PROJECT_GROUP
:
1902 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1903 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1905 amp_group_node_set_file (AMP_GROUP_NODE (g_node
), new_file
);
1906 g_object_unref (new_file
);
1908 g_hash_table_insert (project
->groups
, g_file_get_uri (new_file
), g_node
);
1910 case ANJUTA_PROJECT_SOURCE
:
1911 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1912 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1914 amp_source_node_set_file (AMP_SOURCE_NODE (g_node
), new_file
);
1915 g_object_unref (new_file
);
1923 amp_project_move (AmpProject
*project
, const gchar
*path
)
1930 GHashTable
* old_hash
;
1931 GHashTableIter iter
;
1932 AmpMovePacket packet
= {project
, NULL
};
1934 /* Change project root directory */
1935 packet
.old_root_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
1936 packet
.new_root_file
= g_file_new_for_path (path
);
1938 /* Change project root directory in groups */
1939 old_hash
= project
->groups
;
1940 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
1941 anjuta_project_node_foreach (ANJUTA_PROJECT_NODE (project
), G_POST_ORDER
, foreach_node_move
, &packet
);
1942 g_hash_table_destroy (old_hash
);
1944 /* Change all files */
1945 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1947 AnjutaTokenFile
*tfile
= (AnjutaTokenFile
*)list
->data
;
1949 relative
= get_relative_path (packet
.old_root_file
, anjuta_token_file_get_file (tfile
));
1950 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1952 anjuta_token_file_move (tfile
, new_file
);
1955 /* Change all configs */
1956 old_hash
= project
->configs
;
1957 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
1958 g_hash_table_iter_init (&iter
, old_hash
);
1959 while (g_hash_table_iter_next (&iter
, &key
, (gpointer
*)&cfg
))
1961 relative
= get_relative_path (packet
.old_root_file
, cfg
->file
);
1962 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1964 g_object_unref (cfg
->file
);
1965 cfg
->file
= new_file
;
1967 g_hash_table_insert (project
->configs
, new_file
, cfg
);
1969 g_hash_table_steal_all (old_hash
);
1970 g_hash_table_destroy (old_hash
);
1972 g_object_unref (packet
.old_root_file
);
1973 g_object_unref (packet
.new_root_file
);
1978 /* Dump file content of corresponding node */
1980 amp_project_dump (AmpProject
*project
, AnjutaProjectNode
*node
, AmpFileType type
)
1982 gboolean ok
= FALSE
;
1984 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1989 anjuta_token_dump (amp_group_node_get_makefile_token (AMP_GROUP_NODE (node
)));
1991 case DUMP_CONFIGURE
:
1992 anjuta_token_dump (AMP_PROJECT (node
)->configure_token
);
2004 amp_project_new (GFile
*file
, IAnjutaLanguage
*language
, GError
**error
)
2006 AmpProject
*project
;
2009 project
= AMP_PROJECT (g_object_new (AMP_TYPE_PROJECT
, NULL
));
2010 new_file
= g_file_dup (file
);
2011 amp_root_node_set_file (AMP_ROOT_NODE (project
), new_file
);
2012 g_object_unref (new_file
);
2014 project
->lang_manager
= (language
!= NULL
) ? g_object_ref (language
) : NULL
;
2019 /* Project access functions
2020 *---------------------------------------------------------------------------*/
2023 amp_project_get_root (AmpProject
*project
)
2025 return AMP_PROJECT (project
);
2029 amp_project_get_group (AmpProject
*project
, const gchar
*id
)
2031 return (AmpGroupNode
*)g_hash_table_lookup (project
->groups
, id
);
2035 amp_project_get_target (AmpProject
*project
, const gchar
*id
)
2037 AmpTargetNode
**buffer
;
2038 AmpTargetNode
*target
;
2041 buffer
= (AmpTargetNode
**)g_base64_decode (id
, &dummy
);
2049 amp_project_get_source (AmpProject
*project
, const gchar
*id
)
2051 AmpSourceNode
**buffer
;
2052 AmpSourceNode
*source
;
2055 buffer
= (AmpSourceNode
**)g_base64_decode (id
, &dummy
);
2063 amp_project_get_uri (AmpProject
*project
)
2065 g_return_val_if_fail (project
!= NULL
, NULL
);
2067 return g_file_get_uri (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
2071 amp_project_get_file (AmpProject
*project
)
2073 g_return_val_if_fail (project
!= NULL
, NULL
);
2075 return anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
2079 amp_project_add_file (AmpProject
*project
, GFile
*file
, AnjutaTokenFile
* token
)
2081 project
->files
= g_list_prepend (project
->files
, token
);
2082 g_object_weak_ref (G_OBJECT (token
), remove_config_file
, project
);
2086 amp_project_add_subst_variable (AmpProject
*project
, const gchar
*name
, AnjutaToken
*value
)
2088 g_hash_table_insert (project
->ac_variables
, (gchar
*)name
, value
);
2092 amp_project_get_subst_variable_token (AmpProject
*project
, const gchar
*name
)
2094 return g_hash_table_lookup (project
->ac_variables
, name
);
2099 amp_project_is_busy (AmpProject
*project
)
2101 if (project
->queue
== NULL
) return FALSE
;
2103 return pm_command_queue_is_busy (project
->queue
);
2107 *---------------------------------------------------------------------------*/
2110 amp_load_setup (PmJob
*job
)
2112 //anjuta_project_node_check (job->node);
2113 pm_job_set_parent (job
, anjuta_project_node_parent (job
->node
));
2114 job
->proxy
= ANJUTA_PROJECT_NODE (amp_node_copy (AMP_NODE (job
->node
)));
2120 amp_load_work (PmJob
*job
)
2122 return amp_node_load (AMP_NODE (job
->proxy
), AMP_NODE (job
->parent
), AMP_PROJECT (job
->user_data
), &job
->error
);
2126 amp_load_complete (PmJob
*job
)
2129 //static GTimer *timer = NULL;
2131 g_return_val_if_fail (job
->proxy
!= NULL
, FALSE
);
2133 //anjuta_project_node_check (job->node);
2134 /*if (timer == NULL)
2136 timer = g_timer_new ();
2140 g_timer_continue (timer);
2142 map
= amp_project_map_node (job
->node
, job
->proxy
);
2143 g_object_ref (job
->proxy
);
2145 job
->proxy
->parent
= NULL
; // Mark loaded top node
2146 g_hash_table_foreach (map
, (GHFunc
)amp_project_update_node
, map
);
2147 //anjuta_project_node_check (job->node);
2148 g_hash_table_destroy (map
);
2149 g_object_unref (job
->proxy
);
2151 AMP_PROJECT (job
->user_data
)->loading
--;
2152 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-loaded", job
->node
, job
->error
);
2153 //g_timer_stop (timer);
2154 //g_message ("amp_load_complete completed in %g", g_timer_elapsed (timer, NULL));
2159 static PmCommandWork amp_load_job
= {amp_load_setup
, amp_load_work
, amp_load_complete
};
2162 amp_save_setup (PmJob
*job
)
2168 amp_save_work (PmJob
*job
)
2170 /* It is difficult to save only a particular node, so the whole project is saved */
2171 amp_node_save (AMP_NODE (job
->user_data
), NULL
, AMP_PROJECT (job
->user_data
), &job
->error
);
2177 amp_save_complete (PmJob
*job
)
2179 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-saved", job
->node
, job
->error
);
2184 static PmCommandWork amp_save_job
= {amp_save_setup
, amp_save_work
, amp_save_complete
};
2187 amp_add_before_setup (PmJob
*job
)
2189 /* If add is called to add the root group, the node is already existing */
2190 if (job
->parent
!= job
->node
)
2191 anjuta_project_node_insert_before (job
->parent
, job
->sibling
, job
->node
);
2197 amp_add_after_setup (PmJob
*job
)
2199 /* If add is called to add the root group, the node is already existing */
2200 if (job
->parent
!= job
->node
)
2201 anjuta_project_node_insert_after (job
->parent
, job
->sibling
, job
->node
);
2207 amp_add_work (PmJob
*job
)
2209 AmpNode
*parent
= AMP_NODE (job
->parent
);
2212 ok
= amp_node_write (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2213 /* Add new node properties if existing */
2218 for (item
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (job
->node
)); item
!= NULL
; item
= g_list_next (item
))
2220 AnjutaProjectProperty
*property
= (AnjutaProjectProperty
*)item
->data
;
2223 flags
= ((AmpPropertyInfo
*)property
->info
)->flags
;
2224 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2226 ok
= ok
&& amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), property
);
2228 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2230 if (((AnjutaProjectPropertyInfo
*)property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2232 ok
= ok
&& amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, property
);
2242 amp_add_complete (PmJob
*job
)
2244 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2249 static PmCommandWork amp_add_before_job
= {amp_add_before_setup
, amp_add_work
, amp_add_complete
};
2250 static PmCommandWork amp_add_after_job
= {amp_add_after_setup
, amp_add_work
, amp_add_complete
};
2254 amp_remove_setup (PmJob
*job
)
2256 AnjutaProjectNode
*parent
;
2258 parent
= anjuta_project_node_parent (job
->node
);
2259 if (parent
== NULL
) parent
= job
->node
;
2260 pm_job_set_parent (job
, parent
);
2261 anjuta_project_node_set_state (job
->node
, ANJUTA_PROJECT_REMOVED
);
2267 amp_remove_work (PmJob
*job
)
2269 AmpNode
*parent
= AMP_NODE (job
->parent
);
2272 ok
= amp_node_erase (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2278 amp_remove_complete (PmJob
*job
)
2280 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2285 static PmCommandWork amp_remove_job
= {amp_remove_setup
, amp_remove_work
, amp_remove_complete
};
2288 amp_set_property_setup (PmJob
*job
)
2294 amp_set_property_work (PmJob
*job
)
2298 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2300 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2302 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2304 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2306 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2308 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2316 amp_set_property_complete (PmJob
*job
)
2318 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2323 static PmCommandWork amp_set_property_job
= {amp_set_property_setup
, amp_set_property_work
, amp_set_property_complete
};
2326 amp_remove_property_setup (PmJob
*job
)
2332 amp_remove_property_work (PmJob
*job
)
2336 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2338 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2340 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2342 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2344 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2346 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2354 amp_remove_property_complete (PmJob
*job
)
2356 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2361 static PmCommandWork amp_remove_property_job
= {amp_remove_property_setup
, amp_remove_property_work
, amp_remove_property_complete
};
2363 /* Implement IAnjutaProject
2364 *---------------------------------------------------------------------------*/
2367 iproject_load_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2371 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2372 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2374 AMP_PROJECT (obj
)->loading
++;
2375 load_job
= pm_job_new (&_load_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2377 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, load_job
);
2383 iproject_save_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2387 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2388 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2390 save_job
= pm_job_new (&_save_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2391 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, save_job
);
2396 static AnjutaProjectNode
*
2397 iproject_add_node_before (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2399 AnjutaProjectNode
*node
;
2402 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2404 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2407 add_job
= pm_job_new (&_add_before_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2408 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2414 static AnjutaProjectNode
*
2415 iproject_add_node_after (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2417 AnjutaProjectNode
*node
;
2420 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2422 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2425 add_job
= pm_job_new (&_add_after_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2426 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2433 iproject_remove_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
2437 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2439 remove_job
= pm_job_new (&_remove_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2440 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_job
);
2445 static AnjutaProjectProperty
*
2446 iproject_set_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, const gchar
*value
, GError
**error
)
2448 AnjutaProjectProperty
*new_prop
;
2449 PmJob
*set_property_job
;
2451 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2453 new_prop
= name
== NULL
? amp_node_property_set (node
, id
, value
) : amp_node_map_property_set (node
, id
, name
, value
);
2454 set_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2455 set_property_job
->property
= new_prop
;
2456 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, set_property_job
);
2462 iproject_remove_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, GError
**error
)
2464 AnjutaProjectProperty
*new_prop
;
2465 PmJob
*remove_property_job
;
2467 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2470 new_prop
= amp_node_map_property_set (node
, id
, name
, NULL
);
2471 remove_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2472 remove_property_job
->property
= new_prop
;
2473 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_property_job
);
2478 static AnjutaProjectNode
*
2479 iproject_get_root (IAnjutaProject
*obj
, GError
**err
)
2481 return ANJUTA_PROJECT_NODE (obj
);
2485 iproject_get_node_info (IAnjutaProject
*obj
, GError
**err
)
2487 return amp_project_get_node_info (AMP_PROJECT (obj
), err
);
2491 iproject_is_loaded (IAnjutaProject
*obj
, GError
**err
)
2493 return amp_project_is_loaded (AMP_PROJECT (obj
));
2497 iproject_iface_init(IAnjutaProjectIface
* iface
)
2499 iface
->load_node
= iproject_load_node
;
2500 iface
->save_node
= iproject_save_node
;
2501 iface
->add_node_before
= iproject_add_node_before
;
2502 iface
->add_node_after
= iproject_add_node_after
;
2503 iface
->remove_node
= iproject_remove_node
;
2504 iface
->set_property
= iproject_set_property
;
2505 iface
->remove_property
= iproject_remove_property
;
2506 iface
->get_root
= iproject_get_root
;
2507 iface
->get_node_info
= iproject_get_node_info
;
2508 iface
->is_loaded
= iproject_is_loaded
;
2511 /* AmpNode implementation
2512 *---------------------------------------------------------------------------*/
2515 amp_project_load (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2517 return amp_project_load_root (AMP_PROJECT (root
), error
);
2521 amp_project_save (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2523 AnjutaTokenFile
*tfile
;
2524 AnjutaProjectNode
*child
;
2527 tfile
= AMP_PROJECT (root
)->configure_file
;
2528 if (anjuta_token_file_is_dirty (tfile
))
2530 if (!anjuta_token_file_save (tfile
, error
)) return FALSE
;
2533 if (!AMP_NODE_CLASS (parent_class
)->save (root
, parent
, project
, error
))
2538 /* Save all children */
2539 for (child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (root
)); child
!= NULL
; child
= anjuta_project_node_next_sibling (child
))
2541 if (!amp_node_save (AMP_NODE (child
), root
, project
, error
)) return FALSE
;
2549 amp_project_update (AmpNode
*node
, AmpNode
*new_node
)
2551 amp_project_update_root (AMP_PROJECT (node
), AMP_PROJECT (new_node
));
2557 amp_project_copy (AmpNode
*old_node
)
2561 new_node
= AMP_NODE_CLASS (amp_project_parent_class
)->copy (old_node
);
2562 ((AmpProject
*)new_node
)->lang_manager
= (((AmpProject
*)old_node
)->lang_manager
!= NULL
) ? g_object_ref (((AmpProject
*)old_node
)->lang_manager
) : NULL
;
2568 /* GObject implementation
2569 *---------------------------------------------------------------------------*/
2572 amp_project_dispose (GObject
*object
)
2574 AmpProject
*project
;
2576 g_return_if_fail (AMP_IS_PROJECT (object
));
2578 project
= AMP_PROJECT (object
);
2579 amp_project_unload (project
);
2581 amp_project_clear (project
);
2583 if (project
->groups
) g_hash_table_destroy (project
->groups
);
2584 project
->groups
= NULL
;
2585 if (project
->configs
) g_hash_table_destroy (project
->configs
);
2586 project
->configs
= NULL
;
2587 if (project
->ac_variables
) g_hash_table_destroy (project
->ac_variables
);
2588 project
->ac_variables
= NULL
;
2590 if (project
->queue
) pm_command_queue_free (project
->queue
);
2591 project
->queue
= NULL
;
2593 if (project
->monitor
) g_object_unref (project
->monitor
);
2594 project
->monitor
= NULL
;
2596 if (project
->lang_manager
) g_object_unref (project
->lang_manager
);
2597 project
->lang_manager
= NULL
;
2599 G_OBJECT_CLASS (parent_class
)->dispose (object
);
2603 amp_project_init (AmpProject
*project
)
2605 g_return_if_fail (project
!= NULL
);
2606 g_return_if_fail (AMP_IS_PROJECT (project
));
2609 project
->configure_file
= NULL
;
2610 project
->configure_token
= NULL
;
2613 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
2614 project
->files
= NULL
;
2615 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
2616 project
->ac_variables
= g_hash_table_new_full (g_str_hash
, g_str_equal
, (GDestroyNotify
)g_free
, NULL
);
2619 project
->am_space_list
= NULL
;
2620 project
->ac_space_list
= NULL
;
2621 project
->arg_list
= NULL
;
2623 project
->queue
= NULL
;
2624 project
->loading
= 0;
2628 amp_project_class_init (AmpProjectClass
*klass
)
2630 GObjectClass
*object_class
;
2631 AmpNodeClass
*node_class
;
2633 parent_class
= g_type_class_peek_parent (klass
);
2635 object_class
= G_OBJECT_CLASS (klass
);
2636 object_class
->dispose
= amp_project_dispose
;
2638 node_class
= AMP_NODE_CLASS (klass
);
2639 node_class
->load
= amp_project_load
;
2640 node_class
->save
= amp_project_save
;
2641 node_class
->update
= amp_project_update
;
2642 node_class
->copy
= amp_project_copy
;
2646 amp_project_class_finalize (AmpProjectClass
*klass
)
2651 amp_project_register (GTypeModule
*module
)
2653 amp_node_register (module
);
2654 amp_project_register_type (module
);