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"
48 NPW_PROJECT_TEMPLATE_TAG
,
49 NPW_PROJECT_WIZARD_TAG
,
53 NPW_REQUIRED_PROGRAM_TAG
,
54 NPW_REQUIRED_PACKAGE_TAG
,
70 static NPWStringMapping npw_tag_mapping
[] = {
71 {"project-template", NPW_PROJECT_TEMPLATE_TAG
},
72 {"project-wizard", NPW_PROJECT_WIZARD_TAG
},
73 {"_name", NPW_NAME_TAG
},
74 {"name", NPW_NAME_TAG
},
75 {"_description", NPW_DESCRIPTION_TAG
},
76 {"description", NPW_DESCRIPTION_TAG
},
77 {"icon", NPW_ICON_TAG
},
78 {"order", NPW_ORDER_TAG
},
79 {"category", NPW_CATEGORY_TAG
},
80 {"required-program", NPW_REQUIRED_PROGRAM_TAG
},
81 {"required-package", NPW_REQUIRED_PACKAGE_TAG
},
82 {"page", NPW_PAGE_TAG
},
83 {"property", NPW_PROPERTY_TAG
},
84 {"item", NPW_ITEM_TAG
},
85 {"directory", NPW_DIRECTORY_TAG
},
86 {"content", NPW_CONTENT_TAG
},
87 {"file", NPW_FILE_TAG
},
88 {"action", NPW_ACTION_TAG
},
90 {"open", NPW_OPEN_TAG
},
91 {NULL
, NPW_UNKNOW_TAG
}
98 NPW_DESCRIPTION_ATTRIBUTE
,
103 NPW_SUMMARY_ATTRIBUTE
,
105 NPW_RESTRICTION_ATTRIBUTE
,
106 NPW_MANDATORY_ATTRIBUTE
,
108 NPW_EDITABLE_ATTRIBUTE
,
109 NPW_SOURCE_ATTRIBUTE
,
110 NPW_DESTINATION_ATTRIBUTE
,
111 NPW_EXECUTABLE_ATTRIBUTE
,
112 NPW_PROJECT_ATTRIBUTE
,
113 NPW_AUTOGEN_ATTRIBUTE
,
114 NPW_COMMAND_ATTRIBUTE
,
116 NPW_XML_LANG_ATTRIBUTE
,
117 NPW_UNKNOW_ATTRIBUTE
,
121 static NPWStringMapping npw_attribute_mapping
[] = {
122 {"name", NPW_NAME_ATTRIBUTE
},
123 {"_label", NPW_LABEL_ATTRIBUTE
},
124 {"label", NPW_LABEL_ATTRIBUTE
},
125 {"_description", NPW_DESCRIPTION_ATTRIBUTE
},
126 {"description", NPW_DESCRIPTION_ATTRIBUTE
},
127 {"default", NPW_VALUE_ATTRIBUTE
},
128 {"value", NPW_VALUE_ATTRIBUTE
},
129 {"minimum", NPW_MIN_ATTRIBUTE
},
130 {"maximum", NPW_MAX_ATTRIBUTE
},
131 {"step", NPW_STEP_ATTRIBUTE
},
132 {"type", NPW_TYPE_ATTRIBUTE
},
133 {"restriction", NPW_RESTRICTION_ATTRIBUTE
},
134 {"summary", NPW_SUMMARY_ATTRIBUTE
},
135 {"mandatory", NPW_MANDATORY_ATTRIBUTE
},
136 {"editable", NPW_EDITABLE_ATTRIBUTE
},
137 {"exist", NPW_EXIST_ATTRIBUTE
},
138 {"source", NPW_SOURCE_ATTRIBUTE
},
139 {"destination", NPW_DESTINATION_ATTRIBUTE
},
140 {"executable", NPW_EXECUTABLE_ATTRIBUTE
},
141 {"project", NPW_PROJECT_ATTRIBUTE
},
142 {"autogen", NPW_AUTOGEN_ATTRIBUTE
},
143 {"command", NPW_COMMAND_ATTRIBUTE
},
144 {"file", NPW_FILE_ATTRIBUTE
},
145 {"xml:lang", NPW_XML_LANG_ATTRIBUTE
},
146 {NULL
, NPW_UNKNOW_ATTRIBUTE
}
161 /* Read all project templates in a directory
162 *---------------------------------------------------------------------------*/
165 npw_header_list_readdir (GList
** list
, const gchar
* path
)
171 g_return_val_if_fail (list
!= NULL
, FALSE
);
172 g_return_val_if_fail (path
!= NULL
, FALSE
);
174 /* Read all project template files */
175 dir
= g_dir_open (path
, 0, NULL
);
176 if (!dir
) return FALSE
;
178 while ((name
= g_dir_read_name (dir
)) != NULL
)
180 char* filename
= g_build_filename (path
, name
, NULL
);
182 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
))
184 /* Search recursively in sub directory */
185 if (npw_header_list_readdir (list
, filename
))
190 else if (g_str_has_suffix (name
, PROJECT_WIZARD_EXTENSION
))
192 if (npw_header_list_read (list
, filename
))
194 /* Read at least one project file */
206 /* Common parser functions
207 *---------------------------------------------------------------------------*/
210 parse_tag (const char* name
)
212 NPWStringMapping
*mapping
;
214 for (mapping
= npw_tag_mapping
; mapping
->string
!= NULL
; mapping
++)
216 if (strcmp (name
, mapping
->string
) == 0)
218 return (NPWTag
)mapping
->id
;
222 return NPW_UNKNOW_TAG
;
226 parse_attribute (const char* name
)
228 NPWStringMapping
*mapping
;
230 for (mapping
= npw_attribute_mapping
; mapping
->string
!= NULL
; mapping
++)
232 if (strcmp (name
, mapping
->string
) == 0)
234 return (NPWAttribute
)mapping
->id
;
238 return NPW_UNKNOW_ATTRIBUTE
;
242 parse_boolean_string (const gchar
* value
)
244 return g_ascii_strcasecmp ("no", value
) && g_ascii_strcasecmp ("0", value
) && g_ascii_strcasecmp ("false", value
);
248 parser_error_quark (void)
250 static GQuark error_quark
= 0;
252 if (error_quark
== 0)
253 error_quark
= g_quark_from_static_string ("parser_error_quark");
258 parser_warning (GMarkupParseContext
* ctx
, const gchar
* format
,...)
264 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
265 msg
= g_strdup_printf ("line %d: %s", line
, format
);
266 va_start (args
, format
);
267 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_WARNING
, msg
, args
);
273 parser_critical (GMarkupParseContext
* ctx
, const gchar
* format
,...)
279 g_markup_parse_context_get_position (ctx
, &line
, NULL
);
280 msg
= g_strdup_printf ("line %d: %s", line
, format
);
281 va_start (args
, format
);
282 g_logv (G_LOG_DOMAIN
, G_LOG_LEVEL_CRITICAL
, msg
, args
);
287 /* Represent a language as an integer:
288 * < 0 for a not applicable language
289 * 0 for not specified language
290 * > 0 for an applicable language, higher number means a better match */
292 get_tag_language (const gchar
** attributes
,
293 const gchar
** values
)
295 const gchar
*lang
= NULL
;
297 while (*attributes
!= NULL
)
299 if (parse_attribute (*attributes
) == NPW_XML_LANG_ATTRIBUTE
)
309 const gchar
* const *local
;
312 for (local
= g_get_language_names (); *local
!= NULL
; local
++)
315 if (strcmp (*local
, lang
) == 0)
329 /* Parse project wizard block
330 *---------------------------------------------------------------------------*/
332 #define NPW_HEADER_PARSER_MAX_LEVEL 3 /* Maximum number of nested elements */
334 typedef struct _NPWHeaderParser
336 /* Type of parser (not used) */
338 GMarkupParseContext
* ctx
;
339 /* Known element stack */
340 NPWTag tag
[NPW_HEADER_PARSER_MAX_LEVEL
+ 1];
342 /* Unknown element stack */
346 /* Name of file read */
348 /* Language of current tag */
353 parse_header_start (GMarkupParseContext
* context
,
355 const gchar
** attributes
,
356 const gchar
** values
,
360 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
362 gboolean known
= FALSE
;
364 /* Recognize element */
365 if (parser
->unknown
== 0)
367 /* Not inside an unknown element */
368 tag
= parse_tag (name
);
370 switch (*parser
->last
)
373 case NPW_PROJECT_TEMPLATE_TAG
:
374 /* Top level element */
377 case NPW_PROJECT_WIZARD_TAG
:
378 parser
->header
= npw_header_new ();
379 npw_header_set_filename (parser
->header
, parser
->filename
);
383 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
385 case NPW_PROJECT_TEMPLATE_TAG
:
392 case NPW_PROJECT_WIZARD_TAG
:
393 /* Necessary to avoid neested PROJECT_WIZARD element */
397 case NPW_DESCRIPTION_TAG
:
400 case NPW_CATEGORY_TAG
:
401 case NPW_REQUIRED_PROGRAM_TAG
:
402 case NPW_REQUIRED_PACKAGE_TAG
:
403 parser
->lang
= get_tag_language (attributes
, values
);
407 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
412 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
420 /* Know element stack overflow */
421 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_HEADER_PARSER_MAX_LEVEL
);
432 parse_header_end (GMarkupParseContext
* context
,
437 NPWHeaderParser
* parser
= (NPWHeaderParser
*)data
;
439 if (parser
->unknown
> 0)
441 /* Pop unknown element */
444 else if (*parser
->last
!= NPW_NO_TAG
)
446 /* Pop known element */
448 if (parser
->last
[1] == NPW_PROJECT_WIZARD_TAG
)
450 /* Check if the element is valid */
451 if (parser
->header
&& !npw_header_get_name (parser
->header
))
453 parser_critical (parser
->ctx
, "Missing name attribute");
454 npw_header_free (parser
->header
);
455 parser
->header
= NULL
;
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
;
487 if (parser
->unknown
== 0)
489 switch (*parser
->last
)
492 npw_header_set_name (parser
->header
, text
, parser
->lang
);
494 case NPW_DESCRIPTION_TAG
:
495 npw_header_set_description (parser
->header
, text
, parser
->lang
);
498 path
= g_path_get_dirname (parser
->filename
);
499 filename
= g_build_filename (path
, text
, NULL
);
500 npw_header_set_iconfile (parser
->header
, filename
);
505 npw_header_set_order (parser
->header
, text
);
507 case NPW_CATEGORY_TAG
:
508 npw_header_set_category (parser
->header
, text
);
510 case NPW_REQUIRED_PROGRAM_TAG
:
511 npw_header_add_required_program (parser
->header
, text
);
513 case NPW_REQUIRED_PACKAGE_TAG
:
514 npw_header_add_required_package (parser
->header
, text
);
516 case NPW_PROJECT_WIZARD_TAG
:
517 case NPW_PROJECT_TEMPLATE_TAG
:
522 g_return_if_reached ();
528 static GMarkupParser header_markup_parser
= {
536 static NPWHeaderParser
*
537 npw_header_parser_new (GList
** list
, const gchar
* filename
)
539 NPWHeaderParser
* parser
;
541 g_return_val_if_fail (list
!= NULL
, NULL
);
542 g_return_val_if_fail (filename
!= NULL
, NULL
);
544 parser
= g_new0 (NPWHeaderParser
, 1);
546 parser
->type
= NPW_HEADER_PARSER
;
548 parser
->tag
[0] = NPW_NO_TAG
;
549 parser
->last
= parser
->tag
;
550 parser
->header
= NULL
;
551 parser
->filename
= g_strdup (filename
);
553 parser
->ctx
= g_markup_parse_context_new (&header_markup_parser
, 0, parser
, NULL
);
554 g_assert (parser
->ctx
!= NULL
);
560 npw_header_parser_free (NPWHeaderParser
* parser
)
562 g_return_if_fail (parser
!= NULL
);
564 g_free (parser
->filename
);
565 g_markup_parse_context_free (parser
->ctx
);
570 npw_header_parser_parse (NPWHeaderParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
572 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
578 npw_header_parser_end_parse (NPWHeaderParser* parser, GError** error)
580 return g_markup_parse_context_end_parse (parser->ctx, error);
584 npw_header_list_read (GList
** list
, const gchar
* filename
)
588 NPWHeaderParser
* parser
;
592 g_return_val_if_fail (list
!= NULL
, FALSE
);
593 g_return_val_if_fail (filename
!= NULL
, FALSE
);
595 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
597 g_warning ("%s", err
->message
);
603 parser
= npw_header_parser_new (list
, filename
);
605 npw_header_parser_parse (parser
, content
, len
, &err
);
606 header
= parser
->header
;
607 /* Parse only a part of the file, so need to call parser_end_parse */
609 npw_header_parser_free (parser
);
614 /* Parsing must end with an error
615 * generated at the end of the project wizard block */
616 g_warning ("Missing project wizard block in %s", filename
);
617 npw_header_free (header
);
621 if (g_error_matches (err
, parser_error_quark (), NPW_STOP_PARSING
) == FALSE
)
624 g_warning ("%s", err
->message
);
626 npw_header_free (header
);
632 /* Add header to list if template does not already exist*/
633 if (npw_header_list_find_header (*list
, header
) == NULL
)
635 *list
= npw_header_list_insert_header (*list
, header
);
643 *---------------------------------------------------------------------------*/
645 #define NPW_PAGE_PARSER_MAX_LEVEL 4 /* Maximum number of nested elements */
647 struct _NPWPageParser
649 /* Type of parser (not used) */
651 GMarkupParseContext
* ctx
;
652 /* Known element stack */
653 NPWTag tag
[NPW_PAGE_PARSER_MAX_LEVEL
+ 1];
655 /* Unknown element stack */
657 /* page number to read */
659 /* previous page name list */
661 /* Current page object */
663 /* Current property object */
664 NPWProperty
* property
;
668 get_page_name (const gchar
** attributes
,
669 const gchar
** values
)
671 while (*attributes
!= NULL
)
673 if (parse_attribute (*attributes
) == NPW_NAME_ATTRIBUTE
)
685 parse_page (NPWPageParser
* parser
,
686 const gchar
** attributes
,
687 const gchar
** values
)
691 /* Check page name to avoid duplicated page due to translated version */
692 name
= get_page_name (attributes
, values
);
693 if (name
== NULL
) return FALSE
;
695 /* If this is a new page, add it in the list and decrement counter */
696 if (g_list_find_custom (parser
->previous
, name
, (GCompareFunc
)strcmp
) == NULL
)
698 /* New page, add it in list and decrement counter */
699 parser
->previous
= g_list_prepend (parser
->previous
, strdup (name
));
703 /* Translated page must be after the non translated one */
704 if (parser
->count
== -1)
708 lang
= get_tag_language (attributes
, values
);
710 if (npw_page_set_language (parser
->page
, lang
))
713 while (*attributes
!= NULL
)
715 switch (parse_attribute (*attributes
))
717 case NPW_NAME_ATTRIBUTE
:
718 npw_page_set_name (parser
->page
, *values
);
720 case NPW_LABEL_ATTRIBUTE
:
721 npw_page_set_label (parser
->page
, *values
);
723 case NPW_DESCRIPTION_ATTRIBUTE
:
724 npw_page_set_description (parser
->page
, *values
);
726 case NPW_XML_LANG_ATTRIBUTE
:
729 parser_warning (parser
->ctx
, "Unknown page attribute \"%s\"", *attributes
);
746 parse_property (NPWPageParser
* parser
,
747 const gchar
** attributes
,
748 const gchar
** values
)
750 parser
->property
= npw_property_new ();
752 npw_property_set_language (parser
->property
, get_tag_language (attributes
, values
));
754 while (*attributes
!= NULL
)
756 switch (parse_attribute (*attributes
))
758 case NPW_TYPE_ATTRIBUTE
:
759 npw_property_set_string_type (parser
->property
, *values
);
761 case NPW_RESTRICTION_ATTRIBUTE
:
762 npw_property_set_string_restriction (parser
->property
, *values
);
764 case NPW_NAME_ATTRIBUTE
:
765 npw_property_set_name (parser
->property
, *values
, parser
->page
);
767 case NPW_LABEL_ATTRIBUTE
:
768 npw_property_set_label (parser
->property
, *values
);
770 case NPW_DESCRIPTION_ATTRIBUTE
:
771 npw_property_set_description (parser
->property
, *values
);
773 case NPW_VALUE_ATTRIBUTE
:
774 npw_property_set_default (parser
->property
, *values
);
776 case NPW_MIN_ATTRIBUTE
:
777 if (!npw_property_set_range (parser
->property
, NPW_MIN_MARK
, *values
))
779 parser_warning (parser
->ctx
, "Invalid minimum attribute \"%s\"", *values
);
782 case NPW_MAX_ATTRIBUTE
:
783 if (!npw_property_set_range (parser
->property
, NPW_MAX_MARK
, *values
))
785 parser_warning (parser
->ctx
, "Invalid maximum attribute \"%s\"", *values
);
788 case NPW_STEP_ATTRIBUTE
:
789 if (!npw_property_set_range (parser
->property
, NPW_STEP_MARK
, *values
))
791 parser_warning (parser
->ctx
, "Invalid step attribute \"%s\"", *values
);
794 case NPW_SUMMARY_ATTRIBUTE
:
795 npw_property_set_summary_option (parser
->property
, parse_boolean_string (*values
));
797 case NPW_MANDATORY_ATTRIBUTE
:
798 npw_property_set_mandatory_option (parser
->property
, parse_boolean_string (*values
));
800 case NPW_EDITABLE_ATTRIBUTE
:
801 npw_property_set_editable_option (parser
->property
, parse_boolean_string (*values
));
803 case NPW_EXIST_ATTRIBUTE
:
804 npw_property_set_exist_option (parser
->property
, parse_boolean_string (*values
));
806 case NPW_XML_LANG_ATTRIBUTE
:
809 parser_warning (parser
->ctx
, "Unknown property attribute \"%s\"", *attributes
);
815 parser
->property
= npw_page_add_property (parser
->page
, parser
->property
);
821 parse_item (NPWPageParser
* parser
,
822 const gchar
** attributes
,
823 const gchar
** values
)
825 const gchar
* label
= NULL
;
826 const gchar
* name
= NULL
;
829 lang
= get_tag_language (attributes
, values
);
831 while (*attributes
!= NULL
)
833 switch (parse_attribute (*attributes
))
835 case NPW_NAME_ATTRIBUTE
:
838 case NPW_LABEL_ATTRIBUTE
:
841 case NPW_XML_LANG_ATTRIBUTE
:
844 parser_warning (parser
->ctx
, "Unknown item attribute \"%s\"", *attributes
);
853 parser_warning (parser
->ctx
, "Missing name attribute");
857 npw_property_add_list_item (parser
->property
, name
, label
== NULL
? name
: label
, lang
);
864 parse_page_start (GMarkupParseContext
* context
,
866 const gchar
** attributes
,
867 const gchar
** values
,
871 NPWPageParser
* parser
= (NPWPageParser
*)data
;
873 gboolean known
= FALSE
;
875 /* Recognize element */
876 if (parser
->unknown
== 0)
878 /* Not inside an unknown element */
879 tag
= parse_tag (name
);
881 switch (*parser
->last
)
884 case NPW_PROJECT_TEMPLATE_TAG
:
885 /* Top level element */
889 known
= parse_page (parser
, attributes
, values
);
892 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
894 case NPW_PROJECT_TEMPLATE_TAG
:
902 /* Necessary to avoid neested page element */
905 case NPW_PROPERTY_TAG
:
906 known
= parse_property (parser
, attributes
, values
);
909 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
913 case NPW_PROPERTY_TAG
:
914 /* Necessary to avoid neested page & property element */
918 known
= parse_item (parser
, attributes
, values
);
921 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
926 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
934 /* Know element stack overflow */
935 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_PAGE_PARSER_MAX_LEVEL
);
946 parse_page_end (GMarkupParseContext
* context
,
951 NPWPageParser
* parser
= (NPWPageParser
*)data
;
953 if (parser
->unknown
> 0)
955 /* Pop unknown element */
958 else if (*parser
->last
!= NPW_NO_TAG
)
960 /* Pop known element */
965 /* Know element stack underflow */
966 g_return_if_reached ();
970 static GMarkupParser page_markup_parser
= {
979 npw_page_parser_new (NPWPage
* page
, const gchar
* filename
, gint count
)
981 NPWPageParser
* parser
;
983 g_return_val_if_fail (page
!= NULL
, NULL
);
984 g_return_val_if_fail (count
>= 0, NULL
);
986 parser
= g_new (NPWPageParser
, 1);
988 parser
->type
= NPW_PAGE_PARSER
;
991 parser
->tag
[0] = NPW_NO_TAG
;
992 parser
->last
=parser
->tag
;
994 parser
->count
= count
;
995 parser
->previous
= NULL
;
997 parser
->property
= NULL
;
999 parser
->ctx
= g_markup_parse_context_new (&page_markup_parser
, 0, parser
, NULL
);
1000 g_assert (parser
->ctx
!= NULL
);
1006 npw_page_parser_free (NPWPageParser
* parser
)
1008 g_return_if_fail (parser
!= NULL
);
1010 g_list_foreach (parser
->previous
, (GFunc
)g_free
, NULL
);
1011 g_list_free (parser
->previous
);
1012 g_markup_parse_context_free (parser
->ctx
);
1017 npw_page_parser_parse (NPWPageParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1019 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
1023 npw_page_parser_end_parse (NPWPageParser
* parser
, GError
** error
)
1025 return g_markup_parse_context_end_parse (parser
->ctx
, error
);
1029 npw_page_read (NPWPage
* page
, const gchar
* filename
, gint count
)
1033 NPWPageParser
* parser
;
1036 g_return_val_if_fail (page
!= NULL
, FALSE
);
1037 g_return_val_if_fail (filename
!= NULL
, FALSE
);
1038 g_return_val_if_fail (count
< 0, FALSE
);
1040 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
1042 g_warning ("%s", err
->message
);
1048 parser
= npw_page_parser_new (page
, filename
, count
);
1050 npw_page_parser_parse (parser
, content
, len
, &err
);
1051 if (err
== NULL
) npw_page_parser_end_parse (parser
, &err
);
1053 npw_page_parser_free (parser
);
1059 g_warning ("%s", err
->message
);
1069 /* Parse content block
1070 *---------------------------------------------------------------------------*/
1072 typedef struct _NPWFileTag
1079 struct _NPWFileListParser
1081 /* Type of parser (not used) */
1083 GMarkupParseContext
* ctx
;
1084 /* Known element stack */
1086 /* Unknown element stack */
1088 /* Current file list */
1093 npw_file_tag_free (NPWFileTag
*tag
)
1095 g_free (tag
->destination
);
1096 g_free (tag
->source
);
1097 g_slice_free (NPWFileTag
, tag
);
1100 /* concatenate two directories names, return value must be freed if
1101 * not equal to path1 or path2 */
1104 concat_directory (const gchar
* path1
, const gchar
* path2
)
1108 /* Check for not supported . and .. directory name in path2 */
1109 for (ptr
= path2
; ptr
!= '\0';)
1111 ptr
= strchr (ptr
, '.');
1112 if (ptr
== NULL
) break;
1114 /* Exception "." only is allowed */
1115 if ((ptr
== path2
) && (ptr
[1] == '\0')) break;
1117 if ((ptr
== path2
) || (ptr
[- 1] == G_DIR_SEPARATOR
))
1119 if (ptr
[1] == '.') ptr
++;
1120 if ((ptr
[1] == G_DIR_SEPARATOR
) || (ptr
[1] == '\0')) return NULL
;
1125 if ((*path1
== '\0') || (strcmp (path1
, ".") == 0) || g_path_is_absolute (path2
))
1127 return (char *)path2
;
1129 else if ((*path2
== '\0') || (strcmp (path2
, ".") == 0))
1131 return (char *)path1
;
1137 path
= g_string_new (path1
);
1138 if (path
->str
[path
->len
-1] != G_DIR_SEPARATOR
)
1140 g_string_append_c (path
, G_DIR_SEPARATOR
);
1142 g_string_append (path
, path2
);
1144 return g_string_free (path
, FALSE
);
1149 parse_directory (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1151 const gchar
* source
;
1152 const gchar
* destination
;
1155 /* Set default values */
1159 /* Read all attributes */
1160 while (*attributes
!= NULL
)
1162 switch (parse_attribute (*attributes
))
1164 case NPW_SOURCE_ATTRIBUTE
:
1167 case NPW_DESTINATION_ATTRIBUTE
:
1168 destination
= *values
;
1171 parser_warning (parser
->ctx
, "Unknow directory attribute \"%s\"", *attributes
);
1178 /* Need source or destination */
1179 if ((source
== NULL
) && (destination
!= NULL
))
1181 source
= destination
;
1183 else if ((source
!= NULL
) && (destination
== NULL
))
1185 destination
= source
;
1187 else if ((source
== NULL
) && (destination
== NULL
))
1189 parser_warning (parser
->ctx
, "Missing source or destination attribute");
1190 child
->tag
= NPW_NO_TAG
;
1195 path
= concat_directory (child
->source
, source
);
1198 parser_warning (parser
->ctx
, "Invalid directory source value \"%s\"", source
);
1199 child
->tag
= NPW_NO_TAG
;
1205 g_free (child
->source
);
1206 child
->source
= g_strdup (path
);
1208 else if (path
!= child
->source
)
1210 g_free (child
->source
);
1211 child
->source
= path
;
1215 path
= concat_directory (child
->destination
, destination
);
1218 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1219 child
->tag
= NPW_NO_TAG
;
1223 if (path
== destination
)
1225 g_free (child
->destination
);
1226 child
->destination
= g_strdup (path
);
1228 else if (path
!= child
->destination
)
1230 g_free (child
->destination
);
1231 child
->destination
= path
;
1236 parse_file (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1238 const gchar
* source
;
1239 const gchar
* destination
;
1241 gchar
* full_destination
;
1245 gboolean autogen_set
;
1248 /* Set default values */
1254 autogen_set
= FALSE
;
1256 while (*attributes
!= NULL
)
1258 switch (parse_attribute (*attributes
))
1260 case NPW_SOURCE_ATTRIBUTE
:
1263 case NPW_DESTINATION_ATTRIBUTE
:
1264 destination
= *values
;
1266 case NPW_PROJECT_ATTRIBUTE
:
1267 project
= parse_boolean_string (*values
);
1269 case NPW_EXECUTABLE_ATTRIBUTE
:
1270 execute
= parse_boolean_string (*values
);
1272 case NPW_AUTOGEN_ATTRIBUTE
:
1273 autogen
= parse_boolean_string (*values
);
1277 parser_warning (parser
->ctx
, "Unknow file attribute \"%s\"", *attributes
);
1284 if ((source
== NULL
) && (destination
!= NULL
))
1286 source
= destination
;
1288 else if ((source
!= NULL
) && (destination
== NULL
))
1290 destination
= source
;
1292 else if ((source
== NULL
) && (destination
== NULL
))
1294 parser_warning (parser
->ctx
, "Missing source or destination attribute");
1295 child
->tag
= NPW_NO_TAG
;
1300 full_source
= concat_directory (child
->source
, source
);
1301 if ((full_source
== NULL
) || (full_source
== child
->source
))
1303 parser_warning (parser
->ctx
, "Invalid file source value \"%s\"", source
);
1304 child
->tag
= NPW_NO_TAG
;
1308 full_destination
= concat_directory (child
->destination
, destination
);
1309 if ((full_destination
== NULL
) || (full_destination
== child
->destination
))
1311 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1312 child
->tag
= NPW_NO_TAG
;
1317 file
= npw_file_new_file (full_destination
, full_source
);
1318 parser
->list
= g_list_prepend (parser
->list
, file
);
1319 npw_file_set_execute (file
, execute
);
1320 npw_file_set_project (file
, project
);
1322 npw_file_set_autogen (file
, autogen
? NPW_TRUE
: NPW_FALSE
);
1324 if (source
!= full_source
)
1325 g_free (full_source
);
1326 if (destination
!= full_destination
)
1327 g_free (full_destination
);
1331 parse_file_start (GMarkupParseContext
* context
,
1333 const gchar
** attributes
,
1334 const gchar
** values
,
1338 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1343 child
.tag
= NPW_NO_TAG
;
1344 child
.source
= NULL
;
1345 child
.destination
= NULL
;
1347 /* Recognize element */
1348 if (parser
->unknown
== 0)
1350 /* Not inside an unknown element */
1351 tag
= parse_tag (name
);
1353 parent
= g_queue_peek_head (parser
->tag
);
1354 child
.source
= g_strdup (parent
->source
);
1355 child
.destination
= g_strdup (parent
->destination
);
1356 switch (parent
->tag
)
1359 case NPW_PROJECT_TEMPLATE_TAG
:
1360 /* Top level element */
1363 case NPW_CONTENT_TAG
:
1364 case NPW_PROJECT_TEMPLATE_TAG
:
1367 case NPW_UNKNOW_TAG
:
1368 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1374 case NPW_CONTENT_TAG
:
1377 case NPW_DIRECTORY_TAG
:
1379 parse_directory (parser
, &child
, attributes
, values
);
1382 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1386 case NPW_DIRECTORY_TAG
:
1389 case NPW_DIRECTORY_TAG
:
1391 parse_directory (parser
, &child
, attributes
, values
);
1395 parse_file (parser
, &child
, attributes
, values
);
1398 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1403 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1409 if (child
.tag
!= NPW_NO_TAG
)
1411 NPWFileTag
* new_child
;
1413 new_child
= g_slice_new (NPWFileTag
);
1414 memcpy (new_child
, &child
, sizeof (child
));
1415 g_queue_push_head (parser
->tag
, new_child
);
1419 g_free (child
.source
);
1420 g_free (child
.destination
);
1426 parse_file_end (GMarkupParseContext
* context
,
1431 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1433 DEBUG_PRINT("parser_file_end");
1434 if (parser
->unknown
> 0)
1436 /* Pop unknown element */
1439 else if (((NPWFileTag
*)g_queue_peek_head (parser
->tag
))->tag
!= NPW_NO_TAG
)
1441 /* Pop known element */
1442 npw_file_tag_free (g_queue_pop_head (parser
->tag
));
1446 /* Know stack underflow */
1447 g_return_if_reached ();
1451 static GMarkupParser file_markup_parser
= {
1460 npw_file_list_parser_new (const gchar
* filename
)
1462 NPWFileListParser
* parser
;
1465 g_return_val_if_fail (filename
!= NULL
, NULL
);
1467 parser
= g_new (NPWFileListParser
, 1);
1469 parser
->type
= NPW_FILE_PARSER
;
1471 parser
->unknown
= 0;
1472 parser
->tag
= g_queue_new ();
1473 root
= g_slice_new0 (NPWFileTag
);
1474 root
->tag
= NPW_NO_TAG
;
1475 root
->destination
= g_strdup (".");
1476 /* Use .wiz file path as base source directory */
1477 root
->source
= g_path_get_dirname (filename
);
1478 g_queue_push_head (parser
->tag
, root
);
1480 parser
->list
= NULL
;
1482 parser
->ctx
= g_markup_parse_context_new (&file_markup_parser
, 0, parser
, NULL
);
1483 g_assert (parser
->ctx
!= NULL
);
1489 npw_file_list_parser_free (NPWFileListParser
* parser
)
1491 g_return_if_fail (parser
!= NULL
);
1493 g_markup_parse_context_free (parser
->ctx
);
1494 DEBUG_PRINT("parser free");
1495 g_queue_foreach (parser
->tag
, (GFunc
)npw_file_tag_free
, NULL
);
1496 DEBUG_PRINT("parser free ok");
1497 g_queue_free (parser
->tag
);
1502 npw_file_list_parser_parse (NPWFileListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1504 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
1508 npw_file_list_parser_end_parse (NPWFileListParser
* parser
, GError
** error
)
1512 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1514 /* Reverse file list */
1515 parser
->list
= g_list_reverse (parser
->list
);
1517 list
= parser
->list
;
1523 /* Parse action block
1524 *---------------------------------------------------------------------------*/
1526 #define NPW_ACTION_PARSER_MAX_LEVEL 3
1527 /* Maximum number of nested elements */
1529 struct _NPWActionListParser
1531 /* Type of parser (not used) */
1533 GMarkupParseContext
* ctx
;
1534 /* Known element stack */
1535 NPWTag tag
[NPW_ACTION_PARSER_MAX_LEVEL
+ 1];
1537 /* Unknown element stack */
1539 /* Current action list object */
1544 parse_run (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1546 const gchar
* command
= NULL
;
1548 while (*attributes
!= NULL
)
1550 switch (parse_attribute (*attributes
))
1552 case NPW_COMMAND_ATTRIBUTE
:
1556 parser_warning (parser
->ctx
, "Unknown run attribute \"%s\"", *attributes
);
1563 if (command
== NULL
)
1565 parser_warning (parser
->ctx
, "Missing command attribute");
1571 action
= npw_action_new_command (command
);
1572 parser
->list
= g_list_prepend (parser
->list
, action
);
1579 parse_open (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1581 const gchar
* file
= NULL
;
1583 while (*attributes
!= NULL
)
1585 switch (parse_attribute (*attributes
))
1587 case NPW_FILE_ATTRIBUTE
:
1591 parser_warning (parser
->ctx
, "Unknown open attribute \"%s\"", *attributes
);
1600 parser_warning (parser
->ctx
, "Missing file attribute");
1606 action
= npw_action_new_file (file
);
1607 parser
->list
= g_list_prepend (parser
->list
, action
);
1614 parse_action_start (GMarkupParseContext
* context
, const gchar
* name
, const gchar
** attributes
,
1615 const gchar
** values
, gpointer data
, GError
** error
)
1617 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1619 gboolean known
= FALSE
;
1621 /* Recognize element */
1622 if (parser
->unknown
== 0)
1624 /* Not inside an unknown element */
1625 tag
= parse_tag (name
);
1626 switch (*parser
->last
)
1629 case NPW_PROJECT_TEMPLATE_TAG
:
1630 /* Top level element */
1633 case NPW_ACTION_TAG
:
1636 case NPW_UNKNOW_TAG
:
1637 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1639 case NPW_PROJECT_TEMPLATE_TAG
:
1646 case NPW_ACTION_TAG
:
1647 /* Necessary to avoid neested page element */
1651 known
= parse_run (parser
, attributes
, values
);
1654 known
= parse_open (parser
, attributes
, values
);
1657 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1662 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1670 /* Know element stack overflow */
1671 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_ACTION_PARSER_MAX_LEVEL
);
1673 *parser
->last
= tag
;
1682 parse_action_end (GMarkupParseContext
* context
, const gchar
* name
, gpointer data
, GError
** error
)
1684 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1686 if (parser
->unknown
> 0)
1688 /* Pop unknown element */
1691 else if (*parser
->last
!= NPW_NO_TAG
)
1693 /* Pop known element */
1698 /* Know element stack underflow */
1699 g_return_if_reached ();
1703 static GMarkupParser action_markup_parser
= {
1711 NPWActionListParser
*
1712 npw_action_list_parser_new (void)
1714 NPWActionListParser
* parser
;
1716 parser
= g_new (NPWActionListParser
, 1);
1718 parser
->type
= NPW_ACTION_PARSER
;
1720 parser
->unknown
= 0;
1721 parser
->tag
[0] = NPW_NO_TAG
;
1722 parser
->last
= parser
->tag
;
1724 parser
->list
= NULL
;
1726 parser
->ctx
= g_markup_parse_context_new (&action_markup_parser
, 0, parser
, NULL
);
1727 g_assert (parser
->ctx
!= NULL
);
1733 npw_action_list_parser_free (NPWActionListParser
* parser
)
1735 g_return_if_fail (parser
!= NULL
);
1737 g_markup_parse_context_free (parser
->ctx
);
1742 npw_action_list_parser_parse (NPWActionListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1746 g_markup_parse_context_parse (parser
->ctx
, text
, len
, &err
);
1749 g_warning ("%s", err
->message
);
1756 npw_action_list_parser_end_parse (NPWActionListParser
* parser
, GError
** error
)
1760 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1762 /* Reverse file list */
1763 parser
->list
= g_list_reverse (parser
->list
);
1765 list
= parser
->list
;