1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2
3 /*
4 * csslint.c : a small tester program for libcroco.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 *
20 * Initial Author: Gael Chamoulaud.
21 * Main programmer: Dodji Seketeli
22 * Contributor: Rob Buis
23 * See COPYRGIGHTS file for copyright information.
24 */
25
26 #include "libcroco.h"
27 #include <libxml/xpath.h>
28
29 #include <glib.h>
30 #include <string.h>
31
32 /**
33 *The options data structure.
34 *The variable of this data structure are set
35 *during the parsing the command line by the
36 *parse_command_line() function.
37 */
38 struct Options {
39 gboolean show_version;
40 gboolean use_cssom;
41 gboolean display_help;
42 gboolean evaluate;
43 gboolean dump_location;
44 gchar *author_sheet_path;
45 gchar *user_sheet_path;
46 gchar *ua_sheet_path;
47 gchar *xml_path;
48 gchar *xpath;
49 gchar **css_files_list;
50 };
51
52 struct SacContext {
53 gint level;
54
55 };
56
57 static enum CRStatus sac_parse_and_display_locations (guchar * a_file_uri);
58
59 static void parse_cmd_line (int a_argc, char **a_argv,
60 struct Options *a_options);
61
62 static void display_version (void);
63
64 static void display_usage (void);
65
66 static enum CRStatus cssom_parse (guchar * a_file_uri);
67
68 static enum CRStatus get_and_dump_node_style (xmlNode * a_node,
69 CRSelEng * a_sel_eng,
70 CRCascade * a_cascade);
71
72 static enum CRStatus evaluate_selectors (gchar * a_xml_path,
73 gchar * a_author_sheet_path,
74 gchar * a_user_sheet_path,
75 gchar * a_ua_sheet_path,
76 gchar * a_xpath);
77
78 /**
79 *Parses the command line.
80 *@param a_argc the argc parameter of the main routine.
81 *@param the argv parameter of the main routine.
82 *@param a_options out parameter the parsed options.
83 */
84 static void
parse_cmd_line(int a_argc,char ** a_argv,struct Options * a_options)85 parse_cmd_line (int a_argc, char **a_argv, struct Options *a_options)
86 {
87 int i = 0;
88
89 g_return_if_fail (a_options);
90
91 if (a_argc <= 1) {
92 display_usage ();
93 }
94
95 for (i = 1; i < a_argc; i++) {
96 if (a_argv[i][0] != '-')
97 break;
98
99 if ((!strcmp (a_argv[i], "-version")) ||
100 (!strcmp (a_argv[i], "-v"))) {
101 a_options->show_version = TRUE;
102 } else if (!strcmp (a_argv[i], "--evaluate") ||
103 !strcmp (a_argv[i], "-e")) {
104 for (i++; i < a_argc; i++) {
105 if (!strcmp (a_argv[i], "--author-sheet")) {
106 if (a_options->author_sheet_path) {
107 display_usage ();
108 exit (-1);
109 }
110 i++;
111 if (i >= a_argc
112 || a_argv[i][0] == '-') {
113 g_print ("--author-sheet should be followed by a path to the sheet\n");
114 display_usage ();
115 exit (-1);
116 }
117 a_options->author_sheet_path =
118 a_argv[i];
119 } else if (!strcmp
120 (a_argv[i], "--user-sheet")) {
121 if (a_options->user_sheet_path) {
122 display_usage ();
123 exit (-1);
124 }
125 i++;
126 if (i >= a_argc
127 || a_argv[i][0] == '-') {
128 g_print ("--user-sheet should be followed by a path to the sheet\n");
129 display_usage ();
130 exit (-1);
131 }
132 a_options->user_sheet_path =
133 a_argv[i];
134 } else if (!strcmp (a_argv[i], "--ua-sheet")) {
135 if (a_options->ua_sheet_path) {
136 display_usage ();
137 exit (-1);
138 }
139 i++;
140 if (i >= a_argc
141 || a_argv[i][0] == '-') {
142 g_print ("--ua-sheet should be followed by a path to the sheet\n");
143 display_usage ();
144 exit (-1);
145 }
146 a_options->ua_sheet_path = a_argv[i];
147 } else if (!strcmp (a_argv[i], "--xml")) {
148 i++;
149 if (i >= a_argc
150 || a_argv[i][0] == '-') {
151 g_print ("--xml should be followed by a path to the xml document\n");
152 display_usage ();
153 exit (-1);
154 }
155 a_options->xml_path = a_argv[i];
156 } else if (!strcmp (a_argv[i], "--xpath")) {
157 i++;
158 if (i >= a_argc
159 || a_argv[i][0] == '-') {
160 g_print ("--xpath should be followed by an xpath expresion\n");
161 display_usage ();
162 exit (-1);
163 }
164 a_options->xpath = a_argv[i];
165 } else {
166 break;
167 }
168 }
169 if (!a_options->author_sheet_path
170 && !a_options->user_sheet_path &&
171 !a_options->ua_sheet_path) {
172 g_print ("Error: you must specify at least one stylesheet\n");
173 display_usage ();
174 exit (-1);
175
176 }
177 if (!a_options->xpath) {
178 g_printerr
179 ("Error: you must specify an xpath expression using the --xpath option\n");
180 display_usage ();
181 exit (-1);
182
183 }
184 a_options->evaluate = TRUE;
185 } else if (!strcmp (a_argv[i], "--dump-location")) {
186 a_options->dump_location = TRUE;
187 a_options->use_cssom = FALSE;
188 } else if (!strcmp (a_argv[i], "--help") ||
189 !strcmp (a_argv[i], "-h")) {
190 a_options->display_help = TRUE;
191 } else {
192 display_usage ();
193 exit (-1);
194 }
195 }
196
197 if (i >= a_argc) {
198 a_options->css_files_list = NULL;
199 } else {
200 if (a_argv[i][0] == '-') {
201 display_usage ();
202 exit (-1);
203 }
204 a_options->css_files_list = &a_argv[i];
205 }
206 }
207
208 /**
209 *Displays the version text.
210 *@param a_argc the argc variable passed to the main function.
211 *@param a_argv the argv variable passed to the main function.
212 */
213 static void
display_version(void)214 display_version (void)
215 {
216 g_print ("%s\n", LIBCROCO_VERSION);
217 }
218
219 /**
220 *Displays the usage text.
221 *@param a_argc the argc variable passed to the main function.
222 *@param a_argv the argv variable passed to the main function.
223 */
224 static void
display_usage(void)225 display_usage (void)
226 {
227 g_print ("Usage: csslint <path to a css file>\n");
228 g_print ("\t| csslint -v|--version\n");
229 g_print ("\t| csslint --dump-location <path to a css file>\n");
230 g_print ("\t| csslint <--evaluate | -e> [--author-sheet <path> --user-sheet <path> --ua-sheet <path>\n\t ] --xml <path> --xpath <xpath expression>\n");
231 }
232
233 /**
234 *The test of the cr_input_read_byte() method.
235 *Reads the each byte of a_file_uri using the
236 *cr_input_read_byte() method. Each byte is send to
237 *stdout.
238 *@param a_file_uri the file to read.
239 *@return CR_OK upon successfull completion of the
240 *function, an error code otherwise.
241 */
242 static enum CRStatus
cssom_parse(guchar * a_file_uri)243 cssom_parse (guchar * a_file_uri)
244 {
245 enum CRStatus status = CR_OK;
246 CROMParser *parser = NULL;
247 CRStyleSheet *stylesheet = NULL;
248
249 g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
250
251 parser = cr_om_parser_new (NULL);
252 status = cr_om_parser_parse_file (parser,
253 a_file_uri, CR_ASCII, &stylesheet);
254 if (status == CR_OK && stylesheet) {
255 cr_stylesheet_dump (stylesheet, stdout);
256 g_print ("\n");
257 cr_stylesheet_destroy (stylesheet);
258 }
259 cr_om_parser_destroy (parser);
260
261 return status;
262 }
263
264 static enum CRStatus
get_and_dump_node_style(xmlNode * a_node,CRSelEng * a_sel_eng,CRCascade * a_cascade)265 get_and_dump_node_style (xmlNode * a_node,
266 CRSelEng * a_sel_eng, CRCascade * a_cascade)
267 {
268 CRPropList *prop_list = NULL,
269 *pair = NULL,
270 *prev_pair = NULL;
271 enum CRStatus status = CR_OK;
272
273 g_return_val_if_fail (a_node && a_sel_eng && a_cascade,
274 CR_BAD_PARAM_ERROR);
275
276 status = cr_sel_eng_get_matched_properties_from_cascade
277 (a_sel_eng, a_cascade, a_node, &prop_list);
278 if (status != CR_OK) {
279 g_printerr ("Error: unable to run the selection engine\n");
280 return CR_OK;
281 }
282 g_print ("Properties of xml element %s are:\n", a_node->name);
283 for (pair = prop_list; pair; pair = cr_prop_list_get_next (pair)) {
284 CRDeclaration *decl = NULL;
285
286 cr_prop_list_get_decl (pair, &decl);
287 if (decl) {
288 prev_pair = cr_prop_list_get_prev (pair);
289 if (prev_pair) {
290 g_print ("\n");
291 prev_pair = NULL;
292 }
293 cr_declaration_dump_one (decl, stdout, 2);
294 decl = NULL;
295 }
296 }
297 g_print ("\n=====================\n\n");
298
299 if (prop_list) {
300 cr_prop_list_destroy (prop_list);
301 prop_list = NULL;
302 }
303
304 return CR_OK;
305 }
306
307 static enum CRStatus
evaluate_selectors(gchar * a_xml_path,gchar * a_author_sheet_path,gchar * a_user_sheet_path,gchar * a_ua_sheet_path,gchar * a_xpath)308 evaluate_selectors (gchar * a_xml_path,
309 gchar * a_author_sheet_path,
310 gchar * a_user_sheet_path,
311 gchar * a_ua_sheet_path, gchar * a_xpath)
312 {
313 CRSelEng *sel_eng = NULL;
314 xmlDoc *xml_doc = NULL;
315 xmlXPathContext *xpath_context = NULL;
316 xmlXPathObject *xpath_object = NULL;
317 CRStyleSheet *author_sheet = NULL,
318 *user_sheet = NULL,
319 *ua_sheet = NULL;
320 CRCascade *cascade = NULL;
321 xmlNode *cur_node = NULL;
322 gint i = 0;
323 enum CRStatus status = CR_OK;
324
325 g_return_val_if_fail (a_xml_path && a_xpath, CR_BAD_PARAM_ERROR);
326
327 xml_doc = xmlParseFile (a_xml_path);
328 if (!xml_doc) {
329 g_printerr ("Error: Could not parse file %s\n", a_xml_path);
330 status = CR_ERROR;
331 goto end;
332 }
333 if (a_author_sheet_path) {
334 status = cr_om_parser_simply_parse_file
335 ((const guchar *) a_author_sheet_path, CR_ASCII, &author_sheet);
336 if (!author_sheet) {
337 g_printerr ("Error: Could not parse author sheet\n");
338 }
339 }
340 if (a_user_sheet_path) {
341 status = cr_om_parser_simply_parse_file
342 ((const guchar *) a_user_sheet_path, CR_ASCII, &user_sheet);
343 if (!user_sheet) {
344 g_printerr ("Error: Could not parse author sheet\n");
345 }
346 }
347 if (a_ua_sheet_path) {
348 status = cr_om_parser_simply_parse_file
349 ((const guchar *) a_ua_sheet_path, CR_ASCII, &ua_sheet);
350 if (!ua_sheet) {
351 g_printerr ("Error: Could not parse ua sheet\n");
352 }
353 }
354 cascade = cr_cascade_new (author_sheet, user_sheet, ua_sheet);
355
356 if (author_sheet)
357 cr_stylesheet_unref (author_sheet);
358
359 if (user_sheet)
360 cr_stylesheet_unref (user_sheet);
361
362 if (ua_sheet)
363 cr_stylesheet_unref (ua_sheet);
364
365 if (!cascade) {
366 g_printerr ("Could not instanciate the cascade\n");
367 status = CR_ERROR;
368 goto end;
369 }
370 sel_eng = cr_sel_eng_new ();
371 if (!sel_eng) {
372 g_printerr
373 ("Error: Could not instanciate the selection engine\n");
374 status = CR_ERROR;
375 goto end;
376 }
377 xpath_context = xmlXPathNewContext (xml_doc);
378 if (!xpath_context) {
379 g_printerr
380 ("Error: Could not instanciate the xpath context\n");
381 status = CR_ERROR;
382 goto end;
383 }
384 xpath_object = xmlXPathEvalExpression ((const xmlChar *) a_xpath, xpath_context);
385 if (!xpath_object) {
386 g_printerr ("Error: Could not evaluate xpath expression\n");
387 status = CR_ERROR;
388 goto end;
389 }
390 if (xpath_object->type != XPATH_NODESET || !xpath_object->nodesetval) {
391 g_printerr
392 ("Error: xpath does not evalualuate to a node set\n");
393 status = CR_ERROR;
394 goto end;
395 }
396
397 for (i = 0; i < xpath_object->nodesetval->nodeNr; i++) {
398 cur_node = xpath_object->nodesetval->nodeTab[i];
399 if (cur_node->type == XML_ELEMENT_NODE) {
400 status = get_and_dump_node_style (cur_node, sel_eng,
401 cascade);
402 }
403 }
404
405 end:
406
407 if (xpath_context) {
408 xmlXPathFreeContext (xpath_context);
409 xpath_context = NULL;
410 }
411 if (xpath_object) {
412 xmlXPathFreeObject (xpath_object);
413 xpath_object = NULL;
414 }
415 if (sel_eng) {
416 cr_sel_eng_destroy (sel_eng);
417 sel_eng = NULL;
418 }
419 if (cascade) {
420 cr_cascade_destroy (cascade);
421 cascade = NULL;
422 }
423 if (xml_doc) {
424 xmlFreeDoc (xml_doc);
425 xml_doc = NULL;
426 }
427
428 return status;
429 }
430
431 /***************************
432 *SAC related stuff for the
433 *line/col annotation stylesheet
434 *dumping
435 ***************************/
436 static void
start_document(CRDocHandler * a_this)437 start_document (CRDocHandler * a_this)
438 {
439 struct SacContext *context = NULL;
440
441 g_return_if_fail (a_this);
442
443 context = g_try_malloc (sizeof (struct SacContext));
444 if (!context) {
445 cr_utils_trace_info ("instanciation of sac context failed");
446 return;
447 }
448 cr_doc_handler_set_ctxt (a_this, context);
449 }
450
451 static void
end_document(CRDocHandler * a_this)452 end_document (CRDocHandler * a_this)
453 {
454 struct SacContext *context = NULL;
455
456 g_return_if_fail (a_this);
457
458 cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
459 if (context) {
460 g_free (context);
461 context = NULL;
462 }
463 }
464
465 static void
charset(CRDocHandler * a_this,CRString * a_charset,CRParsingLocation * a_charset_sym_location)466 charset (CRDocHandler *a_this,
467 CRString *a_charset,
468 CRParsingLocation *a_charset_sym_location)
469 {
470 gchar *str = NULL ;
471
472 g_return_if_fail (a_this && a_charset && a_charset_sym_location) ;
473
474 str = (gchar*)cr_string_peek_raw_str (a_charset) ;
475 if (str) {
476 g_print ("\n\n@charset \"%s\";\n\n", str) ;
477 str = NULL ;
478 } else {
479 return ;
480 }
481 g_print ("/********************************************\n") ;
482 g_print (" * Parsing location information of the @charset rule\n") ;
483 g_print (" ********************************************/\n") ;
484 if (a_charset_sym_location) {
485 str = cr_parsing_location_to_string (a_charset_sym_location, 0) ;
486 if (str) {
487 g_print (" /*@charset*/\n") ;
488 g_print (" /*%s*/\n", str) ;
489 g_free (str) ;
490 str = NULL ;
491 }
492 }
493 str = (gchar*) cr_string_peek_raw_str (a_charset) ;
494 if (str) {
495 g_print (" /*%s*/\n", str) ;
496 str = NULL ;
497 }
498 str = cr_parsing_location_to_string (&a_charset->location, 0) ;
499 if (str) {
500 g_print (" /*%s*/\n\n", str) ;
501 g_free (str) ;
502 str = NULL ;
503 }
504 }
505
506 static void
import_style(CRDocHandler * a_this,GList * a_media_list,CRString * a_uri,CRString * a_uri_default_ns,CRParsingLocation * a_location)507 import_style (CRDocHandler *a_this,
508 GList *a_media_list,
509 CRString *a_uri,
510 CRString *a_uri_default_ns,
511 CRParsingLocation *a_location)
512 {
513 gchar *str = NULL ;
514 GString *gstr = NULL ;
515 GList *cur_media = NULL ;
516
517 g_return_if_fail (a_this && a_location) ;
518
519 gstr = g_string_new (NULL) ;
520 if (!gstr) {
521 cr_utils_trace_info ("Out of memory error") ;
522 return ;
523 }
524 for (cur_media = a_media_list ;
525 cur_media ;
526 cur_media = g_list_next (cur_media)) {
527 str = (gchar*)cr_string_peek_raw_str
528 ((CRString*)cur_media->data) ;
529 if (str) {
530 if (g_list_previous (cur_media)) {
531 g_string_append_printf (gstr, ", %s",
532 str) ;
533 } else {
534 g_string_append_printf (gstr, "%s",
535 str) ;
536 }
537 }
538 }
539 str = (gchar*)cr_string_peek_raw_str (a_uri) ;
540 if (str) {
541 g_print ("@import url(\"%s\") ", str) ;
542 if (gstr) {
543 g_print ("%s;\n\n", gstr->str) ;
544 }
545 str = NULL ;
546 }
547 str = cr_parsing_location_to_string (a_location, 0) ;
548 if (str) {
549 g_print ("/*****************************************************\n") ;
550 g_print (" *Parsing location inforamtion for the @import rule\n") ;
551 g_print (" ******************************************************/\n\n") ;
552 g_print (" /*@import*/\n") ;
553 g_print (" /*%s*/\n\n", str) ;
554 g_free (str) ;
555 str = NULL ;
556 }
557
558 str = (gchar*)cr_string_peek_raw_str (a_uri) ;
559 if (str) {
560 g_print (" /*%s*/\n", str) ;
561 str = cr_parsing_location_to_string
562 (&a_uri->location, 0) ;
563 if (str) {
564 g_print (" /*%s*/\n\n", str) ;
565 g_free (str) ;
566 str = NULL ;
567 }
568 }
569
570 for (cur_media = a_media_list ;
571 cur_media ;
572 cur_media = g_list_next (cur_media)) {
573 str = (gchar*)cr_string_peek_raw_str
574 ((CRString*)cur_media->data) ;
575 if (str) {
576 g_print (" /*%s*/\n", str) ;
577 }
578 str = cr_parsing_location_to_string
579 (&((CRString*)cur_media->data)->location, 0) ;
580 if (str) {
581 g_print (" /*%s*/\n\n", str) ;
582 g_free (str) ;
583 str = NULL ;
584 }
585 }
586
587 if (gstr) {
588 g_string_free (gstr, TRUE) ;
589 gstr = NULL ;
590 }
591 }
592
593 static void
start_font_face(CRDocHandler * a_this,CRParsingLocation * a_location)594 start_font_face (CRDocHandler *a_this,
595 CRParsingLocation *a_location)
596 {
597 gchar *str = NULL ;
598
599 g_print ("@font-face {\n") ;
600 g_print ("/******************************************************\n") ;
601 g_print (" Parsing location information for the @font-face rule\n") ;
602 g_print (" ******************************************************/\n\n") ;
603
604 g_print (" /*@font-face*/\n") ;
605 if (a_location) {
606 str = cr_parsing_location_to_string (a_location, 0) ;
607 }
608 if (str) {
609 g_print (" /*%s*/\n", str) ;
610 g_free (str) ;
611 str = NULL ;
612 }
613 }
614
615 static void
end_font_face(CRDocHandler * a_this)616 end_font_face (CRDocHandler *a_this)
617 {
618 g_print ("}\n") ;
619 }
620
621 static void
start_media(CRDocHandler * a_this,GList * a_media_list,CRParsingLocation * a_location)622 start_media (CRDocHandler *a_this,
623 GList *a_media_list,
624 CRParsingLocation *a_location)
625 {
626 GList *cur_media = NULL ;
627 gchar *str = NULL ;
628
629 g_print ("@media ") ;
630 for (cur_media = a_media_list ;
631 cur_media ;
632 cur_media = g_list_next (cur_media)) {
633 CRString *crstr = cur_media->data ;
634 if (crstr) {
635 str = (gchar*)cr_string_peek_raw_str (crstr) ;
636 if (str) {
637 if (cur_media->prev) {
638 g_print (", %s", str) ;
639 } else {
640 g_print ("%s", str) ;
641 }
642 }
643 }
644 }
645 /*****************************
646 *new print parsing locations
647 *****************************/
648 g_print ("\n /*@media*/\n") ;
649 if (a_location)
650 str = cr_parsing_location_to_string (a_location,
651 0) ;
652 if (str) {
653 g_print (" /*%s*/\n", str) ;
654 g_free (str) ;
655 str = NULL ;
656 }
657 for (cur_media = a_media_list ;
658 cur_media ;
659 cur_media = g_list_next (cur_media)) {
660 CRString *crstr = cur_media->data ;
661 if (crstr) {
662 str = (gchar*)cr_string_peek_raw_str (crstr) ;
663 if (str) {
664 g_print (" /*%s*/\n", str) ;
665 str = cr_parsing_location_to_string
666 (&crstr->location, 0) ;
667 if (str) {
668 g_print (" /*%s*/\n", str) ;
669 g_free (str) ;
670 str = NULL ;
671 }
672 }
673 }
674 }
675 g_print ("\n{\n") ;
676 }
677
678 static void
end_media(CRDocHandler * a_this,GList * a_media_list)679 end_media (CRDocHandler *a_this,
680 GList *a_media_list)
681 {
682 g_print ("\n}\n") ;
683 }
684
685 static void
start_page(CRDocHandler * a_this,CRString * a_name,CRString * a_pseudo_page,CRParsingLocation * a_location)686 start_page (CRDocHandler *a_this,
687 CRString *a_name,
688 CRString *a_pseudo_page,
689 CRParsingLocation *a_location)
690 {
691 gchar *str = NULL ;
692
693 g_print ("@page ") ;
694 if (a_name)
695 str = (gchar*)cr_string_peek_raw_str (a_name) ;
696 if (str) {
697 g_print ("%s ", str) ;
698 }
699 if (a_pseudo_page)
700 str = (gchar*) cr_string_peek_raw_str (a_pseudo_page) ;
701 if (str) {
702 g_print (":%s", str) ;
703 str = NULL ;
704 }
705 /*************************************
706 *print parsing location informations
707 ************************************/
708 g_print ("\n\n /*@page*/\n") ;
709 if (a_location)
710 str = cr_parsing_location_to_string
711 (a_location, 0) ;
712 if (str) {
713 g_print (" /*%s*/\n", str) ;
714 g_free (str) ;
715 str = NULL ;
716 }
717 if (a_name)
718 str = (gchar*)cr_string_peek_raw_str (a_name) ;
719 if (str) {
720 g_print (" /*%s*/\n", str) ;
721 str = cr_parsing_location_to_string
722 (&a_name->location, 0) ;
723 if (str) {
724 g_print (" /*%s*/\n", str) ;
725 g_free (str) ;
726 str = NULL ;
727 }
728 }
729 if (a_pseudo_page)
730 str = (gchar*) cr_string_peek_raw_str
731 (a_pseudo_page) ;
732 if (str) {
733 g_print (" /*%s*/\n", str) ;
734 str = cr_parsing_location_to_string
735 (&a_pseudo_page->location, 0) ;
736 if (str) {
737 g_print (" /*%s*/\n", str) ;
738 g_free (str) ;
739 str = NULL ;
740 }
741 }
742 g_print ("\n{\n") ;
743 }
744
745 static void
end_page(CRDocHandler * a_this,CRString * a_name,CRString * pseudo_page)746 end_page (CRDocHandler *a_this,
747 CRString *a_name,
748 CRString *pseudo_page)
749 {
750 g_print ("}\n") ;
751 }
752
753 static void
dump_location_annotated_simple_sel(CRSimpleSel * a_this)754 dump_location_annotated_simple_sel (CRSimpleSel *a_this)
755 {
756 CRSimpleSel *cur_simple_sel = a_this ;
757 CRAdditionalSel *cur_add_sel = NULL ;
758 gchar *str0 = NULL ;
759
760 g_return_if_fail (a_this) ;
761
762 /*first, display the entire simple sel*/
763 str0 = (gchar *) cr_simple_sel_one_to_string
764 (cur_simple_sel) ;
765 if (str0) {
766 g_print ("/*%s*/\n", str0) ;
767 g_free (str0) ;
768 str0 = NULL ;
769 }
770 g_print ("/*") ;
771 cr_parsing_location_dump
772 (&cur_simple_sel->location, 0,
773 stdout);
774 g_print ("*/\n") ;
775
776 /*now display the details of the simple sel*/
777 if (cur_simple_sel->name) {
778 str0 = (gchar*) cr_string_peek_raw_str
779 (cur_simple_sel->name) ;
780 if (str0) {
781 g_print (" /*%s*/\n", str0) ;
782 str0 = NULL ;
783 }
784 str0 = cr_parsing_location_to_string
785 (&cur_simple_sel->name->location,
786 0) ;
787 if (str0) {
788 g_print (" /*%s*/\n", str0) ;
789 g_free (str0) ;
790 str0 = NULL ;
791 }
792 }
793 for (cur_add_sel = cur_simple_sel->add_sel;
794 cur_add_sel;
795 cur_add_sel = cur_add_sel->next) {
796 str0 = (gchar *) cr_additional_sel_one_to_string
797 (cur_add_sel) ;
798 if (str0) {
799 g_print ("\n /*%s*/\n", str0) ;
800 g_free (str0) ;
801 str0 = NULL ;
802 }
803 str0 = cr_parsing_location_to_string
804 (&cur_add_sel->location, 0) ;
805 if (str0) {
806 g_print (" /*%s*/\n", str0) ;
807 g_free (str0) ;
808 str0 = NULL ;
809 }
810 }
811 }
812
813 static void
start_selector(CRDocHandler * a_this,CRSelector * a_selector_list)814 start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
815 {
816 struct SacContext *context = NULL;
817 CRSelector *cur_sel = NULL ;
818 CRSimpleSel *cur_simple_sel = NULL ;
819
820 g_return_if_fail (a_this);
821
822 cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
823 if (context) {
824 context->level++;
825 }
826 cr_selector_dump (a_selector_list, stdout);
827 g_print (" {\n") ;
828 g_print ("/************************************************\n") ;
829 g_print (" *Parsing location information of the selector\n") ;
830 g_print (" ************************************************/\n") ;
831
832 for (cur_sel = a_selector_list;
833 cur_sel ;
834 cur_sel = cur_sel->next) {
835 for (cur_simple_sel = cur_sel->simple_sel ;
836 cur_simple_sel ;
837 cur_simple_sel = cur_simple_sel->next) {
838
839 dump_location_annotated_simple_sel
840 (cur_simple_sel) ;
841 }
842 }
843 }
844
845 static void
end_selector(CRDocHandler * a_this,CRSelector * a_selector_list)846 end_selector (CRDocHandler * a_this,
847 CRSelector *a_selector_list)
848 {
849 struct SacContext *context = NULL;
850
851 g_return_if_fail (a_this);
852
853 cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
854 if (context) {
855 context->level--;
856 }
857 g_print (" }\n") ;
858 }
859
860 static void
property(CRDocHandler * a_this,CRString * a_name,CRTerm * a_expr,gboolean a_is_important)861 property (CRDocHandler *a_this,
862 CRString *a_name,
863 CRTerm *a_expr,
864 gboolean a_is_important)
865 {
866 gchar *str = NULL ;
867 CRTerm *cur_term = NULL ;
868
869 str = (gchar*) cr_string_peek_raw_str (a_name) ;
870 if (str) {
871 g_print ("\n\n") ;
872 g_print ("%s", str) ;
873 str = NULL ;
874 if (a_expr) {
875 str = (gchar *) cr_term_to_string (a_expr) ;
876 if (str) {
877 g_print (" : %s;\n\n", str) ;
878 g_free (str) ;
879 str = NULL ;
880 }
881 } else {
882 g_print (";\n\n") ;
883 }
884 }
885
886 /*Now dump each part of the property declaration*/
887
888 g_print ("\n") ;
889 g_print ("/************************************************\n") ;
890 g_print (" *Parsing location information of the property\n") ;
891 g_print (" ************************************************/\n") ;
892
893 str = (gchar*) cr_string_peek_raw_str (a_name) ;
894 if (str) {
895 g_print (" /*%s*/\n", str) ;
896 str = NULL ;
897 }
898 str = cr_parsing_location_to_string (&a_name->location, 0) ;
899 if (str) {
900 g_print (" /*%s*/\n", str) ;
901 g_free (str) ;
902 str = NULL ;
903 }
904
905 for (cur_term = a_expr ;
906 cur_term;
907 cur_term = cur_term->next) {
908 str = (gchar *) cr_term_one_to_string (cur_term) ;
909 if (str) {
910 g_print (" /*%s*/\n", str) ;
911 g_free (str) ;
912 str = NULL ;
913 }
914 str = cr_parsing_location_to_string
915 (&cur_term->location, 0) ;
916 if (str) {
917 g_print (" /*%s*/\n", str) ;
918 g_free (str) ;
919 str = NULL ;
920 }
921 }
922 }
923
924
925 static enum CRStatus
sac_parse_and_display_locations(guchar * a_file_uri)926 sac_parse_and_display_locations (guchar * a_file_uri)
927 {
928 enum CRStatus status = CR_OK;
929 CRDocHandler *sac_handler = NULL;
930 CRParser *parser = NULL;
931
932 g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
933
934 parser = cr_parser_new_from_file (a_file_uri, CR_UTF_8);
935 if (!parser) {
936 cr_utils_trace_info ("parser instanciation failed");
937 return CR_ERROR;
938 }
939 sac_handler = cr_doc_handler_new ();
940 if (!sac_handler) {
941 cr_utils_trace_info ("sac handler instanciation failed");
942 status = CR_OUT_OF_MEMORY_ERROR;
943 goto cleanup;
944 }
945 sac_handler->start_document = start_document ;
946 sac_handler->end_document = end_document ;
947 sac_handler->charset = charset ;
948 sac_handler->import_style = import_style ;
949 sac_handler->start_font_face = start_font_face ;
950 sac_handler->end_font_face = end_font_face ;
951 sac_handler->start_media = start_media ;
952 sac_handler->end_media = end_media ;
953 sac_handler->start_page = start_page ;
954 sac_handler->end_page = end_page ;
955 sac_handler->start_selector = start_selector;
956 sac_handler->end_selector = end_selector;
957 sac_handler->property = property ;
958
959 cr_parser_set_sac_handler (parser, sac_handler) ;
960 status = cr_parser_parse (parser) ;
961
962 cleanup:
963 if (parser) {
964 cr_parser_destroy (parser);
965 parser = NULL;
966 }
967 return status;
968 }
969
970 int
main(int argc,char ** argv)971 main (int argc, char **argv)
972 {
973 struct Options options;
974 enum CRStatus status = CR_OK;
975
976 memset (&options, 0, sizeof (struct Options));
977 options.use_cssom = TRUE;
978 parse_cmd_line (argc, argv, &options);
979
980 if (options.show_version == TRUE) {
981 display_version ();
982 return 0;
983 }
984
985 if (options.display_help == TRUE) {
986 display_usage ();
987 return 0;
988 }
989 if (options.use_cssom == TRUE) {
990 if (options.evaluate == TRUE) {
991 status = evaluate_selectors
992 (options.xml_path,
993 options.author_sheet_path,
994 options.user_sheet_path,
995 options.ua_sheet_path, options.xpath);
996 } else if (options.css_files_list != NULL) {
997 status = cssom_parse ((guchar *) options.css_files_list[0]);
998 }
999 } else if (options.dump_location == TRUE) {
1000 if (options.css_files_list) {
1001 status = sac_parse_and_display_locations
1002 ((guchar *) options.css_files_list[0]) ;
1003 } else {
1004 display_usage () ;
1005 return -1 ;
1006 }
1007 }
1008
1009 return (status == CR_OK) ? 0 : -2;
1010 }
1011