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