1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * All functions for parsing wizard template (.wiz) files
24 *---------------------------------------------------------------------------*/
35 #include <libanjuta/anjuta-debug.h>
37 /*---------------------------------------------------------------------------*/
39 #define PROJECT_WIZARD_EXTENSION ".wiz"
43 NPW_PROJECT_WIZARD_TAG
,
47 NPW_REQUIRED_PROGRAM_TAG
,
48 NPW_REQUIRED_PACKAGE_TAG
,
66 NPW_DESCRIPTION_ATTRIBUTE
,
68 NPW_SUMMARY_ATTRIBUTE
,
70 NPW_RESTRICTION_ATTRIBUTE
,
71 NPW_MANDATORY_ATTRIBUTE
,
73 NPW_EDITABLE_ATTRIBUTE
,
75 NPW_DESTINATION_ATTRIBUTE
,
76 NPW_EXECUTABLE_ATTRIBUTE
,
77 NPW_PROJECT_ATTRIBUTE
,
78 NPW_AUTOGEN_ATTRIBUTE
,
79 NPW_COMMAND_ATTRIBUTE
,
96 /* Read all project templates in a directory
97 *---------------------------------------------------------------------------*/
100 npw_header_list_readdir (GList
** list
, const gchar
* path
)
106 g_return_val_if_fail (list
!= NULL
, FALSE
);
107 g_return_val_if_fail (path
!= NULL
, FALSE
);
109 /* Read all project template files */
110 dir
= g_dir_open (path
, 0, NULL
);
111 if (!dir
) return FALSE
;
113 while ((name
= g_dir_read_name (dir
)) != NULL
)
115 char* filename
= g_build_filename (path
, name
, NULL
);
117 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
))
119 /* Search recursively in sub directory */
120 if (npw_header_list_readdir (list
, filename
))
125 else if (g_str_has_suffix (name
, PROJECT_WIZARD_EXTENSION
))
127 if (npw_header_list_read (list
, filename
))
129 /* Read at least one project file */
141 /* Common parser functions
142 *---------------------------------------------------------------------------*/
145 parse_tag (const char* name
)
147 if (strcmp (name
, "project-wizard") == 0)
149 return NPW_PROJECT_WIZARD_TAG
;
151 else if ((strcmp ("_name", name
) == 0) || (strcmp ("name", name
) == 0))
155 else if ((strcmp ("_description", name
) == 0) || (strcmp ("description", name
) == 0))
157 return NPW_DESCRIPTION_TAG
;
159 else if (strcmp ("icon", name
) == 0)
163 else if (strcmp ("category", name
) == 0)
165 return NPW_CATEGORY_TAG
;
167 else if (strcmp ("required-program", name
) == 0)
169 return NPW_REQUIRED_PROGRAM_TAG
;
171 else if (strcmp ("required-package", name
) == 0)
173 return NPW_REQUIRED_PACKAGE_TAG
;
175 else if (strcmp ("page", name
) == 0)
179 else if (strcmp ("property", name
) == 0)
181 return NPW_PROPERTY_TAG
;
183 else if (strcmp ("item", name
) == 0)
187 else if (strcmp ("directory", name
) == 0)
189 return NPW_DIRECTORY_TAG
;
191 else if (strcmp ("content", name
) == 0)
193 return NPW_CONTENT_TAG
;
195 else if (strcmp ("file", name
) == 0)
199 else if (strcmp ("action", name
) == 0)
201 return NPW_ACTION_TAG
;
203 else if (strcmp ("run", name
) == 0)
207 else if (strcmp ("open", name
) == 0)
213 return NPW_UNKNOW_TAG
;
218 parse_attribute (const char* name
)
220 if (strcmp ("name", name
) == 0)
222 return NPW_NAME_ATTRIBUTE
;
224 else if (strcmp ("_label", name
) == 0)
226 return NPW_LABEL_ATTRIBUTE
;
228 else if (strcmp ("_description", name
) == 0)
230 return NPW_DESCRIPTION_ATTRIBUTE
;
232 else if (strcmp ("default", name
) == 0 || strcmp ("value", name
) == 0)
234 return NPW_VALUE_ATTRIBUTE
;
236 else if (strcmp ("type", name
) == 0)
238 return NPW_TYPE_ATTRIBUTE
;
240 else if (strcmp ("restriction", name
) == 0)
242 return NPW_RESTRICTION_ATTRIBUTE
;
244 else if (strcmp ("summary", name
) == 0)
246 return NPW_SUMMARY_ATTRIBUTE
;
248 else if (strcmp ("mandatory", name
) == 0)
250 return NPW_MANDATORY_ATTRIBUTE
;
252 else if (strcmp ("editable", name
) == 0)
254 return NPW_EDITABLE_ATTRIBUTE
;
256 else if (strcmp ("exist", name
) == 0)
258 return NPW_EXIST_ATTRIBUTE
;
260 else if (strcmp ("source", name
) == 0)
262 return NPW_SOURCE_ATTRIBUTE
;
264 else if (strcmp ("destination", name
) == 0)
266 return NPW_DESTINATION_ATTRIBUTE
;
268 else if (strcmp ("executable", name
) == 0)
270 return NPW_EXECUTABLE_ATTRIBUTE
;
272 else if (strcmp ("project", name
) == 0)
274 return NPW_PROJECT_ATTRIBUTE
;
276 else if (strcmp ("autogen", name
) == 0)
278 return NPW_AUTOGEN_ATTRIBUTE
;
280 else if (strcmp ("command", name
) == 0)
282 return NPW_COMMAND_ATTRIBUTE
;
284 else if (strcmp ("file", name
) == 0)
286 return NPW_FILE_ATTRIBUTE
;
290 return NPW_UNKNOW_ATTRIBUTE
;
295 parse_boolean_string (const gchar
* value
)
297 return g_ascii_strcasecmp ("no", value
) && g_ascii_strcasecmp ("0", value
) && g_ascii_strcasecmp ("false", value
);
301 parser_error_quark (void)
303 static GQuark error_quark
= 0;
305 if (error_quark
== 0)
306 error_quark
= g_quark_from_static_string ("parser_error_quark");
311 parser_warning (GMarkupParseContext
* ctx
, const gchar
* format
,...)
317 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
318 msg
= g_strdup_printf ("line %d: %s", line
, format
);
319 va_start (args
, format
);
320 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_WARNING
, msg
, args
);
326 parser_critical (GMarkupParseContext
* ctx
, const gchar
* format
,...)
332 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
333 msg
= g_strdup_printf ("line %d: %s", line
, format
);
334 va_start (args
, format
);
335 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_CRITICAL
, msg
, args
);
339 /* Parse project wizard block
340 *---------------------------------------------------------------------------*/
342 #define NPW_HEADER_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
344 typedef struct _NPWHeaderParser
346 /* Type of parser (not used) */
348 GMarkupParseContext
* ctx
;
349 /* Known element stack */
350 NPWTag tag
[NPW_HEADER_PARSER_MAX_LEVEL
+ 1];
352 /* Unknown element stack */
356 /* Name of file read */
361 parse_header_start (GMarkupParseContext
* context
,
363 const gchar
** attributes
,
364 const gchar
** values
,
368 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
370 gboolean known
= FALSE
;
372 /* Recognize element */
373 if (parser
->unknown
== 0)
375 /* Not inside an unknown element */
376 tag
= parse_tag (name
);
377 switch (*parser
->last
)
380 /* Top level element */
383 case NPW_PROJECT_WIZARD_TAG
:
384 parser
->header
= npw_header_new ();
385 npw_header_set_filename (parser
->header
, parser
->filename
);
389 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
395 case NPW_PROJECT_WIZARD_TAG
:
396 /* Necessary to avoid neested PROJECT_WIZARD element */
400 case NPW_DESCRIPTION_TAG
:
402 case NPW_CATEGORY_TAG
:
403 case NPW_REQUIRED_PROGRAM_TAG
:
404 case NPW_REQUIRED_PACKAGE_TAG
:
408 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
413 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
421 /* Know element stack overflow */
422 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_HEADER_PARSER_MAX_LEVEL
);
433 parse_header_end (GMarkupParseContext
* context
,
438 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
440 if (parser
->unknown
> 0)
442 /* Pop unknown element */
445 else if (*parser
->last
!= NPW_NO_TAG
)
447 /* Pop known element */
449 if (parser
->last
[1] == NPW_PROJECT_WIZARD_TAG
)
451 /* Check if the element is valid */
452 if (parser
->header
&& !npw_header_get_name (parser
->header
))
454 parser_critical (parser
->ctx
, "Missing name attribute");
455 npw_header_free (parser
->header
);
458 /* Stop parsing after first project wizard block
459 * Remaining file need to be passed through autogen
460 * to be a valid xml file */
462 /* error should be available to stop parsing */
463 g_return_if_fail (error
!= NULL
);
466 *error
= g_error_new_literal (parser_error_quark (), NPW_STOP_PARSING
, "");
471 /* Know element stack underflow */
472 g_return_if_reached ();
477 parse_header_text (GMarkupParseContext
* context
,
483 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
485 if (parser
->unknown
== 0)
487 switch (*parser
->last
)
490 if (npw_header_get_name (parser
->header
) == NULL
)
492 npw_header_set_name (parser
->header
, text
);
496 parser_critical (parser
->ctx
, "Duplicated name tag");
499 case NPW_DESCRIPTION_TAG
:
500 if (npw_header_get_description (parser
->header
) == NULL
)
502 npw_header_set_description (parser
->header
, text
);
506 parser_critical (parser
->ctx
, "Duplicated description tag");
510 if (npw_header_get_iconfile (parser
->header
) == NULL
)
515 path
= g_path_get_dirname (parser
->filename
);
516 filename
= g_build_filename (path
, text
, NULL
);
517 npw_header_set_iconfile (parser
->header
, filename
);
523 parser_critical (parser
->ctx
, "Duplicated icon tag");
526 case NPW_CATEGORY_TAG
:
527 if (npw_header_get_category (parser
->header
) == NULL
)
529 npw_header_set_category (parser
->header
, text
);
533 parser_critical (parser
->ctx
, "Duplicated category tag");
536 case NPW_REQUIRED_PROGRAM_TAG
:
537 npw_header_add_required_program (parser
->header
, text
);
539 case NPW_REQUIRED_PACKAGE_TAG
:
540 npw_header_add_required_package (parser
->header
, text
);
542 case NPW_PROJECT_WIZARD_TAG
:
547 g_return_if_reached ();
553 static GMarkupParser header_markup_parser
= {
561 static NPWHeaderParser
*
562 npw_header_parser_new (GList
** list
, const gchar
* filename
)
564 NPWHeaderParser
* parser
;
566 g_return_val_if_fail (list
!= NULL
, NULL
);
567 g_return_val_if_fail (filename
!= NULL
, NULL
);
569 parser
= g_new0 (NPWHeaderParser
, 1);
571 parser
->type
= NPW_HEADER_PARSER
;
573 parser
->tag
[0] = NPW_NO_TAG
;
574 parser
->last
= parser
->tag
;
575 parser
->header
= NULL
;
576 parser
->filename
= g_strdup (filename
);
578 parser
->ctx
= g_markup_parse_context_new (&header_markup_parser
, 0, parser
, NULL
);
579 g_assert (parser
->ctx
!= NULL
);
585 npw_header_parser_free (NPWHeaderParser
* parser
)
587 g_return_if_fail (parser
!= NULL
);
589 g_free (parser
->filename
);
590 g_markup_parse_context_free (parser
->ctx
);
595 npw_header_parser_parse (NPWHeaderParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
597 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
603 npw_header_parser_end_parse (NPWHeaderParser* parser, GError** error)
605 return g_markup_parse_context_end_parse (parser->ctx, error);
609 npw_header_list_read (GList
** list
, const gchar
* filename
)
613 NPWHeaderParser
* parser
;
617 g_return_val_if_fail (list
!= NULL
, FALSE
);
618 g_return_val_if_fail (filename
!= NULL
, FALSE
);
620 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
622 g_warning ("%s", err
->message
);
628 parser
= npw_header_parser_new (list
, filename
);
630 npw_header_parser_parse (parser
, content
, len
, &err
);
631 header
= parser
->header
;
632 /* Parse only a part of the file, so need to call parser_end_parse */
634 npw_header_parser_free (parser
);
639 /* Parsing must end with an error
640 * generated at the end of the project wizard block */
641 g_warning ("Missing project wizard block in %s", filename
);
642 npw_header_free (header
);
646 if (g_error_matches (err
, parser_error_quark (), NPW_STOP_PARSING
) == FALSE
)
649 g_warning ("%s", err
->message
);
651 npw_header_free (header
);
657 /* Add header to list if template does not already exist*/
658 if (npw_header_list_find_header (*list
, header
) == NULL
)
660 *list
= npw_header_list_insert_header (*list
, header
);
668 *---------------------------------------------------------------------------*/
670 #define NPW_PAGE_PARSER_MAX_LEVEL 3 /* Maximum number of nested elements */
672 struct _NPWPageParser
674 /* Type of parser (not used) */
676 GMarkupParseContext
* ctx
;
677 /* Known element stack */
678 NPWTag tag
[NPW_PAGE_PARSER_MAX_LEVEL
+ 1];
680 /* Unknown element stack */
682 /* page number to read */
684 /* Current page object */
686 /* Current property object */
687 NPWProperty
* property
;
691 parse_page (NPWPageParser
* parser
,
692 const gchar
** attributes
,
693 const gchar
** values
)
695 if (parser
->count
!= 0)
698 if (parser
->count
> 0) parser
->count
--;
705 while (*attributes
!= NULL
)
707 switch (parse_attribute (*attributes
))
709 case NPW_NAME_ATTRIBUTE
:
710 npw_page_set_name (parser
->page
, *values
);
712 case NPW_LABEL_ATTRIBUTE
:
713 npw_page_set_label (parser
->page
, *values
);
715 case NPW_DESCRIPTION_ATTRIBUTE
:
716 npw_page_set_description (parser
->page
, *values
);
719 parser_warning (parser
->ctx
, "Unknown page attribute \"%s\"", *attributes
);
732 parse_property (NPWPageParser
* parser
,
733 const gchar
** attributes
,
734 const gchar
** values
)
736 parser
->property
= npw_property_new ();
737 npw_page_add_property (parser
->page
, parser
->property
);
739 while (*attributes
!= NULL
)
741 switch (parse_attribute (*attributes
))
743 case NPW_TYPE_ATTRIBUTE
:
744 npw_property_set_string_type (parser
->property
, *values
);
746 case NPW_RESTRICTION_ATTRIBUTE
:
747 npw_property_set_string_restriction (parser
->property
, *values
);
749 case NPW_NAME_ATTRIBUTE
:
750 npw_property_set_name (parser
->property
, *values
, parser
->page
);
752 case NPW_LABEL_ATTRIBUTE
:
753 npw_property_set_label (parser
->property
, *values
);
755 case NPW_DESCRIPTION_ATTRIBUTE
:
756 npw_property_set_description (parser
->property
, *values
);
758 case NPW_VALUE_ATTRIBUTE
:
759 npw_property_set_default (parser
->property
, *values
);
761 case NPW_SUMMARY_ATTRIBUTE
:
762 npw_property_set_summary_option (parser
->property
, parse_boolean_string (*values
));
764 case NPW_MANDATORY_ATTRIBUTE
:
765 npw_property_set_mandatory_option (parser
->property
, parse_boolean_string (*values
));
767 case NPW_EDITABLE_ATTRIBUTE
:
768 npw_property_set_editable_option (parser
->property
, parse_boolean_string (*values
));
770 case NPW_EXIST_ATTRIBUTE
:
771 npw_property_set_exist_option (parser
->property
, parse_boolean_string (*values
));
774 parser_warning (parser
->ctx
, "Unknown property attribute \"%s\"", *attributes
);
785 parse_item (NPWPageParser
* parser
,
786 const gchar
** attributes
,
787 const gchar
** values
)
789 const gchar
* label
= NULL
;
790 const gchar
* name
= NULL
;
792 while (*attributes
!= NULL
)
794 switch (parse_attribute (*attributes
))
796 case NPW_NAME_ATTRIBUTE
:
799 case NPW_LABEL_ATTRIBUTE
:
803 parser_warning (parser
->ctx
, "Unknown item attribute \"%s\"", *attributes
);
812 parser_warning (parser
->ctx
, "Missing name attribute");
816 npw_property_add_list_item (parser
->property
, name
, label
== NULL
? name
: label
);
823 parse_page_start (GMarkupParseContext
* context
,
825 const gchar
** attributes
,
826 const gchar
** values
,
830 NPWPageParser
* parser
= (NPWPageParser
*)data
;
832 gboolean known
= FALSE
;
834 /* Recognize element */
835 if (parser
->unknown
== 0)
837 /* Not inside an unknown element */
838 tag
= parse_tag (name
);
839 switch (*parser
->last
)
842 /* Top level element */
846 known
= parse_page (parser
, attributes
, values
);
849 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
856 /* Necessary to avoid neested page element */
859 case NPW_PROPERTY_TAG
:
860 known
= parse_property (parser
, attributes
, values
);
863 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
867 case NPW_PROPERTY_TAG
:
868 /* Necessary to avoid neested page & property element */
872 known
= parse_item (parser
, attributes
, values
);
875 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
880 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
888 /* Know element stack overflow */
889 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_PAGE_PARSER_MAX_LEVEL
);
900 parse_page_end (GMarkupParseContext
* context
,
905 NPWPageParser
* parser
= (NPWPageParser
*)data
;
907 if (parser
->unknown
> 0)
909 /* Pop unknown element */
912 else if (*parser
->last
!= NPW_NO_TAG
)
914 /* Pop known element */
919 /* Know element stack underflow */
920 g_return_if_reached ();
924 static GMarkupParser page_markup_parser
= {
933 npw_page_parser_new (NPWPage
* page
, const gchar
* filename
, gint count
)
935 NPWPageParser
* parser
;
937 g_return_val_if_fail (page
!= NULL
, NULL
);
938 g_return_val_if_fail (count
>= 0, NULL
);
940 parser
= g_new (NPWPageParser
, 1);
942 parser
->type
= NPW_PAGE_PARSER
;
945 parser
->tag
[0] = NPW_NO_TAG
;
946 parser
->last
=parser
->tag
;
948 parser
->count
= count
;
950 parser
->property
= NULL
;
952 parser
->ctx
= g_markup_parse_context_new (&page_markup_parser
, 0, parser
, NULL
);
953 g_assert (parser
->ctx
!= NULL
);
959 npw_page_parser_free (NPWPageParser
* parser
)
961 g_return_if_fail (parser
!= NULL
);
963 g_markup_parse_context_free (parser
->ctx
);
968 npw_page_parser_parse (NPWPageParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
970 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
974 npw_page_parser_end_parse (NPWPageParser
* parser
, GError
** error
)
976 return g_markup_parse_context_end_parse (parser
->ctx
, error
);
980 npw_page_read (NPWPage
* page
, const gchar
* filename
, gint count
)
984 NPWPageParser
* parser
;
987 g_return_val_if_fail (page
!= NULL
, FALSE
);
988 g_return_val_if_fail (filename
!= NULL
, FALSE
);
989 g_return_val_if_fail (count
< 0, FALSE
);
991 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
993 g_warning ("%s", err
->message
);
999 parser
= npw_page_parser_new (page
, filename
, count
);
1001 npw_page_parser_parse (parser
, content
, len
, &err
);
1002 if (err
== NULL
) npw_page_parser_end_parse (parser
, &err
);
1004 npw_page_parser_free (parser
);
1010 g_warning ("%s", err
->message
);
1020 /* Parse content block
1021 *---------------------------------------------------------------------------*/
1023 typedef struct _NPWFileTag
1030 struct _NPWFileListParser
1032 /* Type of parser (not used) */
1034 GMarkupParseContext
* ctx
;
1035 /* Known element stack */
1037 /* Unknown element stack */
1039 /* Current file list */
1044 npw_file_tag_free (NPWFileTag
*tag
)
1046 g_free (tag
->destination
);
1047 g_free (tag
->source
);
1048 g_slice_free (NPWFileTag
, tag
);
1051 /* concatenate two directories names, return value must be freed if
1052 * not equal to path1 or path2 */
1055 concat_directory (const gchar
* path1
, const gchar
* path2
)
1059 /* Check for not supported . and .. directory name in path2 */
1060 for (ptr
= path2
; ptr
!= '\0';)
1062 ptr
= strchr (ptr
, '.');
1063 if (ptr
== NULL
) break;
1065 /* Exception "." only is allowed */
1066 if ((ptr
== path2
) && (ptr
[1] == '\0')) break;
1068 if ((ptr
== path2
) || (ptr
[- 1] == G_DIR_SEPARATOR
))
1070 if (ptr
[1] == '.') ptr
++;
1071 if ((ptr
[1] == G_DIR_SEPARATOR
) || (ptr
[1] == '\0')) return NULL
;
1076 if ((*path1
== '\0') || (strcmp (path1
, ".") == 0) || g_path_is_absolute (path2
))
1078 return (char *)path2
;
1080 else if ((*path2
== '\0') || (strcmp (path2
, ".") == 0))
1082 return (char *)path1
;
1088 path
= g_string_new (path1
);
1089 if (path
->str
[path
->len
-1] != G_DIR_SEPARATOR
)
1091 g_string_append_c (path
, G_DIR_SEPARATOR
);
1093 g_string_append (path
, path2
);
1095 return g_string_free (path
, FALSE
);
1100 parse_directory (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1102 const gchar
* source
;
1103 const gchar
* destination
;
1106 /* Set default values */
1110 /* Read all attributes */
1111 while (*attributes
!= NULL
)
1113 switch (parse_attribute (*attributes
))
1115 case NPW_SOURCE_ATTRIBUTE
:
1118 case NPW_DESTINATION_ATTRIBUTE
:
1119 destination
= *values
;
1122 parser_warning (parser
->ctx
, "Unknow directory attribute \"%s\"", *attributes
);
1129 /* Need source or destination */
1130 if ((source
== NULL
) && (destination
!= NULL
))
1132 source
= destination
;
1134 else if ((source
!= NULL
) && (destination
== NULL
))
1136 destination
= source
;
1138 else if ((source
== NULL
) && (destination
== NULL
))
1140 parser_warning (parser
->ctx
, "Missing source or destination attribute");
1141 child
->tag
= NPW_NO_TAG
;
1146 path
= concat_directory (child
->source
, source
);
1149 parser_warning (parser
->ctx
, "Invalid directory source value \"%s\"", source
);
1150 child
->tag
= NPW_NO_TAG
;
1156 g_free (child
->source
);
1157 child
->source
= g_strdup (path
);
1159 else if (path
!= child
->source
)
1161 g_free (child
->source
);
1162 child
->source
= path
;
1166 path
= concat_directory (child
->destination
, destination
);
1169 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1170 child
->tag
= NPW_NO_TAG
;
1174 if (path
== destination
)
1176 g_free (child
->destination
);
1177 child
->destination
= g_strdup (path
);
1179 else if (path
!= child
->destination
)
1181 g_free (child
->destination
);
1182 child
->destination
= path
;
1187 parse_file (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1189 const gchar
* source
;
1190 const gchar
* destination
;
1192 gchar
* full_destination
;
1196 gboolean autogen_set
;
1199 /* Set default values */
1205 autogen_set
= FALSE
;
1207 while (*attributes
!= NULL
)
1209 switch (parse_attribute (*attributes
))
1211 case NPW_SOURCE_ATTRIBUTE
:
1214 case NPW_DESTINATION_ATTRIBUTE
:
1215 destination
= *values
;
1217 case NPW_PROJECT_ATTRIBUTE
:
1218 project
= parse_boolean_string (*values
);
1220 case NPW_EXECUTABLE_ATTRIBUTE
:
1221 execute
= parse_boolean_string (*values
);
1223 case NPW_AUTOGEN_ATTRIBUTE
:
1224 autogen
= parse_boolean_string (*values
);
1228 parser_warning (parser
->ctx
, "Unknow file attribute \"%s\"", *attributes
);
1235 if ((source
== NULL
) && (destination
!= NULL
))
1237 source
= destination
;
1239 else if ((source
!= NULL
) && (destination
== NULL
))
1241 destination
= source
;
1243 else if ((source
== NULL
) && (destination
== NULL
))
1245 parser_warning (parser
->ctx
, "Missing source or destination attribute");
1246 child
->tag
= NPW_NO_TAG
;
1251 full_source
= concat_directory (child
->source
, source
);
1252 if ((full_source
== NULL
) || (full_source
== child
->source
))
1254 parser_warning (parser
->ctx
, "Invalid file source value \"%s\"", source
);
1255 child
->tag
= NPW_NO_TAG
;
1259 full_destination
= concat_directory (child
->destination
, destination
);
1260 if ((full_destination
== NULL
) || (full_destination
== child
->destination
))
1262 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1263 child
->tag
= NPW_NO_TAG
;
1268 file
= npw_file_new_file (full_destination
, full_source
);
1269 parser
->list
= g_list_prepend (parser
->list
, file
);
1270 npw_file_set_execute (file
, execute
);
1271 npw_file_set_project (file
, project
);
1273 npw_file_set_autogen (file
, autogen
? NPW_TRUE
: NPW_FALSE
);
1275 if (source
!= full_source
)
1276 g_free (full_source
);
1277 if (destination
!= full_destination
)
1278 g_free (full_destination
);
1282 parse_file_start (GMarkupParseContext
* context
,
1284 const gchar
** attributes
,
1285 const gchar
** values
,
1289 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1294 child
.tag
= NPW_NO_TAG
;
1295 child
.source
= NULL
;
1296 child
.destination
= NULL
;
1298 /* Recognize element */
1299 if (parser
->unknown
== 0)
1301 /* Not inside an unknown element */
1302 tag
= parse_tag (name
);
1304 parent
= g_queue_peek_head (parser
->tag
);
1305 child
.source
= g_strdup (parent
->source
);
1306 child
.destination
= g_strdup (parent
->destination
);
1307 switch (parent
->tag
)
1310 /* Top level element */
1313 case NPW_CONTENT_TAG
:
1316 case NPW_UNKNOW_TAG
:
1317 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1323 case NPW_CONTENT_TAG
:
1326 case NPW_DIRECTORY_TAG
:
1328 parse_directory (parser
, &child
, attributes
, values
);
1331 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1335 case NPW_DIRECTORY_TAG
:
1338 case NPW_DIRECTORY_TAG
:
1340 parse_directory (parser
, &child
, attributes
, values
);
1344 parse_file (parser
, &child
, attributes
, values
);
1347 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1352 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1358 if (child
.tag
!= NPW_NO_TAG
)
1360 NPWFileTag
* new_child
;
1362 new_child
= g_slice_new (NPWFileTag
);
1363 memcpy (new_child
, &child
, sizeof (child
));
1364 g_queue_push_head (parser
->tag
, new_child
);
1368 g_free (child
.source
);
1369 g_free (child
.destination
);
1375 parse_file_end (GMarkupParseContext
* context
,
1380 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1382 DEBUG_PRINT("parser_file_end");
1383 if (parser
->unknown
> 0)
1385 /* Pop unknown element */
1388 else if (((NPWFileTag
*)g_queue_peek_head (parser
->tag
))->tag
!= NPW_NO_TAG
)
1390 /* Pop known element */
1391 npw_file_tag_free (g_queue_pop_head (parser
->tag
));
1395 /* Know stack underflow */
1396 g_return_if_reached ();
1400 static GMarkupParser file_markup_parser
= {
1409 npw_file_list_parser_new (const gchar
* filename
)
1411 NPWFileListParser
* parser
;
1414 g_return_val_if_fail (filename
!= NULL
, NULL
);
1416 parser
= g_new (NPWFileListParser
, 1);
1418 parser
->type
= NPW_FILE_PARSER
;
1420 parser
->unknown
= 0;
1421 parser
->tag
= g_queue_new ();
1422 root
= g_slice_new0 (NPWFileTag
);
1423 root
->tag
= NPW_NO_TAG
;
1424 root
->destination
= g_strdup (".");
1425 /* Use .wiz file path as base source directory */
1426 root
->source
= g_path_get_dirname (filename
);
1427 g_queue_push_head (parser
->tag
, root
);
1429 parser
->list
= NULL
;
1431 parser
->ctx
= g_markup_parse_context_new (&file_markup_parser
, 0, parser
, NULL
);
1432 g_assert (parser
->ctx
!= NULL
);
1438 npw_file_list_parser_free (NPWFileListParser
* parser
)
1440 g_return_if_fail (parser
!= NULL
);
1442 g_markup_parse_context_free (parser
->ctx
);
1443 DEBUG_PRINT("parser free");
1444 g_queue_foreach (parser
->tag
, (GFunc
)npw_file_tag_free
, NULL
);
1445 DEBUG_PRINT("parser free ok");
1446 g_queue_free (parser
->tag
);
1451 npw_file_list_parser_parse (NPWFileListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1453 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
1457 npw_file_list_parser_end_parse (NPWFileListParser
* parser
, GError
** error
)
1461 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1463 /* Reverse file list */
1464 parser
->list
= g_list_reverse (parser
->list
);
1466 list
= parser
->list
;
1472 /* Parse action block
1473 *---------------------------------------------------------------------------*/
1475 #define NPW_ACTION_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
1477 struct _NPWActionListParser
1479 /* Type of parser (not used) */
1481 GMarkupParseContext
* ctx
;
1482 /* Known element stack */
1483 NPWTag tag
[NPW_ACTION_PARSER_MAX_LEVEL
+ 1];
1485 /* Unknown element stack */
1487 /* Current action list object */
1492 parse_run (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1494 const gchar
* command
= NULL
;
1496 while (*attributes
!= NULL
)
1498 switch (parse_attribute (*attributes
))
1500 case NPW_COMMAND_ATTRIBUTE
:
1504 parser_warning (parser
->ctx
, "Unknown run attribute \"%s\"", *attributes
);
1511 if (command
== NULL
)
1513 parser_warning (parser
->ctx
, "Missing command attribute");
1519 action
= npw_action_new_command (command
);
1520 parser
->list
= g_list_prepend (parser
->list
, action
);
1527 parse_open (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1529 const gchar
* file
= NULL
;
1531 while (*attributes
!= NULL
)
1533 switch (parse_attribute (*attributes
))
1535 case NPW_FILE_ATTRIBUTE
:
1539 parser_warning (parser
->ctx
, "Unknown open attribute \"%s\"", *attributes
);
1548 parser_warning (parser
->ctx
, "Missing file attribute");
1554 action
= npw_action_new_file (file
);
1555 parser
->list
= g_list_prepend (parser
->list
, action
);
1562 parse_action_start (GMarkupParseContext
* context
, const gchar
* name
, const gchar
** attributes
,
1563 const gchar
** values
, gpointer data
, GError
** error
)
1565 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1567 gboolean known
= FALSE
;
1569 /* Recognize element */
1570 if (parser
->unknown
== 0)
1572 /* Not inside an unknown element */
1573 tag
= parse_tag (name
);
1574 switch (*parser
->last
)
1577 /* Top level element */
1580 case NPW_ACTION_TAG
:
1583 case NPW_UNKNOW_TAG
:
1584 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1590 case NPW_ACTION_TAG
:
1591 /* Necessary to avoid neested page element */
1595 known
= parse_run (parser
, attributes
, values
);
1598 known
= parse_open (parser
, attributes
, values
);
1601 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1606 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1614 /* Know element stack overflow */
1615 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_ACTION_PARSER_MAX_LEVEL
);
1617 *parser
->last
= tag
;
1626 parse_action_end (GMarkupParseContext
* context
, const gchar
* name
, gpointer data
, GError
** error
)
1628 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1630 if (parser
->unknown
> 0)
1632 /* Pop unknown element */
1635 else if (*parser
->last
!= NPW_NO_TAG
)
1637 /* Pop known element */
1642 /* Know element stack underflow */
1643 g_return_if_reached ();
1647 static GMarkupParser action_markup_parser
= {
1655 NPWActionListParser
*
1656 npw_action_list_parser_new (void)
1658 NPWActionListParser
* parser
;
1660 parser
= g_new (NPWActionListParser
, 1);
1662 parser
->type
= NPW_ACTION_PARSER
;
1664 parser
->unknown
= 0;
1665 parser
->tag
[0] = NPW_NO_TAG
;
1666 parser
->last
= parser
->tag
;
1668 parser
->list
= NULL
;
1670 parser
->ctx
= g_markup_parse_context_new (&action_markup_parser
, 0, parser
, NULL
);
1671 g_assert (parser
->ctx
!= NULL
);
1677 npw_action_list_parser_free (NPWActionListParser
* parser
)
1679 g_return_if_fail (parser
!= NULL
);
1681 g_markup_parse_context_free (parser
->ctx
);
1686 npw_action_list_parser_parse (NPWActionListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1690 g_markup_parse_context_parse (parser
->ctx
, text
, len
, &err
);
1693 g_warning ("%s", err
->message
);
1700 npw_action_list_parser_end_parse (NPWActionListParser
* parser
, GError
** error
)
1704 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1706 /* Reverse file list */
1707 parser
->list
= g_list_reverse (parser
->list
);
1709 list
= parser
->list
;