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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
,
63 NPW_DESCRIPTION_ATTRIBUTE
,
65 NPW_SUMMARY_ATTRIBUTE
,
67 NPW_MANDATORY_ATTRIBUTE
,
69 NPW_EDITABLE_ATTRIBUTE
,
71 NPW_DESTINATION_ATTRIBUTE
,
72 NPW_EXECUTABLE_ATTRIBUTE
,
73 NPW_PROJECT_ATTRIBUTE
,
74 NPW_AUTOGEN_ATTRIBUTE
,
75 NPW_COMMAND_ATTRIBUTE
,
92 /* Read all project templates in a directory
93 *---------------------------------------------------------------------------*/
96 npw_header_list_readdir (NPWHeaderList
* this, const gchar
* path
)
102 g_return_val_if_fail (this != NULL
, FALSE
);
103 g_return_val_if_fail (path
!= NULL
, FALSE
);
105 /* Read all project template files */
106 dir
= g_dir_open (path
, 0, NULL
);
107 if (!dir
) return FALSE
;
109 while ((name
= g_dir_read_name (dir
)) != NULL
)
111 char* filename
= g_build_filename (path
, name
, NULL
);
113 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
))
115 /* Search recursively in sub directory */
116 if (npw_header_list_readdir (this, filename
))
121 else if (g_str_has_suffix (name
, PROJECT_WIZARD_EXTENSION
))
123 if (npw_header_list_read (this, filename
))
125 /* Read at least one project file */
137 /* Common parser functions
138 *---------------------------------------------------------------------------*/
141 parse_tag (const char* name
)
143 if (strcmp (name
, "project-wizard") == 0)
145 return NPW_PROJECT_WIZARD_TAG
;
147 else if ((strcmp ("_name", name
) == 0) || (strcmp ("name", name
) == 0))
151 else if ((strcmp ("_description", name
) == 0) || (strcmp ("description", name
) == 0))
153 return NPW_DESCRIPTION_TAG
;
155 else if (strcmp ("icon", name
) == 0)
159 else if (strcmp ("category", name
) == 0)
161 return NPW_CATEGORY_TAG
;
163 else if (strcmp ("page", name
) == 0)
167 else if (strcmp ("property", name
) == 0)
169 return NPW_PROPERTY_TAG
;
171 else if (strcmp ("item", name
) == 0)
175 else if (strcmp ("directory", name
) == 0)
177 return NPW_DIRECTORY_TAG
;
179 else if (strcmp ("content", name
) == 0)
181 return NPW_CONTENT_TAG
;
183 else if (strcmp ("file", name
) == 0)
187 else if (strcmp ("action", name
) == 0)
189 return NPW_ACTION_TAG
;
191 else if (strcmp ("run", name
) == 0)
195 else if (strcmp ("open", name
) == 0)
201 return NPW_UNKNOW_TAG
;
206 parse_attribute (const char* name
)
208 if (strcmp ("name", name
) == 0)
210 return NPW_NAME_ATTRIBUTE
;
212 else if (strcmp ("_label", name
) == 0)
214 return NPW_LABEL_ATTRIBUTE
;
216 else if (strcmp ("_description", name
) == 0)
218 return NPW_DESCRIPTION_ATTRIBUTE
;
220 else if (strcmp ("default", name
) == 0 || strcmp ("value", name
) == 0)
222 return NPW_VALUE_ATTRIBUTE
;
224 else if (strcmp ("type", name
) == 0)
226 return NPW_TYPE_ATTRIBUTE
;
228 else if (strcmp ("summary", name
) == 0)
230 return NPW_SUMMARY_ATTRIBUTE
;
232 else if (strcmp ("mandatory", name
) == 0)
234 return NPW_MANDATORY_ATTRIBUTE
;
236 else if (strcmp ("editable", name
) == 0)
238 return NPW_EDITABLE_ATTRIBUTE
;
240 else if (strcmp ("exist", name
) == 0)
242 return NPW_EXIST_ATTRIBUTE
;
244 else if (strcmp ("source", name
) == 0)
246 return NPW_SOURCE_ATTRIBUTE
;
248 else if (strcmp ("destination", name
) == 0)
250 return NPW_DESTINATION_ATTRIBUTE
;
252 else if (strcmp ("executable", name
) == 0)
254 return NPW_EXECUTABLE_ATTRIBUTE
;
256 else if (strcmp ("project", name
) == 0)
258 return NPW_PROJECT_ATTRIBUTE
;
260 else if (strcmp ("autogen", name
) == 0)
262 return NPW_AUTOGEN_ATTRIBUTE
;
264 else if (strcmp ("command", name
) == 0)
266 return NPW_COMMAND_ATTRIBUTE
;
268 else if (strcmp ("file", name
) == 0)
270 return NPW_FILE_ATTRIBUTE
;
274 return NPW_UNKNOW_ATTRIBUTE
;
279 parse_boolean_string (const gchar
* value
)
281 return g_ascii_strcasecmp ("no", value
) && g_ascii_strcasecmp ("0", value
) && g_ascii_strcasecmp ("false", value
);
285 parser_error_quark (void)
287 static GQuark error_quark
= 0;
289 if (error_quark
== 0)
290 error_quark
= g_quark_from_static_string ("parser_error_quark");
295 parser_warning (GMarkupParseContext
* ctx
, const gchar
* format
,...)
301 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
302 msg
= g_strdup_printf ("line %d: %s", line
, format
);
303 va_start (args
, format
);
304 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_WARNING
, msg
, args
);
310 parser_critical (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_CRITICAL
, msg
, args
);
323 /* Parse project wizard block
324 *---------------------------------------------------------------------------*/
326 #define NPW_HEADER_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
328 typedef struct _NPWHeaderParser
330 /* Type of parser (not used) */
332 GMarkupParseContext
* ctx
;
333 /* Known element stack */
334 NPWTag tag
[NPW_HEADER_PARSER_MAX_LEVEL
+ 1];
336 /* Unknown element stack */
338 /* List where should be added the header */
342 /* Name of file read */
347 parse_header_start (GMarkupParseContext
* context
,
349 const gchar
** attributes
,
350 const gchar
** values
,
354 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
356 gboolean known
= FALSE
;
358 /* Recognize element */
359 if (parser
->unknown
== 0)
361 /* Not inside an unknown element */
362 tag
= parse_tag (name
);
363 switch (*parser
->last
)
366 /* Top level element */
369 case NPW_PROJECT_WIZARD_TAG
:
370 parser
->header
= npw_header_new (parser
->list
);
371 npw_header_set_filename (parser
->header
, parser
->filename
);
375 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
381 case NPW_PROJECT_WIZARD_TAG
:
382 /* Necessary to avoid neested PROJECT_WIZARD element */
386 case NPW_DESCRIPTION_TAG
:
388 case NPW_CATEGORY_TAG
:
392 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
397 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
405 /* Know element stack overflow */
406 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_HEADER_PARSER_MAX_LEVEL
);
417 parse_header_end (GMarkupParseContext
* context
,
422 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
424 if (parser
->unknown
> 0)
426 /* Pop unknown element */
429 else if (*parser
->last
!= NPW_NO_TAG
)
431 /* Pop known element */
433 if (parser
->last
[1] == NPW_PROJECT_WIZARD_TAG
)
435 /* Check if the element is valid */
436 if (parser
->header
&& !npw_header_get_name (parser
->header
))
438 parser_critical (parser
->ctx
, "Missing name attribute");
439 npw_header_free (parser
->header
);
442 /* Stop parsing after first project wizard block
443 * Remaining file need to be passed through autogen
444 * to be a valid xml file */
446 /* error should be available to stop parsing */
447 g_return_if_fail (error
!= NULL
);
450 *error
= g_error_new_literal (parser_error_quark (), NPW_STOP_PARSING
, "");
455 /* Know element stack underflow */
456 g_return_if_reached ();
461 parse_header_text (GMarkupParseContext
* context
,
467 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
469 if (parser
->unknown
== 0)
471 switch (*parser
->last
)
474 if (npw_header_get_name (parser
->header
) == NULL
)
476 npw_header_set_name (parser
->header
, text
);
480 parser_critical (parser
->ctx
, "Duplicated name tag");
483 case NPW_DESCRIPTION_TAG
:
484 if (npw_header_get_description (parser
->header
) == NULL
)
486 npw_header_set_description (parser
->header
, text
);
490 parser_critical (parser
->ctx
, "Duplicated description tag");
494 if (npw_header_get_iconfile (parser
->header
) == NULL
)
499 path
= g_path_get_dirname (parser
->filename
);
500 filename
= g_build_filename (path
, text
, NULL
);
501 npw_header_set_iconfile (parser
->header
, filename
);
507 parser_critical (parser
->ctx
, "Duplicated icon tag");
510 case NPW_CATEGORY_TAG
:
511 if (npw_header_get_category (parser
->header
) == NULL
)
513 npw_header_set_category (parser
->header
, text
);
517 parser_critical (parser
->ctx
, "Duplicated category tag");
520 case NPW_PROJECT_WIZARD_TAG
:
525 g_return_if_reached ();
531 static GMarkupParser header_markup_parser
= {
539 static NPWHeaderParser
*
540 npw_header_parser_new (NPWHeaderList
* list
, const gchar
* filename
)
542 NPWHeaderParser
* this;
544 g_return_val_if_fail (list
!= NULL
, NULL
);
545 g_return_val_if_fail (filename
!= NULL
, NULL
);
547 this = g_new0 (NPWHeaderParser
, 1);
549 this->type
= NPW_HEADER_PARSER
;
551 this->tag
[0] = NPW_NO_TAG
;
552 this->last
= this->tag
;
555 this->filename
= g_strdup (filename
);
557 this->ctx
= g_markup_parse_context_new (&header_markup_parser
, 0, this, NULL
);
558 g_assert (this->ctx
!= NULL
);
564 npw_header_parser_free (NPWHeaderParser
* this)
566 g_return_if_fail (this != NULL
);
568 g_free (this->filename
);
569 g_markup_parse_context_free (this->ctx
);
574 npw_header_parser_parse (NPWHeaderParser
* this, const gchar
* text
, gssize len
, GError
** error
)
576 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
582 npw_header_parser_end_parse (NPWHeaderParser* this, GError** error)
584 return g_markup_parse_context_end_parse (this->ctx, error);
588 npw_header_list_read (NPWHeaderList
* this, const gchar
* filename
)
592 NPWHeaderParser
* parser
;
595 g_return_val_if_fail (this != NULL
, FALSE
);
596 g_return_val_if_fail (filename
!= NULL
, FALSE
);
598 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
600 g_warning (err
->message
);
606 parser
= npw_header_parser_new (this, filename
);
608 npw_header_parser_parse (parser
, content
, len
, &err
);
609 /* Parse only a part of the file, so need to call parser_end_parse */
611 npw_header_parser_free (parser
);
616 /* Parsing must end with an error
617 * generated at the end of the project wizard block */
618 g_warning ("Missing project wizard block in %s", filename
);
622 if (g_error_matches (err
, parser_error_quark (), NPW_STOP_PARSING
) == FALSE
)
625 g_warning (err
->message
);
637 *---------------------------------------------------------------------------*/
639 #define NPW_PAGE_PARSER_MAX_LEVEL 3 /* Maximum number of nested elements */
641 struct _NPWPageParser
643 /* Type of parser (not used) */
645 GMarkupParseContext
* ctx
;
646 /* Known element stack */
647 NPWTag tag
[NPW_PAGE_PARSER_MAX_LEVEL
+ 1];
649 /* Unknown element stack */
651 /* page number to read */
653 /* Current page object */
655 /* Current property object */
656 NPWProperty
* property
;
660 parse_page (NPWPageParser
* this,
661 const gchar
** attributes
,
662 const gchar
** values
)
664 if (this->count
!= 0)
667 if (this->count
> 0) this->count
--;
674 while (*attributes
!= NULL
)
676 switch (parse_attribute (*attributes
))
678 case NPW_NAME_ATTRIBUTE
:
679 npw_page_set_name (this->page
, *values
);
681 case NPW_LABEL_ATTRIBUTE
:
682 npw_page_set_label (this->page
, *values
);
684 case NPW_DESCRIPTION_ATTRIBUTE
:
685 npw_page_set_description (this->page
, *values
);
688 parser_warning (this->ctx
, "Unknown page attribute \"%s\"", *attributes
);
701 parse_property (NPWPageParser
* this,
702 const gchar
** attributes
,
703 const gchar
** values
)
705 this->property
= npw_property_new (this->page
);
707 while (*attributes
!= NULL
)
709 switch (parse_attribute (*attributes
))
711 case NPW_TYPE_ATTRIBUTE
:
712 npw_property_set_string_type (this->property
, *values
);
714 case NPW_NAME_ATTRIBUTE
:
715 npw_property_set_name (this->property
, *values
);
717 case NPW_LABEL_ATTRIBUTE
:
718 npw_property_set_label (this->property
, *values
);
720 case NPW_DESCRIPTION_ATTRIBUTE
:
721 npw_property_set_description (this->property
, *values
);
723 case NPW_VALUE_ATTRIBUTE
:
724 npw_property_set_default (this->property
, *values
);
726 case NPW_SUMMARY_ATTRIBUTE
:
727 npw_property_set_summary_option (this->property
, parse_boolean_string (*values
));
729 case NPW_MANDATORY_ATTRIBUTE
:
730 npw_property_set_mandatory_option (this->property
, parse_boolean_string (*values
));
732 case NPW_EDITABLE_ATTRIBUTE
:
733 npw_property_set_editable_option (this->property
, parse_boolean_string (*values
));
735 case NPW_EXIST_ATTRIBUTE
:
736 npw_property_set_exist_option (this->property
, parse_boolean_string (*values
));
739 parser_warning (this->ctx
, "Unknown property attribute \"%s\"", *attributes
);
750 parse_item (NPWPageParser
* this,
751 const gchar
** attributes
,
752 const gchar
** values
)
754 const gchar
* label
= NULL
;
755 const gchar
* name
= NULL
;
757 while (*attributes
!= NULL
)
759 switch (parse_attribute (*attributes
))
761 case NPW_NAME_ATTRIBUTE
:
764 case NPW_LABEL_ATTRIBUTE
:
768 parser_warning (this->ctx
, "Unknown item attribute \"%s\"", *attributes
);
777 parser_warning (this->ctx
, "Missing name attribute");
781 npw_property_add_list_item (this->property
, name
, label
== NULL
? name
: label
);
788 parse_page_start (GMarkupParseContext
* context
,
790 const gchar
** attributes
,
791 const gchar
** values
,
795 NPWPageParser
* parser
= (NPWPageParser
*)data
;
797 gboolean known
= FALSE
;
799 /* Recognize element */
800 if (parser
->unknown
== 0)
802 /* Not inside an unknown element */
803 tag
= parse_tag (name
);
804 switch (*parser
->last
)
807 /* Top level element */
811 known
= parse_page (parser
, attributes
, values
);
814 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
821 /* Necessary to avoid neested page element */
824 case NPW_PROPERTY_TAG
:
825 known
= parse_property (parser
, attributes
, values
);
828 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
832 case NPW_PROPERTY_TAG
:
833 /* Necessary to avoid neested page & property element */
837 known
= parse_item (parser
, attributes
, values
);
840 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
845 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
853 /* Know element stack overflow */
854 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_PAGE_PARSER_MAX_LEVEL
);
865 parse_page_end (GMarkupParseContext
* context
,
870 NPWPageParser
* parser
= (NPWPageParser
*)data
;
872 if (parser
->unknown
> 0)
874 /* Pop unknown element */
877 else if (*parser
->last
!= NPW_NO_TAG
)
879 /* Pop known element */
884 /* Know element stack underflow */
885 g_return_if_reached ();
889 static GMarkupParser page_markup_parser
= {
898 npw_page_parser_new (NPWPage
* page
, const gchar
* filename
, gint count
)
902 g_return_val_if_fail (page
!= NULL
, NULL
);
903 g_return_val_if_fail (count
>= 0, NULL
);
905 this = g_new (NPWPageParser
, 1);
907 this->type
= NPW_PAGE_PARSER
;
910 this->tag
[0] = NPW_NO_TAG
;
911 this->last
= this->tag
;
915 this->property
= NULL
;
917 this->ctx
= g_markup_parse_context_new (&page_markup_parser
, 0, this, NULL
);
918 g_assert (this->ctx
!= NULL
);
924 npw_page_parser_free (NPWPageParser
* this)
926 g_return_if_fail (this != NULL
);
928 g_markup_parse_context_free (this->ctx
);
933 npw_page_parser_parse (NPWPageParser
* this, const gchar
* text
, gssize len
, GError
** error
)
935 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
939 npw_page_parser_end_parse (NPWPageParser
* this, GError
** error
)
941 return g_markup_parse_context_end_parse (this->ctx
, error
);
945 npw_page_read (NPWPage
* this, const gchar
* filename
, gint count
)
949 NPWPageParser
* parser
;
952 g_return_val_if_fail (this != NULL
, FALSE
);
953 g_return_val_if_fail (filename
!= NULL
, FALSE
);
954 g_return_val_if_fail (count
< 0, FALSE
);
956 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
958 g_warning (err
->message
);
964 parser
= npw_page_parser_new (this, filename
, count
);
966 npw_page_parser_parse (parser
, content
, len
, &err
);
967 if (err
== NULL
) npw_page_parser_end_parse (parser
, &err
);
969 npw_page_parser_free (parser
);
975 g_warning (err
->message
);
985 /* Parse content block
986 *---------------------------------------------------------------------------*/
988 #define NPW_FILE_PARSER_DEFAULT_LEVEL 4 /* Default number of nested elements
989 * Dynamically allocated (no maximum) */
990 typedef struct _NPWFileTag
993 const gchar
* destination
;
997 struct _NPWFileListParser
999 /* Type of parser (not used) */
1001 GMarkupParseContext
* ctx
;
1002 /* Known element stack */
1004 GStringChunk
* str_pool
;
1005 GMemChunk
* tag_pool
;
1007 /* Unknown element stack */
1009 /* Current file list */
1013 /* concatenate two directories names, return value must be freed if
1014 * not equal to path1 or path2 */
1017 concat_directory (const gchar
* path1
, const gchar
* path2
)
1021 /* Check for not supported . and .. directory name in path2 */
1022 for (ptr
= path2
; ptr
!= '\0';)
1024 ptr
= strchr (ptr
, '.');
1025 if (ptr
== NULL
) break;
1027 /* Exception "." only is allowed */
1028 if ((ptr
== path2
) && (ptr
[1] == '\0')) break;
1030 if ((ptr
== path2
) || (ptr
[- 1] == G_DIR_SEPARATOR
))
1032 if (ptr
[1] == '.') ptr
++;
1033 if ((ptr
[1] == G_DIR_SEPARATOR
) || (ptr
[1] == '\0')) return NULL
;
1038 if ((*path1
== '\0') || (strcmp (path1
, ".") == 0) || g_path_is_absolute (path2
))
1040 return (char *)path2
;
1042 else if ((*path2
== '\0') || (strcmp (path2
, ".") == 0))
1044 return (char *)path1
;
1050 path
= g_string_new (path1
);
1051 if (path
->str
[path
->len
-1] != G_DIR_SEPARATOR
)
1053 g_string_append_c (path
, G_DIR_SEPARATOR
);
1055 g_string_append (path
, path2
);
1057 return g_string_free (path
, FALSE
);
1062 parse_directory (NPWFileListParser
* this, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1064 const gchar
* source
;
1065 const gchar
* destination
;
1068 /* Set default values */
1072 /* Read all attributes */
1073 while (*attributes
!= NULL
)
1075 switch (parse_attribute (*attributes
))
1077 case NPW_SOURCE_ATTRIBUTE
:
1080 case NPW_DESTINATION_ATTRIBUTE
:
1081 destination
= *values
;
1084 parser_warning (this->ctx
, "Unknow directory attribute \"%s\"", *attributes
);
1091 /* Need source or destination */
1092 if ((source
== NULL
) && (destination
!= NULL
))
1094 source
= destination
;
1096 else if ((source
!= NULL
) && (destination
== NULL
))
1098 destination
= source
;
1100 else if ((source
== NULL
) && (destination
== NULL
))
1102 parser_warning (this->ctx
, "Missing source or destination attribute");
1103 child
->tag
= NPW_NO_TAG
;
1108 path
= concat_directory (child
->source
, source
);
1111 parser_warning (this->ctx
, "Invalid directory source value \"%s\"", source
);
1112 child
->tag
= NPW_NO_TAG
;
1116 if (path
!= child
->source
)
1118 child
->source
= g_string_chunk_insert (this->str_pool
, path
);
1119 if (path
!= source
) g_free (path
);
1122 path
= concat_directory (child
->destination
, destination
);
1125 parser_warning (this->ctx
, "Invalid directory destination value \"%s\"", source
);
1126 child
->tag
= NPW_NO_TAG
;
1130 if (path
!= child
->destination
)
1132 child
->destination
= g_string_chunk_insert (this->str_pool
, path
);
1133 if (path
!= destination
) g_free (path
);
1138 parse_file (NPWFileListParser
* this, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1140 const gchar
* source
;
1141 const gchar
* destination
;
1143 gchar
* full_destination
;
1147 gboolean autogen_set
;
1150 /* Set default values */
1156 autogen_set
= FALSE
;
1158 while (*attributes
!= NULL
)
1160 switch (parse_attribute (*attributes
))
1162 case NPW_SOURCE_ATTRIBUTE
:
1165 case NPW_DESTINATION_ATTRIBUTE
:
1166 destination
= *values
;
1168 case NPW_PROJECT_ATTRIBUTE
:
1169 project
= parse_boolean_string (*values
);
1171 case NPW_EXECUTABLE_ATTRIBUTE
:
1172 execute
= parse_boolean_string (*values
);
1174 case NPW_AUTOGEN_ATTRIBUTE
:
1175 autogen
= parse_boolean_string (*values
);
1179 parser_warning (this->ctx
, "Unknow file attribute \"%s\"", *attributes
);
1186 if ((source
== NULL
) && (destination
!= NULL
))
1188 source
= destination
;
1190 else if ((source
!= NULL
) && (destination
== NULL
))
1192 destination
= source
;
1194 else if ((source
== NULL
) && (destination
== NULL
))
1196 parser_warning (this->ctx
, "Missing source or destination attribute");
1197 child
->tag
= NPW_NO_TAG
;
1202 full_source
= concat_directory (child
->source
, source
);
1203 if ((full_source
== NULL
) || (full_source
== child
->source
))
1205 parser_warning (this->ctx
, "Invalid file source value \"%s\"", source
);
1206 child
->tag
= NPW_NO_TAG
;
1210 full_destination
= concat_directory (child
->destination
, destination
);
1211 if ((full_destination
== NULL
) || (full_destination
== child
->source
))
1213 parser_warning (this->ctx
, "Invalid directory destination value \"%s\"", source
);
1214 child
->tag
= NPW_NO_TAG
;
1219 file
= npw_file_new (this->list
);
1220 npw_file_set_type (file
, NPW_FILE
);
1221 npw_file_set_source (file
, full_source
);
1222 npw_file_set_destination (file
, full_destination
);
1223 npw_file_set_execute (file
, execute
);
1224 npw_file_set_project (file
, project
);
1226 npw_file_set_autogen (file
, autogen
? NPW_TRUE
: NPW_FALSE
);
1228 if (source
!= full_source
)
1229 g_free (full_source
);
1230 if (destination
!= full_destination
)
1231 g_free (full_destination
);
1235 parse_file_start (GMarkupParseContext
* context
,
1237 const gchar
** attributes
,
1238 const gchar
** values
,
1242 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1247 child
.tag
= NPW_NO_TAG
;
1249 /* Recognize element */
1250 if (parser
->unknown
== 0)
1252 /* Not inside an unknown element */
1253 tag
= parse_tag (name
);
1255 parent
= g_queue_peek_head (parser
->tag
);
1256 child
.source
= parent
->source
;
1257 child
.destination
= parent
->destination
;
1258 switch (parent
->tag
)
1261 /* Top level element */
1264 case NPW_CONTENT_TAG
:
1267 case NPW_UNKNOW_TAG
:
1268 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1274 case NPW_CONTENT_TAG
:
1277 case NPW_DIRECTORY_TAG
:
1279 parse_directory (parser
, &child
, attributes
, values
);
1282 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1286 case NPW_DIRECTORY_TAG
:
1289 case NPW_DIRECTORY_TAG
:
1291 parse_directory (parser
, &child
, attributes
, values
);
1295 parse_file (parser
, &child
, attributes
, values
);
1298 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1303 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1309 if (child
.tag
!= NPW_NO_TAG
)
1311 NPWFileTag
* new_child
;
1313 new_child
= g_chunk_new (NPWFileTag
, parser
->tag_pool
);
1314 memcpy (new_child
, &child
, sizeof (child
));
1315 g_queue_push_head (parser
->tag
, new_child
);
1324 parse_file_end (GMarkupParseContext
* context
,
1329 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1331 if (parser
->unknown
> 0)
1333 /* Pop unknown element */
1336 else if (((NPWFileTag
*)g_queue_peek_head (parser
->tag
))->tag
!= NPW_NO_TAG
)
1338 /* Pop known element */
1339 g_mem_chunk_free (parser
->tag_pool
, g_queue_pop_head (parser
->tag
));
1343 /* Know stack underflow */
1344 g_return_if_reached ();
1348 static GMarkupParser file_markup_parser
= {
1357 npw_file_list_parser_new (NPWFileList
* list
, const gchar
* filename
)
1359 NPWFileListParser
* this;
1362 g_return_val_if_fail (list
!= NULL
, NULL
);
1363 g_return_val_if_fail (filename
!= NULL
, NULL
);
1365 this = g_new (NPWFileListParser
, 1);
1367 this->type
= NPW_FILE_PARSER
;
1370 this->tag
= g_queue_new ();
1371 this->str_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
1372 this->tag_pool
= g_mem_chunk_new ("file tag pool", sizeof (NPWFileTag
), NPW_FILE_PARSER_DEFAULT_LEVEL
* sizeof (NPWFileTag
) , G_ALLOC_AND_FREE
);
1373 this->root
.tag
= NPW_NO_TAG
;
1374 this->root
.destination
= ".";
1375 /* Use .wiz file path as base source directory */
1376 path
= g_path_get_dirname (filename
);
1377 this->root
.source
= g_string_chunk_insert (this->str_pool
, path
);
1379 g_queue_push_head (this->tag
, &this->root
);
1383 this->ctx
= g_markup_parse_context_new (&file_markup_parser
, 0, this, NULL
);
1384 g_assert (this->ctx
!= NULL
);
1390 npw_file_list_parser_free (NPWFileListParser
* this)
1392 g_return_if_fail (this != NULL
);
1394 g_markup_parse_context_free (this->ctx
);
1395 g_string_chunk_free (this->str_pool
);
1396 g_mem_chunk_destroy (this->tag_pool
);
1397 g_queue_free (this->tag
);
1402 npw_file_list_parser_parse (NPWFileListParser
* this, const gchar
* text
, gssize len
, GError
** error
)
1404 return g_markup_parse_context_parse (this->ctx
, text
, len
, error
);
1408 npw_file_list_parser_end_parse (NPWFileListParser
* this, GError
** error
)
1410 return g_markup_parse_context_end_parse (this->ctx
, error
);
1414 npw_file_list_read (NPWFileList
* this, const gchar
* filename
)
1418 NPWFileListParser
* parser
;
1421 g_return_val_if_fail (this != NULL
, FALSE
);
1422 g_return_val_if_fail (filename
!= NULL
, FALSE
);
1424 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
1426 g_warning (err
->message
);
1432 parser
= npw_file_list_parser_new (this, filename
);
1434 npw_file_list_parser_parse (parser
, content
, len
, &err
);
1435 if (err
== NULL
) npw_file_list_parser_end_parse (parser
, &err
);
1437 npw_file_list_parser_free (parser
);
1443 g_warning (err
->message
);
1452 /* Parse action block
1453 *---------------------------------------------------------------------------*/
1455 #define NPW_ACTION_PARSER_MAX_LEVEL 2 /* Maximum number of nested elements */
1457 struct _NPWActionListParser
1459 /* Type of parser (not used) */
1461 GMarkupParseContext
* ctx
;
1462 /* Known element stack */
1463 NPWTag tag
[NPW_ACTION_PARSER_MAX_LEVEL
+ 1];
1465 /* Unknown element stack */
1467 /* Current action list object */
1468 NPWActionList
* list
;
1472 parse_run (NPWActionListParser
* this, const gchar
** attributes
, const gchar
** values
)
1474 const gchar
* command
= NULL
;
1476 while (*attributes
!= NULL
)
1478 switch (parse_attribute (*attributes
))
1480 case NPW_COMMAND_ATTRIBUTE
:
1484 parser_warning (this->ctx
, "Unknown run attribute \"%s\"", *attributes
);
1491 if (command
== NULL
)
1493 parser_warning (this->ctx
, "Missing command attribute");
1499 action
= npw_action_new (this->list
, NPW_RUN_ACTION
);
1500 npw_action_set_command (action
, command
);
1507 parse_open (NPWActionListParser
* this, const gchar
** attributes
, const gchar
** values
)
1509 const gchar
* file
= NULL
;
1511 while (*attributes
!= NULL
)
1513 switch (parse_attribute (*attributes
))
1515 case NPW_FILE_ATTRIBUTE
:
1519 parser_warning (this->ctx
, "Unknown open attribute \"%s\"", *attributes
);
1528 parser_warning (this->ctx
, "Missing file attribute");
1534 action
= npw_action_new (this->list
, NPW_OPEN_ACTION
);
1535 npw_action_set_file (action
, file
);
1542 parse_action_start (GMarkupParseContext
* context
, const gchar
* name
, const gchar
** attributes
,
1543 const gchar
** values
, gpointer data
, GError
** error
)
1545 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1547 gboolean known
= FALSE
;
1549 /* Recognize element */
1550 if (parser
->unknown
== 0)
1552 /* Not inside an unknown element */
1553 tag
= parse_tag (name
);
1554 switch (*parser
->last
)
1557 /* Top level element */
1560 case NPW_ACTION_TAG
:
1563 case NPW_UNKNOW_TAG
:
1564 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1570 case NPW_ACTION_TAG
:
1571 /* Necessary to avoid neested page element */
1575 known
= parse_run (parser
, attributes
, values
);
1578 known
= parse_open (parser
, attributes
, values
);
1581 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1586 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1594 /* Know element stack overflow */
1595 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_ACTION_PARSER_MAX_LEVEL
);
1597 *parser
->last
= tag
;
1606 parse_action_end (GMarkupParseContext
* context
, const gchar
* name
, gpointer data
, GError
** error
)
1608 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1610 if (parser
->unknown
> 0)
1612 /* Pop unknown element */
1615 else if (*parser
->last
!= NPW_NO_TAG
)
1617 /* Pop known element */
1622 /* Know element stack underflow */
1623 g_return_if_reached ();
1627 static GMarkupParser action_markup_parser
= {
1635 NPWActionListParser
*
1636 npw_action_list_parser_new (NPWActionList
* list
)
1638 NPWActionListParser
* this;
1640 g_return_val_if_fail (list
!= NULL
, NULL
);
1642 this = g_new (NPWActionListParser
, 1);
1644 this->type
= NPW_ACTION_PARSER
;
1647 this->tag
[0] = NPW_NO_TAG
;
1648 this->last
= this->tag
;
1652 this->ctx
= g_markup_parse_context_new (&action_markup_parser
, 0, this, NULL
);
1653 g_assert (this->ctx
!= NULL
);
1659 npw_action_list_parser_free (NPWActionListParser
* this)
1661 g_return_if_fail (this != NULL
);
1663 g_markup_parse_context_free (this->ctx
);
1668 npw_action_list_parser_parse (NPWActionListParser
* this, const gchar
* text
, gssize len
, GError
** error
)
1672 g_markup_parse_context_parse (this->ctx
, text
, len
, &err
);
1675 g_warning (err
->message
);
1682 npw_action_list_parser_end_parse (NPWActionListParser
* this, GError
** error
)
1684 return g_markup_parse_context_end_parse (this->ctx
, error
);