search: Use G_REGEX_MULTILINE for find in files.
[anjuta.git] / plugins / am-project / am-writer.c
blob5462e0e73d39870ef1fdeb6bc53ede77e19d96ae
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* am-writer.c
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include "am-writer.h"
28 #include "ac-scanner.h"
29 #include "ac-parser.h"
31 #include "am-project-private.h"
32 #include "amp-node.h"
33 #include "amp-group.h"
34 #include "amp-target.h"
35 #include "amp-source.h"
36 #include "am-properties.h"
37 #include "am-scanner.h"
39 #include <libanjuta/anjuta-debug.h>
40 #include <libanjuta/anjuta-utils.h>
42 #include <string.h>
43 #include <ctype.h>
45 /* Types & Constants
46 *---------------------------------------------------------------------------*/
48 const static gchar* AmpStandardDirectory[] = {"bindir", "sbindir", "libdir", "pkglibdir", "libexecdir", "pkglibexecdir", "datadir", "pkgdatadir", "mandir", "infodir", "docdir", NULL};
50 /* Helper functions
51 *---------------------------------------------------------------------------*/
53 /* Private functions
54 *---------------------------------------------------------------------------*/
56 static AnjutaToken *
57 anjuta_token_find_target_property_position (AmpTargetNode *target,
58 AnjutaTokenType type)
60 AnjutaToken *pos = NULL;
61 gboolean after = FALSE;
62 GList *list;
63 AmpGroupNode *group;
64 AnjutaToken *makefile;
66 group = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
68 /* Try to find a better position */
70 /* 1. With the other properties of the target */
71 list = amp_target_node_get_all_token (target);
72 if (list != NULL)
74 GList *link;
75 AnjutaTokenType best = 0;
77 for (link = list; link != NULL; link = g_list_next (link))
79 AnjutaToken *token = (AnjutaToken *)link->data;
80 AnjutaTokenType existing = anjuta_token_get_type (token);
82 if ((existing < AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) || (existing > AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
84 token = anjuta_token_list (token);
85 if (token != NULL) existing = anjuta_token_get_type (token);
88 if ((existing >= AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) && (existing <= AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
90 if (existing > type)
92 if ((best == 0) || ((existing - type) < best))
94 best = existing - type;
95 pos = token;
96 after = FALSE;
99 else
101 if ((best == 0) || ((type -existing) < best))
103 best = type - existing;
104 pos = token;
105 after = TRUE;
110 g_list_free (list);
114 /* 2. With properties of sibling targets */
115 if (pos == NULL)
117 AnjutaProjectNode *prev = ANJUTA_PROJECT_NODE (target);
118 AnjutaProjectNode *next = ANJUTA_PROJECT_NODE (target);
119 AmpTargetNode *sibling;
120 AnjutaTokenFile *makefile;
121 AnjutaToken *target_list = NULL;
122 GList *link;
124 link = amp_target_node_get_token (target, ANJUTA_TOKEN_ARGUMENT);
125 if ((link != NULL) && (link->data != NULL))
127 target_list = anjuta_token_list ((AnjutaToken *)link->data);
130 makefile = amp_group_node_get_make_token_file (group);
132 if (makefile != NULL)
134 after = TRUE;
135 while ((prev != NULL) || (next != NULL))
137 /* Find sibling */
138 if (after)
140 while (prev != NULL)
142 prev = anjuta_project_node_prev_sibling (prev);
143 if (anjuta_project_node_get_node_type (prev) == ANJUTA_PROJECT_TARGET) break;
145 sibling = AMP_TARGET_NODE (prev);
147 else
149 while (next != NULL)
151 next = anjuta_project_node_next_sibling (next);
152 if (anjuta_project_node_get_node_type (next) == ANJUTA_PROJECT_TARGET) break;
154 sibling = AMP_TARGET_NODE (next);
156 list = sibling == NULL ? NULL : amp_target_node_get_all_token (sibling);
158 /* Check that the target is in the same list */
159 if ((list != NULL) && (target_list != NULL))
161 AnjutaToken *token;
163 link = amp_target_node_get_token (sibling, ANJUTA_TOKEN_ARGUMENT);
164 if ((link != NULL) && (link->data != NULL))
166 token = anjuta_token_list ((AnjutaToken *)link->data);
169 if ((token != NULL) && (target_list != token))
171 /* Target is in another list, do not use it, nor following ones */
172 list = NULL;
173 if (after)
175 prev = NULL;
177 else
179 next = NULL;
184 if (list != NULL)
186 gsize best = 0;
188 for (link = list; link != NULL; link = g_list_next (link))
190 AnjutaToken *token = (AnjutaToken *)link->data;
191 AnjutaTokenType existing = anjuta_token_get_type (token);
193 if ((existing < AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) || (existing > AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
195 token = anjuta_token_list (token);
196 if (token != NULL) existing = anjuta_token_get_type (token);
199 if ((existing >= AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) && (existing <= AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
201 gsize tpos;
203 tpos = anjuta_token_file_get_token_position (makefile, token);
205 if ((best == 0) ||
206 (after && (tpos > best)) ||
207 (!after && (tpos < best)))
209 pos = token;
210 best = tpos;
214 g_list_free (list);
215 list = NULL;
217 if (best != 0) break;
220 after = after ? FALSE : TRUE;
226 /* 3. After target declaration */
227 if (pos == NULL)
229 list = amp_target_node_get_token (AMP_TARGET_NODE (target), ANJUTA_TOKEN_ARGUMENT);
230 if (list != NULL)
232 pos = (AnjutaToken *)list->data;
233 if (pos != NULL)
235 pos = anjuta_token_list (pos);
236 if (pos != NULL)
238 pos = anjuta_token_list (pos);
242 after = TRUE;
245 /* 4. At the end of the file */
246 if (pos == NULL)
248 makefile = amp_group_node_get_makefile_token (group);
250 for (pos = anjuta_token_first_item (makefile); (pos != NULL) && (anjuta_token_next_item (pos) != NULL); pos = anjuta_token_next_item (pos));
252 after = TRUE;
255 /* 5. Create new file */
256 if (pos == NULL)
258 /* Empty file */
259 pos = anjuta_token_new_string (ANJUTA_TOKEN_COMMENT | ANJUTA_TOKEN_ADDED, "## Process this file with automake to produce Makefile.in\n");
260 anjuta_token_append_child (makefile, pos);
261 amp_group_node_update_makefile (group, pos);
265 /* Find end of line */
266 if (after)
268 while (pos != NULL)
270 if (anjuta_token_get_type (pos) == ANJUTA_TOKEN_EOL) break;
271 if (anjuta_token_next (pos) == NULL)
273 pos = anjuta_token_insert_token_list (after, pos,
274 ANJUTA_TOKEN_EOL, "\n",
275 NULL);
277 break;
279 pos = anjuta_token_next (pos);
283 pos = anjuta_token_insert_token_list (after, pos,
284 ANJUTA_TOKEN_EOL, "\n",
285 NULL);
286 pos = anjuta_token_insert_token_list (after, pos,
287 ANJUTA_TOKEN_EOL, "\n",
288 NULL);
289 amp_group_node_update_makefile (group, pos);
292 return pos;
295 static AnjutaToken *
296 anjuta_token_find_group_property_position (AmpGroupNode *group,
297 AnjutaTokenType type)
299 AnjutaToken *pos = NULL;
300 gboolean after = FALSE;
301 GList *list;
302 AnjutaToken *makefile;
305 /* Try to find a better position */
307 /* 1. With the other properties of the group */
308 list = amp_group_node_get_all_token (group);
309 if (list != NULL)
311 GList *link;
312 AnjutaTokenType best = 0;
314 for (link = list; link != NULL; link = g_list_next (link))
316 AnjutaToken *token = (AnjutaToken *)link->data;
317 AnjutaTokenType existing = anjuta_token_get_type (token);
319 if ((existing < AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) || (existing > AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
321 token = anjuta_token_list (token);
322 if (token != NULL) existing = anjuta_token_get_type (token);
325 if ((existing >= AM_TOKEN_FIRST_ORDERED_TARGET_MACRO) && (existing <= AM_TOKEN_LAST_ORDERED_TARGET_MACRO))
327 if (existing > type)
329 if ((best == 0) || ((existing - type) < best))
331 best = existing - type;
332 pos = token;
333 after = FALSE;
336 else
338 if ((best == 0) || ((type -existing) < best))
340 best = type - existing;
341 pos = token;
342 after = TRUE;
347 g_list_free (list);
350 /* 2. At the end of the file */
351 if (pos == NULL)
353 makefile = amp_group_node_get_makefile_token (group);
355 for (pos = anjuta_token_first_item (makefile); (pos != NULL) && (anjuta_token_next_item (pos) != NULL); pos = anjuta_token_next_item (pos));
357 after = TRUE;
360 /* 3. Create new file */
361 if (pos == NULL)
363 /* Empty file */
364 pos = anjuta_token_new_string (ANJUTA_TOKEN_COMMENT | ANJUTA_TOKEN_ADDED, "## Process this file with automake to produce Makefile.in\n");
365 anjuta_token_append_child (makefile, pos);
366 amp_group_node_update_makefile (group, pos);
369 /* Find end of line */
370 if (after)
372 while (pos != NULL)
374 if (anjuta_token_get_type (pos) == ANJUTA_TOKEN_EOL) break;
375 if (anjuta_token_next (pos) == NULL)
377 pos = anjuta_token_insert_token_list (after, pos,
378 ANJUTA_TOKEN_EOL, "\n",
379 NULL);
381 break;
383 pos = anjuta_token_next (pos);
387 pos = anjuta_token_insert_token_list (after, pos,
388 ANJUTA_TOKEN_EOL, "\n",
389 NULL);
390 pos = anjuta_token_insert_token_list (after, pos,
391 ANJUTA_TOKEN_EOL, "\n",
392 NULL);
393 amp_group_node_update_makefile (group, pos);
396 return pos;
400 /* Public functions
401 *---------------------------------------------------------------------------*/
403 static AnjutaToken *
404 amp_project_write_config_list (AmpProject *project)
406 AnjutaToken *pos;
407 AnjutaToken *token;
408 static gint output_type[] = {AC_TOKEN_AC_OUTPUT, 0};
409 static gint eol_type[] = {ANJUTA_TOKEN_EOL, ANJUTA_TOKEN_SPACE, ANJUTA_TOKEN_COMMENT, 0};
410 AnjutaToken *configure;
412 configure = amp_project_get_configure_token (project);
413 pos = anjuta_token_find_type (configure, 0, output_type);
414 if (pos == NULL)
416 gint other_type[] = {AC_TOKEN_AC_INIT,
417 AC_TOKEN_PKG_CHECK_MODULES,
418 AC_TOKEN_AC_CONFIG_FILES,
419 AC_TOKEN_OBSOLETE_AC_OUTPUT,
420 AC_TOKEN_AC_PREREQ,
423 pos = anjuta_token_find_type (configure, ANJUTA_TOKEN_SEARCH_LAST, other_type);
424 if (pos == NULL)
426 pos = anjuta_token_skip_comment (configure);
428 else
430 AnjutaToken* next;
432 next = anjuta_token_find_type (pos, ANJUTA_TOKEN_SEARCH_NOT, eol_type);
437 token = anjuta_token_insert_token_list (FALSE, pos,
438 AC_TOKEN_AC_CONFIG_FILES, "AC_CONFIG_FILES(",
439 ANJUTA_TOKEN_LIST, NULL,
440 ANJUTA_TOKEN_LAST, NULL,
441 RIGHT_PAREN, ")",
442 NULL);
444 return token;
447 static AnjutaToken *
448 amp_project_write_config_file (AmpProject *project, AnjutaToken *list, gboolean after, AnjutaToken *sibling, const gchar *filename)
450 AnjutaToken *token;
452 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, filename);
453 //fprintf (stdout, "Dump config list:\n");
454 //anjuta_token_dump (list);
455 if (after)
457 anjuta_token_insert_word_after (list, sibling, token);
459 else
461 anjuta_token_insert_word_before (list, sibling, token);
463 //fprintf (stdout, "Dump config list after insertion:\n");
464 //anjuta_token_dump (list);
466 anjuta_token_style_format (project->ac_space_list, list);
468 //fprintf (stdout, "Dump config list after format:\n");
469 //anjuta_token_dump (list);
471 amp_project_update_configure (project, list);
473 return token;
477 /* Target objects
478 *---------------------------------------------------------------------------*/
480 gboolean
481 amp_group_node_create_token (AmpProject *project, AmpGroupNode *group, GError **error)
483 GFile *directory;
484 GFile *makefile;
485 AnjutaToken *list;
486 gchar *basename;
487 AnjutaTokenFile* tfile;
488 AnjutaProjectNode *sibling;
489 AmpGroupNode *parent;
490 gboolean after;
491 const gchar *name;
493 /* Get parent target */
494 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type(ANJUTA_PROJECT_NODE (group), ANJUTA_PROJECT_GROUP));
495 name = anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (group));
496 directory = g_file_get_child (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (parent)), name);
498 /* Find a sibling if possible */
499 after = TRUE;
500 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (group)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
502 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_GROUP) break;
504 if (sibling == NULL)
506 after = FALSE;
507 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (group)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
509 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_GROUP) break;
512 if (sibling == NULL) after = TRUE;
514 /* Create directory */
515 g_file_make_directory (directory, NULL, NULL);
517 /* Create Makefile.am */
518 basename = amp_group_node_get_makefile_name (parent);
519 if (basename != NULL)
521 makefile = g_file_get_child (directory, basename);
522 g_free (basename);
524 else
526 makefile = g_file_get_child (directory, "Makefile.am");
528 g_file_replace_contents (makefile, "", 0, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
531 /* Add in configure */
532 list = NULL;
533 if (sibling) list = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_CONFIGURE);
534 if (list == NULL) list= amp_group_node_get_first_token (parent, AM_GROUP_TOKEN_CONFIGURE);
535 if (list != NULL) list = anjuta_token_list (list);
536 if (list == NULL)
538 list = amp_project_write_config_list (project);
539 list = anjuta_token_next (list);
541 if (list != NULL)
543 gchar *relative_make;
544 gchar *ext;
545 AnjutaToken *prev = NULL;
546 AnjutaToken *token;
548 if (sibling)
550 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_CONFIGURE);
551 /*if ((prev != NULL) && after)
553 prev = anjuta_token_next_word (prev);
556 //prev_token = (AnjutaToken *)token_list->data;
558 relative_make = g_file_get_relative_path (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project)), makefile);
559 ext = relative_make + strlen (relative_make) - 3;
560 if (strcmp (ext, ".am") == 0)
562 *ext = '\0';
564 token = amp_project_write_config_file (project, list, after, prev, relative_make);
565 amp_group_node_add_token (AMP_GROUP_NODE (group), token, AM_GROUP_TOKEN_CONFIGURE);
566 g_free (relative_make);
569 /* Add in Makefile.am */
570 if (sibling == NULL)
572 list = anjuta_token_find_group_property_position (parent, AM_TOKEN_SUBDIRS);
574 list = anjuta_token_insert_token_list (FALSE, list,
575 AM_TOKEN_SUBDIRS, "SUBDIRS",
576 ANJUTA_TOKEN_SPACE, " ",
577 ANJUTA_TOKEN_OPERATOR, "=",
578 ANJUTA_TOKEN_LIST, NULL,
579 ANJUTA_TOKEN_LAST, NULL,
580 NULL);
581 list = anjuta_token_next (anjuta_token_next ( anjuta_token_next (list)));
583 else
585 AnjutaToken *prev;
587 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_SUBDIRS);
588 list = anjuta_token_list (prev);
591 if (list != NULL)
593 AnjutaToken *token;
594 AnjutaToken *prev;
595 AnjutaTokenStyle *style;
597 style = anjuta_token_style_new_from_base (project->am_space_list);
598 anjuta_token_style_update (style, list);
600 if (sibling)
602 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_SUBDIRS);
605 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
606 if (after)
608 anjuta_token_insert_word_after (list, prev, token);
610 else
612 anjuta_token_insert_word_before (list, prev, token);
615 /* Try to use the same style than the current group list */
616 anjuta_token_style_format (style, list);
617 anjuta_token_style_free (style);
619 amp_group_node_update_makefile (parent, token);
621 amp_group_node_add_token (group, token, AM_GROUP_TOKEN_SUBDIRS);
624 tfile = amp_group_node_set_makefile (group, makefile, project);
625 amp_project_add_file (project, makefile, tfile);
627 return TRUE;
630 gboolean
631 amp_group_node_delete_token (AmpProject *project, AmpGroupNode *group, GError **error)
633 GList *item;
634 AnjutaProjectNode *parent;
636 /* Get parent group */
637 parent = anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (group), ANJUTA_PROJECT_GROUP);
638 if (parent == NULL) return FALSE;
640 for (item = amp_group_node_get_token (group, AM_GROUP_TOKEN_SUBDIRS); item != NULL; item = g_list_next (item))
642 AnjutaToken *token = (AnjutaToken *)item->data;
643 AnjutaTokenStyle *style;
644 AnjutaToken *list;
646 list = anjuta_token_list (token);
648 /* Try to use the same style than the current target list */
649 style = anjuta_token_style_new_from_base (project->am_space_list);
650 anjuta_token_style_update (style, list);
652 anjuta_token_remove_word (token);
653 anjuta_token_style_format (style, list);
654 anjuta_token_style_free (style);
656 /* Remove whole variable if empty */
657 if (anjuta_token_first_word (list) == NULL)
659 anjuta_token_remove_list (anjuta_token_list (list));
662 amp_group_node_update_makefile (AMP_GROUP_NODE (parent), list);
665 /* Remove from configure file */
666 for (item = amp_group_node_get_token (group, AM_GROUP_TOKEN_CONFIGURE); item != NULL; item = g_list_next (item))
668 AnjutaToken *token = (AnjutaToken *)item->data;
669 AnjutaToken *args;
670 AnjutaTokenStyle *style;
672 args = anjuta_token_list (token);
674 /* Try to use the same style than the current group list */
675 style = anjuta_token_style_new_from_base (project->ac_space_list);
676 anjuta_token_style_update (style, args);
678 anjuta_token_remove_word (token);
680 anjuta_token_style_format (style, args);
681 anjuta_token_style_free (style);
683 amp_project_update_configure (project, args);
686 return TRUE;
690 /* Target objects
691 *---------------------------------------------------------------------------*/
693 static AnjutaToken *
694 amp_project_write_target (AmpGroupNode *group, gint type, const gchar *name, gboolean after, AnjutaToken* sibling)
696 AnjutaToken *pos = sibling;
698 if (pos != NULL)
700 /* Find top level parent */
703 AnjutaTokenType type = anjuta_token_get_type (pos);
705 if ((type >= AM_TOKEN_FIRST_ORDERED_MACRO) && (type <= AM_TOKEN_LAST_ORDERED_MACRO)) break;
706 pos = anjuta_token_list (pos);
708 while (pos != NULL);
710 if (pos != NULL)
712 /* Add target just near sibling target */
713 pos = anjuta_token_insert_token_list (after, pos,
714 ANJUTA_TOKEN_EOL, "\n",
715 NULL);
716 pos = anjuta_token_insert_token_list (after, pos,
717 ANJUTA_TOKEN_EOL, "\n",
718 NULL);
719 amp_group_node_update_makefile (group, pos);
723 if (pos == NULL)
725 /* Find ordered position in Makefile.am */
726 pos = anjuta_token_find_group_property_position (group, type);
729 pos = anjuta_token_insert_token_list (after, pos,
730 ANJUTA_TOKEN_LIST, NULL,
731 type, name,
732 ANJUTA_TOKEN_SPACE, " ",
733 ANJUTA_TOKEN_OPERATOR, "=",
734 ANJUTA_TOKEN_LIST, NULL,
735 ANJUTA_TOKEN_SPACE, " ",
736 NULL);
737 pos = anjuta_token_last_item (pos);
738 amp_group_node_update_makefile (group, pos);
740 /* Return list token */
741 return pos;
744 static AnjutaToken *
745 amp_target_add_in_list (AmpProject *project, AnjutaToken *list, AnjutaProjectNode *target, gboolean after, AnjutaToken* sibling)
747 AnjutaTokenStyle *style;
748 AnjutaToken *token;
749 AmpGroupNode *parent;
751 g_return_val_if_fail (list != NULL, NULL);
753 /* Get parent target */
754 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (target, ANJUTA_PROJECT_GROUP));
756 style = anjuta_token_style_new_from_base (project->am_space_list);
757 anjuta_token_style_update (style, list);
759 token = anjuta_token_new_string (ANJUTA_TOKEN_ARGUMENT | ANJUTA_TOKEN_ADDED, anjuta_project_node_get_name (target));
760 if (after)
762 anjuta_token_insert_word_after (list, sibling, token);
764 else
766 anjuta_token_insert_word_before (list, sibling, token);
769 /* Try to use the same style than the current target list */
770 anjuta_token_style_format (style, list);
771 anjuta_token_style_free (style);
773 amp_group_node_update_makefile (parent, token);
775 amp_target_node_add_token (AMP_TARGET_NODE (target), ANJUTA_TOKEN_ARGUMENT, token);
777 return token;
781 gboolean
782 amp_target_node_create_token (AmpProject *project, AmpTargetNode *target, GError **error)
784 AnjutaToken *args;
785 AnjutaToken *var;
786 AnjutaToken *prev;
787 AmpNodeInfo *info;
788 gchar *targetname;
789 const gchar *name;
790 GList *last;
791 AnjutaProjectNode *sibling;
792 AmpGroupNode *parent;
793 gboolean after;
795 /* Get parent target */
796 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
798 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (ANJUTA_PROJECT_NODE (target)));
799 name = anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (target));
801 /* Find a sibling if possible */
802 after = TRUE;
803 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (target)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
805 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_TARGET) break;
807 if (sibling == NULL)
809 after = FALSE;
810 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (target)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
812 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_TARGET) break;
815 if (sibling == NULL) after = TRUE;
817 /* Add in Makefile.am */
818 targetname = g_strconcat (info->install, "_", info->prefix, NULL);
820 // Get token corresponding to sibling and check if the target are compatible
821 args = NULL;
822 var = NULL;
823 prev = NULL;
824 if (sibling != NULL)
826 last = amp_target_node_get_token (AMP_TARGET_NODE (sibling), ANJUTA_TOKEN_ARGUMENT);
828 if (last != NULL)
830 AnjutaToken *token = (AnjutaToken *)last->data;
832 /* Check that the sibling is of the same kind */
833 token = anjuta_token_list (token);
834 if (token != NULL)
836 token = anjuta_token_list (token);
837 var = token;
838 if (token != NULL)
840 token = anjuta_token_first_item (token);
841 if (token != NULL)
843 gchar *value;
845 value = anjuta_token_evaluate (token);
847 if ((value != NULL) && (strcmp (targetname, value) == 0))
849 g_free (value);
850 prev = (AnjutaToken *)last->data;
851 args = anjuta_token_list (prev);
860 /* Check if a valid target variable is already defined */
861 if (args == NULL)
863 for (last = amp_group_node_get_token (parent, AM_GROUP_TARGET); last != NULL; last = g_list_next (last))
865 gchar *value = anjuta_token_evaluate (anjuta_token_first_word ((AnjutaToken *)last->data));
867 if ((value != NULL) && (strcmp (targetname, value) == 0))
869 g_free (value);
870 args = anjuta_token_last_item ((AnjutaToken *)last->data);
871 break;
873 g_free (value);
878 if (args == NULL)
880 args = amp_project_write_target (parent, info->token, targetname, FALSE, NULL);
882 g_free (targetname);
884 switch (anjuta_project_node_get_full_type (ANJUTA_PROJECT_NODE (target)) & ANJUTA_PROJECT_ID_MASK)
886 case ANJUTA_PROJECT_SHAREDLIB:
887 case ANJUTA_PROJECT_STATICLIB:
888 case ANJUTA_PROJECT_LT_MODULE:
889 case ANJUTA_PROJECT_PROGRAM:
890 amp_target_add_in_list (project, args, ANJUTA_PROJECT_NODE (target), after, prev);
891 break;
892 default:
893 if (args != NULL)
895 amp_target_node_add_token (target, AM_TOKEN__SOURCES, args);
897 break;
900 return TRUE;
903 gboolean
904 amp_target_node_delete_token (AmpProject *project, AmpTargetNode *target, GList *list, GError **error)
906 GList *item;
907 GList *removed_dir = NULL;
908 AmpGroupNode *parent;
910 /* Get parent group */
911 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
913 /* Remove all associated token */
914 for (item = list; item != NULL; item = g_list_next (item))
916 AnjutaToken *token = (AnjutaToken *)item->data;
917 AnjutaTokenStyle *style;
918 AnjutaToken *list;
920 switch (anjuta_token_get_type (token))
922 case ANJUTA_TOKEN_ARGUMENT:
924 list = anjuta_token_list (token);
926 /* Try to use the same style than the current target list */
927 style = anjuta_token_style_new_from_base (project->am_space_list);
928 anjuta_token_style_update (style, list);
930 anjuta_token_remove_word (token);
931 anjuta_token_style_format (style, list);
932 anjuta_token_style_free (style);
934 /* Remove whole variable if empty */
935 if (anjuta_token_first_word (list) == NULL)
937 AnjutaToken *variable = anjuta_token_list (list);
938 gchar *value;
939 gint flags;
940 gchar *install = NULL;
942 value = anjuta_token_evaluate (anjuta_token_first_word (variable));
943 split_automake_variable (value, &flags, &install, NULL);
945 if (install != NULL)
947 /* Mark all removed directory, normally only one */
948 removed_dir = g_list_prepend (removed_dir, g_strdup (install));
950 g_free (value);
951 anjuta_token_remove_list (variable);
954 amp_group_node_update_makefile (parent, list);
956 break;
957 case AM_TOKEN__SOURCES:
958 case AM_TOKEN__DATA:
959 case AM_TOKEN__HEADERS:
960 case AM_TOKEN__LISP:
961 case AM_TOKEN__MANS:
962 case AM_TOKEN__PYTHON:
963 case AM_TOKEN__JAVA:
964 case AM_TOKEN__SCRIPTS:
965 case AM_TOKEN__TEXINFOS:
966 case AM_TOKEN_TARGET_LDFLAGS:
967 case AM_TOKEN_TARGET_CPPFLAGS:
968 case AM_TOKEN_TARGET_CFLAGS:
969 case AM_TOKEN_TARGET_CXXFLAGS:
970 case AM_TOKEN_TARGET_JAVACFLAGS:
971 case AM_TOKEN_TARGET_VALAFLAGS:
972 case AM_TOKEN_TARGET_FCFLAGS:
973 case AM_TOKEN_TARGET_OBJCFLAGS:
974 case AM_TOKEN_TARGET_LFLAGS:
975 case AM_TOKEN_TARGET_YFLAGS:
976 case AM_TOKEN_TARGET_DEPENDENCIES:
977 case AM_TOKEN_TARGET_LIBADD:
978 case AM_TOKEN_TARGET_LDADD:
979 anjuta_token_remove_list (token);
980 amp_group_node_update_makefile (parent, token);
981 break;
983 amp_target_node_remove_token (target, token);
986 /* Check if we need to remove dir variable */
987 for (item = removed_dir; item != NULL; item = g_list_next(item))
989 gchar* dir = (gchar *)item->data;
990 GList *list;
992 /* Check if dir is used in another target */
993 for (list = amp_group_node_get_token (parent, AM_GROUP_TARGET); list != NULL; list = g_list_next (list))
995 AnjutaToken *target_list = (AnjutaToken *)list->data;
996 gchar *value;
997 gint flags;
998 gchar *install = NULL;
999 gboolean same;
1001 value = anjuta_token_evaluate (anjuta_token_first_word (target_list));
1002 /* value can be NULL if we have a list can has just been removed */
1003 if (value != NULL) split_automake_variable (value, &flags, &install, NULL);
1005 same = g_strcmp0 (install, dir) == 0;
1006 g_free (value);
1008 if (same)
1010 /* directory use elsewhere */
1012 g_free (dir);
1013 dir = NULL;
1014 break;
1018 if (dir != NULL)
1020 /* Directory is not used anymore, remove variable */
1021 gchar* install = g_strconcat (dir, "dir", NULL);
1023 for (list = anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE(parent)); list != NULL; list = g_list_next (list))
1025 AmpProperty *prop = (AmpProperty *)list->data;
1027 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN_DIR) &&
1028 (g_strcmp0(prop->base.name, install) == 0))
1030 AnjutaProjectProperty *new_prop;
1032 new_prop = amp_node_map_property_set (ANJUTA_PROJECT_NODE (parent), prop->base.info->id, prop->base.name, NULL);
1033 amp_project_update_am_property (project, ANJUTA_PROJECT_NODE (parent), new_prop);
1036 g_free (install);
1037 g_free (dir);
1040 g_list_free (removed_dir);
1043 return TRUE;
1048 /* Source objects
1049 *---------------------------------------------------------------------------*/
1052 /* Source objects
1053 *---------------------------------------------------------------------------*/
1055 gboolean
1056 amp_source_node_create_token (AmpProject *project, AmpSourceNode *source, GError **error)
1058 AmpGroupNode *group;
1059 AmpTargetNode *target;
1060 AnjutaProjectNode *sibling;
1061 gboolean after;
1062 AnjutaToken *token;
1063 AnjutaToken *prev;
1064 AnjutaToken *args;
1065 gchar *relative_name;
1067 /* Get parent target */
1068 target = AMP_TARGET_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (source), ANJUTA_PROJECT_TARGET));
1069 if (target == NULL) return FALSE;
1071 group = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
1072 relative_name = get_relative_path (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (group)), anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (source)));
1074 /* Add in Makefile.am */
1075 /* Find a sibling if possible */
1076 after = TRUE;
1077 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (source)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
1079 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_SOURCE)
1081 break;
1083 else if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_OBJECT)
1085 sibling = anjuta_project_node_first_child (sibling);
1086 break;
1089 if (sibling == NULL)
1091 after = FALSE;
1092 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (source)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
1094 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_SOURCE)
1096 break;
1098 else if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_OBJECT)
1100 sibling = anjuta_project_node_first_child (sibling);
1101 break;
1105 if (sibling == NULL)
1107 after = TRUE;
1108 prev = NULL;
1109 args = NULL;
1111 else
1113 prev = amp_source_node_get_token (AMP_SOURCE_NODE (sibling));
1114 args = anjuta_token_list (prev);
1117 /* Check if a valid source variable is already defined */
1118 if (args == NULL)
1120 GList *last;
1121 for (last = amp_target_node_get_token (target, AM_TOKEN__SOURCES); last != NULL; last = g_list_next (last))
1123 args = anjuta_token_last_item ((AnjutaToken *)last->data);
1124 break;
1126 if (last == NULL)
1128 for (last = amp_target_node_get_token (target, AM_TOKEN__DATA); last != NULL; last = g_list_next (last))
1130 args = anjuta_token_last_item ((AnjutaToken *)last->data);
1131 break;
1137 if (args == NULL)
1139 gchar *target_var;
1140 gchar *canon_name;
1141 AnjutaToken *var;
1143 canon_name = canonicalize_automake_variable (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (target)));
1144 target_var = g_strconcat (canon_name, "_SOURCES", NULL);
1146 var = anjuta_token_find_target_property_position (target, AM_TOKEN__SOURCES);
1147 if (var == NULL)
1148 var = anjuta_token_find_target_property_position (target, AM_TOKEN__DATA);
1150 args = anjuta_token_insert_token_list (FALSE, var,
1151 ANJUTA_TOKEN_LIST, NULL,
1152 ANJUTA_TOKEN_NAME, target_var,
1153 ANJUTA_TOKEN_SPACE, " ",
1154 ANJUTA_TOKEN_OPERATOR, "=",
1155 ANJUTA_TOKEN_LIST, NULL,
1156 ANJUTA_TOKEN_SPACE, " ",
1157 NULL);
1159 args = anjuta_token_last_item (args);
1160 g_free (target_var);
1163 if (args != NULL)
1165 AnjutaTokenStyle *style;
1167 style = anjuta_token_style_new_from_base (project->am_space_list);
1168 anjuta_token_style_update (style, args);
1170 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, relative_name);
1171 if (after)
1173 anjuta_token_insert_word_after (args, prev, token);
1175 else
1177 anjuta_token_insert_word_before (args, prev, token);
1180 /* Try to use the same style than the current target list */
1181 anjuta_token_style_format (style, args);
1182 anjuta_token_style_free (style);
1184 amp_group_node_update_makefile (group, token);
1186 amp_source_node_add_token (source, token);
1189 return TRUE;
1192 gboolean
1193 amp_source_node_delete_token (AmpProject *project, AmpSourceNode *source, GError **error)
1195 AnjutaProjectNode *group;
1196 AnjutaToken *token;
1198 /* Get parent group */
1199 group = anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (source), ANJUTA_PROJECT_GROUP);
1200 if (group == NULL) return FALSE;
1202 token = amp_source_node_get_token (source);
1203 if (token != NULL)
1205 AnjutaTokenStyle *style;
1206 AnjutaToken *list;
1208 list = anjuta_token_list (token);
1210 /* Try to use the same style than the current target list */
1211 style = anjuta_token_style_new_from_base (project->am_space_list);
1212 anjuta_token_style_update (style, list);
1214 anjuta_token_remove_word (token);
1215 anjuta_token_style_format (style, list);
1216 anjuta_token_style_free (style);
1218 /* Remove whole variable if empty */
1219 if (anjuta_token_first_word (list) == NULL)
1221 anjuta_token_remove_list (anjuta_token_list (list));
1224 amp_group_node_update_makefile (AMP_GROUP_NODE (group), list);
1227 return TRUE;
1231 /* Properties
1232 *---------------------------------------------------------------------------*/
1234 static AnjutaToken*
1235 amp_property_delete_token (AmpProject *project, AnjutaToken *token)
1237 gboolean updated = FALSE;
1239 if (token != NULL)
1241 anjuta_token_remove_list (anjuta_token_list (token));
1243 updated = TRUE;
1246 return token;
1249 static AnjutaToken *
1250 amp_project_write_property_list (AmpGroupNode *group, AnjutaProjectNode *node, AmpPropertyInfo *info)
1252 AnjutaToken *pos;
1253 gchar *name;
1255 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_GROUP)
1257 /* Group property */
1258 name = g_strdup (info->suffix);
1260 pos = anjuta_token_find_group_property_position (AMP_GROUP_NODE (node), info->token_type);
1262 else
1264 /* Target property */
1265 gchar *canon_name;
1267 canon_name = canonicalize_automake_variable (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (node)));
1268 name = g_strconcat (canon_name, info->suffix, NULL);
1269 g_free (canon_name);
1271 pos = anjuta_token_find_target_property_position (AMP_TARGET_NODE (node), info->token_type);
1274 pos = anjuta_token_insert_token_list (FALSE, pos,
1275 info->token_type, NULL,
1276 ANJUTA_TOKEN_NAME, name,
1277 ANJUTA_TOKEN_SPACE, " ",
1278 ANJUTA_TOKEN_OPERATOR, "=",
1279 ANJUTA_TOKEN_SPACE, " ",
1280 ANJUTA_TOKEN_LIST, NULL,
1281 ANJUTA_TOKEN_SPACE, " ",
1282 NULL);
1284 g_free (name);
1286 return anjuta_token_last_item (pos);
1289 static gint
1290 compare_property_position (gconstpointer a, gconstpointer b)
1292 return ((const AmpPropertyInfo *)a)->position - ((const AmpPropertyInfo *)b)->position;
1295 static AnjutaToken *
1296 amp_property_rename_target (AmpProject *project, AnjutaProjectNode *node)
1298 AnjutaProjectNode *group;
1299 GList *infos;
1300 GList *item;
1301 GString *new_name;
1302 AmpNodeInfo *info;
1303 GList *list;
1304 AnjutaToken *update = NULL;
1305 AnjutaToken *existing_target_list;
1306 gboolean after;
1307 gchar *target_dir;
1309 g_return_val_if_fail (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_TARGET, NULL);
1311 group = anjuta_project_node_parent_type (node, ANJUTA_PROJECT_GROUP);
1313 /* Find all program properties */
1314 infos = NULL;
1315 for (item = anjuta_project_node_get_properties_info (node); item != NULL; item = g_list_next (item))
1317 AmpPropertyInfo *info = (AmpPropertyInfo *)item->data;
1319 if (info->token_type == AM_TOKEN__PROGRAMS)
1321 infos = g_list_insert_sorted (infos, info, compare_property_position);
1325 /* Create new name */
1326 new_name = g_string_new (NULL);
1327 for (item = infos; item != NULL; item = g_list_next (item))
1329 AmpPropertyInfo *info = (AmpPropertyInfo *)item->data;
1330 AmpProperty *prop;
1332 /* Check if property is enabled by another property */
1333 if (info->link != NULL)
1335 AnjutaProjectProperty *en_prop;
1337 en_prop = anjuta_project_node_get_property (node, info->link->id);
1339 if ((en_prop->value != NULL) && (*en_prop->value == '1')) continue;
1342 prop = (AmpProperty *)anjuta_project_node_get_property (node, info->base.id);
1343 if ((prop == (AmpProperty *)info->base.default_value) || (g_strcmp0 (prop->base.value, info->base.default_value->value) == 0))
1345 /* Default value, add only string properties */
1346 if (info->base.type == ANJUTA_PROJECT_PROPERTY_STRING)
1348 g_string_append (new_name, info->suffix);
1349 g_string_append_c (new_name, '_');
1352 else
1354 switch (info->base.type)
1356 case ANJUTA_PROJECT_PROPERTY_STRING:
1357 if ((info->flags & AM_PROPERTY_DIRECTORY) &&
1358 (strlen (prop->base.value) > 4) &&
1359 (strcmp (prop->base.value + strlen (prop->base.value) - 3, "dir") == 0))
1361 /* Remove "dir" suffix */
1362 g_string_append_len (new_name, prop->base.value, strlen (prop->base.value) - 3);
1364 else
1366 g_string_append (new_name, prop->base.value);
1368 g_string_append_c (new_name, '_');
1369 break;
1370 case ANJUTA_PROJECT_PROPERTY_BOOLEAN:
1371 if ((prop->base.value != NULL) && (g_strcmp0 (prop->base.value, info->base.default_value->value) != 0))
1373 g_string_append (new_name, info->suffix);
1375 break;
1376 default:
1377 break;
1382 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (node));
1383 g_string_append (new_name, info->prefix);
1386 // Check if the target already exist.
1387 after = TRUE;
1388 for (item = amp_group_node_get_token (AMP_GROUP_NODE (group), AM_GROUP_TARGET); item != NULL; item = g_list_next (item))
1390 existing_target_list = (AnjutaToken *)item->data;
1391 gchar *target_name = anjuta_token_evaluate (anjuta_token_first_word (existing_target_list));
1392 gboolean same;
1394 same = strcmp (target_name, new_name->str) == 0;
1395 g_free (target_name);
1397 if (after)
1399 GList *list;
1400 GList *item;
1402 list = amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT);
1403 for (item = g_list_first (list); item != NULL; item = g_list_next (item))
1405 AnjutaToken *arg = (AnjutaToken *)item->data;
1406 AnjutaToken *target_list;
1408 if (arg != NULL)
1410 target_list = anjuta_token_list (arg);
1411 if (anjuta_token_list (target_list) == existing_target_list)
1413 /* token in group_node are stored in reverse order */
1414 after = FALSE;
1415 break;
1421 if (same)
1423 existing_target_list = anjuta_token_last_item (existing_target_list);
1424 break;
1426 existing_target_list = NULL;
1429 if (existing_target_list != NULL)
1431 GList *token_list;
1433 /* Get old tokens */
1434 token_list = g_list_copy (amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT));
1436 /* Add target in already existing list */
1437 amp_target_add_in_list (project, existing_target_list, node, after, NULL);
1439 /* Remove old token */
1440 amp_target_node_delete_token (project, AMP_TARGET_NODE (node), token_list, NULL);
1441 g_list_free (token_list);
1443 else
1445 list = amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT);
1446 for (item = g_list_first (list); item != NULL; item = g_list_next (item))
1448 AnjutaToken *arg = (AnjutaToken *)item->data;
1449 AnjutaToken *target_list;
1451 if (arg == NULL) continue;
1453 target_list = anjuta_token_list (arg);
1455 if (anjuta_token_nth_word (target_list, 1) == NULL)
1457 /* Only one target in list, just replace list name */
1458 AnjutaToken *target_variable = anjuta_token_list (target_list);
1460 if (target_variable != NULL)
1462 AnjutaToken *old_token;
1464 old_token = anjuta_token_first_word (target_variable);
1465 if (old_token != NULL)
1467 AnjutaToken *token;
1469 token = anjuta_token_new_string (ANJUTA_TOKEN_ADDED, new_name->str);
1470 update = anjuta_token_insert_word_after (target_variable, old_token, token);
1471 anjuta_token_remove_word (old_token);
1472 update = target_variable;
1476 else
1478 gchar *old_target;
1479 AmpNodeInfo *info;
1480 gboolean after = TRUE;
1481 AnjutaToken *sibling = NULL;
1482 AnjutaTokenStyle *style;
1483 AnjutaToken *token;
1485 old_target = anjuta_token_evaluate (arg);
1487 /* Find sibling target */
1488 if (anjuta_token_first_word (target_list) == arg)
1490 sibling = anjuta_token_next_word (arg);
1491 after = FALSE;
1493 else
1495 for (sibling = anjuta_token_first_word (target_list); sibling != NULL; sibling = anjuta_token_next_word (sibling))
1497 if (anjuta_token_next_word (sibling) == arg) break;
1499 after = TRUE;
1502 /* More than one target, remove target in list */
1503 arg = anjuta_token_remove_word (arg);
1504 if (arg != NULL) amp_group_node_update_makefile (AMP_GROUP_NODE (group), arg);
1507 /* Add target in new list */
1508 style = anjuta_token_style_new_from_base (project->am_space_list);
1509 anjuta_token_style_update (style, target_list);
1511 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (node));
1512 target_list = amp_project_write_target (AMP_GROUP_NODE (group), info->token, new_name->str, after, sibling);
1514 token = anjuta_token_new_string (ANJUTA_TOKEN_ARGUMENT | ANJUTA_TOKEN_ADDED, old_target);
1515 anjuta_token_insert_word_after (target_list, NULL, token);
1517 /* Try to use the same style than the current target list */
1518 anjuta_token_style_format (style, target_list);
1519 anjuta_token_style_free (style);
1521 amp_group_node_update_makefile (AMP_GROUP_NODE (group), token);
1522 amp_target_node_add_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT, token);
1524 g_free (old_target);
1526 update = anjuta_token_list (target_list);
1532 /* Add directory variable if needed */
1533 target_dir = NULL;
1534 for (item = anjuta_project_node_get_properties (node); item != NULL; item = g_list_next (item))
1536 AmpProperty *prop = (AmpProperty *)item->data;
1538 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN__PROGRAMS) && (((AmpPropertyInfo *)prop->base.info)->flags & AM_PROPERTY_DIRECTORY))
1540 target_dir = prop->base.value;
1541 if ((strlen (target_dir) <= 3) || (strcmp (target_dir + strlen(target_dir) - 3, "dir") != 0))
1543 target_dir = g_strconcat (target_dir, "dir", NULL);
1544 g_free (prop->base.value);
1545 prop->base.value = target_dir;
1547 break;
1551 /* If it is a standard directory do not add a variable*/
1552 if (target_dir != NULL)
1554 const gchar **std_dir;
1556 for (std_dir = AmpStandardDirectory; *std_dir != NULL; std_dir++)
1558 if (strcmp(*std_dir, target_dir) == 0)
1560 target_dir = NULL;
1561 break;
1566 if (target_dir != NULL)
1568 for (item = anjuta_project_node_get_properties (group); item != NULL; item = g_list_next (item))
1570 AmpProperty *prop = (AmpProperty *)item->data;
1572 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN_DIR) && (g_strcmp0 (prop->base.name, target_dir) == 0))
1574 /* Find already existing directory variable */
1575 target_dir = NULL;
1576 break;
1581 if ((update != NULL) && (target_dir != NULL))
1583 update = anjuta_token_insert_token_list (FALSE, update,
1584 AM_TOKEN_DIR, NULL,
1585 ANJUTA_TOKEN_NAME, target_dir,
1586 ANJUTA_TOKEN_SPACE, " ",
1587 ANJUTA_TOKEN_OPERATOR, "=",
1588 ANJUTA_TOKEN_SPACE, " ",
1589 ANJUTA_TOKEN_LIST, NULL,
1590 ANJUTA_TOKEN_SPACE, " ",
1591 ANJUTA_TOKEN_EOL, "\n",
1592 NULL);
1595 g_string_free (new_name, TRUE);
1598 return update;
1601 gboolean amp_project_update_am_property (AmpProject *project, AnjutaProjectNode *node, AnjutaProjectProperty *property)
1603 AnjutaProjectNode *group;
1604 AnjutaToken *args;
1606 /* Find group of the property */
1607 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_GROUP)
1609 group = node;
1611 else
1613 group = anjuta_project_node_parent_type (node, ANJUTA_PROJECT_GROUP);
1616 if (property->value == NULL)
1618 /* Remove property */
1619 if (((AmpPropertyInfo *)property->info)->token_type == AM_TOKEN__PROGRAMS)
1621 /* Properties added in the target name */
1622 args = amp_property_rename_target (project, node);
1624 else
1626 /* Other properties having their own variable */
1627 args = amp_property_delete_token (project, ((AmpProperty *)property)->token);
1630 anjuta_project_node_remove_property (node, property);
1632 else
1634 if (((AmpPropertyInfo *)property->info)->token_type == AM_TOKEN__PROGRAMS)
1636 /* Properties added in the target name */
1637 args = amp_property_rename_target (project, node);
1639 else
1641 /* Other properties having their own variable */
1642 GString *new_value;
1643 AnjutaToken *arg;
1644 AnjutaToken *token;
1645 const gchar *value;
1646 AnjutaTokenStyle *style;
1648 args = ((AmpProperty *)property)->token;
1650 /* Try to use the same style than the current target list */
1651 style = anjuta_token_style_new_from_base (project->am_space_list);
1652 anjuta_token_style_update (style, args);
1654 if (args == NULL)
1656 args = amp_project_write_property_list (AMP_GROUP_NODE (group), node, (AmpPropertyInfo *)property->info);
1657 ((AmpProperty *)property)->token = args;
1660 switch (property->info->type)
1662 case ANJUTA_PROJECT_PROPERTY_LIST:
1663 new_value = g_string_new (property->value);
1664 g_string_assign (new_value, "");
1665 value = property->value;
1667 for (arg = anjuta_token_first_word (args); arg != NULL;)
1669 gchar *arg_value = anjuta_token_evaluate (arg);
1671 while (isspace (*value)) value++;
1673 if (*value == '\0')
1675 AnjutaToken *next;
1677 next = anjuta_token_next_word (arg);
1678 anjuta_token_remove_word (arg);
1679 arg = next;
1681 else
1683 const gchar *end;
1684 gchar *name;
1686 for (end = value; !isspace (*end) && (*end != '\0'); end++);
1687 name = g_strndup (value, end - value);
1689 if (strcmp (arg_value, name) != 0)
1691 /* New argument in property list */
1692 AnjutaToken *token;
1694 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
1695 anjuta_token_insert_word_before (args, arg, token);
1697 else
1699 arg = anjuta_token_next_word (arg);
1701 value = end;
1703 if (arg_value != NULL)
1705 if (new_value->len != 0) g_string_append_c (new_value, ' ');
1706 g_string_append (new_value, name);
1709 g_free (arg_value);
1712 while (*value != '\0')
1714 AnjutaToken *token;
1715 const gchar *end;
1716 gchar *name;
1718 while (isspace (*value)) value++;
1719 if (*value == '\0') break;
1721 for (end = value; !isspace (*end) && (*end != '\0'); end++);
1723 name = g_strndup (value, end - value);
1724 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
1726 anjuta_token_insert_word_before (args, NULL, token);
1728 if (new_value->len != 0) g_string_append_c (new_value, ' ');
1729 g_string_append (new_value, name);
1731 g_free (name);
1732 value = end;
1735 anjuta_token_style_format (style, args);
1736 anjuta_token_style_free (style);
1738 g_free (property->value);
1739 property->value = g_string_free (new_value, FALSE);
1741 break;
1742 case ANJUTA_PROJECT_PROPERTY_MAP:
1744 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, property->value);
1745 anjuta_token_insert_word_after (args, NULL, token);
1747 for (token = anjuta_token_next_word (token); token != NULL; token = anjuta_token_next_word (token))
1749 anjuta_token_remove_word (token);
1751 break;
1752 default:
1753 break;
1758 if (args != NULL) amp_group_node_update_makefile (AMP_GROUP_NODE (group), args);
1760 return args != NULL ? TRUE : FALSE;