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
;
593 g_return_val_if_fail (list
!= NULL
, NULL
);
594 g_return_val_if_fail (filename
!= NULL
, NULL
);
596 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
598 g_warning ("%s", err
->message
);
604 parser
= npw_header_parser_new (list
, filename
);
606 npw_header_parser_parse (parser
, content
, len
, &err
);
607 header
= parser
->header
;
608 /* Parse only a part of the file, so need to call parser_end_parse */
610 npw_header_parser_free (parser
);
615 /* Parsing must end with an error
616 * generated at the end of the project wizard block */
617 g_warning ("Missing project wizard block in %s", filename
);
618 npw_header_free (header
);
622 if (g_error_matches (err
, parser_error_quark (), NPW_STOP_PARSING
) == FALSE
)
625 g_warning ("%s", err
->message
);
627 npw_header_free (header
);
633 /* Add header to list if template does not already exist*/
634 found
= npw_header_list_find_header (*list
, header
);
637 *list
= npw_header_list_insert_header (*list
, header
);
641 npw_header_free (header
);
650 *---------------------------------------------------------------------------*/
652 #define NPW_PAGE_PARSER_MAX_LEVEL 4 /* Maximum number of nested elements */
654 struct _NPWPageParser
656 /* Type of parser (not used) */
658 GMarkupParseContext
* ctx
;
659 /* Known element stack */
660 NPWTag tag
[NPW_PAGE_PARSER_MAX_LEVEL
+ 1];
662 /* Unknown element stack */
664 /* page number to read */
666 /* previous page name list */
668 /* Current page object */
670 /* Current property object */
671 NPWProperty
* property
;
675 get_page_name (const gchar
** attributes
,
676 const gchar
** values
)
678 while (*attributes
!= NULL
)
680 if (parse_attribute (*attributes
) == NPW_NAME_ATTRIBUTE
)
692 parse_page (NPWPageParser
* parser
,
693 const gchar
** attributes
,
694 const gchar
** values
)
698 /* Check page name to avoid duplicated page due to translated version */
699 name
= get_page_name (attributes
, values
);
700 if (name
== NULL
) return FALSE
;
702 /* If this is a new page, add it in the list and decrement counter */
703 if (g_list_find_custom (parser
->previous
, name
, (GCompareFunc
)strcmp
) == NULL
)
705 /* New page, add it in list and decrement counter */
706 parser
->previous
= g_list_prepend (parser
->previous
, strdup (name
));
710 /* Translated page must be after the non translated one */
711 if (parser
->count
== -1)
715 lang
= get_tag_language (attributes
, values
);
717 if (npw_page_set_language (parser
->page
, lang
))
720 while (*attributes
!= NULL
)
722 switch (parse_attribute (*attributes
))
724 case NPW_NAME_ATTRIBUTE
:
725 npw_page_set_name (parser
->page
, *values
);
727 case NPW_LABEL_ATTRIBUTE
:
728 npw_page_set_label (parser
->page
, *values
);
730 case NPW_DESCRIPTION_ATTRIBUTE
:
731 npw_page_set_description (parser
->page
, *values
);
733 case NPW_XML_LANG_ATTRIBUTE
:
736 parser_warning (parser
->ctx
, "Unknown page attribute \"%s\"", *attributes
);
753 parse_property (NPWPageParser
* parser
,
754 const gchar
** attributes
,
755 const gchar
** values
)
757 parser
->property
= npw_property_new ();
759 npw_property_set_language (parser
->property
, get_tag_language (attributes
, values
));
761 while (*attributes
!= NULL
)
763 switch (parse_attribute (*attributes
))
765 case NPW_TYPE_ATTRIBUTE
:
766 npw_property_set_string_type (parser
->property
, *values
);
768 case NPW_RESTRICTION_ATTRIBUTE
:
769 npw_property_set_string_restriction (parser
->property
, *values
);
771 case NPW_NAME_ATTRIBUTE
:
772 npw_property_set_name (parser
->property
, *values
, parser
->page
);
774 case NPW_LABEL_ATTRIBUTE
:
775 npw_property_set_label (parser
->property
, *values
);
777 case NPW_DESCRIPTION_ATTRIBUTE
:
778 npw_property_set_description (parser
->property
, *values
);
780 case NPW_VALUE_ATTRIBUTE
:
781 npw_property_set_default (parser
->property
, *values
);
783 case NPW_MIN_ATTRIBUTE
:
784 if (!npw_property_set_range (parser
->property
, NPW_MIN_MARK
, *values
))
786 parser_warning (parser
->ctx
, "Invalid minimum attribute \"%s\"", *values
);
789 case NPW_MAX_ATTRIBUTE
:
790 if (!npw_property_set_range (parser
->property
, NPW_MAX_MARK
, *values
))
792 parser_warning (parser
->ctx
, "Invalid maximum attribute \"%s\"", *values
);
795 case NPW_STEP_ATTRIBUTE
:
796 if (!npw_property_set_range (parser
->property
, NPW_STEP_MARK
, *values
))
798 parser_warning (parser
->ctx
, "Invalid step attribute \"%s\"", *values
);
801 case NPW_SUMMARY_ATTRIBUTE
:
802 npw_property_set_summary_option (parser
->property
, parse_boolean_string (*values
));
804 case NPW_MANDATORY_ATTRIBUTE
:
805 npw_property_set_mandatory_option (parser
->property
, parse_boolean_string (*values
));
807 case NPW_EDITABLE_ATTRIBUTE
:
808 npw_property_set_editable_option (parser
->property
, parse_boolean_string (*values
));
810 case NPW_EXIST_ATTRIBUTE
:
811 npw_property_set_exist_option (parser
->property
, parse_boolean_string (*values
));
813 case NPW_XML_LANG_ATTRIBUTE
:
816 parser_warning (parser
->ctx
, "Unknown property attribute \"%s\"", *attributes
);
822 parser
->property
= npw_page_add_property (parser
->page
, parser
->property
);
828 parse_item (NPWPageParser
* parser
,
829 const gchar
** attributes
,
830 const gchar
** values
)
832 const gchar
* label
= NULL
;
833 const gchar
* name
= NULL
;
836 lang
= get_tag_language (attributes
, values
);
838 while (*attributes
!= NULL
)
840 switch (parse_attribute (*attributes
))
842 case NPW_NAME_ATTRIBUTE
:
845 case NPW_LABEL_ATTRIBUTE
:
848 case NPW_XML_LANG_ATTRIBUTE
:
851 parser_warning (parser
->ctx
, "Unknown item attribute \"%s\"", *attributes
);
860 parser_warning (parser
->ctx
, "Missing name attribute");
864 npw_property_add_list_item (parser
->property
, name
, label
== NULL
? name
: label
, lang
);
871 parse_page_start (GMarkupParseContext
* context
,
873 const gchar
** attributes
,
874 const gchar
** values
,
878 NPWPageParser
* parser
= (NPWPageParser
*)data
;
880 gboolean known
= FALSE
;
882 /* Recognize element */
883 if (parser
->unknown
== 0)
885 /* Not inside an unknown element */
886 tag
= parse_tag (name
);
888 switch (*parser
->last
)
891 case NPW_PROJECT_TEMPLATE_TAG
:
892 /* Top level element */
896 known
= parse_page (parser
, attributes
, values
);
899 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
901 case NPW_PROJECT_TEMPLATE_TAG
:
909 /* Necessary to avoid neested page element */
912 case NPW_PROPERTY_TAG
:
913 known
= parse_property (parser
, attributes
, values
);
916 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
920 case NPW_PROPERTY_TAG
:
921 /* Necessary to avoid neested page & property element */
925 known
= parse_item (parser
, attributes
, values
);
928 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
933 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
941 /* Know element stack overflow */
942 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_PAGE_PARSER_MAX_LEVEL
);
953 parse_page_end (GMarkupParseContext
* context
,
958 NPWPageParser
* parser
= (NPWPageParser
*)data
;
960 if (parser
->unknown
> 0)
962 /* Pop unknown element */
965 else if (*parser
->last
!= NPW_NO_TAG
)
967 /* Pop known element */
972 /* Know element stack underflow */
973 g_return_if_reached ();
977 static GMarkupParser page_markup_parser
= {
986 npw_page_parser_new (NPWPage
* page
, const gchar
* filename
, gint count
)
988 NPWPageParser
* parser
;
990 g_return_val_if_fail (page
!= NULL
, NULL
);
991 g_return_val_if_fail (count
>= 0, NULL
);
993 parser
= g_new (NPWPageParser
, 1);
995 parser
->type
= NPW_PAGE_PARSER
;
998 parser
->tag
[0] = NPW_NO_TAG
;
999 parser
->last
=parser
->tag
;
1001 parser
->count
= count
;
1002 parser
->previous
= NULL
;
1003 parser
->page
= page
;
1004 parser
->property
= NULL
;
1006 parser
->ctx
= g_markup_parse_context_new (&page_markup_parser
, 0, parser
, NULL
);
1007 g_assert (parser
->ctx
!= NULL
);
1013 npw_page_parser_free (NPWPageParser
* parser
)
1015 g_return_if_fail (parser
!= NULL
);
1017 g_list_foreach (parser
->previous
, (GFunc
)g_free
, NULL
);
1018 g_list_free (parser
->previous
);
1019 g_markup_parse_context_free (parser
->ctx
);
1024 npw_page_parser_parse (NPWPageParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1026 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
1030 npw_page_parser_end_parse (NPWPageParser
* parser
, GError
** error
)
1032 return g_markup_parse_context_end_parse (parser
->ctx
, error
);
1036 npw_page_read (NPWPage
* page
, const gchar
* filename
, gint count
)
1040 NPWPageParser
* parser
;
1043 g_return_val_if_fail (page
!= NULL
, FALSE
);
1044 g_return_val_if_fail (filename
!= NULL
, FALSE
);
1045 g_return_val_if_fail (count
< 0, FALSE
);
1047 if (!g_file_get_contents (filename
, &content
, &len
, &err
))
1049 g_warning ("%s", err
->message
);
1055 parser
= npw_page_parser_new (page
, filename
, count
);
1057 npw_page_parser_parse (parser
, content
, len
, &err
);
1058 if (err
== NULL
) npw_page_parser_end_parse (parser
, &err
);
1060 npw_page_parser_free (parser
);
1066 g_warning ("%s", err
->message
);
1076 /* Parse content block
1077 *---------------------------------------------------------------------------*/
1079 typedef struct _NPWFileTag
1086 struct _NPWFileListParser
1088 /* Type of parser (not used) */
1090 GMarkupParseContext
* ctx
;
1091 /* Known element stack */
1093 /* Unknown element stack */
1095 /* Current file list */
1100 npw_file_tag_free (NPWFileTag
*tag
)
1102 g_free (tag
->destination
);
1103 g_free (tag
->source
);
1104 g_slice_free (NPWFileTag
, tag
);
1107 /* concatenate two directories names, return value must be freed if
1108 * not equal to path1 or path2 */
1111 concat_directory (const gchar
* path1
, const gchar
* path2
)
1115 /* Check for not supported . and .. directory name in path2 */
1116 for (ptr
= path2
; ptr
!= '\0';)
1118 ptr
= strchr (ptr
, '.');
1119 if (ptr
== NULL
) break;
1121 /* Exception "." only is allowed */
1122 if ((ptr
== path2
) && (ptr
[1] == '\0')) break;
1124 if ((ptr
== path2
) || (ptr
[- 1] == G_DIR_SEPARATOR
))
1126 if (ptr
[1] == '.') ptr
++;
1127 if ((ptr
[1] == G_DIR_SEPARATOR
) || (ptr
[1] == '\0')) return NULL
;
1132 if ((*path1
== '\0') || (strcmp (path1
, ".") == 0) || g_path_is_absolute (path2
))
1134 return (char *)path2
;
1136 else if ((*path2
== '\0') || (strcmp (path2
, ".") == 0))
1138 return (char *)path1
;
1144 path
= g_string_new (path1
);
1145 if (path
->str
[path
->len
-1] != G_DIR_SEPARATOR
)
1147 g_string_append_c (path
, G_DIR_SEPARATOR
);
1149 g_string_append (path
, path2
);
1151 return g_string_free (path
, FALSE
);
1156 parse_directory (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1158 const gchar
* source
;
1159 const gchar
* destination
;
1162 /* Set default values */
1166 /* Read all attributes */
1167 while (*attributes
!= NULL
)
1169 switch (parse_attribute (*attributes
))
1171 case NPW_SOURCE_ATTRIBUTE
:
1174 case NPW_DESTINATION_ATTRIBUTE
:
1175 destination
= *values
;
1178 parser_warning (parser
->ctx
, "Unknow directory attribute \"%s\"", *attributes
);
1185 /* Need source or destination */
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 (parser
->ctx
, "Missing source or destination attribute");
1197 child
->tag
= NPW_NO_TAG
;
1202 path
= concat_directory (child
->source
, source
);
1205 parser_warning (parser
->ctx
, "Invalid directory source value \"%s\"", source
);
1206 child
->tag
= NPW_NO_TAG
;
1212 g_free (child
->source
);
1213 child
->source
= g_strdup (path
);
1215 else if (path
!= child
->source
)
1217 g_free (child
->source
);
1218 child
->source
= path
;
1222 path
= concat_directory (child
->destination
, destination
);
1225 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1226 child
->tag
= NPW_NO_TAG
;
1230 if (path
== destination
)
1232 g_free (child
->destination
);
1233 child
->destination
= g_strdup (path
);
1235 else if (path
!= child
->destination
)
1237 g_free (child
->destination
);
1238 child
->destination
= path
;
1243 parse_file (NPWFileListParser
* parser
, NPWFileTag
* child
, const gchar
** attributes
, const gchar
** values
)
1245 const gchar
* source
;
1246 const gchar
* destination
;
1248 gchar
* full_destination
;
1252 gboolean autogen_set
;
1255 /* Set default values */
1261 autogen_set
= FALSE
;
1263 while (*attributes
!= NULL
)
1265 switch (parse_attribute (*attributes
))
1267 case NPW_SOURCE_ATTRIBUTE
:
1270 case NPW_DESTINATION_ATTRIBUTE
:
1271 destination
= *values
;
1273 case NPW_PROJECT_ATTRIBUTE
:
1274 project
= parse_boolean_string (*values
);
1276 case NPW_EXECUTABLE_ATTRIBUTE
:
1277 execute
= parse_boolean_string (*values
);
1279 case NPW_AUTOGEN_ATTRIBUTE
:
1280 autogen
= parse_boolean_string (*values
);
1284 parser_warning (parser
->ctx
, "Unknow file attribute \"%s\"", *attributes
);
1291 if ((source
== NULL
) && (destination
!= NULL
))
1293 source
= destination
;
1295 else if ((source
!= NULL
) && (destination
== NULL
))
1297 destination
= source
;
1299 else if ((source
== NULL
) && (destination
== NULL
))
1301 parser_warning (parser
->ctx
, "Missing source or destination attribute");
1302 child
->tag
= NPW_NO_TAG
;
1307 full_source
= concat_directory (child
->source
, source
);
1308 if ((full_source
== NULL
) || (full_source
== child
->source
))
1310 parser_warning (parser
->ctx
, "Invalid file source value \"%s\"", source
);
1311 child
->tag
= NPW_NO_TAG
;
1315 full_destination
= concat_directory (child
->destination
, destination
);
1316 if ((full_destination
== NULL
) || (full_destination
== child
->destination
))
1318 parser_warning (parser
->ctx
, "Invalid directory destination value \"%s\"", source
);
1319 child
->tag
= NPW_NO_TAG
;
1324 file
= npw_file_new_file (full_destination
, full_source
);
1325 parser
->list
= g_list_prepend (parser
->list
, file
);
1326 npw_file_set_execute (file
, execute
);
1327 npw_file_set_project (file
, project
);
1329 npw_file_set_autogen (file
, autogen
? NPW_TRUE
: NPW_FALSE
);
1331 if (source
!= full_source
)
1332 g_free (full_source
);
1333 if (destination
!= full_destination
)
1334 g_free (full_destination
);
1338 parse_file_start (GMarkupParseContext
* context
,
1340 const gchar
** attributes
,
1341 const gchar
** values
,
1345 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1350 child
.tag
= NPW_NO_TAG
;
1351 child
.source
= NULL
;
1352 child
.destination
= NULL
;
1354 /* Recognize element */
1355 if (parser
->unknown
== 0)
1357 /* Not inside an unknown element */
1358 tag
= parse_tag (name
);
1360 parent
= g_queue_peek_head (parser
->tag
);
1361 child
.source
= g_strdup (parent
->source
);
1362 child
.destination
= g_strdup (parent
->destination
);
1363 switch (parent
->tag
)
1366 case NPW_PROJECT_TEMPLATE_TAG
:
1367 /* Top level element */
1370 case NPW_CONTENT_TAG
:
1371 case NPW_PROJECT_TEMPLATE_TAG
:
1374 case NPW_UNKNOW_TAG
:
1375 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1381 case NPW_CONTENT_TAG
:
1384 case NPW_DIRECTORY_TAG
:
1386 parse_directory (parser
, &child
, attributes
, values
);
1389 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1393 case NPW_DIRECTORY_TAG
:
1396 case NPW_DIRECTORY_TAG
:
1398 parse_directory (parser
, &child
, attributes
, values
);
1402 parse_file (parser
, &child
, attributes
, values
);
1405 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1410 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1416 if (child
.tag
!= NPW_NO_TAG
)
1418 NPWFileTag
* new_child
;
1420 new_child
= g_slice_new (NPWFileTag
);
1421 memcpy (new_child
, &child
, sizeof (child
));
1422 g_queue_push_head (parser
->tag
, new_child
);
1426 g_free (child
.source
);
1427 g_free (child
.destination
);
1433 parse_file_end (GMarkupParseContext
* context
,
1438 NPWFileListParser
* parser
= (NPWFileListParser
*)data
;
1440 DEBUG_PRINT("parser_file_end");
1441 if (parser
->unknown
> 0)
1443 /* Pop unknown element */
1446 else if (((NPWFileTag
*)g_queue_peek_head (parser
->tag
))->tag
!= NPW_NO_TAG
)
1448 /* Pop known element */
1449 npw_file_tag_free (g_queue_pop_head (parser
->tag
));
1453 /* Know stack underflow */
1454 g_return_if_reached ();
1458 static GMarkupParser file_markup_parser
= {
1467 npw_file_list_parser_new (const gchar
* filename
)
1469 NPWFileListParser
* parser
;
1472 g_return_val_if_fail (filename
!= NULL
, NULL
);
1474 parser
= g_new (NPWFileListParser
, 1);
1476 parser
->type
= NPW_FILE_PARSER
;
1478 parser
->unknown
= 0;
1479 parser
->tag
= g_queue_new ();
1480 root
= g_slice_new0 (NPWFileTag
);
1481 root
->tag
= NPW_NO_TAG
;
1482 root
->destination
= g_strdup (".");
1483 /* Use .wiz file path as base source directory */
1484 root
->source
= g_path_get_dirname (filename
);
1485 g_queue_push_head (parser
->tag
, root
);
1487 parser
->list
= NULL
;
1489 parser
->ctx
= g_markup_parse_context_new (&file_markup_parser
, 0, parser
, NULL
);
1490 g_assert (parser
->ctx
!= NULL
);
1496 npw_file_list_parser_free (NPWFileListParser
* parser
)
1498 g_return_if_fail (parser
!= NULL
);
1500 g_markup_parse_context_free (parser
->ctx
);
1501 DEBUG_PRINT("parser free");
1502 g_queue_foreach (parser
->tag
, (GFunc
)npw_file_tag_free
, NULL
);
1503 DEBUG_PRINT("parser free ok");
1504 g_queue_free (parser
->tag
);
1509 npw_file_list_parser_parse (NPWFileListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1511 return g_markup_parse_context_parse (parser
->ctx
, text
, len
, error
);
1515 npw_file_list_parser_end_parse (NPWFileListParser
* parser
, GError
** error
)
1519 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1521 /* Reverse file list */
1522 parser
->list
= g_list_reverse (parser
->list
);
1524 list
= parser
->list
;
1530 /* Parse action block
1531 *---------------------------------------------------------------------------*/
1533 #define NPW_ACTION_PARSER_MAX_LEVEL 3
1534 /* Maximum number of nested elements */
1536 struct _NPWActionListParser
1538 /* Type of parser (not used) */
1540 GMarkupParseContext
* ctx
;
1541 /* Known element stack */
1542 NPWTag tag
[NPW_ACTION_PARSER_MAX_LEVEL
+ 1];
1544 /* Unknown element stack */
1546 /* Current action list object */
1551 parse_run (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1553 const gchar
* command
= NULL
;
1555 while (*attributes
!= NULL
)
1557 switch (parse_attribute (*attributes
))
1559 case NPW_COMMAND_ATTRIBUTE
:
1563 parser_warning (parser
->ctx
, "Unknown run attribute \"%s\"", *attributes
);
1570 if (command
== NULL
)
1572 parser_warning (parser
->ctx
, "Missing command attribute");
1578 action
= npw_action_new_command (command
);
1579 parser
->list
= g_list_prepend (parser
->list
, action
);
1586 parse_open (NPWActionListParser
* parser
, const gchar
** attributes
, const gchar
** values
)
1588 const gchar
* file
= NULL
;
1590 while (*attributes
!= NULL
)
1592 switch (parse_attribute (*attributes
))
1594 case NPW_FILE_ATTRIBUTE
:
1598 parser_warning (parser
->ctx
, "Unknown open attribute \"%s\"", *attributes
);
1607 parser_warning (parser
->ctx
, "Missing file attribute");
1613 action
= npw_action_new_file (file
);
1614 parser
->list
= g_list_prepend (parser
->list
, action
);
1621 parse_action_start (GMarkupParseContext
* context
, const gchar
* name
, const gchar
** attributes
,
1622 const gchar
** values
, gpointer data
, GError
** error
)
1624 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1626 gboolean known
= FALSE
;
1628 /* Recognize element */
1629 if (parser
->unknown
== 0)
1631 /* Not inside an unknown element */
1632 tag
= parse_tag (name
);
1633 switch (*parser
->last
)
1636 case NPW_PROJECT_TEMPLATE_TAG
:
1637 /* Top level element */
1640 case NPW_ACTION_TAG
:
1643 case NPW_UNKNOW_TAG
:
1644 parser_warning (parser
->ctx
, "Unknown element \"%s\"", name
);
1646 case NPW_PROJECT_TEMPLATE_TAG
:
1653 case NPW_ACTION_TAG
:
1654 /* Necessary to avoid neested page element */
1658 known
= parse_run (parser
, attributes
, values
);
1661 known
= parse_open (parser
, attributes
, values
);
1664 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1669 parser_warning (parser
->ctx
, "Unexpected element \"%s\"", name
);
1677 /* Know element stack overflow */
1678 g_return_if_fail ((parser
->last
- parser
->tag
) <= NPW_ACTION_PARSER_MAX_LEVEL
);
1680 *parser
->last
= tag
;
1689 parse_action_end (GMarkupParseContext
* context
, const gchar
* name
, gpointer data
, GError
** error
)
1691 NPWActionListParser
* parser
= (NPWActionListParser
*)data
;
1693 if (parser
->unknown
> 0)
1695 /* Pop unknown element */
1698 else if (*parser
->last
!= NPW_NO_TAG
)
1700 /* Pop known element */
1705 /* Know element stack underflow */
1706 g_return_if_reached ();
1710 static GMarkupParser action_markup_parser
= {
1718 NPWActionListParser
*
1719 npw_action_list_parser_new (void)
1721 NPWActionListParser
* parser
;
1723 parser
= g_new (NPWActionListParser
, 1);
1725 parser
->type
= NPW_ACTION_PARSER
;
1727 parser
->unknown
= 0;
1728 parser
->tag
[0] = NPW_NO_TAG
;
1729 parser
->last
= parser
->tag
;
1731 parser
->list
= NULL
;
1733 parser
->ctx
= g_markup_parse_context_new (&action_markup_parser
, 0, parser
, NULL
);
1734 g_assert (parser
->ctx
!= NULL
);
1740 npw_action_list_parser_free (NPWActionListParser
* parser
)
1742 g_return_if_fail (parser
!= NULL
);
1744 g_markup_parse_context_free (parser
->ctx
);
1749 npw_action_list_parser_parse (NPWActionListParser
* parser
, const gchar
* text
, gssize len
, GError
** error
)
1753 g_markup_parse_context_parse (parser
->ctx
, text
, len
, &err
);
1756 g_warning ("%s", err
->message
);
1763 npw_action_list_parser_end_parse (NPWActionListParser
* parser
, GError
** error
)
1767 if (g_markup_parse_context_end_parse (parser
->ctx
, error
))
1769 /* Reverse file list */
1770 parser
->list
= g_list_reverse (parser
->list
);
1772 list
= parser
->list
;