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 *---------------------------------------------------------------------------*/
30 #include <glib/gdir.h>
35 /*---------------------------------------------------------------------------*/
37 #define PROJECT_WIZARD_EXTENSION ".wiz"
38 #define STRING_CHUNK_SIZE 256
42 NPW_PROJECT_WIZARD_TAG
,
46 NPW_REQUIRED_PROGRAM_TAG
,
47 NPW_REQUIRED_PACKAGE_TAG
,
65 NPW_DESCRIPTION_ATTRIBUTE
,
67 NPW_SUMMARY_ATTRIBUTE
,
69 NPW_RESTRICTION_ATTRIBUTE
,
70 NPW_MANDATORY_ATTRIBUTE
,
72 NPW_EDITABLE_ATTRIBUTE
,
74 NPW_DESTINATION_ATTRIBUTE
,
75 NPW_EXECUTABLE_ATTRIBUTE
,
76 NPW_PROJECT_ATTRIBUTE
,
77 NPW_AUTOGEN_ATTRIBUTE
,
78 NPW_COMMAND_ATTRIBUTE
,
95 /* Read all project templates in a directory
96 *---------------------------------------------------------------------------*/
99 npw_header_list_readdir (NPWHeaderList
* this, const gchar
* path
)
105 g_return_val_if_fail (this != NULL
, FALSE
);
106 g_return_val_if_fail (path
!= NULL
, FALSE
);
108 /* Read all project template files */
109 dir
= g_dir_open (path
, 0, NULL
);
110 if (!dir
) return FALSE
;
112 while ((name
= g_dir_read_name (dir
)) != NULL
)
114 char* filename
= g_build_filename (path
, name
, NULL
);
116 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
))
118 /* Search recursively in sub directory */
119 if (npw_header_list_readdir (this, filename
))
124 else if (g_str_has_suffix (name
, PROJECT_WIZARD_EXTENSION
))
126 if (npw_header_list_read (this, filename
))
128 /* Read at least one project file */
140 /* Common parser functions
141 *---------------------------------------------------------------------------*/
144 parse_tag (const char* name
)
146 if (strcmp (name
, "project-wizard") == 0)
148 return NPW_PROJECT_WIZARD_TAG
;
150 else if ((strcmp ("_name", name
) == 0) || (strcmp ("name", name
) == 0))
154 else if ((strcmp ("_description", name
) == 0) || (strcmp ("description", name
) == 0))
156 return NPW_DESCRIPTION_TAG
;
158 else if (strcmp ("icon", name
) == 0)
162 else if (strcmp ("category", name
) == 0)
164 return NPW_CATEGORY_TAG
;
166 else if (strcmp ("required-program", name
) == 0)
168 return NPW_REQUIRED_PROGRAM_TAG
;
170 else if (strcmp ("required-package", name
) == 0)
172 return NPW_REQUIRED_PACKAGE_TAG
;
174 else if (strcmp ("page", name
) == 0)
178 else if (strcmp ("property", name
) == 0)
180 return NPW_PROPERTY_TAG
;
182 else if (strcmp ("item", name
) == 0)
186 else if (strcmp ("directory", name
) == 0)
188 return NPW_DIRECTORY_TAG
;
190 else if (strcmp ("content", name
) == 0)
192 return NPW_CONTENT_TAG
;
194 else if (strcmp ("file", name
) == 0)
198 else if (strcmp ("action", name
) == 0)
200 return NPW_ACTION_TAG
;
202 else if (strcmp ("run", name
) == 0)
206 else if (strcmp ("open", name
) == 0)
212 return NPW_UNKNOW_TAG
;
217 parse_attribute (const char* name
)
219 if (strcmp ("name", name
) == 0)
221 return NPW_NAME_ATTRIBUTE
;
223 else if (strcmp ("_label", name
) == 0)
225 return NPW_LABEL_ATTRIBUTE
;
227 else if (strcmp ("_description", name
) == 0)
229 return NPW_DESCRIPTION_ATTRIBUTE
;
231 else if (strcmp ("default", name
) == 0 || strcmp ("value", name
) == 0)
233 return NPW_VALUE_ATTRIBUTE
;
235 else if (strcmp ("type", name
) == 0)
237 return NPW_TYPE_ATTRIBUTE
;
239 else if (strcmp ("restriction", name
) == 0)
241 return NPW_RESTRICTION_ATTRIBUTE
;
243 else if (strcmp ("summary", name
) == 0)
245 return NPW_SUMMARY_ATTRIBUTE
;
247 else if (strcmp ("mandatory", name
) == 0)
249 return NPW_MANDATORY_ATTRIBUTE
;
251 else if (strcmp ("editable", name
) == 0)
253 return NPW_EDITABLE_ATTRIBUTE
;
255 else if (strcmp ("exist", name
) == 0)
257 return NPW_EXIST_ATTRIBUTE
;
259 else if (strcmp ("source", name
) == 0)
261 return NPW_SOURCE_ATTRIBUTE
;
263 else if (strcmp ("destination", name
) == 0)
265 return NPW_DESTINATION_ATTRIBUTE
;
267 else if (strcmp ("executable", name
) == 0)
269 return NPW_EXECUTABLE_ATTRIBUTE
;
271 else if (strcmp ("project", name
) == 0)
273 return NPW_PROJECT_ATTRIBUTE
;
275 else if (strcmp ("autogen", name
) == 0)
277 return NPW_AUTOGEN_ATTRIBUTE
;
279 else if (strcmp ("command", name
) == 0)
281 return NPW_COMMAND_ATTRIBUTE
;
283 else if (strcmp ("file", name
) == 0)
285 return NPW_FILE_ATTRIBUTE
;
289 return NPW_UNKNOW_ATTRIBUTE
;
294 parse_boolean_string (const gchar
* value
)
296 return g_ascii_strcasecmp ("no", value
) && g_ascii_strcasecmp ("0", value
) && g_ascii_strcasecmp ("false", value
);
300 parser_error_quark (void)
302 static GQuark error_quark
= 0;
304 if (error_quark
== 0)
305 error_quark
= g_quark_from_static_string ("parser_error_quark");
310 parser_warning (GMarkupParseContext
* ctx
, const gchar
* format
,...)
316 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
317 msg
= g_strdup_printf ("line %d: %s", line
, format
);
318 va_start (args
, format
);
319 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_WARNING
, msg
, args
);
325 parser_critical (GMarkupParseContext
* ctx
, const gchar
* format
,...)
331 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
332 msg
= g_strdup_printf ("line %d: %s", line
, format
);
333 va_start (args
, format
);
334 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_CRITICAL
, msg
, args
);
338 /* Parse project wizard block
339 *---------------------------------------------------------------------------*/
341 #define NPW_HEADER_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
343 typedef struct _NPWHeaderParser
345 /* Type of parser (not used) */
347 GMarkupParseContext
* ctx
;
348 /* Known element stack */
349 NPWTag tag
[NPW_HEADER_PARSER_MAX_LEVEL
+ 1];
351 /* Unknown element stack */
353 /* List where should be added the header */
357 /* Name of file read */
362 parse_header_start (GMarkupParseContext
* context
,
364 const gchar
** attributes
,
365 const gchar
** values
,
369 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
371 gboolean known
= FALSE
;
373 /* Recognize element */
374 if (parser
->unknown
== 0)
376 /* Not inside an unknown element */
377 tag
= parse_tag (name
);
378 switch (*parser
->last
)
381 /* Top level element */
384 case NPW_PROJECT_WIZARD_TAG
:
385 parser
->header
= npw_header_new (parser
->list
);
386 npw_header_set_filename (parser
->header
, parser
->filename
);
390 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
396 case NPW_PROJECT_WIZARD_TAG
:
397 /* Necessary to avoid neested PROJECT_WIZARD element */
401 case NPW_DESCRIPTION_TAG
:
403 case NPW_CATEGORY_TAG
:
404 case NPW_REQUIRED_PROGRAM_TAG
:
405 case NPW_REQUIRED_PACKAGE_TAG
:
409 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
414 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
422 /* Know element stack overflow */
423 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_HEADER_PARSER_MAX_LEVEL
);
434 parse_header_end (GMarkupParseContext
* context
,
439 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
441 if (parser
->unknown
> 0)
443 /* Pop unknown element */
446 else if (*parser
->last
!= NPW_NO_TAG
)
448 /* Pop known element */
450 if (parser
->last
[1] == NPW_PROJECT_WIZARD_TAG
)
452 /* Check if the element is valid */
453 if (parser
->header
&& !npw_header_get_name (parser
->header
))
455 parser_critical (parser
->ctx
, "Missing name attribute");
456 npw_header_free (parser
->header
);
459 /* Stop parsing after first project wizard block
460 * Remaining file need to be passed through autogen
461 * to be a valid xml file */
463 /* error should be available to stop parsing */
464 g_return_if_fail (error
!= NULL
);
467 *error
= g_error_new_literal (parser_error_quark (), NPW_STOP_PARSING
, "");
472 /* Know element stack underflow */
473 g_return_if_reached ();
478 parse_header_text (GMarkupParseContext
* context
,
484 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
486 if (parser
->unknown
== 0)
488 switch (*parser
->last
)
491 if (npw_header_get_name (parser
->header
) == NULL
)
493 npw_header_set_name (parser
->header
, text
);
497 parser_critical (parser
->ctx
, "Duplicated name tag");
500 case NPW_DESCRIPTION_TAG
:
501 if (npw_header_get_description (parser
->header
) == NULL
)
503 npw_header_set_description (parser
->header
, text
);
507 parser_critical (parser
->ctx
, "Duplicated description tag");
511 if (npw_header_get_iconfile (parser
->header
) == NULL
)
516 path
= g_path_get_dirname (parser
->filename
);
517 filename
= g_build_filename (path
, text
, NULL
);
518 npw_header_set_iconfile (parser
->header
, filename
);
524 parser_critical (parser
->ctx
, "Duplicated icon tag");
527 case NPW_CATEGORY_TAG
:
528 if (npw_header_get_category (parser
->header
) == NULL
)
530 npw_header_set_category (parser
->header
, text
);
534 parser_critical (parser
->ctx
, "Duplicated category tag");
537 case NPW_REQUIRED_PROGRAM_TAG
:
538 npw_header_add_required_program (parser
->header
, text
);
540 case NPW_REQUIRED_PACKAGE_TAG
:
541 npw_header_add_required_package (parser
->header
, text
);
543 case NPW_PROJECT_WIZARD_TAG
:
548 g_return_if_reached ();
554 static GMarkupParser header_markup_parser
= {
562 static NPWHeaderParser
*
563 npw_header_parser_new (NPWHeaderList
* list
, const gchar
* filename
)
565 NPWHeaderParser
* this;
567 g_return_val_if_fail (list
!= NULL
, NULL
);
568 g_return_val_if_fail (filename
!= NULL
, NULL
);
570 this = g_new0 (NPWHeaderParser
, 1);
572 this->type
= NPW_HEADER_PARSER
;
574 this->tag
[0] = NPW_NO_TAG
;
575 this->last
= this->tag
;
578 this->filename
= g_strdup (filename
);
580 this->ctx
= g_markup_parse_context_new (&header_markup_parser
, 0, this, NULL
);
581 g_assert (this->ctx
!= NULL
);
587 npw_header_parser_free (NPWHeaderParser
* this)
589 g_return_if_fail (this != NULL
);
591 g_free (this->filename
);
592 g_markup_parse_context_free (this->ctx
);
597 npw_header_parser_parse (NPWHeaderParser
* this, const gchar
* text
, gssize len
, GError
** error
)
599 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
605 npw_header_parser_end_parse (NPWHeaderParser* this, GError** error)
607 return g_markup_parse_context_end_parse (this->ctx, error);
611 npw_header_list_read (NPWHeaderList
* this, const gchar
* filename
)
615 NPWHeaderParser
* parser
;
618 g_return_val_if_fail (this != NULL
, FALSE
);
619 g_return_val_if_fail (filename
!= NULL
, FALSE
);
621 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
623 g_warning (err
->message
);
629 parser
= npw_header_parser_new (this, filename
);
631 npw_header_parser_parse (parser
, content
, len
, &err
);
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
);
645 if (g_error_matches (err
, parser_error_quark (), NPW_STOP_PARSING
) == FALSE
)
648 g_warning (err
->message
);
660 *---------------------------------------------------------------------------*/
662 #define NPW_PAGE_PARSER_MAX_LEVEL 3 /* Maximum number of nested elements */
664 struct _NPWPageParser
666 /* Type of parser (not used) */
668 GMarkupParseContext
* ctx
;
669 /* Known element stack */
670 NPWTag tag
[NPW_PAGE_PARSER_MAX_LEVEL
+ 1];
672 /* Unknown element stack */
674 /* page number to read */
676 /* Current page object */
678 /* Current property object */
679 NPWProperty
* property
;
683 parse_page (NPWPageParser
* this,
684 const gchar
** attributes
,
685 const gchar
** values
)
687 if (this->count
!= 0)
690 if (this->count
> 0) this->count
--;
697 while (*attributes
!= NULL
)
699 switch (parse_attribute (*attributes
))
701 case NPW_NAME_ATTRIBUTE
:
702 npw_page_set_name (this->page
, *values
);
704 case NPW_LABEL_ATTRIBUTE
:
705 npw_page_set_label (this->page
, *values
);
707 case NPW_DESCRIPTION_ATTRIBUTE
:
708 npw_page_set_description (this->page
, *values
);
711 parser_warning (this->ctx
, "Unknown page attribute \"%s\"", *attributes
);
724 parse_property (NPWPageParser
* this,
725 const gchar
** attributes
,
726 const gchar
** values
)
728 this->property
= npw_property_new (this->page
);
730 while (*attributes
!= NULL
)
732 switch (parse_attribute (*attributes
))
734 case NPW_TYPE_ATTRIBUTE
:
735 npw_property_set_string_type (this->property
, *values
);
737 case NPW_RESTRICTION_ATTRIBUTE
:
738 npw_property_set_string_restriction (this->property
, *values
);
740 case NPW_NAME_ATTRIBUTE
:
741 npw_property_set_name (this->property
, *values
);
743 case NPW_LABEL_ATTRIBUTE
:
744 npw_property_set_label (this->property
, *values
);
746 case NPW_DESCRIPTION_ATTRIBUTE
:
747 npw_property_set_description (this->property
, *values
);
749 case NPW_VALUE_ATTRIBUTE
:
750 npw_property_set_default (this->property
, *values
);
752 case NPW_SUMMARY_ATTRIBUTE
:
753 npw_property_set_summary_option (this->property
, parse_boolean_string (*values
));
755 case NPW_MANDATORY_ATTRIBUTE
:
756 npw_property_set_mandatory_option (this->property
, parse_boolean_string (*values
));
758 case NPW_EDITABLE_ATTRIBUTE
:
759 npw_property_set_editable_option (this->property
, parse_boolean_string (*values
));
761 case NPW_EXIST_ATTRIBUTE
:
762 npw_property_set_exist_option (this->property
, parse_boolean_string (*values
));
765 parser_warning (this->ctx
, "Unknown property attribute \"%s\"", *attributes
);
776 parse_item (NPWPageParser
* this,
777 const gchar
** attributes
,
778 const gchar
** values
)
780 const gchar
* label
= NULL
;
781 const gchar
* name
= NULL
;
783 while (*attributes
!= NULL
)
785 switch (parse_attribute (*attributes
))
787 case NPW_NAME_ATTRIBUTE
:
790 case NPW_LABEL_ATTRIBUTE
:
794 parser_warning (this->ctx
, "Unknown item attribute \"%s\"", *attributes
);
803 parser_warning (this->ctx
, "Missing name attribute");
807 npw_property_add_list_item (this->property
, name
, label
== NULL
? name
: label
);
814 parse_page_start (GMarkupParseContext
* context
,
816 const gchar
** attributes
,
817 const gchar
** values
,
821 NPWPageParser
* parser
= (NPWPageParser
*)data
;
823 gboolean known
= FALSE
;
825 /* Recognize element */
826 if (parser
->unknown
== 0)
828 /* Not inside an unknown element */
829 tag
= parse_tag (name
);
830 switch (*parser
->last
)
833 /* Top level element */
837 known
= parse_page (parser
, attributes
, values
);
840 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
847 /* Necessary to avoid neested page element */
850 case NPW_PROPERTY_TAG
:
851 known
= parse_property (parser
, attributes
, values
);
854 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
858 case NPW_PROPERTY_TAG
:
859 /* Necessary to avoid neested page & property element */
863 known
= parse_item (parser
, attributes
, values
);
866 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
871 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
879 /* Know element stack overflow */
880 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_PAGE_PARSER_MAX_LEVEL
);
891 parse_page_end (GMarkupParseContext
* context
,
896 NPWPageParser
* parser
= (NPWPageParser
*)data
;
898 if (parser
->unknown
> 0)
900 /* Pop unknown element */
903 else if (*parser
->last
!= NPW_NO_TAG
)
905 /* Pop known element */
910 /* Know element stack underflow */
911 g_return_if_reached ();
915 static GMarkupParser page_markup_parser
= {
924 npw_page_parser_new (NPWPage
* page
, const gchar
* filename
, gint count
)
928 g_return_val_if_fail (page
!= NULL
, NULL
);
929 g_return_val_if_fail (count
>= 0, NULL
);
931 this = g_new (NPWPageParser
, 1);
933 this->type
= NPW_PAGE_PARSER
;
936 this->tag
[0] = NPW_NO_TAG
;
937 this->last
= this->tag
;
941 this->property
= NULL
;
943 this->ctx
= g_markup_parse_context_new (&page_markup_parser
, 0, this, NULL
);
944 g_assert (this->ctx
!= NULL
);
950 npw_page_parser_free (NPWPageParser
* this)
952 g_return_if_fail (this != NULL
);
954 g_markup_parse_context_free (this->ctx
);
959 npw_page_parser_parse (NPWPageParser
* this, const gchar
* text
, gssize len
, GError
** error
)
961 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
965 npw_page_parser_end_parse (NPWPageParser
* this, GError
** error
)
967 return g_markup_parse_context_end_parse (this->ctx
, error
);
971 npw_page_read (NPWPage
* this, const gchar
* filename
, gint count
)
975 NPWPageParser
* parser
;
978 g_return_val_if_fail (this != NULL
, FALSE
);
979 g_return_val_if_fail (filename
!= NULL
, FALSE
);
980 g_return_val_if_fail (count
< 0, FALSE
);
982 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
984 g_warning (err
->message
);
990 parser
= npw_page_parser_new (this, filename
, count
);
992 npw_page_parser_parse (parser
, content
, len
, &err
);
993 if (err
== NULL
) npw_page_parser_end_parse (parser
, &err
);
995 npw_page_parser_free (parser
);
1001 g_warning (err
->message
);
1011 /* Parse content block
1012 *---------------------------------------------------------------------------*/
1014 #define NPW_FILE_PARSER_DEFAULT_LEVEL 4 /* Default number of nested elements
1015 * Dynamically allocated (no maximum) */
1016 typedef struct _NPWFileTag
1019 const gchar
* destination
;
1020 const gchar
* source
;
1023 struct _NPWFileListParser
1025 /* Type of parser (not used) */
1027 GMarkupParseContext
* ctx
;
1028 /* Known element stack */
1030 GStringChunk
* str_pool
;
1031 GMemChunk
* tag_pool
;
1033 /* Unknown element stack */
1035 /* Current file list */
1039 /* concatenate two directories names, return value must be freed if
1040 * not equal to path1 or path2 */
1043 concat_directory (const gchar
* path1
, const gchar
* path2
)
1047 /* Check for not supported . and .. directory name in path2 */
1048 for (ptr
= path2
; ptr
!= '\0';)
1050 ptr
= strchr (ptr
, '.');
1051 if (ptr
== NULL
) break;
1053 /* Exception "." only is allowed */
1054 if ((ptr
== path2
) && (ptr
[1] == '\0')) break;
1056 if ((ptr
== path2
) || (ptr
[- 1] == G_DIR_SEPARATOR
))
1058 if (ptr
[1] == '.') ptr
++;
1059 if ((ptr
[1] == G_DIR_SEPARATOR
) || (ptr
[1] == '\0')) return NULL
;
1064 if ((*path1
== '\0') || (strcmp (path1
, ".") == 0) || g_path_is_absolute (path2
))
1066 return (char *)path2
;
1068 else if ((*path2
== '\0') || (strcmp (path2
, ".") == 0))
1070 return (char *)path1
;
1076 path
= g_string_new (path1
);
1077 if (path
->str
[path
->len
-1] != G_DIR_SEPARATOR
)
1079 g_string_append_c (path
, G_DIR_SEPARATOR
);
1081 g_string_append (path
, path2
);
1083 return g_string_free (path
, FALSE
);
1088 parse_directory (NPWFileListParser
* this, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1090 const gchar
* source
;
1091 const gchar
* destination
;
1094 /* Set default values */
1098 /* Read all attributes */
1099 while (*attributes
!= NULL
)
1101 switch (parse_attribute (*attributes
))
1103 case NPW_SOURCE_ATTRIBUTE
:
1106 case NPW_DESTINATION_ATTRIBUTE
:
1107 destination
= *values
;
1110 parser_warning (this->ctx
, "Unknow directory attribute \"%s\"", *attributes
);
1117 /* Need source or destination */
1118 if ((source
== NULL
) && (destination
!= NULL
))
1120 source
= destination
;
1122 else if ((source
!= NULL
) && (destination
== NULL
))
1124 destination
= source
;
1126 else if ((source
== NULL
) && (destination
== NULL
))
1128 parser_warning (this->ctx
, "Missing source or destination attribute");
1129 child
->tag
= NPW_NO_TAG
;
1134 path
= concat_directory (child
->source
, source
);
1137 parser_warning (this->ctx
, "Invalid directory source value \"%s\"", source
);
1138 child
->tag
= NPW_NO_TAG
;
1142 if (path
!= child
->source
)
1144 child
->source
= g_string_chunk_insert (this->str_pool
, path
);
1145 if (path
!= source
) g_free (path
);
1148 path
= concat_directory (child
->destination
, destination
);
1151 parser_warning (this->ctx
, "Invalid directory destination value \"%s\"", source
);
1152 child
->tag
= NPW_NO_TAG
;
1156 if (path
!= child
->destination
)
1158 child
->destination
= g_string_chunk_insert (this->str_pool
, path
);
1159 if (path
!= destination
) g_free (path
);
1164 parse_file (NPWFileListParser
* this, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1166 const gchar
* source
;
1167 const gchar
* destination
;
1169 gchar
* full_destination
;
1173 gboolean autogen_set
;
1176 /* Set default values */
1182 autogen_set
= FALSE
;
1184 while (*attributes
!= NULL
)
1186 switch (parse_attribute (*attributes
))
1188 case NPW_SOURCE_ATTRIBUTE
:
1191 case NPW_DESTINATION_ATTRIBUTE
:
1192 destination
= *values
;
1194 case NPW_PROJECT_ATTRIBUTE
:
1195 project
= parse_boolean_string (*values
);
1197 case NPW_EXECUTABLE_ATTRIBUTE
:
1198 execute
= parse_boolean_string (*values
);
1200 case NPW_AUTOGEN_ATTRIBUTE
:
1201 autogen
= parse_boolean_string (*values
);
1205 parser_warning (this->ctx
, "Unknow file attribute \"%s\"", *attributes
);
1212 if ((source
== NULL
) && (destination
!= NULL
))
1214 source
= destination
;
1216 else if ((source
!= NULL
) && (destination
== NULL
))
1218 destination
= source
;
1220 else if ((source
== NULL
) && (destination
== NULL
))
1222 parser_warning (this->ctx
, "Missing source or destination attribute");
1223 child
->tag
= NPW_NO_TAG
;
1228 full_source
= concat_directory (child
->source
, source
);
1229 if ((full_source
== NULL
) || (full_source
== child
->source
))
1231 parser_warning (this->ctx
, "Invalid file source value \"%s\"", source
);
1232 child
->tag
= NPW_NO_TAG
;
1236 full_destination
= concat_directory (child
->destination
, destination
);
1237 if ((full_destination
== NULL
) || (full_destination
== child
->source
))
1239 parser_warning (this->ctx
, "Invalid directory destination value \"%s\"", source
);
1240 child
->tag
= NPW_NO_TAG
;
1245 file
= npw_file_new (this->list
);
1246 npw_file_set_type (file
, NPW_FILE
);
1247 npw_file_set_source (file
, full_source
);
1248 npw_file_set_destination (file
, full_destination
);
1249 npw_file_set_execute (file
, execute
);
1250 npw_file_set_project (file
, project
);
1252 npw_file_set_autogen (file
, autogen
? NPW_TRUE
: NPW_FALSE
);
1254 if (source
!= full_source
)
1255 g_free (full_source
);
1256 if (destination
!= full_destination
)
1257 g_free (full_destination
);
1261 parse_file_start (GMarkupParseContext
* context
,
1263 const gchar
** attributes
,
1264 const gchar
** values
,
1268 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1273 child
.tag
= NPW_NO_TAG
;
1275 /* Recognize element */
1276 if (parser
->unknown
== 0)
1278 /* Not inside an unknown element */
1279 tag
= parse_tag (name
);
1281 parent
= g_queue_peek_head (parser
->tag
);
1282 child
.source
= parent
->source
;
1283 child
.destination
= parent
->destination
;
1284 switch (parent
->tag
)
1287 /* Top level element */
1290 case NPW_CONTENT_TAG
:
1293 case NPW_UNKNOW_TAG
:
1294 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1300 case NPW_CONTENT_TAG
:
1303 case NPW_DIRECTORY_TAG
:
1305 parse_directory (parser
, &child
, attributes
, values
);
1308 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1312 case NPW_DIRECTORY_TAG
:
1315 case NPW_DIRECTORY_TAG
:
1317 parse_directory (parser
, &child
, attributes
, values
);
1321 parse_file (parser
, &child
, attributes
, values
);
1324 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1329 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1335 if (child
.tag
!= NPW_NO_TAG
)
1337 NPWFileTag
* new_child
;
1339 new_child
= g_chunk_new (NPWFileTag
, parser
->tag_pool
);
1340 memcpy (new_child
, &child
, sizeof (child
));
1341 g_queue_push_head (parser
->tag
, new_child
);
1350 parse_file_end (GMarkupParseContext
* context
,
1355 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1357 if (parser
->unknown
> 0)
1359 /* Pop unknown element */
1362 else if (((NPWFileTag
*)g_queue_peek_head (parser
->tag
))->tag
!= NPW_NO_TAG
)
1364 /* Pop known element */
1365 g_mem_chunk_free (parser
->tag_pool
, g_queue_pop_head (parser
->tag
));
1369 /* Know stack underflow */
1370 g_return_if_reached ();
1374 static GMarkupParser file_markup_parser
= {
1383 npw_file_list_parser_new (NPWFileList
* list
, const gchar
* filename
)
1385 NPWFileListParser
* this;
1388 g_return_val_if_fail (list
!= NULL
, NULL
);
1389 g_return_val_if_fail (filename
!= NULL
, NULL
);
1391 this = g_new (NPWFileListParser
, 1);
1393 this->type
= NPW_FILE_PARSER
;
1396 this->tag
= g_queue_new ();
1397 this->str_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
1398 this->tag_pool
= g_mem_chunk_new ("file tag pool", sizeof (NPWFileTag
), NPW_FILE_PARSER_DEFAULT_LEVEL
* sizeof (NPWFileTag
) , G_ALLOC_AND_FREE
);
1399 this->root
.tag
= NPW_NO_TAG
;
1400 this->root
.destination
= ".";
1401 /* Use .wiz file path as base source directory */
1402 path
= g_path_get_dirname (filename
);
1403 this->root
.source
= g_string_chunk_insert (this->str_pool
, path
);
1405 g_queue_push_head (this->tag
, &this->root
);
1409 this->ctx
= g_markup_parse_context_new (&file_markup_parser
, 0, this, NULL
);
1410 g_assert (this->ctx
!= NULL
);
1416 npw_file_list_parser_free (NPWFileListParser
* this)
1418 g_return_if_fail (this != NULL
);
1420 g_markup_parse_context_free (this->ctx
);
1421 g_string_chunk_free (this->str_pool
);
1422 g_mem_chunk_destroy (this->tag_pool
);
1423 g_queue_free (this->tag
);
1428 npw_file_list_parser_parse (NPWFileListParser
* this, const gchar
* text
, gssize len
, GError
** error
)
1430 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
1434 npw_file_list_parser_end_parse (NPWFileListParser
* this, GError
** error
)
1436 return g_markup_parse_context_end_parse (this->ctx
, error
);
1440 npw_file_list_read (NPWFileList
* this, const gchar
* filename
)
1444 NPWFileListParser
* parser
;
1447 g_return_val_if_fail (this != NULL
, FALSE
);
1448 g_return_val_if_fail (filename
!= NULL
, FALSE
);
1450 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
1452 g_warning (err
->message
);
1458 parser
= npw_file_list_parser_new (this, filename
);
1460 npw_file_list_parser_parse (parser
, content
, len
, &err
);
1461 if (err
== NULL
) npw_file_list_parser_end_parse (parser
, &err
);
1463 npw_file_list_parser_free (parser
);
1469 g_warning (err
->message
);
1478 /* Parse action block
1479 *---------------------------------------------------------------------------*/
1481 #define NPW_ACTION_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
1483 struct _NPWActionListParser
1485 /* Type of parser (not used) */
1487 GMarkupParseContext
* ctx
;
1488 /* Known element stack */
1489 NPWTag tag
[NPW_ACTION_PARSER_MAX_LEVEL
+ 1];
1491 /* Unknown element stack */
1493 /* Current action list object */
1494 NPWActionList
* list
;
1498 parse_run (NPWActionListParser
* this, const gchar
** attributes
, const gchar
** values
)
1500 const gchar
* command
= NULL
;
1502 while (*attributes
!= NULL
)
1504 switch (parse_attribute (*attributes
))
1506 case NPW_COMMAND_ATTRIBUTE
:
1510 parser_warning (this->ctx
, "Unknown run attribute \"%s\"", *attributes
);
1517 if (command
== NULL
)
1519 parser_warning (this->ctx
, "Missing command attribute");
1525 action
= npw_action_new (this->list
, NPW_RUN_ACTION
);
1526 npw_action_set_command (action
, command
);
1533 parse_open (NPWActionListParser
* this, const gchar
** attributes
, const gchar
** values
)
1535 const gchar
* file
= NULL
;
1537 while (*attributes
!= NULL
)
1539 switch (parse_attribute (*attributes
))
1541 case NPW_FILE_ATTRIBUTE
:
1545 parser_warning (this->ctx
, "Unknown open attribute \"%s\"", *attributes
);
1554 parser_warning (this->ctx
, "Missing file attribute");
1560 action
= npw_action_new (this->list
, NPW_OPEN_ACTION
);
1561 npw_action_set_file (action
, file
);
1568 parse_action_start (GMarkupParseContext
* context
, const gchar
* name
, const gchar
** attributes
,
1569 const gchar
** values
, gpointer data
, GError
** error
)
1571 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1573 gboolean known
= FALSE
;
1575 /* Recognize element */
1576 if (parser
->unknown
== 0)
1578 /* Not inside an unknown element */
1579 tag
= parse_tag (name
);
1580 switch (*parser
->last
)
1583 /* Top level element */
1586 case NPW_ACTION_TAG
:
1589 case NPW_UNKNOW_TAG
:
1590 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1596 case NPW_ACTION_TAG
:
1597 /* Necessary to avoid neested page element */
1601 known
= parse_run (parser
, attributes
, values
);
1604 known
= parse_open (parser
, attributes
, values
);
1607 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1612 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1620 /* Know element stack overflow */
1621 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_ACTION_PARSER_MAX_LEVEL
);
1623 *parser
->last
= tag
;
1632 parse_action_end (GMarkupParseContext
* context
, const gchar
* name
, gpointer data
, GError
** error
)
1634 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1636 if (parser
->unknown
> 0)
1638 /* Pop unknown element */
1641 else if (*parser
->last
!= NPW_NO_TAG
)
1643 /* Pop known element */
1648 /* Know element stack underflow */
1649 g_return_if_reached ();
1653 static GMarkupParser action_markup_parser
= {
1661 NPWActionListParser
*
1662 npw_action_list_parser_new (NPWActionList
* list
)
1664 NPWActionListParser
* this;
1666 g_return_val_if_fail (list
!= NULL
, NULL
);
1668 this = g_new (NPWActionListParser
, 1);
1670 this->type
= NPW_ACTION_PARSER
;
1673 this->tag
[0] = NPW_NO_TAG
;
1674 this->last
= this->tag
;
1678 this->ctx
= g_markup_parse_context_new (&action_markup_parser
, 0, this, NULL
);
1679 g_assert (this->ctx
!= NULL
);
1685 npw_action_list_parser_free (NPWActionListParser
* this)
1687 g_return_if_fail (this != NULL
);
1689 g_markup_parse_context_free (this->ctx
);
1694 npw_action_list_parser_parse (NPWActionListParser
* this, const gchar
* text
, gssize len
, GError
** error
)
1698 g_markup_parse_context_parse (this->ctx
, text
, len
, &err
);
1701 g_warning (err
->message
);
1708 npw_action_list_parser_end_parse (NPWActionListParser
* this, GError
** error
)
1710 return g_markup_parse_context_end_parse (this->ctx
, error
);