Added byline
[anjuta.git] / plugins / am-project / am-writer.c
blobba3e363bdde01f601082d90ae26cb311ab9401c8
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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, 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 /* makefile can be NULL for the root node if there isn't any corresponding Makefile.am */
361 if (makefile != NULL)
363 /* 3. Create new file */
364 if (pos == NULL)
366 /* Empty file */
367 pos = anjuta_token_new_string (ANJUTA_TOKEN_COMMENT | ANJUTA_TOKEN_ADDED, "## Process this file with automake to produce Makefile.in\n");
368 anjuta_token_append_child (makefile, pos);
369 amp_group_node_update_makefile (group, pos);
372 /* Find end of line */
373 if (after)
375 while (pos != NULL)
377 if (anjuta_token_get_type (pos) == ANJUTA_TOKEN_EOL) break;
378 if (anjuta_token_next (pos) == NULL)
380 pos = anjuta_token_insert_token_list (after, pos,
381 ANJUTA_TOKEN_EOL, "\n",
382 NULL);
384 break;
386 pos = anjuta_token_next (pos);
390 pos = anjuta_token_insert_token_list (after, pos,
391 ANJUTA_TOKEN_EOL, "\n",
392 NULL);
393 pos = anjuta_token_insert_token_list (after, pos,
394 ANJUTA_TOKEN_EOL, "\n",
395 NULL);
396 amp_group_node_update_makefile (group, pos);
399 return pos;
403 /* Public functions
404 *---------------------------------------------------------------------------*/
406 static AnjutaToken *
407 amp_project_write_config_list (AmpProject *project)
409 AnjutaToken *pos;
410 AnjutaToken *token;
411 static gint output_type[] = {AC_TOKEN_AC_OUTPUT, 0};
412 static gint eol_type[] = {ANJUTA_TOKEN_EOL, ANJUTA_TOKEN_SPACE, ANJUTA_TOKEN_COMMENT, 0};
413 AnjutaToken *configure;
415 configure = amp_project_get_configure_token (project);
416 pos = anjuta_token_find_type (configure, 0, output_type);
417 if (pos == NULL)
419 gint other_type[] = {AC_TOKEN_AC_INIT,
420 AC_TOKEN_PKG_CHECK_MODULES,
421 AC_TOKEN_AC_CONFIG_FILES,
422 AC_TOKEN_OBSOLETE_AC_OUTPUT,
423 AC_TOKEN_AC_PREREQ,
426 pos = anjuta_token_find_type (configure, ANJUTA_TOKEN_SEARCH_LAST, other_type);
427 if (pos == NULL)
429 pos = anjuta_token_skip_comment (configure);
431 else
433 AnjutaToken* next;
435 next = anjuta_token_find_type (pos, ANJUTA_TOKEN_SEARCH_NOT, eol_type);
440 token = anjuta_token_insert_token_list (FALSE, pos,
441 AC_TOKEN_AC_CONFIG_FILES, "AC_CONFIG_FILES(",
442 ANJUTA_TOKEN_LIST, NULL,
443 ANJUTA_TOKEN_LAST, NULL,
444 RIGHT_PAREN, ")",
445 ANJUTA_TOKEN_EOL, "\n",
446 NULL);
448 return token;
451 static AnjutaToken *
452 amp_project_write_config_file (AmpProject *project, AnjutaToken *list, gboolean after, AnjutaToken *sibling, const gchar *filename)
454 AnjutaToken *token;
456 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, filename);
457 //fprintf (stdout, "Dump config list:\n");
458 //anjuta_token_dump (list);
459 if (after)
461 anjuta_token_insert_word_after (list, sibling, token);
463 else
465 anjuta_token_insert_word_before (list, sibling, token);
467 //fprintf (stdout, "Dump config list after insertion:\n");
468 //anjuta_token_dump (list);
470 anjuta_token_style_format (project->ac_space_list, list);
472 //fprintf (stdout, "Dump config list after format:\n");
473 //anjuta_token_dump (list);
475 amp_project_update_configure (project, list);
477 return token;
481 /* Target objects
482 *---------------------------------------------------------------------------*/
484 gboolean
485 amp_group_node_create_token (AmpProject *project, AmpGroupNode *group, GError **error)
487 GFile *directory;
488 GFile *makefile;
489 AnjutaToken *list;
490 gchar *basename;
491 AnjutaTokenFile* tfile;
492 AnjutaProjectNode *sibling;
493 AmpGroupNode *parent;
494 gboolean after;
495 const gchar *name;
497 /* Get parent target */
498 name = anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (group));
499 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type(ANJUTA_PROJECT_NODE (group), ANJUTA_PROJECT_GROUP));
500 if (parent != NULL)
502 directory = g_file_get_child (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (parent)), name);
504 else
506 /* Used only when adding root group (a group named . in an empty project) */
507 parent = group;
508 directory = g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (parent)));
511 /* Find a sibling if possible */
512 after = TRUE;
513 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (group)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
515 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_GROUP) break;
517 if (sibling == NULL)
519 after = FALSE;
520 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (group)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
522 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_GROUP) break;
525 if (sibling == NULL) after = TRUE;
527 /* Create Makefile.am */
528 basename = amp_group_node_get_makefile_name (parent);
529 if (basename != NULL)
531 makefile = g_file_get_child (directory, basename);
532 g_free (basename);
534 else
536 makefile = g_file_get_child (directory, "Makefile.am");
539 /* Add in configure */
540 list = NULL;
541 if (sibling) list = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_CONFIGURE);
542 if (list == NULL) list= amp_group_node_get_first_token (parent, AM_GROUP_TOKEN_CONFIGURE);
543 if (list != NULL) list = anjuta_token_list (list);
544 if (list == NULL)
546 list = amp_project_write_config_list (project);
547 list = anjuta_token_next (list);
549 if (list != NULL)
551 gchar *relative_make;
552 gchar *ext;
553 AnjutaToken *prev = NULL;
554 AnjutaToken *token;
556 if (sibling)
558 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_CONFIGURE);
559 /*if ((prev != NULL) && after)
561 prev = anjuta_token_next_word (prev);
564 //prev_token = (AnjutaToken *)token_list->data;
566 relative_make = g_file_get_relative_path (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project)), makefile);
567 ext = relative_make + strlen (relative_make) - 3;
568 if (strcmp (ext, ".am") == 0)
570 *ext = '\0';
572 token = amp_project_write_config_file (project, list, after, prev, relative_make);
573 amp_group_node_add_token (AMP_GROUP_NODE (group), token, AM_GROUP_TOKEN_CONFIGURE);
574 g_free (relative_make);
577 /* Add in Makefile.am */
578 if (sibling == NULL)
580 list = anjuta_token_find_group_property_position (parent, AM_TOKEN_SUBDIRS);
582 if (list != NULL)
584 list = anjuta_token_insert_token_list (FALSE, list,
585 AM_TOKEN_SUBDIRS, "SUBDIRS",
586 ANJUTA_TOKEN_SPACE, " ",
587 ANJUTA_TOKEN_OPERATOR, "=",
588 ANJUTA_TOKEN_LIST, NULL,
589 ANJUTA_TOKEN_LAST, NULL,
590 NULL);
591 list = anjuta_token_next (anjuta_token_next ( anjuta_token_next (list)));
594 else
596 AnjutaToken *prev;
598 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_SUBDIRS);
599 list = anjuta_token_list (prev);
602 if (list != NULL)
604 AnjutaToken *token;
605 AnjutaToken *prev;
606 AnjutaTokenStyle *style;
608 style = anjuta_token_style_new_from_base (project->am_space_list);
609 anjuta_token_style_update (style, list);
611 if (sibling)
613 prev = amp_group_node_get_first_token (AMP_GROUP_NODE (sibling), AM_GROUP_TOKEN_SUBDIRS);
616 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
617 if (after)
619 anjuta_token_insert_word_after (list, prev, token);
621 else
623 anjuta_token_insert_word_before (list, prev, token);
626 /* Try to use the same style than the current group list */
627 anjuta_token_style_format (style, list);
628 anjuta_token_style_free (style);
630 amp_group_node_update_makefile (parent, token);
632 amp_group_node_add_token (group, token, AM_GROUP_TOKEN_SUBDIRS);
635 tfile = amp_group_node_set_makefile (group, makefile, project);
636 amp_project_add_file (project, makefile, tfile);
638 return TRUE;
641 gboolean
642 amp_group_node_delete_token (AmpProject *project, AmpGroupNode *group, GError **error)
644 GList *item;
645 AnjutaProjectNode *parent;
647 /* Get parent group */
648 parent = anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (group), ANJUTA_PROJECT_GROUP);
649 if (parent == NULL) return FALSE;
651 for (item = amp_group_node_get_token (group, AM_GROUP_TOKEN_SUBDIRS); item != NULL; item = g_list_next (item))
653 AnjutaToken *token = (AnjutaToken *)item->data;
654 AnjutaTokenStyle *style;
655 AnjutaToken *list;
657 list = anjuta_token_list (token);
659 /* Try to use the same style than the current target list */
660 style = anjuta_token_style_new_from_base (project->am_space_list);
661 anjuta_token_style_update (style, list);
663 anjuta_token_remove_word (token);
664 anjuta_token_style_format (style, list);
665 anjuta_token_style_free (style);
667 /* Remove whole variable if empty */
668 if (anjuta_token_first_word (list) == NULL)
670 anjuta_token_remove_list (anjuta_token_list (list));
673 amp_group_node_update_makefile (AMP_GROUP_NODE (parent), list);
676 /* Remove from configure file */
677 for (item = amp_group_node_get_token (group, AM_GROUP_TOKEN_CONFIGURE); item != NULL; item = g_list_next (item))
679 AnjutaToken *token = (AnjutaToken *)item->data;
680 AnjutaToken *args;
681 AnjutaTokenStyle *style;
683 args = anjuta_token_list (token);
685 /* Try to use the same style than the current group list */
686 style = anjuta_token_style_new_from_base (project->ac_space_list);
687 anjuta_token_style_update (style, args);
689 anjuta_token_remove_word (token);
691 anjuta_token_style_format (style, args);
692 anjuta_token_style_free (style);
694 amp_project_update_configure (project, args);
697 return TRUE;
701 /* Target objects
702 *---------------------------------------------------------------------------*/
704 static AnjutaToken *
705 amp_project_write_target (AmpGroupNode *group, gint type, const gchar *name, gboolean after, AnjutaToken* sibling)
707 AnjutaToken *pos = sibling;
709 if (pos != NULL)
711 /* Find top level parent */
714 AnjutaTokenType type = anjuta_token_get_type (pos);
716 if ((type >= AM_TOKEN_FIRST_ORDERED_MACRO) && (type <= AM_TOKEN_LAST_ORDERED_MACRO)) break;
717 pos = anjuta_token_list (pos);
719 while (pos != NULL);
721 if (pos != NULL)
723 /* Add target just near sibling target */
724 pos = anjuta_token_insert_token_list (after, pos,
725 ANJUTA_TOKEN_EOL, "\n",
726 NULL);
727 pos = anjuta_token_insert_token_list (after, pos,
728 ANJUTA_TOKEN_EOL, "\n",
729 NULL);
730 amp_group_node_update_makefile (group, pos);
734 if (pos == NULL)
736 /* Find ordered position in Makefile.am */
737 pos = anjuta_token_find_group_property_position (group, type);
740 pos = anjuta_token_insert_token_list (after, pos,
741 ANJUTA_TOKEN_LIST, NULL,
742 type, name,
743 ANJUTA_TOKEN_SPACE, " ",
744 ANJUTA_TOKEN_OPERATOR, "=",
745 ANJUTA_TOKEN_LIST, NULL,
746 ANJUTA_TOKEN_SPACE, " ",
747 NULL);
748 pos = anjuta_token_last_item (pos);
749 amp_group_node_update_makefile (group, pos);
751 /* Return list token */
752 return pos;
755 static AnjutaToken *
756 amp_target_add_in_list (AmpProject *project, AnjutaToken *list, AnjutaProjectNode *target, gboolean after, AnjutaToken* sibling)
758 AnjutaTokenStyle *style;
759 AnjutaToken *token;
760 AmpGroupNode *parent;
762 g_return_val_if_fail (list != NULL, NULL);
764 /* Get parent target */
765 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (target, ANJUTA_PROJECT_GROUP));
767 style = anjuta_token_style_new_from_base (project->am_space_list);
768 anjuta_token_style_update (style, list);
770 token = anjuta_token_new_string (ANJUTA_TOKEN_ARGUMENT | ANJUTA_TOKEN_ADDED, anjuta_project_node_get_name (target));
771 if (after)
773 anjuta_token_insert_word_after (list, sibling, token);
775 else
777 anjuta_token_insert_word_before (list, sibling, token);
780 /* Try to use the same style than the current target list */
781 anjuta_token_style_format (style, list);
782 anjuta_token_style_free (style);
784 amp_group_node_update_makefile (parent, token);
786 amp_target_node_add_token (AMP_TARGET_NODE (target), ANJUTA_TOKEN_ARGUMENT, token);
788 return token;
792 gboolean
793 amp_target_node_create_token (AmpProject *project, AmpTargetNode *target, GError **error)
795 AnjutaToken *args;
796 AnjutaToken *var;
797 AnjutaToken *prev;
798 AmpNodeInfo *info;
799 gchar *targetname;
800 const gchar *name;
801 GList *last;
802 AnjutaProjectNode *sibling;
803 AmpGroupNode *parent;
804 gboolean after;
806 /* Get parent target */
807 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
809 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (ANJUTA_PROJECT_NODE (target)));
810 name = anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (target));
812 /* Find a sibling if possible */
813 after = TRUE;
814 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (target)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
816 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_TARGET) break;
818 if (sibling == NULL)
820 after = FALSE;
821 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (target)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
823 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_TARGET) break;
826 if (sibling == NULL) after = TRUE;
828 /* Add in Makefile.am */
829 targetname = g_strconcat (amp_target_node_get_install_directory (target) != NULL ? amp_target_node_get_install_directory (target) : info->install, "_", info->prefix, NULL);
831 // Get token corresponding to sibling and check if the target are compatible
832 args = NULL;
833 var = NULL;
834 prev = NULL;
835 if (sibling != NULL)
837 last = amp_target_node_get_token (AMP_TARGET_NODE (sibling), ANJUTA_TOKEN_ARGUMENT);
839 if (last != NULL)
841 AnjutaToken *token = (AnjutaToken *)last->data;
843 /* Check that the sibling is of the same kind */
844 token = anjuta_token_list (token);
845 if (token != NULL)
847 token = anjuta_token_list (token);
848 var = token;
849 if (token != NULL)
851 token = anjuta_token_first_item (token);
852 if (token != NULL)
854 gchar *value;
856 value = anjuta_token_evaluate (token);
858 if ((value != NULL) && (strcmp (targetname, value) == 0))
860 g_free (value);
861 prev = (AnjutaToken *)last->data;
862 args = anjuta_token_list (prev);
871 /* Check if a valid target variable is already defined */
872 if (args == NULL)
874 for (last = amp_group_node_get_token (parent, AM_GROUP_TARGET); last != NULL; last = g_list_next (last))
876 gchar *value = anjuta_token_evaluate (anjuta_token_first_word ((AnjutaToken *)last->data));
878 if ((value != NULL) && (strcmp (targetname, value) == 0))
880 g_free (value);
881 args = anjuta_token_last_item ((AnjutaToken *)last->data);
882 break;
884 g_free (value);
889 if (args == NULL)
891 args = amp_project_write_target (parent, info->token, targetname, FALSE, NULL);
893 g_free (targetname);
895 switch (anjuta_project_node_get_full_type (ANJUTA_PROJECT_NODE (target)) & ANJUTA_PROJECT_ID_MASK)
897 case ANJUTA_PROJECT_SHAREDLIB:
898 case ANJUTA_PROJECT_STATICLIB:
899 case ANJUTA_PROJECT_LT_MODULE:
900 case ANJUTA_PROJECT_PROGRAM:
901 amp_target_add_in_list (project, args, ANJUTA_PROJECT_NODE (target), after, prev);
902 break;
903 default:
904 if (args != NULL)
906 amp_target_node_add_token (target, AM_TOKEN__SOURCES, args);
908 break;
911 return TRUE;
914 gboolean
915 amp_target_node_delete_token (AmpProject *project, AmpTargetNode *target, GList *list, GError **error)
917 GList *item;
918 GList *removed_dir = NULL;
919 AmpGroupNode *parent;
921 /* Get parent group */
922 parent = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
924 /* Remove all associated token */
925 for (item = list; item != NULL; item = g_list_next (item))
927 AnjutaToken *token = (AnjutaToken *)item->data;
928 AnjutaTokenStyle *style;
929 AnjutaToken *list;
931 switch (anjuta_token_get_type (token))
933 case ANJUTA_TOKEN_ARGUMENT:
935 list = anjuta_token_list (token);
937 /* Try to use the same style than the current target list */
938 style = anjuta_token_style_new_from_base (project->am_space_list);
939 anjuta_token_style_update (style, list);
941 anjuta_token_remove_word (token);
942 anjuta_token_style_format (style, list);
943 anjuta_token_style_free (style);
945 /* Remove whole variable if empty */
946 if (anjuta_token_first_word (list) == NULL)
948 AnjutaToken *variable = anjuta_token_list (list);
949 gchar *value;
950 gint flags;
951 gchar *install = NULL;
953 value = anjuta_token_evaluate (anjuta_token_first_word (variable));
954 split_automake_variable (value, &flags, &install, NULL);
956 if (install != NULL)
958 /* Mark all removed directory, normally only one */
959 removed_dir = g_list_prepend (removed_dir, g_strdup (install));
961 g_free (value);
962 anjuta_token_remove_list (variable);
965 amp_group_node_update_makefile (parent, list);
967 break;
968 case AM_TOKEN__SOURCES:
969 case AM_TOKEN__DATA:
970 case AM_TOKEN__HEADERS:
971 case AM_TOKEN__LISP:
972 case AM_TOKEN__MANS:
973 case AM_TOKEN__PYTHON:
974 case AM_TOKEN__JAVA:
975 case AM_TOKEN__SCRIPTS:
976 case AM_TOKEN__TEXINFOS:
977 case AM_TOKEN_TARGET_LDFLAGS:
978 case AM_TOKEN_TARGET_CPPFLAGS:
979 case AM_TOKEN_TARGET_CFLAGS:
980 case AM_TOKEN_TARGET_CXXFLAGS:
981 case AM_TOKEN_TARGET_JAVACFLAGS:
982 case AM_TOKEN_TARGET_VALAFLAGS:
983 case AM_TOKEN_TARGET_FCFLAGS:
984 case AM_TOKEN_TARGET_OBJCFLAGS:
985 case AM_TOKEN_TARGET_LFLAGS:
986 case AM_TOKEN_TARGET_YFLAGS:
987 case AM_TOKEN_TARGET_DEPENDENCIES:
988 case AM_TOKEN_TARGET_LIBADD:
989 case AM_TOKEN_TARGET_LDADD:
990 anjuta_token_remove_list (token);
991 amp_group_node_update_makefile (parent, token);
992 break;
994 amp_target_node_remove_token (target, token);
997 /* Check if we need to remove dir variable */
998 for (item = removed_dir; item != NULL; item = g_list_next(item))
1000 gchar* dir = (gchar *)item->data;
1001 GList *list;
1003 /* Check if dir is used in another target */
1004 for (list = amp_group_node_get_token (parent, AM_GROUP_TARGET); list != NULL; list = g_list_next (list))
1006 AnjutaToken *target_list = (AnjutaToken *)list->data;
1007 gchar *value;
1008 gint flags;
1009 gchar *install = NULL;
1010 gboolean same;
1012 value = anjuta_token_evaluate (anjuta_token_first_word (target_list));
1013 /* value can be NULL if we have a list can has just been removed */
1014 if (value != NULL) split_automake_variable (value, &flags, &install, NULL);
1016 same = g_strcmp0 (install, dir) == 0;
1017 g_free (value);
1019 if (same)
1021 /* directory use elsewhere */
1023 g_free (dir);
1024 dir = NULL;
1025 break;
1029 if (dir != NULL)
1031 /* Directory is not used anymore, remove variable */
1032 gchar* install = g_strconcat (dir, "dir", NULL);
1034 for (list = anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE(parent)); list != NULL; list = g_list_next (list))
1036 AmpProperty *prop = (AmpProperty *)list->data;
1038 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN_DIR) &&
1039 (g_strcmp0(prop->base.name, install) == 0))
1041 AnjutaProjectProperty *new_prop;
1043 new_prop = amp_node_map_property_set (ANJUTA_PROJECT_NODE (parent), prop->base.info->id, prop->base.name, NULL);
1044 amp_project_update_am_property (project, ANJUTA_PROJECT_NODE (parent), new_prop);
1047 g_free (install);
1048 g_free (dir);
1051 g_list_free (removed_dir);
1054 return TRUE;
1059 /* Source objects
1060 *---------------------------------------------------------------------------*/
1063 /* Source objects
1064 *---------------------------------------------------------------------------*/
1066 gboolean
1067 amp_source_node_create_token (AmpProject *project, AmpSourceNode *source, GError **error)
1069 AmpGroupNode *group;
1070 AmpTargetNode *target;
1071 AnjutaProjectNode *sibling;
1072 gboolean after;
1073 AnjutaToken *token;
1074 AnjutaToken *prev;
1075 AnjutaToken *args;
1076 gchar *relative_name;
1078 /* Get parent target */
1079 target = AMP_TARGET_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (source), ANJUTA_PROJECT_TARGET));
1080 if (target == NULL) return FALSE;
1082 group = AMP_GROUP_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (target), ANJUTA_PROJECT_GROUP));
1083 relative_name = get_relative_path (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (group)), anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (source)));
1085 /* Add in Makefile.am */
1086 /* Find a sibling if possible */
1087 after = TRUE;
1088 for (sibling = anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (source)); sibling != NULL; sibling = anjuta_project_node_prev_sibling (sibling))
1090 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_SOURCE)
1092 break;
1094 else if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_OBJECT)
1096 sibling = anjuta_project_node_first_child (sibling);
1097 break;
1100 if (sibling == NULL)
1102 after = FALSE;
1103 for (sibling = anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (source)); sibling != NULL; sibling = anjuta_project_node_next_sibling (sibling))
1105 if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_SOURCE)
1107 break;
1109 else if (anjuta_project_node_get_node_type (sibling) == ANJUTA_PROJECT_OBJECT)
1111 sibling = anjuta_project_node_first_child (sibling);
1112 break;
1116 if (sibling == NULL)
1118 after = TRUE;
1119 prev = NULL;
1120 args = NULL;
1122 else
1124 prev = amp_source_node_get_token (AMP_SOURCE_NODE (sibling));
1125 args = anjuta_token_list (prev);
1128 /* Check if a valid source variable is already defined */
1129 if (args == NULL)
1131 GList *last;
1132 for (last = amp_target_node_get_token (target, AM_TOKEN__SOURCES); last != NULL; last = g_list_next (last))
1134 args = anjuta_token_last_item ((AnjutaToken *)last->data);
1135 break;
1137 if (last == NULL)
1139 for (last = amp_target_node_get_token (target, AM_TOKEN__DATA); last != NULL; last = g_list_next (last))
1141 args = anjuta_token_last_item ((AnjutaToken *)last->data);
1142 break;
1148 if (args == NULL)
1150 gchar *target_var;
1151 gchar *canon_name;
1152 AnjutaToken *var;
1154 canon_name = canonicalize_automake_variable (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (target)));
1155 target_var = g_strconcat (canon_name, "_SOURCES", NULL);
1157 var = anjuta_token_find_target_property_position (target, AM_TOKEN__SOURCES);
1158 if (var == NULL)
1159 var = anjuta_token_find_target_property_position (target, AM_TOKEN__DATA);
1161 args = anjuta_token_insert_token_list (FALSE, var,
1162 ANJUTA_TOKEN_LIST, NULL,
1163 ANJUTA_TOKEN_NAME, target_var,
1164 ANJUTA_TOKEN_SPACE, " ",
1165 ANJUTA_TOKEN_OPERATOR, "=",
1166 ANJUTA_TOKEN_LIST, NULL,
1167 ANJUTA_TOKEN_SPACE, " ",
1168 NULL);
1170 args = anjuta_token_last_item (args);
1171 g_free (target_var);
1174 if (args != NULL)
1176 AnjutaTokenStyle *style;
1178 style = anjuta_token_style_new_from_base (project->am_space_list);
1179 anjuta_token_style_update (style, args);
1181 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, relative_name);
1182 if (after)
1184 anjuta_token_insert_word_after (args, prev, token);
1186 else
1188 anjuta_token_insert_word_before (args, prev, token);
1191 /* Try to use the same style than the current target list */
1192 anjuta_token_style_format (style, args);
1193 anjuta_token_style_free (style);
1195 amp_group_node_update_makefile (group, token);
1197 amp_source_node_add_token (source, token);
1200 return TRUE;
1203 gboolean
1204 amp_source_node_delete_token (AmpProject *project, AmpSourceNode *source, GError **error)
1206 AnjutaProjectNode *group;
1207 AnjutaToken *token;
1209 /* Get parent group */
1210 group = anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (source), ANJUTA_PROJECT_GROUP);
1211 if (group == NULL) return FALSE;
1213 token = amp_source_node_get_token (source);
1214 if (token != NULL)
1216 AnjutaTokenStyle *style;
1217 AnjutaToken *list;
1219 list = anjuta_token_list (token);
1221 /* Try to use the same style than the current target list */
1222 style = anjuta_token_style_new_from_base (project->am_space_list);
1223 anjuta_token_style_update (style, list);
1225 anjuta_token_remove_word (token);
1226 anjuta_token_style_format (style, list);
1227 anjuta_token_style_free (style);
1229 /* Remove whole variable if empty */
1230 if (anjuta_token_first_word (list) == NULL)
1232 anjuta_token_remove_list (anjuta_token_list (list));
1235 amp_group_node_update_makefile (AMP_GROUP_NODE (group), list);
1238 return TRUE;
1242 /* Properties
1243 *---------------------------------------------------------------------------*/
1245 static AnjutaToken*
1246 amp_property_delete_token (AmpProject *project, AnjutaToken *token)
1248 gboolean updated = FALSE;
1250 if (token != NULL)
1252 anjuta_token_remove_list (anjuta_token_list (token));
1254 updated = TRUE;
1257 return token;
1260 static AnjutaToken *
1261 amp_project_write_property_list (AmpGroupNode *group, AnjutaProjectNode *node, AmpPropertyInfo *info)
1263 AnjutaToken *pos;
1264 gchar *name;
1266 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_GROUP)
1268 /* Group property */
1269 name = g_strdup (info->suffix);
1271 pos = anjuta_token_find_group_property_position (AMP_GROUP_NODE (node), info->token_type);
1273 else
1275 /* Target property */
1276 gchar *canon_name;
1278 canon_name = canonicalize_automake_variable (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (node)));
1279 name = g_strconcat (canon_name, info->suffix, NULL);
1280 g_free (canon_name);
1282 pos = anjuta_token_find_target_property_position (AMP_TARGET_NODE (node), info->token_type);
1285 pos = anjuta_token_insert_token_list (FALSE, pos,
1286 info->token_type, NULL,
1287 ANJUTA_TOKEN_NAME, name,
1288 ANJUTA_TOKEN_SPACE, " ",
1289 ANJUTA_TOKEN_OPERATOR, "=",
1290 ANJUTA_TOKEN_SPACE, " ",
1291 ANJUTA_TOKEN_LIST, NULL,
1292 ANJUTA_TOKEN_SPACE, " ",
1293 NULL);
1295 g_free (name);
1297 return anjuta_token_last_item (pos);
1300 static gint
1301 compare_property_position (gconstpointer a, gconstpointer b)
1303 return ((const AmpPropertyInfo *)a)->position - ((const AmpPropertyInfo *)b)->position;
1306 static AnjutaToken *
1307 amp_property_rename_target (AmpProject *project, AnjutaProjectNode *node)
1309 AnjutaProjectNode *group;
1310 GList *infos;
1311 GList *item;
1312 GString *new_name;
1313 AmpNodeInfo *info;
1314 GList *list;
1315 AnjutaToken *update = NULL;
1316 AnjutaToken *existing_target_list;
1317 gboolean after;
1318 gchar *target_dir;
1320 g_return_val_if_fail (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_TARGET, NULL);
1322 group = anjuta_project_node_parent_type (node, ANJUTA_PROJECT_GROUP);
1324 /* Find all program properties */
1325 infos = NULL;
1326 for (item = anjuta_project_node_get_properties_info (node); item != NULL; item = g_list_next (item))
1328 AmpPropertyInfo *info = (AmpPropertyInfo *)item->data;
1330 if (info->token_type == AM_TOKEN__PROGRAMS)
1332 infos = g_list_insert_sorted (infos, info, compare_property_position);
1336 /* Create new name */
1337 new_name = g_string_new (NULL);
1338 for (item = infos; item != NULL; item = g_list_next (item))
1340 AmpPropertyInfo *info = (AmpPropertyInfo *)item->data;
1341 AmpProperty *prop;
1343 /* Check if property is enabled by another property */
1344 if (info->link != NULL)
1346 AnjutaProjectProperty *en_prop;
1348 en_prop = anjuta_project_node_get_property (node, info->link->id);
1350 if ((en_prop->value != NULL) && (*en_prop->value == '1')) continue;
1353 prop = (AmpProperty *)anjuta_project_node_get_property (node, info->base.id);
1354 if ((prop == (AmpProperty *)info->base.default_value) || (g_strcmp0 (prop->base.value, info->base.default_value->value) == 0))
1356 /* Default value, add only string properties */
1357 if (info->base.type == ANJUTA_PROJECT_PROPERTY_STRING)
1359 g_string_append (new_name, info->suffix);
1360 g_string_append_c (new_name, '_');
1363 else
1365 switch (info->base.type)
1367 case ANJUTA_PROJECT_PROPERTY_STRING:
1368 if ((info->flags & AM_PROPERTY_DIRECTORY) &&
1369 (strlen (prop->base.value) > 4) &&
1370 (strcmp (prop->base.value + strlen (prop->base.value) - 3, "dir") == 0))
1372 /* Remove "dir" suffix */
1373 g_string_append_len (new_name, prop->base.value, strlen (prop->base.value) - 3);
1375 else
1377 g_string_append (new_name, prop->base.value);
1379 g_string_append_c (new_name, '_');
1380 break;
1381 case ANJUTA_PROJECT_PROPERTY_BOOLEAN:
1382 if ((prop->base.value != NULL) && (g_strcmp0 (prop->base.value, info->base.default_value->value) != 0))
1384 g_string_append (new_name, info->suffix);
1386 break;
1387 default:
1388 break;
1393 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (node));
1394 g_string_append (new_name, info->prefix);
1396 if ((anjuta_project_node_get_full_type (node) & ANJUTA_PROJECT_ID_MASK) == ANJUTA_PROJECT_DATA)
1398 list = amp_target_node_get_token (AMP_TARGET_NODE (node), AM_TOKEN__DATA);
1400 if ((list != NULL) && (list->data != NULL))
1402 AnjutaToken *old_token;
1403 AnjutaToken *parent;
1405 parent = (AnjutaToken *)list->data;
1406 old_token = anjuta_token_first_word (parent);
1407 if (old_token != NULL)
1409 AnjutaToken *token;
1412 token = anjuta_token_new_string (ANJUTA_TOKEN_ADDED, new_name->str);
1413 update = anjuta_token_insert_word_after (parent, old_token, token);
1414 anjuta_token_remove_word (old_token);
1415 update = parent;
1419 else
1421 // Check if the target already exist.
1422 after = TRUE;
1423 for (item = amp_group_node_get_token (AMP_GROUP_NODE (group), AM_GROUP_TARGET); item != NULL; item = g_list_next (item))
1425 existing_target_list = (AnjutaToken *)item->data;
1426 gchar *target_name = anjuta_token_evaluate (anjuta_token_first_word (existing_target_list));
1427 gboolean same;
1429 same = strcmp (target_name, new_name->str) == 0;
1430 g_free (target_name);
1432 if (after)
1434 GList *list;
1435 GList *item;
1437 list = amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT);
1438 for (item = g_list_first (list); item != NULL; item = g_list_next (item))
1440 AnjutaToken *arg = (AnjutaToken *)item->data;
1441 AnjutaToken *target_list;
1443 if (arg != NULL)
1445 target_list = anjuta_token_list (arg);
1446 if (anjuta_token_list (target_list) == existing_target_list)
1448 /* token in group_node are stored in reverse order */
1449 after = FALSE;
1450 break;
1456 if (same)
1458 existing_target_list = anjuta_token_last_item (existing_target_list);
1459 break;
1461 existing_target_list = NULL;
1464 if (existing_target_list != NULL)
1466 GList *token_list;
1468 /* Get old tokens */
1469 token_list = g_list_copy (amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT));
1471 /* Add target in already existing list */
1472 amp_target_add_in_list (project, existing_target_list, node, after, NULL);
1474 /* Remove old token */
1475 amp_target_node_delete_token (project, AMP_TARGET_NODE (node), token_list, NULL);
1476 g_list_free (token_list);
1478 else
1480 list = amp_target_node_get_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT);
1481 for (item = g_list_first (list); item != NULL; item = g_list_next (item))
1483 AnjutaToken *arg = (AnjutaToken *)item->data;
1484 AnjutaToken *target_list;
1486 if (arg == NULL) continue;
1488 target_list = anjuta_token_list (arg);
1490 if (anjuta_token_nth_word (target_list, 1) == NULL)
1492 /* Only one target in list, just replace list name */
1493 AnjutaToken *target_variable = anjuta_token_list (target_list);
1495 if (target_variable != NULL)
1497 AnjutaToken *old_token;
1499 old_token = anjuta_token_first_word (target_variable);
1500 if (old_token != NULL)
1502 AnjutaToken *token;
1504 token = anjuta_token_new_string (ANJUTA_TOKEN_ADDED, new_name->str);
1505 update = anjuta_token_insert_word_after (target_variable, old_token, token);
1506 anjuta_token_remove_word (old_token);
1507 update = target_variable;
1511 else
1513 gchar *old_target;
1514 AmpNodeInfo *info;
1515 gboolean after = TRUE;
1516 AnjutaToken *sibling = NULL;
1517 AnjutaTokenStyle *style;
1518 AnjutaToken *token;
1520 old_target = anjuta_token_evaluate (arg);
1522 /* Find sibling target */
1523 if (anjuta_token_first_word (target_list) == arg)
1525 sibling = anjuta_token_next_word (arg);
1526 after = FALSE;
1528 else
1530 for (sibling = anjuta_token_first_word (target_list); sibling != NULL; sibling = anjuta_token_next_word (sibling))
1532 if (anjuta_token_next_word (sibling) == arg) break;
1534 after = TRUE;
1537 /* More than one target, remove target in list */
1538 arg = anjuta_token_remove_word (arg);
1539 if (arg != NULL) amp_group_node_update_makefile (AMP_GROUP_NODE (group), arg);
1542 /* Add target in new list */
1543 style = anjuta_token_style_new_from_base (project->am_space_list);
1544 anjuta_token_style_update (style, target_list);
1546 info = (AmpNodeInfo *)amp_project_get_type_info (project, anjuta_project_node_get_full_type (node));
1547 target_list = amp_project_write_target (AMP_GROUP_NODE (group), info->token, new_name->str, after, sibling);
1549 token = anjuta_token_new_string (ANJUTA_TOKEN_ARGUMENT | ANJUTA_TOKEN_ADDED, old_target);
1550 anjuta_token_insert_word_after (target_list, NULL, token);
1552 /* Try to use the same style than the current target list */
1553 anjuta_token_style_format (style, target_list);
1554 anjuta_token_style_free (style);
1556 amp_group_node_update_makefile (AMP_GROUP_NODE (group), token);
1557 amp_target_node_add_token (AMP_TARGET_NODE (node), ANJUTA_TOKEN_ARGUMENT, token);
1559 g_free (old_target);
1561 update = anjuta_token_list (target_list);
1568 /* Add directory variable if needed */
1569 target_dir = NULL;
1570 for (item = anjuta_project_node_get_properties (node); item != NULL; item = g_list_next (item))
1572 AmpProperty *prop = (AmpProperty *)item->data;
1574 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN__PROGRAMS) && (((AmpPropertyInfo *)prop->base.info)->flags & AM_PROPERTY_DIRECTORY))
1576 target_dir = prop->base.value;
1577 if ((strlen (target_dir) <= 3) || (strcmp (target_dir + strlen(target_dir) - 3, "dir") != 0))
1579 target_dir = g_strconcat (target_dir, "dir", NULL);
1580 g_free (prop->base.value);
1581 prop->base.value = target_dir;
1583 break;
1587 /* If it is a standard directory do not add a variable*/
1588 if (target_dir != NULL)
1590 const gchar **std_dir;
1592 for (std_dir = AmpStandardDirectory; *std_dir != NULL; std_dir++)
1594 if (strcmp(*std_dir, target_dir) == 0)
1596 target_dir = NULL;
1597 break;
1602 if (target_dir != NULL)
1604 for (item = anjuta_project_node_get_properties (group); item != NULL; item = g_list_next (item))
1606 AmpProperty *prop = (AmpProperty *)item->data;
1608 if ((((AmpPropertyInfo *)prop->base.info)->token_type == AM_TOKEN_DIR) && (g_strcmp0 (prop->base.name, target_dir) == 0))
1610 /* Find already existing directory variable */
1611 target_dir = NULL;
1612 break;
1617 if ((update != NULL) && (target_dir != NULL))
1619 update = anjuta_token_insert_token_list (FALSE, update,
1620 AM_TOKEN_DIR, NULL,
1621 ANJUTA_TOKEN_NAME, target_dir,
1622 ANJUTA_TOKEN_SPACE, " ",
1623 ANJUTA_TOKEN_OPERATOR, "=",
1624 ANJUTA_TOKEN_SPACE, " ",
1625 ANJUTA_TOKEN_LIST, NULL,
1626 ANJUTA_TOKEN_SPACE, " ",
1627 ANJUTA_TOKEN_EOL, "\n",
1628 NULL);
1631 g_string_free (new_name, TRUE);
1634 return update;
1637 gboolean amp_project_update_am_property (AmpProject *project, AnjutaProjectNode *node, AnjutaProjectProperty *property)
1639 AnjutaProjectNode *group;
1640 AnjutaToken *args;
1642 /* Find group of the property */
1643 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_GROUP)
1645 group = node;
1647 else
1649 group = anjuta_project_node_parent_type (node, ANJUTA_PROJECT_GROUP);
1652 if (property->value == NULL)
1654 /* Remove property */
1655 if (((AmpPropertyInfo *)property->info)->token_type == AM_TOKEN__PROGRAMS)
1657 /* Properties added in the target name */
1658 args = amp_property_rename_target (project, node);
1660 else
1662 /* Other properties having their own variable */
1663 args = amp_property_delete_token (project, ((AmpProperty *)property)->token);
1666 anjuta_project_node_remove_property (node, property);
1668 else
1670 if (((AmpPropertyInfo *)property->info)->token_type == AM_TOKEN__PROGRAMS)
1672 /* Properties added in the target name */
1673 args = amp_property_rename_target (project, node);
1675 else
1677 /* Other properties having their own variable */
1678 GString *new_value;
1679 AnjutaToken *arg;
1680 AnjutaToken *token;
1681 const gchar *value;
1682 AnjutaTokenStyle *style;
1684 args = ((AmpProperty *)property)->token;
1686 /* Try to use the same style than the current target list */
1687 style = anjuta_token_style_new_from_base (project->am_space_list);
1688 anjuta_token_style_update (style, args);
1690 if (args == NULL)
1692 args = amp_project_write_property_list (AMP_GROUP_NODE (group), node, (AmpPropertyInfo *)property->info);
1693 ((AmpProperty *)property)->token = args;
1696 switch (property->info->type)
1698 case ANJUTA_PROJECT_PROPERTY_LIST:
1699 new_value = g_string_new (property->value);
1700 g_string_assign (new_value, "");
1701 value = property->value;
1703 for (arg = anjuta_token_first_word (args); arg != NULL;)
1705 gchar *arg_value = anjuta_token_evaluate_name (arg);
1707 while (isspace (*value)) value++;
1709 if (*value == '\0')
1711 AnjutaToken *next;
1713 next = anjuta_token_next_word (arg);
1714 anjuta_token_remove_word (arg);
1715 arg = next;
1717 else
1719 const gchar *end;
1720 gchar *name;
1722 for (end = value; !isspace (*end) && (*end != '\0'); end++);
1723 name = g_strndup (value, end - value);
1725 if (strcmp (arg_value, name) != 0)
1727 /* New argument in property list */
1728 AnjutaToken *token;
1730 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
1731 anjuta_token_insert_word_before (args, arg, token);
1733 else
1735 arg = anjuta_token_next_word (arg);
1737 value = end;
1739 if (arg_value != NULL)
1741 if (new_value->len != 0) g_string_append_c (new_value, ' ');
1742 g_string_append (new_value, name);
1745 g_free (arg_value);
1748 while (*value != '\0')
1750 AnjutaToken *token;
1751 const gchar *end;
1752 gchar *name;
1754 while (isspace (*value)) value++;
1755 if (*value == '\0') break;
1757 for (end = value; !isspace (*end) && (*end != '\0'); end++);
1759 name = g_strndup (value, end - value);
1760 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, name);
1762 anjuta_token_insert_word_before (args, NULL, token);
1764 if (new_value->len != 0) g_string_append_c (new_value, ' ');
1765 g_string_append (new_value, name);
1767 g_free (name);
1768 value = end;
1771 anjuta_token_style_format (style, args);
1772 anjuta_token_style_free (style);
1774 g_free (property->value);
1775 property->value = g_string_free (new_value, FALSE);
1777 break;
1778 case ANJUTA_PROJECT_PROPERTY_MAP:
1780 token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, property->value);
1781 anjuta_token_insert_word_after (args, NULL, token);
1783 for (token = anjuta_token_next_word (token); token != NULL; token = anjuta_token_next_word (token))
1785 anjuta_token_remove_word (token);
1787 break;
1788 default:
1789 break;
1794 if (args != NULL) amp_group_node_update_makefile (AMP_GROUP_NODE (group), args);
1796 return args != NULL ? TRUE : FALSE;