/******************************************** -*-c-*- ***********************************************/
/* */
/* xmlPrint.lib.c: */
/* */
/****************************************************************************************************/
/****************************************************************************************************/
/* */
/* Copyright (C) 2004 Joerg Kunze */
/* */
/* This file is part of siliconBrainLib. */
/* */
/* siliconBrainLib is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* siliconBrainLib is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/****************************************************************************************************/
// char *siliconBrainRelease = "$siliconBrainRelease: 0.0.4 $";
// char *siliconBrainRcsIdentifier = "$Id: xmlPrint.lib.c,v 1.25 2004/12/14 23:09:01 joerg Exp $";
// char *siliconBrainSaveStamp = "$siliconBrainSaveStamp: 2004/12/14 22:31:26, Joerg Kunze$";
#include <stdarg.h>
#include "unistd.h"
#include "siliconBrainLib"
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
static const char red [] = "\e[0;31m";
static const char green [] = "\e[0;32m";
static const char brown [] = "\e[1;33m";
static const char blue [] = "\e[0;34m";
static const char magenta[] = "\e[0;35m";
static const char cyan [] = "\e[0;36m";
static const char normal [] = "\e[0m" ;
static const char *special = brown ;
static const char *keyWord = cyan ;
static const char *variable = green ;
static const char *string = magenta;
static const char *comment = red ;
static const char *quote = blue ;
/****************************************************************************************************/
/* */
/* osprintf: obstack_printf and obstack_finish convenience wrapper */
/* */
/****************************************************************************************************/
extern int osprintf( struct obstack *obstack, char **target, const char *template, ... ) {
va_list ap;
int numberOfCharactersWritten;
va_start( ap, template );
numberOfCharactersWritten = obstack_vprintf( obstack, template, ap );
va_end( ap );
obstack_1grow( obstack, 0 );
*target = obstack_finish( obstack );
return numberOfCharactersWritten;
}
/****************************************************************************************************/
/* */
/* StringBuffer: */
/* */
/****************************************************************************************************/
void stringBufferInit( StringBuffer *stringBuffer, Obstack *obstack ) {
stringBuffer->obstack = obstack;
stringBuffer->length = 23;
stringBuffer->value = obstack_alloc( stringBuffer->obstack, stringBuffer->length );
stringBuffer->value[ 0 ] = 0;
}
char *stringBufferAlloc( StringBuffer *stringBuffer, unsigned length ) {
if( stringBuffer->length < length ) {
stringBuffer->length = 2*length;
stringBuffer->value = obstack_alloc( stringBuffer->obstack, stringBuffer->length );
}
return stringBuffer->value;
}
/****************************************************************************************************/
/* */
/* StringStack: */
/* */
/****************************************************************************************************/
static void stringStackInit( StringStack *stack ) {
stack->chunk = g_string_chunk_new ( 42 );
stack->strings = g_ptr_array_sized_new( 42 );
}
static void stringStackDestroy( StringStack *stack ) {
if( stack->chunk ) g_string_chunk_free( stack->chunk );
if( stack->strings ) g_ptr_array_free ( stack->strings, true );
}
static void stringStackPush( StringStack *stack, const char *newString ) {
g_ptr_array_add( stack->strings, g_string_chunk_insert_const( stack->chunk, newString ) );
}
static char *stringStackGet( StringStack *stack ) {
return g_ptr_array_index( stack->strings, stack->strings->len - 1 );
}
static void stringStackPop( StringStack *stack ) {
g_ptr_array_remove_index_fast( stack->strings, stack->strings->len - 1 );
}
/****************************************************************************************************/
/* */
/* indentationFilter: */
/* */
/****************************************************************************************************/
static void printCharacterStandard ( SiliconBrainPrinter *printer, char characterToPrint ) {
putchar( characterToPrint );
}
static void printStringStandard ( SiliconBrainPrinter *printer, const char *stringToPrint ) {
printu( stringToPrint );
}
static void printCharacterIndent ( SiliconBrainPrinter *printer, char characterToPrint ) {
int spaceCounter;
if( printer->deferredIndentation ) {
printer->deferredIndentation = false;
if( characterToPrint != '\n' ) {
for( spaceCounter = printer->indent; spaceCounter; --spaceCounter )
putchar( ' ' );
if( printer->insideComment )
printu( printer->commentIndent );
}
}
putchar( characterToPrint );
if( characterToPrint == '\n' ) {
printer->deferredIndentation = true;
}
}
static void printStringIndent ( SiliconBrainPrinter *printer, const char *stringToPrint ) {
for( ; *stringToPrint; ++stringToPrint ) {
printCharacterIndent( printer, *stringToPrint );
}
}
/****************************************************************************************************/
/* */
/* quote: */
/* */
/****************************************************************************************************/
static void normalQuote( SiliconBrainPrinter *printer, const char *source ) {
printer->printString( printer, source );
}
static void coloredQuote( SiliconBrainPrinter *printer, const char *source ) {
printer->printString( printer, quote );
printer->printString( printer, source );
printer->printString( printer, printer->stringColor );
}
/****************************************************************************************************/
/* */
/* Xml: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* escape: */
/*--------------------------------------------------------------------------------------------------*/
static void printEscapedCharXml( struct SiliconBrainPrinter *printer, char characterToPrint ) {
switch( characterToPrint ) {
case '&' : printer->quoter( printer, "&" ); break;
case '<' : printer->quoter( printer, "<" ); break;
case '>' : printer->quoter( printer, ">" ); break;
case '\'': printer->quoter( printer, "'"); break;
case '"' : printer->quoter( printer, """); break;
default : printer->printCharacter( printer, characterToPrint );
}
}
/****************************************************************************************************/
/* */
/* Tty: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* escape: */
/*--------------------------------------------------------------------------------------------------*/
static void printEscapedCharTty( struct SiliconBrainPrinter *printer, char characterToPrint ) {
printer->printCharacter( printer, characterToPrint );
}
/****************************************************************************************************/
/* */
/* Bash: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* escape: */
/*--------------------------------------------------------------------------------------------------*/
static void printEscapedCharBash( struct SiliconBrainPrinter *printer, char characterToPrint ) {
switch( characterToPrint ) {
case '\'' : printer->quoter( printer, "'\"'\"'" ); break;
default : printer->printCharacter( printer, characterToPrint );
}
}
/*--------------------------------------------------------------------------------------------------*/
/* comment: */
/*--------------------------------------------------------------------------------------------------*/
static void printCommentCharBash( struct SiliconBrainPrinter *printer, char characterToPrint ) {
switch( characterToPrint ) {
case '\n' : printer->printString( printer, "\n# " ); break;
default : printer->printCharacter( printer, characterToPrint );
}
}
/****************************************************************************************************/
/* */
/* BashEnvironment: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* onRootTag: */
/*--------------------------------------------------------------------------------------------------*/
static void onRootTagBashEnvironment( struct SiliconBrainPrinter *printer, StartEnd mode ) {
if( mode == start ) {
stringBufferAlloc( &printer->namePrefix, strlen( printer->nameOfRootTag ) + 2 );
stpcpy( stpcpy( printer->namePrefix.value, printer->nameOfRootTag ), "_" );
}
else if( mode == end ) {
printer->namePrefix.value[ 0 ] = 0;
}
}
/****************************************************************************************************/
/* */
/* Perl: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* escape: */
/*--------------------------------------------------------------------------------------------------*/
static void printEscapedCharPerl( struct SiliconBrainPrinter *printer, char characterToPrint ) {
switch( characterToPrint ) {
case '\'' : printer->quoter( printer, "\\'" ); break;
default : printer->printCharacter( printer, characterToPrint );
}
}
/****************************************************************************************************/
/* */
/* Generic: */
/* */
/****************************************************************************************************/
/*--------------------------------------------------------------------------------------------------*/
/* tag: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterTag( SiliconBrainPrinter *printer, const char *name ) {
if( printer->insideTag ) {
printer->insideTag = false;
printer->printString( printer, printer->tagEndTagBeforeNewTag );
}
if( printer->insideText ) {
printer->insideText = false;
printer->printString( printer, printer->textValueEnd );
}
printer->printString( printer, printer->tagStartTag );
printer->printString( printer, printer->namePrefix.value );
printer->printString( printer, name );
printer->insideTag = true;
stringStackPush( &printer->tagNameStack, name );
if( !printer->nestingDepth ) {
printer->nameOfRootTag = name;
if( printer->onRootTag )
printer->onRootTag( printer, start );
}
printer->indent += printer->indentation;
++printer->nestingDepth;
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* text: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterText( SiliconBrainPrinter *printer, const char *value ) {
if( !value ) return 0;
printer->insideText = true;
if( printer->insideTag ) {
printer->insideTag = false;
printer->printString( printer, printer->textEndTagBeforeText );
}
printer->stringColor = normal;
for(; *value; ++value ) {
printer->printEscapedChar( printer, *value );
}
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* comment: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterComment( SiliconBrainPrinter *printer, const char *value ) {
if( !printer->doIndent ) return 0;
if( !value ) return 0;
if( printer->insideTag ) {
printer->insideTag = false;
printer->printString( printer, printer->tagEndTagBeforeNewTag );
}
printer->printString( printer, printer->commentStart );
printer->insideComment = true;
if( printer->printCommentChar ) {
for(; *value; ++value ) {
printer->printCommentChar( printer, *value );
}
} else {
printer->printString( printer, value );
}
printer->printString( printer, printer->commentEnd );
printer->insideComment = false;
printer->printCharacter( printer, '\n' );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* atttribute: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterAttribute( SiliconBrainPrinter *printer, const char *name, const char *value ) {
if( !value ) return 0;
if( printer->attributeIsOutsideTag ) {
if( printer->insideTag ) {
printer->insideTag = false;
printer->printString( printer, printer->attributeEndTagBeforeAttribute );
}
}
printer->printString( printer, printer->attributeNameStart );
printer->printString( printer, printer->namePrefix.value );
printer->printString( printer, name );
printer->printString( printer, printer->attributeNameEnd );
printer->stringColor = string;
for(; *value; ++value ) {
printer->printEscapedChar( printer, *value );
}
printer->printString( printer, printer->attributeValueEnd );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* key: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterKey( SiliconBrainPrinter *printer, const char *key, const char *value ) {
if( !value ) return 0;
siliconBrainPrinterTag ( printer, key );
siliconBrainPrinterText( printer, value );
siliconBrainPrinterEnd ( printer );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* keyBool: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterKeyBool( SiliconBrainPrinter *printer, const char *key, bool value ) {
siliconBrainPrinterTag ( printer, key );
if( printer->boolTrue && value ) {
printer->insideTag = false;
printer->printString( printer, printer->boolTrue );
}
else if( printer->boolFalse && !value ) {
printer->insideTag = false;
printer->printString( printer, printer->boolFalse );
}
siliconBrainPrinterEnd ( printer );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* end: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterEnd( SiliconBrainPrinter *printer ) {
--printer->nestingDepth;
printer->indent -= printer->indentation;
if( !printer->nestingDepth ) {
printer->nameOfRootTag = 0;
if( printer->onRootTag )
printer->onRootTag( printer, end );
}
if( printer->insideText ) {
printer->insideText = false;
printer->printString( printer, printer->textValueEnd );
}
if( printer->insideTag ) {
printer->insideTag = false;
printer->printString( printer, printer->endInsideTag );
} else {
if( printer->endTagStart ) {
printer->printString( printer, printer->endTagStart );
printer->printString( printer, stringStackGet( &printer->tagNameStack ) );
}
printer->printString( printer, printer->endTagEnd );
}
stringStackPop( &printer->tagNameStack );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* destroy: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterDestroy( SiliconBrainPrinter *printer ) {
stringStackDestroy( &printer->tagNameStack );
obstack_free( &printer->obstack, 0 );
return 0;
}
/*--------------------------------------------------------------------------------------------------*/
/* create: */
/*--------------------------------------------------------------------------------------------------*/
int siliconBrainPrinterInit( SiliconBrainPrinter *printer, int argc, const char *argv[] ) {
const char *mode = 0;
obstack_init( &printer->obstack );
printer->tagNameStack.chunk = 0;
printer->tagNameStack.strings = 0;
printer->insideTag = false;
printer->insideText = false;
printer->insideComment = false;
printer->indent = 0;
printer->nestingDepth = 0;
printer->quoter = &normalQuote;
printer->nameOfRootTag = 0;
printer->onRootTag = 0;
stringBufferInit( &printer->namePrefix, &printer->obstack );
stringStackInit ( &printer->tagNameStack );
/*-------------------------------------------------*/
/* some defaults to things, which are configurable */
/*-------------------------------------------------*/
printer->indentation = 3;
printer->usageDescription = 0;
printer->printCommentChar = 0;
printer->printCharacter = &printCharacterStandard;
printer->printString = &printStringStandard;
printer->doIndent = false;
/*-----------------------------------------------------------------*/
/* tty: */
/*-----------------------------------------------------------------*/
if( isatty( 1 ) ) {
printer->doIndent = true;
if( argc == 0 || argv[ 1 ] == 0 ) mode = "--tty";
} else {
if( argc == 0 || argv[ 1 ] == 0 ) mode = "--xml";
}
mode = mode ?: argv[ 1 ];
if( getenv( "siliconBrainLibPrintIndent" ) ) {
printer->doIndent = true;
}
if( printer->doIndent ) {
printer->printCharacter = &printCharacterIndent;
printer->printString = &printStringIndent;
}
if( strequ( mode, "--xml" ) ) {
printer->tagEndTagBeforeNewTag = ">\n" ;
printer->tagStartTag = "<";
printer->attributeEndTagBeforeAttribute = "";
printer->attributeIsOutsideTag = false;
printer->attributeNameStart = " ";
printer->attributeNameEnd = "=\"";
printer->attributeValueEnd = "\"";
printer->endInsideTag = "/>\n";
printer->endTagStart = "</";
printer->endTagEnd = ">\n";
printer->textEndTagBeforeText = "> ";
printer->textValueEnd = " ";
printer->boolTrue = 0;
printer->boolFalse = "> false ";
printer->commentStart = "\n<!-- ";
printer->commentEnd = " -->";
printer->commentIndent = " ";
printer->printEscapedChar = printEscapedCharXml;
}
else if( strequ( mode, "--tty" ) ) {
printer->tagEndTagBeforeNewTag = ":\n";
printer->tagStartTag = "";
printer->attributeEndTagBeforeAttribute = ":\n";
printer->attributeIsOutsideTag = true;
printer->attributeNameStart = "";
printer->attributeNameEnd = " = ";
printer->attributeValueEnd = "\n";
printer->endInsideTag = ":\n";
printer->endTagStart = 0;
printer->endTagEnd = "\n";
printer->textEndTagBeforeText = " = ";
printer->textValueEnd = "";
printer->boolTrue = ": yes";
printer->boolFalse = ": no";
printer->commentStart = "\n# ";
printer->commentEnd = "";
printer->commentIndent = "";
printer->printEscapedChar = printEscapedCharTty;
printer->printCommentChar = printCommentCharBash;
}
else if(
strequ( mode, "--bash" ) ||
strequ( mode, "--bashEnvironment" )
) {
printer->tagEndTagBeforeNewTag = "='<configured>'\n";
printer->tagStartTag = "";
printer->attributeEndTagBeforeAttribute = "='<configured>'\n";
printer->attributeIsOutsideTag = true;
printer->attributeNameStart = "";
printer->attributeNameEnd = "='";
printer->attributeValueEnd = "'\n";
printer->endInsideTag = "='<configured>'\n";
printer->endTagStart = 0;
printer->endTagEnd = "\n";
printer->textEndTagBeforeText = "='";
printer->textValueEnd = "'";
printer->boolTrue = "=";
printer->boolFalse = "='false'";
printer->commentStart = "\n# ";
printer->commentEnd = "";
printer->commentIndent = "";
printer->printEscapedChar = printEscapedCharBash;
printer->printCommentChar = printCommentCharBash;
printer->usageDescription = "Usage: eval \"$(<thisCommand> --bash)\"";
if( strequ( mode, "--bashEnvironment" ) ) {
printer->tagStartTag = "export ";
printer->attributeNameStart = "export ";
printer->onRootTag = onRootTagBashEnvironment;
printer->usageDescription = "Usage: eval \"$(<thisCommand> --bashEnvironment)\"";
}
}
else if( strequ( mode, "--perl" ) ) {
printer->tagEndTagBeforeNewTag = "='<configured>';\n";
printer->tagStartTag = "$";
printer->attributeEndTagBeforeAttribute = "='<configured>';\n";
printer->attributeIsOutsideTag = true;
printer->attributeNameStart = "$";
printer->attributeNameEnd = "='";
printer->attributeValueEnd = "';\n";
printer->endInsideTag = "='<configured>';\n";
printer->endTagStart = 0;
printer->endTagEnd = "\n";
printer->textEndTagBeforeText = "='";
printer->textValueEnd = "';";
printer->boolTrue = "=1;";
printer->boolFalse = "=0;";
printer->commentStart = "\n# ";
printer->commentEnd = "";
printer->commentIndent = "";
printer->printEscapedChar = printEscapedCharPerl;
printer->printCommentChar = printCommentCharBash;
printer->usageDescription = "Usage: eval `<thisCommand> --perl`;";
}
else {
fprintf( stderr, "siliconBrainPrinterCreate: invalid target format \"%s\"\n", argv[ 1 ] );
exit( 42 );
}
if( isatty( 1 ) ) {
struct obstack *obstack = &printer->obstack;
#define colorize( field, start, end ) \
if( printer->field ) \
osprintf( obstack, &printer->field, "%s%s%s", start, printer->field, end );
colorize( tagEndTagBeforeNewTag , special, "" );
colorize( tagStartTag , special, keyWord );
colorize( attributeEndTagBeforeAttribute , special, "" );
colorize( attributeNameStart , special, variable );
colorize( attributeNameEnd , special, string );
colorize( attributeValueEnd , special, "" );
colorize( endInsideTag , special, "" );
colorize( endTagStart , special, keyWord );
colorize( endTagEnd , special, "" );
colorize( textEndTagBeforeText , special, normal );
colorize( textValueEnd , special, keyWord );
colorize( boolTrue , normal , normal );
colorize( boolFalse , normal , normal );
colorize( commentStart , comment, "" );
colorize( commentEnd , "" , "" );
colorize( commentIndent , "" , "" );
printer->quoter = &coloredQuote;
}
if( printer->usageDescription ) siliconBrainPrinterComment( printer, printer->usageDescription );
return 0;
}
/*
$Log: xmlPrint.lib.c,v $
Revision 1.25 2004/12/14 23:09:01 joerg
published for new release 0.0.4
Revision 1.24 2004/12/14 23:02:56 joerg
published for new release 0.0.3
Revision 1.23 2004/12/14 22:44:36 joerg
allFiles: all sources have a Log CVS keyword at the end now.
*/