Annotation of gpl/axl/knife/axl-knife.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Axl Knife: Console tool on top of Axl Library
3: * Copyright (C) 2007 Advanced Software Production Line, S.L.
4: *
5: * This program is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU General Public License as
7: * published by the Free Software Foundation; either version 2.1 of
8: * the License, or (at your option) any later version.
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 Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU General Public
16: * License along with this program; if not, write to the Free
17: * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18: * 02111-1307 USA
19: *
20: * For commercial support on build XML enabled solutions contact us:
21: *
22: * Postal address:
23: * Advanced Software Production Line, S.L.
24: * Edificio Alius A, Oficina 102,
25: * C/ Antonio Suarez Nº 10,
26: * Alcalá de Henares 28802 Madrid
27: * Spain
28: *
29: * Email address:
30: * info@aspl.es - http://www.aspl.es/xml
31: */
32: /* main include */
33: #include <axl-knife.h>
34: #include <errno.h>
35:
36: /* internal errno redefinition */
37: #if defined(AXL_OS_WIN32)
38: #define S_ISLNK(m) (0)
39: #endif
40:
41: #define HELP_HEADER "Axl Knife: Console Tool on top of Axl Library\n\
42: Copyright (C) 2007 Advanced Software Production Line, S.L.\n\n"
43:
44: #define POST_HEADER "\n\
45: If you have question, bugs to report, patches, you can reach us\n\
46: at <axl@lists.aspl.es>."
47:
48: /**
49: * @internal Controls if messages must be send to the console log.
50: */
51: axl_bool console_enabled = axl_true;
52: axl_bool console_debug = axl_false;
53: axl_bool console_debug2 = axl_false;
54: axl_bool console_debug3 = axl_false;
55: axl_bool console_color_debug = axl_false;
56: int axl_knife_pid = -1;
57:
58: /**
59: * @internal Simple macro to check if the console output is activated
60: * or not.
61: */
62: #define CONSOLE if (console_enabled) fprintf
63:
64: /**
65: * @internal Simple macro to check if the console output is activated
66: * or not.
67: */
68: #define CONSOLEV if (console_enabled) vfprintf
69:
70: /**
71: * @brief Allows to get the file part from the provided path.
72: *
73: * @param path The path that is provided to return the file part.
74: *
75: * @return A reference newly allocated to the file, or an empty string
76: * that is also required to deallocate.
77: */
78: char * axl_knife_file_name (const char * path)
79: {
80: int iterator;
81: axl_return_val_if_fail (path, NULL);
82:
83: /* start with string length */
84: iterator = strlen (path) - 1;
85:
86: /* lookup for the back-slash */
87: while ((iterator >= 0) && (path [iterator] != '/'))
88: iterator--;
89:
90: /* check if the file provided doesn't have any file part */
91: if (iterator == -1) {
92: /* return the an empty file part */
93: return axl_strdup (path);
94: }
95:
96: /* copy the base dir found */
97: return axl_strdup (path + iterator + 1);
98: }
99:
100: /**
101: * @brief Cleans the string provided removing all values found "-" and
102: * ".", replacing them with "_".
103: *
104: * @param path The path that must be cleaned.
105: *
106: */
107: void axl_knife_clean_name (char * path)
108: {
109: int iterator;
110:
111: /* lookup for the back-slash */
112: iterator = 0;
113: while (path [iterator]) {
114: /* change values found */
115: if (path [iterator] == '.')
116: path [iterator] = '_';
117: if (path [iterator] == '-')
118: path [iterator] = '_';
119:
120: /* next position */
121: iterator++;
122: } /* end while */
123:
124: return;
125: }
126:
127:
128: /**
129: * @internal function that actually handles the console msg.
130: */
131: void axl_knife_msg (const char * file, int line, const char * format, ...)
132: {
133: va_list args;
134:
135: /* check extended console log */
136: if (console_debug3) {
137: #if defined(AXL_OS_UNIX)
138: if (console_color_debug) {
139: CONSOLE (stderr, "(proc:%d) [\e[1;32mmsg\e[0m] (%s:%d) ", axl_knife_pid, file, line);
140: } else
141: #endif
142: CONSOLE (stderr, "(proc:%d) [msg] (%s:%d) ", axl_knife_pid, file, line);
143: } else {
144: #if defined(AXL_OS_UNIX)
145: if (console_color_debug) {
146: CONSOLE (stderr, "\e[1;32mI: \e[0m");
147: } else
148: #endif
149: CONSOLE (stderr, "I: ");
150: } /* end if */
151:
152: va_start (args, format);
153:
154: /* report to console */
155: CONSOLEV (stderr, format, args);
156:
157: va_end (args);
158:
159: CONSOLE (stderr, "\n");
160:
161: fflush (stderr);
162:
163: return;
164: }
165:
166: /**
167: * @internal function that actually handles the console access
168: */
169: void axl_knife_access (const char * file, int line, const char * format, ...)
170: {
171: va_list args;
172:
173: /* check extended console log */
174: if (console_debug3) {
175: #if defined(AXL_OS_UNIX)
176: if (console_color_debug) {
177: CONSOLE (stderr, "(proc:%d) [\e[1;32mmsg\e[0m] (%s:%d) ", axl_knife_pid, file, line);
178: } else
179: #endif
180: CONSOLE (stderr, "(proc:%d) [msg] (%s:%d) ", axl_knife_pid, file, line);
181: } else {
182: #if defined(AXL_OS_UNIX)
183: if (console_color_debug) {
184: CONSOLE (stderr, "\e[1;32mI: \e[0m");
185: } else
186: #endif
187: CONSOLE (stderr, "I: ");
188: } /* end if */
189:
190: va_start (args, format);
191:
192: /* report to console */
193: CONSOLEV (stderr, format, args);
194:
195: va_end (args);
196:
197: CONSOLE (stderr, "\n");
198:
199: fflush (stderr);
200:
201: return;
202: }
203:
204: /**
205: * @internal function that actually handles the console msg (second level debug)
206: */
207: void axl_knife_msg2 (const char * file, int line, const char * format, ...)
208: {
209: va_list args;
210:
211: /* check second level debug */
212: if (! console_debug2)
213: return;
214:
215: /* check extended console log */
216: if (console_debug3) {
217: #if defined(AXL_OS_UNIX)
218: if (exarg_is_defined ("color-debug")) {
219: CONSOLE (stderr, "(proc:%d) [\e[1;32mmsg\e[0m] (%s:%d) ", axl_knife_pid, file, line);
220: } else
221: #endif
222: CONSOLE (stderr, "(proc:%d) [msg] (%s:%d) ", axl_knife_pid, file, line);
223: } else {
224: #if defined(AXL_OS_UNIX)
225: if (console_color_debug) {
226: CONSOLE (stderr, "\e[1;32mI: \e[0m");
227: } else
228: #endif
229: CONSOLE (stderr, "I: ");
230: } /* end if */
231:
232: va_start (args, format);
233:
234: /* report to console */
235: CONSOLEV (stderr, format, args);
236:
237: va_end (args);
238:
239: CONSOLE (stderr, "\n");
240:
241: fflush (stderr);
242:
243: return;
244: }
245:
246: /**
247: * @internal function that actually handles the console wrn.
248: */
249: void axl_knife_wrn (const char * file, int line, const char * format, ...)
250: {
251: va_list args;
252:
253: /* check extended console log */
254: if (console_debug3) {
255: #if defined(AXL_OS_UNIX)
256: if (exarg_is_defined ("color-debug")) {
257: CONSOLE (stderr, "(proc:%d) [\e[1;33m!!!\e[0m] (%s:%d) ", axl_knife_pid, file, line);
258: } else
259: #endif
260: CONSOLE (stderr, "(proc:%d) [!!!] (%s:%d) ", axl_knife_pid, file, line);
261: } else {
262: #if defined(AXL_OS_UNIX)
263: if (console_color_debug) {
264: CONSOLE (stderr, "\e[1;33m!: \e[0m");
265: } else
266: #endif
267: CONSOLE (stderr, "!: ");
268: } /* end if */
269:
270: va_start (args, format);
271:
272: CONSOLEV (stderr, format, args);
273:
274: va_end (args);
275:
276: CONSOLE (stderr, "\n");
277:
278: fflush (stderr);
279:
280: return;
281: }
282:
283:
284: /**
285: * @internal function that actually handles the console error.
286: */
287: void axl_knife_error (const char * file, int line, const char * format, ...)
288: {
289: va_list args;
290:
291:
292: /* check extended console log */
293: if (console_debug3) {
294: #if defined(AXL_OS_UNIX)
295: if (exarg_is_defined ("color-debug")) {
296: CONSOLE (stderr, "(proc:%d) [\e[1;31merr\e[0m] (%s:%d) ", axl_knife_pid, file, line);
297: } else
298: #endif
299: CONSOLE (stderr, "(proc:%d) [err] (%s:%d) ", axl_knife_pid, file, line);
300: } else {
301: #if defined(AXL_OS_UNIX)
302: if (console_color_debug) {
303: CONSOLE (stderr, "\e[1;31mE: \e[0m");
304: } else
305: #endif
306: CONSOLE (stderr, "E: ");
307: } /* end if */
308:
309: va_start (args, format);
310:
311: /* report to the console */
312: CONSOLEV (stderr, format, args);
313:
314: va_end (args);
315:
316: CONSOLE (stderr, "\n");
317:
318: fflush (stderr);
319:
320: return;
321: }
322:
323: void axl_knife_introduce_indentation (FILE * fstream, int level)
324: {
325: int iterator;
326:
327: iterator = 0;
328: while (iterator < level) {
329: fprintf (fstream, " ");
330: iterator++;
331: } /* end while */
332:
333: return;
334: }
335:
336: axl_bool axl_knife_htmlize_iterator_node (FILE * fstream, axlNode * node, int level)
337: {
338:
339: axlItem * item;
340: axlAttrCursor * cursor;
341: int iterator;
342: axl_bool found_content;
343:
344: /* introduce indentation level */
345: axl_knife_introduce_indentation (fstream, level);
346:
347: /* print document node */
348: if (axl_node_has_attributes (node)) {
349: fprintf (fstream, "<<span class=\"node\">%s</span> ",
350: axl_node_get_name (node));
351:
352: /* get the first cursor */
353: cursor = axl_node_attr_cursor_new (node);
354:
355: if (axl_node_num_attributes (node) < 3) {
356: while (axl_node_attr_cursor_has_item (cursor)) {
357:
358: /* print values */
359: fprintf (fstream, "%s=<span class=\"attrvalue\">\"%s\"</span> ",
360: axl_node_attr_cursor_get_key (cursor),
361: axl_node_attr_cursor_get_value (cursor));
362:
363: /* get the next cursor */
364: axl_node_attr_cursor_next (cursor);
365: } /* end while */
366: } else {
367: while (axl_node_attr_cursor_has_item (cursor)) {
368:
369: /* print values */
370: fprintf (fstream, "%s=<span class=\"attrvalue\">\"%s\"</span> ",
371: axl_node_attr_cursor_get_key (cursor),
372: axl_node_attr_cursor_get_value (cursor));
373:
374: /* get the next cursor */
375: axl_node_attr_cursor_next (cursor);
376:
377: /* before getting the next */
378: if (axl_node_attr_cursor_has_item (cursor)) {
379: fprintf (fstream, "\n");
380:
381: /* introduce indentation level */
382: axl_knife_introduce_indentation (fstream, level);
383:
384: iterator = 0;
385: while (iterator < (strlen (axl_node_get_name (node)) + 2)) {
386: fprintf (fstream, " ");
387: iterator++;
388: } /* while */
389: } /* end if */
390:
391: } /* end while */
392: }
393:
394: /* free cursor */
395: axl_node_attr_cursor_free (cursor);
396:
397: /* check if the node have not child on any kind ... */
398: if (axl_item_get_first_child (node) == NULL) {
399: fprintf (fstream, "/>\n");
400: return axl_true;
401: } else {
402: fprintf (fstream, ">\n");
403: }
404:
405: } else {
406: /* check if the node has childs or only content to avoid placing a \n */
407: fprintf (fstream, "<<span class=\"node\">%s</span>>%s",
408: axl_node_get_name (node),
409: axl_node_have_childs (node) ? "\n" : "");
410: }
411:
412: /* call to produce internal content representation */
413: item = axl_item_get_first_child (node);
414: found_content = axl_false;
415: while (item != NULL) {
416: found_content = axl_true;
417: /* according to the type do */
418: switch (axl_item_get_type (item)) {
419: case ITEM_NODE:
420: /* found node, call to represent this node */
421: axl_knife_htmlize_iterator_node (fstream, axl_item_get_data (item), level + 1);
422: break;
423: case ITEM_CONTENT_FROM_FACTORY:
424: case ITEM_CONTENT:
425: fprintf (fstream, "%s", axl_item_get_content (item, NULL));
426: break;
427: case ITEM_PI:
428: break;
429: case ITEM_FROM_FACTORY:
430: /* never reached */
431: break;
432: case ITEM_COMMENT:
433: /* introduce indentation level */
434: axl_knife_introduce_indentation (fstream, level + 1);
435: fprintf (fstream, "<span class=\"comment\"><!-- %s --></span>\n",
436: axl_item_get_content (item, NULL));
437: break;
438: case ITEM_REF:
439: break;
440: case ITEM_CDATA:
441: fprintf (fstream, "<span class=\"cdata\"><![CDATA[</span>%s<span class=\"cdata\">]]></span>",
442: axl_item_get_content (item, NULL));
443: break;
444: } /* end switch */
445:
446: /* next item */
447: item = axl_item_get_next (item);
448: }
449:
450:
451: if (axl_node_have_childs (node)) {
452: /* introduce indentation level */
453: axl_knife_introduce_indentation (fstream, level);
454: }
455:
456: if (found_content) {
457: fprintf (fstream, "</<span class=\"node\">%s</span>>\n",
458: axl_node_get_name (node));
459: } /* end if */
460:
461: /* don't stop iteration */
462: return axl_true;
463: }
464:
465: axl_bool axl_knife_htmlize (axlDoc * doc)
466: {
467: FILE * fstream = stdout;
468:
469: /* currently we only support stderr so reached this place
470: * means it is already checked */
471:
472: /* check output argument */
473: if (exarg_is_defined ("output")) {
474: /* abrimos el fichero de salida */
475: fstream = fopen (exarg_get_string ("output"), "w");
476: if (fstream == NULL) {
477: error ("unable to open output document: %s, errno=%d:%s", exarg_get_string ("output"),
478: errno, strerror (errno));
479: return axl_false;
480: } /* end if */
481: } /* end if */
482:
483: /* call to iterate */
484: if (exarg_is_defined ("pre-class"))
485: fprintf (fstream, "<pre class='%s'>\n", exarg_get_string ("pre-class"));
486: else
487: fprintf (fstream, "<pre>\n");
488: axl_knife_htmlize_iterator_node (fstream, axl_doc_get_root (doc), 0);
489: fprintf (fstream, "</pre>\n");
490:
491: return axl_true;
492: }
493:
1.1.1.2 ! misho 494: axl_bool axl_knife_dtd_to_c (void)
1.1 misho 495: {
496:
497: /* check the document received is a DTD */
498: axlError * err = NULL;
499: axlDtd * dtd = axl_dtd_parse_from_file (exarg_get_string ("input"), &err);
500: axlStream * stream;
501: char * file;
502: int line_length;
503: int max;
504: int chunk_matched;
505: char * ref;
506: char * format;
507: int iterator;
508: FILE * fstream = stdout;
509:
510: if (dtd == NULL) {
511: error ("unable to translate document into C, found invalid DTD: %s",
512: axl_error_get (err));
513: axl_error_free (err);
514: return axl_false;
515: } /* end if */
516:
517: /* free dtd document */
518: axl_dtd_free (dtd);
519:
520: /* open the stream */
521: stream = axl_stream_new (NULL, -1, exarg_get_string ("input"), -1, &err);
522:
523: /* check output argument */
524: if (exarg_is_defined ("output")) {
525: /* abrimos el fichero de salida */
526: fstream = fopen (exarg_get_string ("output"), "w");
527: if (fstream == NULL) {
528: error ("unable to open output document: %s, errno=%d:%s", exarg_get_string ("output"),
529: errno, strerror (errno));
530: return axl_false;
531: } /* end if */
532: } /* end if */
533:
534: /* try to get the maximum lenght */
535: line_length = 0;
536: do {
537: /* get next */
538: ref = axl_stream_get_until_zero (stream, NULL, &chunk_matched, axl_true, 1, "\n", NULL);
539:
540: /* get lenght and update */
541: max = ref ? strlen (ref) : 0;
542: if (max > line_length)
543: line_length = max;
544:
545: } while (chunk_matched != -2);
546:
547: /* close the stream */
548: axl_stream_free (stream);
549: stream = axl_stream_new (NULL, -1, exarg_get_string ("input"), -1, &err);
550:
551: /* build format for each line */
552: format = axl_strdup_printf ("%%-%ds \\\n", line_length + 1);
553:
554: file = axl_knife_file_name (exarg_get_string ("input"));
555:
556:
557:
558: fprintf (fstream, "/**\n");
559: fprintf (fstream, " * C inline representation for DTD %s, created by axl-knife\n", file);
560: fprintf (fstream, " */\n");
561:
562: axl_knife_clean_name (file);
563: axl_stream_to_upper (file);
564:
565: fprintf (fstream, "#ifndef __%s_H__\n", file);
566: fprintf (fstream, "#define __%s_H__\n", file);
567: fprintf (fstream, "#define %s \"\\n\\\n", file);
568: do {
569: /* get next */
570: ref = axl_stream_get_until_zero (stream, NULL, &chunk_matched, axl_true, 1, "\n", NULL);
571: if (ref != NULL) {
572: iterator = 0;
573: while (iterator < strlen (ref)) {
574: /* update blank */
575: if (ref[iterator] == '\t')
576: ref[iterator] = ' ';
577: if (ref[iterator] == '\"')
578: ref[iterator] = '\'';
579:
580: /* next iterator */
581: iterator++;
582: } /* end while */
583: } /* end if */
584:
585: /* get lenght and update */
586: fprintf (fstream, format, ref);
587:
588: } while (chunk_matched != -2);
589:
590:
591:
592: fprintf (fstream, "\\n\"\n");
593:
594: fprintf (fstream, "#endif\n");
595:
596: axl_stream_free (stream);
597: axl_free (file);
598: axl_free (format);
599:
600: /* check output argument */
601: if (exarg_is_defined ("output"))
602: fclose (fstream);
603:
604: return axl_true;
605: }
606:
607: /**
608: * @brief Allows to check if the provided file (basefile) is newer
609: * than the file (compare).
610: *
611: * @param basefile The base file to check.
612: * @param compare The compare file to check
613: *
614: * @return axl_true if the modification time is newer than compare,
615: * otherwise axl_false is returned.
616: */
617: axl_bool axl_knife_check_if_newer (const char * basefile, const char * compare)
618: {
619: struct stat stat1, stat2;
620:
621: /* get stats from both files */
622: if (stat (basefile, &stat1) != 0)
623: return axl_false;
624: if (stat (compare, &stat2) != 0)
625: return axl_false;
626:
627: /* return value comparation */
628: return stat1.st_mtime > stat2.st_mtime;
629: }
630:
631:
632: int main (int argc, char ** argv)
633: {
634:
635: axlDoc * doc = NULL;
636: axlError * err = NULL;
637:
638: /* init the axl library */
639: if (! axl_init ()) {
640: printf ("Failed to initialize axl library. Terminating axl-knife tool..\n");
641: return -1;
642: } /* end if */
643:
644: /* install headers for help */
645: exarg_add_usage_header (HELP_HEADER);
646: exarg_add_help_header (HELP_HEADER);
647: exarg_post_help_header (POST_HEADER);
648: exarg_post_usage_header (POST_HEADER);
649:
650: /* init exarg library */
651: exarg_install_arg ("version", "v", EXARG_NONE,
652: "Shows current axl-knife version.");
653:
654: /* file options */
655: exarg_install_arg ("input", "i", EXARG_STRING,
656: "Allows to configure the input document to process.");
657: exarg_install_arg ("output", "o", EXARG_STRING,
658: "Allows to configure the output file to be used. This is optional. If the knife command produces an output, it is by default sent to the stdout.");
659: exarg_install_arg ("ifnewer", "n", EXARG_NONE,
660: "In process involving generating output from an input file, this option allows to stop the process and return success code (0) if the output file is found to be newer than input file. ");
661:
662:
663: exarg_install_arg ("htmlize", "e", EXARG_NONE,
664: "Takes an input xml document and produces an transformation preparing the document to be included into an html web page");
665:
666: exarg_install_arg ("pre-class", "p", EXARG_STRING,
667: "In conjunction with --htmlize option, which option allows to configure the CSS class to be placed on top most <pre> node.");
668:
669: /* log options */
670: exarg_install_arg ("enable-log", "l", EXARG_NONE,
671: "Allows to activate the console log debug.");
672:
673: exarg_install_arg ("enable-log-color", "g", EXARG_NONE,
674: "Activates the console logs and uses some ansi characters to colorify the log output. If this option is activated, it is implicitly activated the --enable-log");
675:
676: /* dtd-to-c options */
677: exarg_install_arg ("dtd-to-c", NULL, EXARG_NONE,
678: "Creates a C header definition representing the DTD provided, suitable to be opened by libaxl");
679:
680: exarg_install_arg ("check-xml", "c", EXARG_NONE,
681: "Allows to check an xml document (if it is properly formated). Combine this option with --input");
682:
683: /* add dependecies */
684: exarg_add_dependency ("htmlize", "input");
685: exarg_add_dependency ("pre-class", "htmlize");
686: exarg_add_dependency ("dtd-to-c", "input");
687: exarg_add_dependency ("check-xml", "input");
688:
689: exarg_add_dependency ("ifnewer", "input");
690: exarg_add_dependency ("ifnewer", "output");
691:
692: /* exclusion */
693: exarg_add_exclusion ("htmlize", "dtd-to-c");
694:
695: /* call to parse arguments */
696: exarg_parse (argc, argv);
697:
698: /* get current process id */
699: axl_knife_pid = getpid ();
700:
701: /* normal operations */
702: if (exarg_is_defined ("version")) {
703: return printf ("%s\n", VERSION);
704: }
705:
706: /* check ifnewer option */
707: if (exarg_is_defined ("ifnewer")) {
708: /* check that both files exists */
709: if (axl_knife_file_test (exarg_get_string ("input"), FILE_EXISTS) &&
710: axl_knife_file_test (exarg_get_string ("output"), FILE_EXISTS)) {
711: if (! axl_knife_check_if_newer (exarg_get_string ("input"), exarg_get_string ("output"))) {
712: goto finish;
713: } /* end if */
714: } /* end if */
715: } /* end if */
716:
717: /* check parameters defined */
718: if (! exarg_is_defined ("htmlize") &&
719: ! exarg_is_defined ("check-xml") &&
720: ! exarg_is_defined ("dtd-to-c")) {
721: msg ("no action was defined..");
722: goto finish;
723: }
724:
725: /* parse log options */
726: axl_log_enable (exarg_is_defined ("enable-log"));
727:
728: /* check color to activate both logs */
729: if (exarg_is_defined ("enable-log-color")) {
730: axl_log_enable (axl_true);
731: axl_log_color_enable (axl_true);
732: }
733:
734: /* check to load a document */
735: if (exarg_is_defined ("dtd-to-c")) {
736: /* do not open any document, as it is opened by an axl
737: * stream directly */
738: } else if (exarg_is_defined ("input")) {
739: /* parse document from file */
740: doc = axl_doc_parse_from_file (exarg_get_string ("input"), &err);
741: if (doc == NULL) {
742: error ("Failed to open document (%s), error found: %s",
743: exarg_get_string ("input"), axl_error_get (err));
744: axl_error_free (err);
745: goto finish;
746: } /* end if */
747: msg ("document loaded properly: %s", exarg_get_string ("input"));
748: } /* end if */
749:
750:
751: /* check process options */
752: if (exarg_is_defined ("htmlize")) {
753: /* call to htmlize the content received */
754: axl_knife_htmlize (doc);
755: } else if (exarg_is_defined ("dtd-to-c")) {
756:
757: /* call to produce a C representation from the DTD
758: * provided */
759: axl_knife_dtd_to_c ();
760: } else if (exarg_is_defined ("check-xml")) {
761: /* do nothing because if reached this code, document
762: * was loadedd properly */
763: msg ("document is OK");
764: } /* end if */
765:
766:
767: finish:
768: /* dealloc document opened */
769: axl_doc_free (doc);
770:
771: /* terminating axl */
772: axl_end ();
773:
774: /* terminate exarg */
775: exarg_end ();
776:
777: return 0;
778: }
779:
780: /**
781: * @brief Allows to perform a set of test for the provided path.
782: *
783: * @param path The path that will be checked.
784: *
785: * @param test The set of test to be performed. Separate each test
786: * with "|" to perform several test at the same time.
787: *
788: * @return axl_true if all test returns axl_true. Otherwise axl_false is returned.
789: */
790: axl_bool axl_knife_file_test (const char * path, FileTest test)
791: {
792: axl_bool result = axl_false;
793: struct stat file_info;
794:
795: /* perform common checks */
796: axl_return_val_if_fail (path, axl_false);
797:
798: /* call to get status */
799: result = (stat (path, &file_info) == 0);
800: if (! result) {
801: /* check that it is requesting for not file exists */
802: if (errno == ENOENT && (test & FILE_EXISTS) == FILE_EXISTS)
803: return axl_false;
804:
805: error ("filed to check test on %s, stat call has failed (result=%d, error=%s)", path, result, strerror (errno));
806: return axl_false;
807: } /* end if */
808:
809: /* check for file exists */
810: if ((test & FILE_EXISTS) == FILE_EXISTS) {
811: /* check result */
812: if (result == axl_false)
813: return axl_false;
814:
815: /* reached this point the file exists */
816: result = axl_true;
817: }
818:
819: /* check if the file is a link */
820: if ((test & FILE_IS_LINK) == FILE_IS_LINK) {
821: if (! S_ISLNK (file_info.st_mode))
822: return axl_false;
823:
824: /* reached this point the file is link */
825: result = axl_true;
826: }
827:
828: /* check if the file is a regular */
829: if ((test & FILE_IS_REGULAR) == FILE_IS_REGULAR) {
830: if (! S_ISREG (file_info.st_mode))
831: return axl_false;
832:
833: /* reached this point the file is link */
834: result = axl_true;
835: }
836:
837: /* check if the file is a directory */
838: if ((test & FILE_IS_DIR) == FILE_IS_DIR) {
839: if (! S_ISDIR (file_info.st_mode)) {
840: return axl_false;
841: }
842:
843: /* reached this point the file is link */
844: result = axl_true;
845: }
846:
847: /* return current result */
848: return result;
849: }
850:
851: /**
852: * \page axl_knife_manual axl-knife: command line tool built on top of Axl.
853: *
854: * \section intro Introduction
855: *
856: * <b>axl-knife</b> is a command line tool that includes xml related
857: * features and the intention is to concentrate into the tool,
858: * features to make Axl Library available to the command line.
859: *
860: * This manual includes information about operations that support the
861: * tool and how to activate them:
862: *
863: * - \ref axl_knife_dtd_to_c
864: * - \ref axl_knife_htmlize
865: *
866: * \section axl_knife_dtd_to_c Building a C inline representation from a DTD file
867: *
868: * This feature allows to create a C header file representing a
869: * particular DTD file, so it can be used and parsed as it were a file
870: * by included into the source.
871: *
872: * The main advantage from this approach is that the application or
873: * library using Axl Library services do not have to bundle DTD files
874: * into its installers. Those files are already included into the
875: * source. In many cases, those DTD files are than less than 1K.
876: *
877: * To create a C DTD representation use:
878: * \code
879: * >> axl-knife --input DTD-FILE.dtd --dtd-to-c --output DTD-FILE.dtd.h --ifnewer
880: * \endcode
881: *
882: * The argument <b>--ifnewer</b> allows to signal the tool to not
883: * produce any output if the input file is not found to be newer.
884: *
885: * Now use \ref axl_dtd_parse to open a reference to the DTD.
886: *
887: * \section axl_knife_htmlize Prepare xml content to be included into xml
888: *
889: * In the case you require to include xml content into a web page, you
890: * can use <b>--htmlize</b> option to prepare the content, adding CSS
891: * style classes to configure how your xml document will look.
892: *
893: * Use the following to produce xml content ready to be included into html:
894: *
895: * \code
896: * >> axl-knife --input xml-file.xml --htmlize
897: * \endcode
898: *
899: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>