diff --git a/libanjuta/anjuta-token-file.c b/libanjuta/anjuta-token-file.c index a362a27..f833dc6 100644 --- a/libanjuta/anjuta-token-file.c +++ b/libanjuta/anjuta-token-file.c @@ -218,6 +218,94 @@ anjuta_token_file_get_file (AnjutaTokenFile *file) return file->file; } +/** + * anjuta_token_file_update: + * @file: a #AnjutaTokenFile derived class object. + * @token: Token to update. + * + * Update the file with all changed token starting from @token. The function can + * return an error if the token is not in the file. + * + * Return value: TRUE is the update is done without error. + */ +gboolean +anjuta_token_file_update (AnjutaTokenFile *file, AnjutaToken *token) +{ + AnjutaToken *prev; + AnjutaToken *start = NULL; + AnjutaToken *next; + const gchar *pos; + const gchar *ptr; + const gchar *last; + const gchar *end; + + /* Find position a token in the file */ + for (prev = token; prev != NULL; prev = anjuta_token_previous_sibling (prev)) + { + if (anjuta_token_get_string (prev) != NULL) + { + gint flags = anjuta_token_get_flags (prev); + if (!(flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))) break; + token = prev; + } + } + + /* Find token position */ + if (prev != NULL) + { + pos = anjuta_token_get_string (prev); + for (start = file->content; start != NULL; start = anjuta_token_next (start)) + { + guint len = anjuta_token_get_length (start); + + if (len) + { + ptr = anjuta_token_get_string (start); + end = ptr + len; + + if ((pos >= ptr) && (pos < end)) break; + } + } + if (ptr != pos) + { + start = anjuta_token_split (start, ptr - pos); + start = anjuta_token_next (start); + } + } + + /* Updated token */ + last = pos; + for (next = token; next != NULL; next = anjuta_token_next_sibling (next)) + { + gint flags = anjuta_token_get_flags (next); + + if (flags & ANJUTA_TOKEN_REMOVED) + { + guint len = anjuta_token_get_length (next); + } + else if (flags & ANJUTA_TOKEN_ADDED) + { + AnjutaToken* copy = anjuta_token_copy_token (next); + + if (start == NULL) + { + start = anjuta_token_insert_child (file->content, copy); + } + else + { + start = anjuta_token_insert_after (start, copy); + } + } + else + { + break; + } + } + + return TRUE; +} + + /* GObject functions *---------------------------------------------------------------------------*/ diff --git a/libanjuta/anjuta-token-file.h b/libanjuta/anjuta-token-file.h index ebb8593..05de291 100644 --- a/libanjuta/anjuta-token-file.h +++ b/libanjuta/anjuta-token-file.h @@ -56,6 +56,8 @@ void anjuta_token_file_move (AnjutaTokenFile *file, GFile *new_file); gboolean anjuta_token_file_get_token_location (AnjutaTokenFile *file, AnjutaTokenFileLocation *location, AnjutaToken *token); +gboolean anjuta_token_file_update (AnjutaTokenFile *file, AnjutaToken *token); + AnjutaToken* anjuta_token_file_get_content (AnjutaTokenFile *file); GFile *anjuta_token_file_get_file (AnjutaTokenFile *file); diff --git a/libanjuta/anjuta-token-style.c b/libanjuta/anjuta-token-style.c index e39f990..6587c3d 100644 --- a/libanjuta/anjuta-token-style.c +++ b/libanjuta/anjuta-token-style.c @@ -305,15 +305,15 @@ anjuta_token_list_first (AnjutaToken *list) { AnjutaToken *token; - token = anjuta_token_next_child (list); - if (token == NULL) return token; - - if (anjuta_token_get_type (token) == ANJUTA_TOKEN_START) + for (token = list; token != NULL; token = anjuta_token_next (token)) { - token = anjuta_token_next_sibling (token); + if (anjuta_token_get_type (token) == ANJUTA_TOKEN_START) + { + return token; + } } - return token; + return NULL; } AnjutaToken * @@ -321,13 +321,15 @@ anjuta_token_list_last (AnjutaToken *list) { AnjutaToken *token; - token = anjuta_token_list_first (list); - for (;;) + for (token = list; token != NULL; token = anjuta_token_next (token)) { - AnjutaToken *next = anjuta_token_list_next (list); - if (next == NULL) return token; - token = next; + if (anjuta_token_get_type (token) == ANJUTA_TOKEN_LAST) + { + return token; + } } + + return NULL; } AnjutaToken * @@ -347,23 +349,31 @@ anjuta_token_list_next (AnjutaToken *sibling) } AnjutaToken * -anjuta_token_list_replace (AnjutaToken *sibling, AnjutaToken *baby) +anjuta_token_list_replace (AnjutaToken *sibling, AnjutaToken *token) { - AnjutaToken *token; - - token = anjuta_token_insert_before (sibling, baby); - if ((anjuta_token_get_type (sibling) != ANJUTA_TOKEN_NEXT) && (anjuta_token_get_type (sibling) != ANJUTA_TOKEN_LAST)) + for (;; sibling = anjuta_token_next (sibling)) { - anjuta_token_remove (sibling); + switch (anjuta_token_get_type (sibling)) + { + case ANJUTA_TOKEN_NEXT: + case ANJUTA_TOKEN_LAST: + break; + default: + anjuta_token_remove (sibling); + continue; + } + break; } + token = anjuta_token_insert_before (sibling, token); return token; } AnjutaToken * -anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *baby) +anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *item) { AnjutaToken *token; + gboolean no_item = TRUE; token = anjuta_token_list_first (list); if (token == NULL) @@ -372,31 +382,28 @@ anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *baby) token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL)); } - for (; n != 0; n--) + for (n++; n == 0;) { AnjutaToken *next; switch (anjuta_token_get_type (token)) { - case ANJUTA_TOKEN_LAST: - anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL)); - continue; - case ANJUTA_TOKEN_NEXT: - break; - default: - token = anjuta_token_next_sibling (token); - if (token == NULL) - { - token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL)); - } - else if (anjuta_token_get_type (token) == ANJUTA_TOKEN_LAST) - { - token = anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL)); - } - break; + case ANJUTA_TOKEN_LAST: + anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL)); + continue; + case ANJUTA_TOKEN_NEXT: + if (no_item) n--; + no_item = TRUE; + break; + case ANJUTA_TOKEN_ITEM: + n--; + no_item = FALSE; + break; + default: + break; } - next = anjuta_token_next_sibling (token); + next = anjuta_token_next (token); if (next == NULL) { token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL)); @@ -407,7 +414,7 @@ anjuta_token_list_replace_nth (AnjutaToken *list, guint n, AnjutaToken *baby) } } - return anjuta_token_list_replace (token, baby); + return anjuta_token_list_replace (token, item); } AnjutaToken * diff --git a/libanjuta/anjuta-token.c b/libanjuta/anjuta-token.c index 837d6ea..28e5540 100644 --- a/libanjuta/anjuta-token.c +++ b/libanjuta/anjuta-token.c @@ -536,7 +536,16 @@ anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *token) AnjutaToken * anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *baby) { - return (AnjutaToken *)g_node_insert_before ((GNode *)sibling->parent, (GNode *)sibling, (GNode *)baby); + AnjutaToken *next = NULL; + AnjutaToken *token; + + for (token = baby; token != NULL; token = next) + { + next = anjuta_token_next (token); + g_node_insert_before ((GNode *)sibling->parent, (GNode *)sibling, (GNode *)token); + } + + return baby; } void diff --git a/src/ac-parser.y b/src/ac-parser.y index 7859a86..5103f15 100644 --- a/src/ac-parser.y +++ b/src/ac-parser.y @@ -30,6 +30,7 @@ /* Token location is found directly from token value, there is no need to * maintain a separate location variable */ #define YYLLOC_DEFAULT(Current, Rhs, N) ((Current) = YYRHSLOC(Rhs, (N) ? 1 : 0)) + %} %union { @@ -52,7 +53,8 @@ %token COMMA ',' %token LOWER '<' %token GREATER '>' - + +%token COMMENT %token NAME %token VARIABLE %token MACRO @@ -221,7 +223,7 @@ ac_macro_with_arg: ac_init: AC_INIT arg_list { - amp_ac_scanner_load_properties (scanner, $2); + amp_ac_scanner_load_properties (scanner, $1, $2); } ac_output: diff --git a/src/ac-scanner.h b/src/ac-scanner.h index fa136e1..da92b53 100644 --- a/src/ac-scanner.h +++ b/src/ac-scanner.h @@ -39,7 +39,7 @@ AnjutaToken* amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *tok void amp_ac_scanner_load_module (AmpAcScanner *scanner, AnjutaTokenGroup *module); void amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaTokenGroup *list); -void amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaTokenGroup *list); +void amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaTokenGroup *args); void amp_ac_yyerror (YYLTYPE *loc, AmpAcScanner *scanner, char const *s); @@ -52,7 +52,8 @@ enum AC_TOKEN_AC_OUTPUT, AC_TOKEN_SPACE_LIST, AC_TOKEN_OPEN_STRING, - AC_TOKEN_CLOSE_STRING + AC_TOKEN_CLOSE_STRING, + AC_TOKEN_AC_PREREQ, }; enum diff --git a/src/ac-scanner.l b/src/ac-scanner.l index 55f994e..1131933 100644 --- a/src/ac-scanner.l +++ b/src/ac-scanner.l @@ -362,9 +362,9 @@ amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaTokenGroup *list) } void -amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaTokenGroup *list) +amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaTokenGroup *list) { - amp_project_load_properties (scanner->project, list); + amp_project_load_properties (scanner->project, macro, list); } diff --git a/src/ac-writer.c b/src/ac-writer.c index 71d2bfc..7877c27 100644 --- a/src/ac-writer.c +++ b/src/ac-writer.c @@ -25,6 +25,8 @@ #endif #include "ac-writer.h" +#include "ac-scanner.h" +#include "ac-parser.h" #include "am-project-private.h" @@ -93,6 +95,81 @@ add_list_item (AnjutaToken *list, AnjutaToken *token, AnjutaTokenStyle *user_sty return TRUE; } +static AnjutaToken* +find_tokens (AnjutaToken *list, AnjutaTokenType* types) +{ + AnjutaToken *tok; + + for (tok = list; tok != NULL; tok = anjuta_token_next (tok)) + { + AnjutaTokenType *type; + for (type = types; *type != 0; type++) + { + if (anjuta_token_get_type (tok) == *type) + { + return tok; + } + } + } + + return NULL; +} + +static AnjutaToken * +find_next_eol (AnjutaToken *token) +{ + if (token == NULL) return NULL; + + for (;;) + { + AnjutaToken *next = anjuta_token_next (token); + + if (next == NULL) return token; + token = next; + if (anjuta_token_get_type (token) == EOL) return token; + } +} + +static AnjutaToken * +skip_comment (AnjutaToken *token) +{ + if (token == NULL) return NULL; + + for (;;) + { + for (;;) + { + AnjutaToken *next = anjuta_token_next (token); + AnjutaTokenType type; + + if (next == NULL) return token; + + type = anjuta_token_get_type (token); + if (type == SPACE) + { + token = next; + continue; + } + if (type == COMMENT) + { + token = next; + break; + } + + return token; + } + + for (;;) + { + AnjutaToken *next = anjuta_token_next (token); + + if (next == NULL) return token; + token = next; + if (anjuta_token_get_type (token) == EOL) break; + } + } +} + /* Public functions *---------------------------------------------------------------------------*/ @@ -102,16 +179,8 @@ amp_project_update_property (AmpProject *project, AmpPropertyType type) AnjutaToken *token; guint pos; const gchar *value; - - if (project->property == NULL) - { - return FALSE; - } - gchar *name; - gchar *version; - gchar *bug_report; - gchar *tarname; - gchar *url; + + g_return_val_if_fail (project->property != NULL, FALSE); switch (type) { @@ -137,9 +206,45 @@ amp_project_update_property (AmpProject *project, AmpPropertyType type) break; } + if (project->property->ac_init == NULL) + { + gint types[] = {AC_TOKEN_AC_PREREQ, 0}; + AnjutaTokenGroup *group; + + token = find_tokens (project->configure_token, types); + if (token == NULL) + { + token = skip_comment (project->configure_token); + if (token == NULL) + { + token = anjuta_token_append_child (project->configure_token, anjuta_token_new_string (COMMENT | ANJUTA_TOKEN_ADDED, "#")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (SPACE | ANJUTA_TOKEN_ADDED, " Created by Anjuta project manager")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (EOL | ANJUTA_TOKEN_ADDED, "\n")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (EOL | ANJUTA_TOKEN_ADDED, "\n")); + } + } + token = find_next_eol (token); + + token = anjuta_token_insert_after (token, anjuta_token_new_string (AC_TOKEN_AC_INIT | ANJUTA_TOKEN_ADDED, "AC_INIT(")); + project->property->ac_init = token; + group = anjuta_token_group_new (ANJUTA_TOKEN_LIST, NULL); + project->property->args = group; + group = anjuta_token_group_append (project->property->args, anjuta_token_group_new (ANJUTA_TOKEN_ARGUMENT, NULL)); + group = anjuta_token_group_append (project->property->args, anjuta_token_group_new (ANJUTA_TOKEN_ARGUMENT, NULL)); + token = anjuta_token_insert_after (token, anjuta_token_new_string (ANJUTA_TOKEN_START | ANJUTA_TOKEN_ADDED, NULL)); + token = anjuta_token_insert_after (token, anjuta_token_new_string (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL)); + token = anjuta_token_insert_after (token, anjuta_token_new_string (COMMA | ANJUTA_TOKEN_ADDED, ",")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (SPACE | ANJUTA_TOKEN_ADDED, " ")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (RIGHT_PAREN | ANJUTA_TOKEN_ADDED, ")")); + token = anjuta_token_insert_after (token, anjuta_token_new_string (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL)); + token = anjuta_token_insert_after (token, anjuta_token_new_string (EOL | ANJUTA_TOKEN_ADDED, "\n")); + } + anjuta_token_dump (project->property->ac_init); token = anjuta_token_new_string (ANJUTA_TOKEN_NAME | ANJUTA_TOKEN_ADDED, value); anjuta_token_list_replace_nth (project->property->ac_init, pos, token); + anjuta_token_dump (project->property->ac_init); anjuta_token_style_format (project->arg_list, project->property->ac_init); + anjuta_token_file_update (project->configure_file, token); return TRUE; } diff --git a/src/am-project-private.h b/src/am-project-private.h index 94a3460..81d2640 100644 --- a/src/am-project-private.h +++ b/src/am-project-private.h @@ -37,7 +37,8 @@ struct _AmpModule { }; struct _AmpProperty { - AnjutaTokenGroup *ac_init; /* AC_INIT macro */ + AnjutaToken *ac_init; /* AC_INIT macro */ + AnjutaTokenGroup *args; gchar *name; gchar *version; gchar *bug_report; diff --git a/src/am-project.c b/src/am-project.c index 3dbc786..0162103 100644 --- a/src/am-project.c +++ b/src/am-project.c @@ -67,6 +67,10 @@ static const gchar *valid_am_makefiles[] = {"GNUmakefile.am", "makefile.am", "Ma #define AMP_TARGET_DATA(node) ((node) != NULL ? (AmpTargetData *)((node)->data) : NULL) #define AMP_SOURCE_DATA(node) ((node) != NULL ? (AmpSourceData *)((node)->data) : NULL) +#define STR_REPLACE(target, source) \ + { g_free (target); target = source == NULL ? NULL : g_strdup (source);} + + typedef struct _AmpPackage AmpPackage; typedef struct _AmpModule AmpModule; @@ -608,24 +612,28 @@ amp_project_free_module_hash (AmpProject *project) *---------------------------------------------------------------------------*/ static AmpProperty* -amp_property_new (AnjutaTokenGroup *list) +amp_property_new (AnjutaToken *macro, AnjutaTokenGroup *list) { AmpProperty *prop; AnjutaTokenGroup *arg; prop = g_slice_new0(AmpProperty); - prop->ac_init = list; - - arg = anjuta_token_group_first (list); - prop->name = anjuta_token_group_evaluate (arg); - arg = anjuta_token_group_next (arg); - prop->version = anjuta_token_group_evaluate (arg); - arg = anjuta_token_group_next (arg); - prop->bug_report = anjuta_token_group_evaluate (arg); - arg = anjuta_token_group_next (arg); - prop->tarname = anjuta_token_group_evaluate (arg); - arg = anjuta_token_group_next (arg); - prop->url = anjuta_token_group_evaluate (arg); + prop->ac_init = macro; + prop->args = list; + + if (list != NULL) + { + arg = anjuta_token_group_first (list); + prop->name = anjuta_token_group_evaluate (arg); + arg = anjuta_token_group_next (arg); + prop->version = anjuta_token_group_evaluate (arg); + arg = anjuta_token_group_next (arg); + prop->bug_report = anjuta_token_group_evaluate (arg); + arg = anjuta_token_group_next (arg); + prop->tarname = anjuta_token_group_evaluate (arg); + arg = anjuta_token_group_next (arg); + prop->url = anjuta_token_group_evaluate (arg); + } return prop; } @@ -980,9 +988,9 @@ project_node_destroy (AmpProject *project, AnjutaProjectNode *g_node) } void -amp_project_load_properties (AmpProject *project, AnjutaTokenGroup *list) +amp_project_load_properties (AmpProject *project, AnjutaToken *macro, AnjutaTokenGroup *list) { - project->property = amp_property_new (list); + project->property = amp_property_new (macro, list); } void @@ -2415,30 +2423,30 @@ amp_project_get_property (AmpProject *project, AmpPropertyType type) gboolean amp_project_set_property (AmpProject *project, AmpPropertyType type, const gchar *value) { - if (project->property != NULL) + if (project->property == NULL) { - switch (type) - { - case AMP_PROPERTY_NAME: - project->property->name = g_strdup (value); - break; - case AMP_PROPERTY_VERSION: - project->property->version = g_strdup (value); - break; - case AMP_PROPERTY_BUG_REPORT: - project->property->bug_report = g_strdup (value); - break; - case AMP_PROPERTY_TARNAME: - project->property->tarname = g_strdup (value); - break; - case AMP_PROPERTY_URL: - project->property->url = g_strdup (value); - break; - } - return amp_project_update_property (project, type); + project->property = amp_property_new (NULL, NULL); + } + switch (type) + { + case AMP_PROPERTY_NAME: + STR_REPLACE (project->property->name, value); + break; + case AMP_PROPERTY_VERSION: + STR_REPLACE (project->property->version, value); + break; + case AMP_PROPERTY_BUG_REPORT: + STR_REPLACE (project->property->bug_report, value); + break; + case AMP_PROPERTY_TARNAME: + STR_REPLACE (project->property->tarname, value); + break; + case AMP_PROPERTY_URL: + STR_REPLACE (project->property->url, value); + break; } - return TRUE; + return amp_project_update_property (project, type); } /* Implement IAnjutaProject diff --git a/src/am-project.h b/src/am-project.h index 1856daf..4da8eff 100644 --- a/src/am-project.h +++ b/src/am-project.h @@ -73,7 +73,7 @@ gboolean amp_project_reload (AmpProject *project, GError **error); void amp_project_unload (AmpProject *project); void amp_project_load_config (AmpProject *project, AnjutaTokenGroup *arg_list); -void amp_project_load_properties (AmpProject *project, AnjutaTokenGroup *list); +void amp_project_load_properties (AmpProject *project, AnjutaToken *macro, AnjutaTokenGroup *list); void amp_project_load_module (AmpProject *project, AnjutaTokenGroup *module); diff --git a/tests/Makefile.am b/tests/Makefile.am index 13047ee..eb50845 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,7 +20,8 @@ TESTSUITE_AT = \ $(srcdir)/group.at \ $(srcdir)/target.at \ $(srcdir)/parser.at \ - $(srcdir)/makefile.at + $(srcdir)/makefile.at \ + $(srcdir)/acinit.at TESTSUITE = $(srcdir)/testsuite diff --git a/tests/testsuite.at b/tests/testsuite.at index 83df46c..1fbe687 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -4,3 +4,4 @@ m4_include([group.at]) m4_include([target.at]) m4_include([parser.at]) m4_include([makefile.at]) +m4_include([acinit.at])