File:  [ELWIX - Embedded LightWeight unIX -] / gpl / axl / knife / axl-knife.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 12:50:02 2012 UTC (12 years, 4 months ago) by misho
Branches: axl, MAIN
CVS tags: HEAD, AXL0_6_7
version 0.6.7

    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, "&lt;<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, "&lt;<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\">&lt;!-- %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\">&lt;![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, "&lt;/<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: 
  494: axl_bool axl_knife_dtd_to_c (void)
  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>