search: Use G_REGEX_MULTILINE for find in files.
[anjuta.git] / plugins / am-project / ac-writer.c
blob751ce0da4cf1f910d8425e725d1e56ff4fbf23bd
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* ac-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 <string.h>
29 #include "ac-writer.h"
30 #include "ac-scanner.h"
31 #include "ac-parser.h"
32 #include "amp-node.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>
42 /* Types
43 *---------------------------------------------------------------------------*/
46 /* Helper functions
47 *---------------------------------------------------------------------------*/
49 /* Private functions
50 *---------------------------------------------------------------------------*/
52 static AnjutaToken *
53 anjuta_token_find_position (AnjutaToken *list, gboolean after, AnjutaTokenType type, AnjutaToken *sibling)
55 AnjutaToken *tok;
56 AnjutaToken *pos = sibling;
58 if (sibling == NULL)
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 */
70 if (after)
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
76 if (current == type)
78 pos = tok;
79 found = TRUE;
81 else if (!found && (current < type))
83 pos = tok;
86 else
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
92 if (current == type)
94 pos = tok;
95 break;
97 else if (!found && (current > type))
99 pos = tok;
100 found = TRUE;
104 last = tok;
108 if (after && (pos == NULL)) pos = last;
111 if (after)
113 for (; pos != NULL; pos = anjuta_token_next (pos))
115 AnjutaTokenType current = anjuta_token_get_type (pos);
117 if (current == ANJUTA_TOKEN_EOL) break;
122 return pos;
125 static AnjutaToken*
126 find_tokens (AnjutaToken *list, AnjutaTokenType* types)
128 AnjutaToken *tok;
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)
137 return tok;
142 return NULL;
145 static AnjutaToken *
146 skip_comment (AnjutaToken *token)
148 if (token == NULL) return NULL;
150 for (;;)
152 for (;;)
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:
161 case SPACE:
162 token = next;
163 continue;
164 case COMMENT:
165 token = next;
166 break;
167 default:
168 return token;
170 break;
173 for (;;)
175 AnjutaToken *next = anjuta_token_next (token);
177 if (next == NULL) return token;
178 token = next;
179 if (anjuta_token_get_type (token) == END_OF_LINE) break;
184 /* Find an already existing property using the same token */
185 static AmpProperty *
186 find_similar_property (AnjutaProjectNode *node, AmpProperty *property)
188 GList *item;
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))
196 return prop;
200 return NULL;
203 /* Public functions
204 *---------------------------------------------------------------------------*/
206 gboolean
207 amp_project_update_ac_property (AmpProject *project, AnjutaProjectProperty *property)
209 AnjutaToken *token;
210 AnjutaToken *arg;
211 AnjutaToken *args;
212 AmpProperty *prop;
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)
223 token = prop->token;
225 anjuta_token_remove_list (anjuta_token_list (token));
228 anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (project), property);
230 else
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;
238 if (args == NULL)
240 AnjutaToken *group;
241 AnjutaToken *configure;
242 const char *suffix;
244 configure = amp_project_get_configure_token (project);
245 token = anjuta_token_find_position (configure, TRUE, info->token_type, NULL);
246 if (token == NULL)
248 token = skip_comment (configure);
249 if (token == NULL)
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));
263 args = group;
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"));
269 if (args != NULL)
271 guint pos;
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);
286 return TRUE;
289 /* Module objects
290 *---------------------------------------------------------------------------*/
292 static AnjutaToken *
293 amp_project_write_module_list (AmpProject *project, const gchar *name, gboolean after, AnjutaToken* sibling)
295 AnjutaToken *pos;
296 AnjutaToken *token;
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",
305 NULL);
307 pos = anjuta_token_insert_token_list (after, pos,
308 ANJUTA_TOKEN_EOL, "\n",
309 NULL);
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,
318 RIGHT_PAREN, ")",
319 NULL);
321 return token;
325 gboolean
326 amp_module_node_create_token (AmpProject *project, AmpModuleNode *module, GError **error)
328 gboolean after;
329 AnjutaToken *token;
330 AnjutaToken *prev;
331 AnjutaToken *next;
332 AnjutaProjectNode *sibling;
334 /* Add in configure.ac */
335 /* Find a sibling if possible */
336 prev = NULL;
337 after = TRUE;
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));
343 if (prev != NULL)
345 prev = anjuta_token_list (prev);
346 break;
350 if (prev == NULL)
352 after = FALSE;
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));
358 if (prev != NULL)
360 prev = anjuta_token_list (prev);
361 break;
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);
375 return TRUE;
378 gboolean
379 amp_module_node_delete_token (AmpProject *project, AmpModuleNode *module, GError **error)
381 AnjutaToken *token;
383 token = amp_module_node_get_token (module);
384 if (token != NULL)
386 AnjutaToken *eol;
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);
404 return TRUE;
407 /* Package objects
408 *---------------------------------------------------------------------------*/
410 gboolean
411 amp_package_node_create_token (AmpProject *project, AmpPackageNode *package, GError **error)
413 AmpModuleNode *module;
414 AnjutaProjectNode *sibling;
415 gboolean after;
416 AnjutaToken *token;
417 AnjutaToken *prev;
418 AnjutaToken *args;
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));
431 after = TRUE;
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));
437 after = FALSE;
438 args = anjuta_token_list (prev);
440 else
442 prev = NULL;
443 args = NULL;
446 /* Check if a valid source variable is already defined */
447 if (args == NULL)
449 args = amp_module_node_get_token (module);
452 if (args != NULL)
454 AnjutaTokenStyle *style;
455 const gchar *name;
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);
463 if (after)
465 anjuta_token_insert_word_after (args, prev, token);
467 else
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);
481 return TRUE;
484 gboolean
485 amp_package_node_delete_token (AmpProject *project, AmpPackageNode *package, GError **error)
487 AnjutaProjectNode *module;
488 AnjutaToken *token;
490 /* Get parent module */
491 module = anjuta_project_node_parent_type (ANJUTA_PROJECT_NODE (package), ANJUTA_PROJECT_MODULE);
492 if (module == NULL)
494 return FALSE;
497 token = amp_package_node_get_token (package);
498 if (token != NULL)
500 AnjutaToken *args;
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);
517 return TRUE;