1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
4 * Copyright (C) 2009 Sébastien Granjoux
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
29 #include "ac-writer.h"
30 #include "ac-scanner.h"
31 #include "ac-parser.h"
33 #include "amp-module.h"
34 #include "amp-package.h"
37 #include "am-project-private.h"
39 #include <libanjuta/anjuta-debug.h>
40 #include <libanjuta/anjuta-utils.h>
43 *---------------------------------------------------------------------------*/
47 *---------------------------------------------------------------------------*/
50 *---------------------------------------------------------------------------*/
53 anjuta_token_find_position (AnjutaToken
*list
, gboolean after
, AnjutaTokenType type
, AnjutaToken
*sibling
)
56 AnjutaToken
*pos
= sibling
;
60 AnjutaToken
*last
= NULL
;
61 gboolean found
= FALSE
;
63 for (tok
= list
; tok
!= NULL
; tok
= anjuta_token_next (tok
))
65 AnjutaTokenType current
= anjuta_token_get_type (tok
);
67 if ((current
>= AC_TOKEN_FIRST_ORDERED_MACRO
) && (current
<= AC_TOKEN_LAST_ORDERED_MACRO
))
69 /* Find a valid position */
72 /* 1. After the last similar macro
73 * 2. After the last macro with a higher priority
74 * 3. At the end of the file
81 else if (!found
&& (current
< type
))
88 /* 1. Before the first similar macro
89 * 2. Before the first macro with an lower priority
90 * 3. At the beginning of the file
97 else if (!found
&& (current
> type
))
108 if (after
&& (pos
== NULL
)) pos
= last
;
113 for (; pos
!= NULL
; pos
= anjuta_token_next (pos
))
115 AnjutaTokenType current
= anjuta_token_get_type (pos
);
117 if (current
== ANJUTA_TOKEN_EOL
) break;
126 find_tokens (AnjutaToken
*list
, AnjutaTokenType
* types
)
130 for (tok
= list
; tok
!= NULL
; tok
= anjuta_token_next (tok
))
132 AnjutaTokenType
*type
;
133 for (type
= types
; *type
!= 0; type
++)
135 if (anjuta_token_get_type (tok
) == *type
)
146 skip_comment (AnjutaToken
*token
)
148 if (token
== NULL
) return NULL
;
154 AnjutaToken
*next
= anjuta_token_next (token
);
156 if (next
== NULL
) return token
;
158 switch (anjuta_token_get_type (token
))
160 case ANJUTA_TOKEN_FILE
:
175 AnjutaToken
*next
= anjuta_token_next (token
);
177 if (next
== NULL
) return token
;
179 if (anjuta_token_get_type (token
) == END_OF_LINE
) break;
184 /* Find an already existing property using the same token */
186 find_similar_property (AnjutaProjectNode
*node
, AmpProperty
*property
)
190 for (item
= anjuta_project_node_get_properties (node
); item
!= NULL
; item
= g_list_next (item
))
192 AmpProperty
*prop
= (AmpProperty
*)item
->data
;
194 if ((((AmpPropertyInfo
*)prop
->base
.info
)->token_type
== ((AmpPropertyInfo
*)property
->base
.info
)->token_type
) && (prop
->token
!= NULL
))
204 *---------------------------------------------------------------------------*/
207 amp_project_update_ac_property (AmpProject
*project
, AnjutaProjectProperty
*property
)
213 AmpPropertyInfo
*info
;
215 if (g_strcmp0 (((AmpPropertyInfo
*)property
->info
)->value
, property
->value
) == 0)
217 /* Remove property */
218 info
= (AmpPropertyInfo
*)property
->info
;
219 prop
= (AmpProperty
*)property
;
221 if (info
->position
== -1)
225 anjuta_token_remove_list (anjuta_token_list (token
));
228 anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (project
), property
);
232 info
= (AmpPropertyInfo
*)property
->info
;
233 prop
= find_similar_property (ANJUTA_PROJECT_NODE (project
), (AmpProperty
*)property
);
234 args
= prop
!= NULL
? prop
->token
: NULL
;
236 prop
= (AmpProperty
*)property
;
241 AnjutaToken
*configure
;
244 configure
= amp_project_get_configure_token (project
);
245 token
= anjuta_token_find_position (configure
, TRUE
, info
->token_type
, NULL
);
248 token
= skip_comment (configure
);
251 token
= anjuta_token_append_child (configure
, anjuta_token_new_string (COMMENT
| ANJUTA_TOKEN_ADDED
, "#"));
252 token
= anjuta_token_insert_after (token
, anjuta_token_new_string (SPACE
| ANJUTA_TOKEN_ADDED
, " Created by Anjuta project manager"));
253 token
= anjuta_token_insert_after (token
, anjuta_token_new_string (END_OF_LINE
| ANJUTA_TOKEN_ADDED
, "\n"));
254 token
= anjuta_token_insert_after (token
, anjuta_token_new_string (END_OF_LINE
| ANJUTA_TOKEN_ADDED
, "\n"));
258 suffix
= info
->suffix
;
259 token
= anjuta_token_insert_after (token
, anjuta_token_new_string (AC_TOKEN_AC_INIT
| ANJUTA_TOKEN_ADDED
, suffix
));
260 if (suffix
[strlen(suffix
) - 1] == '(')
262 group
= anjuta_token_insert_after (token
, anjuta_token_new_static (ANJUTA_TOKEN_LIST
| ANJUTA_TOKEN_ADDED
, NULL
));
264 token
= anjuta_token_insert_after (group
, anjuta_token_new_static (ANJUTA_TOKEN_LAST
| ANJUTA_TOKEN_ADDED
, NULL
));
265 anjuta_token_merge (group
, token
);
267 anjuta_token_insert_after (token
, anjuta_token_new_string (END_OF_LINE
| ANJUTA_TOKEN_ADDED
, "\n"));
273 token
= anjuta_token_new_string (ANJUTA_TOKEN_NAME
| ANJUTA_TOKEN_ADDED
, prop
->base
.value
);
274 arg
= anjuta_token_insert_before (token
, anjuta_token_new_static (ANJUTA_TOKEN_ITEM
| ANJUTA_TOKEN_ADDED
, NULL
));
275 anjuta_token_merge (arg
, token
);
277 pos
= info
->position
;
278 if (pos
== -1) pos
= 0;
279 anjuta_token_replace_nth_word (args
, pos
, arg
);
280 anjuta_token_style_format (project
->arg_list
, args
);
284 amp_project_update_configure (project
, token
);
290 *---------------------------------------------------------------------------*/
293 amp_project_write_module_list (AmpProject
*project
, const gchar
*name
, gboolean after
, AnjutaToken
* sibling
)
297 AnjutaToken
*configure
;
299 configure
= amp_project_get_configure_token (project
);
301 pos
= anjuta_token_find_position (configure
, after
, AC_TOKEN_PKG_CHECK_MODULES
, sibling
);
303 pos
= anjuta_token_insert_token_list (after
, pos
,
304 ANJUTA_TOKEN_EOL
, "\n",
307 pos
= anjuta_token_insert_token_list (after
, pos
,
308 ANJUTA_TOKEN_EOL
, "\n",
310 amp_project_update_configure (project
, pos
);
312 token
= anjuta_token_insert_token_list (FALSE
, pos
,
313 AC_TOKEN_AC_CONFIG_FILES
, "PKG_CHECK_MODULES(",
314 ANJUTA_TOKEN_LIST
, NULL
,
315 ANJUTA_TOKEN_NAME
, name
,
316 ANJUTA_TOKEN_COMMA
, ",",
317 ANJUTA_TOKEN_LAST
, NULL
,
326 amp_module_node_create_token (AmpProject
*project
, AmpModuleNode
*module
, GError
**error
)
332 AnjutaProjectNode
*sibling
;
334 /* Add in configure.ac */
335 /* Find a sibling if possible */
338 for (sibling
= anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (module
)); sibling
!= NULL
; sibling
= anjuta_project_node_prev_sibling (sibling
))
340 if (anjuta_project_node_get_node_type (sibling
) == ANJUTA_PROJECT_MODULE
)
342 prev
= amp_module_node_get_token (AMP_MODULE_NODE (sibling
));
345 prev
= anjuta_token_list (prev
);
353 for (sibling
= anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (module
)); sibling
!= NULL
; sibling
= anjuta_project_node_next_sibling (sibling
))
355 if (anjuta_project_node_get_node_type (sibling
) == ANJUTA_PROJECT_MODULE
)
357 prev
= amp_module_node_get_token (AMP_MODULE_NODE (sibling
));
360 prev
= anjuta_token_list (prev
);
367 token
= amp_project_write_module_list (project
, anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (module
)), after
, prev
);
368 next
= anjuta_token_next (token
);
369 next
= anjuta_token_next (next
);
370 next
= anjuta_token_next (next
);
371 amp_module_node_add_token (module
, next
);
373 amp_project_update_configure (project
, token
);
379 amp_module_node_delete_token (AmpProject
*project
, AmpModuleNode
*module
, GError
**error
)
383 token
= amp_module_node_get_token (module
);
388 token
= anjuta_token_list (token
);
389 anjuta_token_set_flags (token
, ANJUTA_TOKEN_REMOVED
);
390 eol
= anjuta_token_next_item (token
);
391 if (anjuta_token_get_type (eol
) == ANJUTA_TOKEN_EOL
)
393 anjuta_token_set_flags (eol
, ANJUTA_TOKEN_REMOVED
);
395 eol
= anjuta_token_next_item (eol
);
396 if (anjuta_token_get_type (eol
) == ANJUTA_TOKEN_EOL
)
398 anjuta_token_set_flags (eol
, ANJUTA_TOKEN_REMOVED
);
401 amp_project_update_configure (project
, token
);
408 *---------------------------------------------------------------------------*/
411 amp_package_node_create_token (AmpProject
*project
, AmpPackageNode
*package
, GError
**error
)
413 AmpModuleNode
*module
;
414 AnjutaProjectNode
*sibling
;
421 /* Get parent module */
422 module
= AMP_MODULE_NODE (anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (package
), ANJUTA_PROJECT_MODULE
));
423 if (module
== NULL
) return FALSE
;
426 /* Add in configure.ac */
427 /* Find a sibling if possible */
428 if ((sibling
= anjuta_project_node_prev_sibling (ANJUTA_PROJECT_NODE (package
))) != NULL
)
430 prev
= amp_package_node_get_token (AMP_PACKAGE_NODE (sibling
));
432 args
= anjuta_token_list (prev
);
434 else if ((sibling
= anjuta_project_node_next_sibling (ANJUTA_PROJECT_NODE (package
))) != NULL
)
436 prev
= amp_package_node_get_token (AMP_PACKAGE_NODE (sibling
));
438 args
= anjuta_token_list (prev
);
446 /* Check if a valid source variable is already defined */
449 args
= amp_module_node_get_token (module
);
454 AnjutaTokenStyle
*style
;
457 name
= anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (package
));
458 style
= anjuta_token_style_new_from_base (project
->ac_space_list
);
459 //anjuta_token_style_update (style, args);
461 token
= anjuta_token_new_string (ANJUTA_TOKEN_NAME
| ANJUTA_TOKEN_ADDED
, name
);
465 anjuta_token_insert_word_after (args
, prev
, token
);
469 anjuta_token_insert_word_before (args
, prev
, token
);
472 /* Try to use the same style than the current target list */
473 anjuta_token_style_format (style
, args
);
474 anjuta_token_style_free (style
);
476 amp_project_update_configure (project
, token
);
478 amp_package_node_add_token (package
, token
);
485 amp_package_node_delete_token (AmpProject
*project
, AmpPackageNode
*package
, GError
**error
)
487 AnjutaProjectNode
*module
;
490 /* Get parent module */
491 module
= anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (package
), ANJUTA_PROJECT_MODULE
);
497 token
= amp_package_node_get_token (package
);
501 AnjutaTokenStyle
*style
;
503 args
= anjuta_token_list (token
);
505 /* Try to use the same style than the current target list */
506 style
= anjuta_token_style_new_from_base (project
->ac_space_list
);
507 anjuta_token_style_update (style
, args
);
509 anjuta_token_remove_word (token
);
511 anjuta_token_style_format (style
, args
);
512 anjuta_token_style_free (style
);
514 amp_project_update_configure (project
, args
);