hs-bibutils-5.0: bibutils/wordin.c
/*
* wordin.c
*
* Copyright (c) Chris Putnam 2010-2013
*
* Source code released under the GPL version 2
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "is_ws.h"
#include "newstr.h"
#include "newstr_conv.h"
#include "fields.h"
#include "xml.h"
#include "xml_encoding.h"
#include "wordin.h"
void
wordin_initparams( param *p, const char *progname )
{
p->readformat = BIBL_WORDIN;
p->charsetin = BIBL_CHARSET_DEFAULT;
p->charsetin_src = BIBL_SRC_DEFAULT;
p->latexin = 0;
p->xmlin = 1;
p->utf8in = 1;
p->nosplittitle = 0;
p->verbose = 0;
p->addcount = 0;
p->output_raw = BIBL_RAW_WITHMAKEREFID |
BIBL_RAW_WITHCHARCONVERT;
p->readf = wordin_readf;
p->processf = wordin_processf;
p->cleanf = NULL;
p->typef = NULL;
p->convertf = NULL;
p->all = NULL;
p->nall = 0;
list_init( &(p->asis) );
list_init( &(p->corps) );
if ( !progname ) p->progname = NULL;
else p->progname = strdup( progname );
}
static char *
wordin_findstartwrapper( char *buf, int *ntype )
{
char *startptr = xml_findstart( buf, "b:Source" );
return startptr;
}
static char *
wordin_findendwrapper( char *buf, int ntype )
{
char *endptr = xml_findend( buf, "b:Source" );
return endptr;
}
int
wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
{
newstr tmp;
char *startptr = NULL, *endptr;
int haveref = 0, inref = 0, file_charset = CHARSET_UNKNOWN, m, type = 1;
newstr_init( &tmp );
while ( !haveref && newstr_fget( fp, buf, bufsize, bufpos, line ) ) {
if ( line->data ) {
m = xml_getencoding( line );
if ( m!=CHARSET_UNKNOWN ) file_charset = m;
}
if ( line->data ) {
startptr = wordin_findstartwrapper( line->data, &type );
}
if ( startptr || inref ) {
if ( inref ) newstr_strcat( &tmp, line->data );
else {
newstr_strcat( &tmp, startptr );
inref = 1;
}
endptr = wordin_findendwrapper( tmp.data, type );
if ( endptr ) {
newstr_segcpy( reference, tmp.data, endptr );
haveref = 1;
}
}
}
newstr_free( &tmp );
*fcharset = file_charset;
return haveref;
}
static inline int
xml_hasdata( xml *node )
{
if ( node && node->value && node->value->data ) return 1;
return 0;
}
static inline char *
xml_data( xml *node )
{
return node->value->data;
}
static inline int
xml_tagwithdata( xml *node, char *tag )
{
if ( !xml_hasdata( node ) ) return 0;
return xml_tagexact( node, tag );
}
typedef struct xml_convert {
char *in; /* The input tag */
char *a, *aval; /* The attribute="attribute_value" pair, if nec. */
char *out; /* The output tag */
int level;
} xml_convert;
static void
wordin_person( xml *node, fields *info, char *type )
{
xml *last, *first;
newstr name;
newstr_init( &name );
last = node;
while ( last && !xml_tagexact( last, "b:Last" ) )
last = last->next;
if ( last ) newstr_strcpy( &name, last->value->data );
first = node;
while ( first ) {
if ( xml_tagexact( first, "b:First" ) ) {
if ( name.len ) newstr_addchar( &name, '|' );
newstr_strcat( &name, first->value->data );
}
first = first->next;
}
fields_add( info, type, name.data, 0 );
newstr_free( &name );
}
static void
wordin_people( xml *node, fields *info, char *type )
{
if ( xml_tagexact( node, "b:Author" ) && node->down ) {
wordin_people( node->down, info, type );
} else if ( xml_tagexact( node, "b:NameList" ) && node->down ) {
wordin_people( node->down, info, type );
} else if ( xml_tagexact( node, "b:Person" ) ) {
if ( node->down ) wordin_person( node->down, info, type );
if ( node->next ) wordin_people( node->next, info, type );
}
}
static void
wordin_pages( xml *node, fields *info )
{
newstr sp, ep;
char *p;
int i;
newstrs_init( &sp, &ep, NULL );
/*
newstr_init( &sp );
newstr_init( &ep );
*/
p = xml_data( node );
while ( *p && *p!='-' )
newstr_addchar( &sp, *p++ );
if ( *p=='-' ) p++;
while ( *p )
newstr_addchar( &ep, *p++ );
if ( sp.len ) fields_add( info, "PAGESTART", sp.data, 1 );
if ( ep.len ) {
if ( sp.len > ep.len ) {
for ( i=sp.len-ep.len; i<sp.len; ++i )
sp.data[i] = ep.data[i-sp.len+ep.len];
fields_add( info, "PAGEEND", sp.data, 1 );
} else
fields_add( info, "PAGEEND", ep.data, 1 );
}
newstrs_free( &sp, &ep, NULL );
/*
newstr_free( &sp );
newstr_free( &ep );
*/
}
static void
wordin_reference( xml *node, fields *info )
{
if ( xml_hasdata( node ) ) {
if ( xml_tagexact( node, "b:Tag" ) ) {
fields_add( info, "REFNUM", xml_data( node ), 0 );
} else if ( xml_tagexact( node, "b:SourceType" ) ) {
} else if ( xml_tagexact( node, "b:City" ) ) {
fields_add( info, "ADDRESS", xml_data( node ), 0 );
} else if ( xml_tagexact( node, "b:Publisher" ) ) {
fields_add( info, "PUBLISHER", xml_data( node ), 0 );
} else if ( xml_tagexact( node, "b:Title" ) ) {
fields_add( info, "TITLE", xml_data( node ), 0 );
} else if ( xml_tagexact( node, "b:JournalName" ) ) {
fields_add( info, "TITLE", xml_data( node ), 1 );
} else if ( xml_tagexact( node, "b:Volume" ) ) {
fields_add( info, "VOLUME", xml_data( node ), 1 );
} else if ( xml_tagexact( node, "b:Comments" ) ) {
fields_add( info, "NOTES", xml_data( node ), 0 );
} else if ( xml_tagexact( node, "b:Pages" ) ) {
wordin_pages( node, info );
} else if ( xml_tagexact( node, "b:Author" ) && node->down ) {
wordin_people( node->down, info, "AUTHOR" );
} else if ( xml_tagexact( node, "b:Editor" ) && node->down ) {
wordin_people( node->down, info, "EDITOR" );
}
}
if ( node->next ) wordin_reference( node->next, info );
}
static void
wordin_assembleref( xml *node, fields *info )
{
if ( xml_tagexact( node, "b:Source" ) ) {
if ( node->down ) wordin_reference( node->down, info );
} else if ( node->tag->len==0 && node->down ) {
wordin_assembleref( node->down, info );
}
}
int
wordin_processf( fields *wordin, char *data, char *filename, long nref )
{
xml top;
xml_init( &top );
xml_tree( data, &top );
wordin_assembleref( &top, wordin );
xml_free( &top );
return 1;
}