Ejemplo n.º 1
0
static void
output_citeparts( fields *f, FILE *outptr, int level, int max )
{
	int orig_level;

	output_title(       f, outptr, level );
	output_names(       f, outptr, level );
	output_origin(      f, outptr, level );
	output_type(        f, outptr, level );
	output_language(    f, outptr, level );
	output_description( f, outptr, level );

	if ( level >= 0 && level < max ) {
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "host", NULL );
		output_citeparts( f, outptr, incr_level(level,1), max );
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
	}
	/* Look for original item things */
	orig_level = original_items( f, level );
	if ( orig_level ) {
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "original", NULL );
		output_citeparts( f, outptr, orig_level, max );
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
	}
	output_abs(        f, outptr, level );
	output_notes(      f, outptr, level );
	output_toc(        f, outptr, level );
	output_key(        f, outptr, level );
	output_sn(         f, outptr, level );
	output_url(        f, outptr, level );
	output_part(       f, outptr, level );

	output_recordInfo( f, outptr, level );
}
Ejemplo n.º 2
0
/* output_url()
 *
 * <location>
 *     <url>URL</url>
 *     <url urlType="pdf">PDFLINK</url>
 *     <url displayLabel="Electronic full text" access="raw object">PDFLINK</url>
 *     <physicalLocation>LOCATION</physicalLocation>
 * </location>
 */
static void
output_url( fields *f, FILE *outptr, int level )
{
	int location   = fields_find( f, "LOCATION",   level );
	int url        = fields_find( f, "URL",        level );
	int fileattach = fields_find( f, "FILEATTACH", level );
	int pdflink    = fields_find( f, "PDFLINK",    level );
	int i, n;

	if ( url==-1 && location==-1 && pdflink==-1 && fileattach==-1 ) return;
	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_OPEN, TAG_NEWLINE, NULL );

	n = fields_num( f );
	for ( i=0; i<n; ++i ) {
		if ( f->level[i]!=level ) continue;
		if ( strcasecmp( f->tag[i].data, "URL" ) ) continue;
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
	for ( i=0; i<n; ++i ) {
		if ( f->level[i]!=level ) continue;
		if ( strcasecmp( f->tag[i].data, "PDFLINK" ) ) continue;
/*		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "urlType", "pdf", NULL ); */
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
	for ( i=0; i<n; ++i ) {
		if ( f->level[i]!=level ) continue;
		if ( strcasecmp( f->tag[i].data, "FILEATTACH" ) ) continue;
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "displayLabel", "Electronic full text", "access", "raw object", NULL );
	}
	if ( location!=-1 )
		output_fil( outptr, lvl2indent(incr_level(level,1)), "physicalLocation", f, location, TAG_OPENCLOSE, TAG_NEWLINE, NULL );

	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
}
Ejemplo n.º 3
0
/* detail output
 *
 * for example:
 *
 * <detail type="volume"><number>xxx</number></detail
 */
static void
mods_output_detail( fields *f, FILE *outptr, int n, char *item_name, int level )
{
	if ( n!=-1 ) {
		output_tag( outptr, lvl2indent(incr_level(level,1)), "detail", NULL,  TAG_OPEN,      TAG_NONEWLINE, "type", item_name, NULL );
		output_fil( outptr, 0,                                "number", f, n,  TAG_OPENCLOSE, TAG_NONEWLINE, NULL );
		output_tag( outptr, 0,                                "detail", NULL,  TAG_CLOSE,     TAG_NEWLINE,   NULL );                       
	}
}
Ejemplo n.º 4
0
static void
output_recordInfo( fields *f, FILE *outptr, int level )
{
	int n;
	n = fields_find( f, "LANGCATALOG", level );
	if ( n!=-1 ) {
		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
		output_language_core( f, n, outptr, "languageOfCataloging", incr_level(level,1) );
		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
	}
}
Ejemplo n.º 5
0
static void
output_description( fields *f, FILE *outptr, int level )
{
	char *val;
	int n;

	n = fields_find( f, "DESCRIPTION", level );
	if ( n!=-1 ) {
		val = ( char * ) fields_value( f, n, FIELDS_CHRP );
		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
		output_tag( outptr, lvl2indent(incr_level(level,1)), "note",                val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );
		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
	}
}
Ejemplo n.º 6
0
static void
output_origin( fields *f, FILE *outptr, int level )
{
	convert parts[] = {
		{ "issuance",	  "ISSUANCE",      0, 0 },
		{ "publisher",	  "PUBLISHER",     0, 0 },
		{ "place",	  "ADDRESS",       0, 1 },
		{ "place",	  "AUTHORADDRESS", 0, 0 },
		{ "edition",	  "EDITION",       0, 0 },
		{ "dateCaptured", "URLDATE",       0, 0 }
	};
	int nparts = sizeof( parts ) / sizeof( parts[0] );
	int i, found, datefound, datepos[ NUM_DATE_TYPES ];

	found     = convert_findallfields( f, parts, nparts, level );
	datefound = find_dateinfo( f, level, datepos );
	if ( !found && !datefound ) return;


	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );

	/* issuance must precede date */
	if ( parts[0].pos!=-1 )
		output_fil( outptr, lvl2indent(incr_level(level,1)), "issuance", f, parts[0].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL );

	/* date */
	if ( datefound )
		output_dateissued( f, outptr, level, datepos );

	/* rest of the originInfo elements */
	for ( i=1; i<nparts; i++ ) {

		/* skip missing originInfo elements */
		if ( parts[i].pos==-1 ) continue;

		/* normal originInfo element */
		if ( parts[i].code==0 ) {
			output_fil( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
		}

		/* originInfo with placeTerm info */
		else {
			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_OPEN,      TAG_NEWLINE, NULL );
			output_fil( outptr, lvl2indent(incr_level(level,2)), "placeTerm",   f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_CLOSE,     TAG_NEWLINE, NULL );
		}
	}

	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
}
Ejemplo n.º 7
0
/* output_key()
 *
 * <subject>
 *    <topic>xxxx</topic>
 * </subject>
 */
static void
output_key( fields *f, FILE *outptr, int level )
{
	int i, n;

	n = fields_num( f );
	for ( i=0; i<n; ++i ) {
		if ( fields_level( f, i ) != level ) continue;
		if ( !strcasecmp( f->tag[i].data, "KEYWORD" ) ) {
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
			output_fil( outptr, lvl2indent(incr_level(level,1)), "topic",   f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
		}
	}
}
Ejemplo n.º 8
0
/* output_language_core()
 *
 *      generates language output for tag="langauge" or tag="languageOfCataloging"
 *      if possible, outputs iso639-2b code for the language
 *
 * <language>
 *     <languageTerm type="text">xxx</languageTerm>
 * </language>
 *
 * <language>
 *     <languageTerm type="text">xxx</languageTerm>
 *     <languageTerm type="code" authority="iso639-2b">xxx</languageTerm>
 * </language>
 *
 */
static void
output_language_core( fields *f, int n, FILE *outptr, char *tag, int level )
{
	char *lang, *code;

	lang = (char *) fields_value( f, n, FIELDS_CHRP );
	code = iso639_2_from_language( lang );

	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
	output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", lang, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
	if ( code ) {
		output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", code, TAG_OPENCLOSE, TAG_NEWLINE, "type", "code", "authority", "iso639-2b", NULL );
	}
	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
}
Ejemplo n.º 9
0
/* part date output
 *
 * <date>xxxx-xx-xx</date>
 *
 */
static int
output_partdate( fields *f, FILE *outptr, int level, int wrote_header )
{
	convert parts[] = {
		{ "",	"PARTYEAR",                0, 0 },
		{ "",	"PARTMONTH",               0, 0 },
		{ "",	"PARTDAY",                 0, 0 },
	};
	int nparts = sizeof(parts)/sizeof(parts[0]);

	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;

	try_output_partheader( outptr, wrote_header, level );

	output_tag( outptr, lvl2indent(incr_level(level,1)), "date", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );

	if ( parts[0].pos!=-1 ) {
		fprintf( outptr, "%s", (char *) fields_value( f, parts[0].pos, FIELDS_CHRP ) );
	} else fprintf( outptr, "XXXX" );

	if ( parts[1].pos!=-1 ) {
		fprintf( outptr, "-%s", (char *) fields_value( f, parts[1].pos, FIELDS_CHRP ) );
	}

	if ( parts[2].pos!=-1 ) {
		if ( parts[1].pos==-1 )
			fprintf( outptr, "-XX" );
		fprintf( outptr, "-%s", (char *) fields_value( f, parts[2].pos, FIELDS_CHRP ) );
	}

	fprintf( outptr,"</date>\n");

	return 1;
}
Ejemplo n.º 10
0
/* extents output
 *
 * <extent unit="page">
 * 	<start>xxx</start>
 * 	<end>xxx</end>
 * </extent>
 */
static void
mods_output_extents( fields *f, FILE *outptr, int start, int end, int total, char *extype, int level )
{
	char *val;

	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_OPEN, TAG_NEWLINE, "unit", extype, NULL );
	if ( start!=-1 ) {
		val = (char *) fields_value( f, start, FIELDS_CHRP );
		output_tag( outptr, lvl2indent(incr_level(level,2)), "start", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
	if ( end!=-1 ) {
		val = (char *) fields_value( f, end, FIELDS_CHRP );
		output_tag( outptr, lvl2indent(incr_level(level,2)), "end",   val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
	if ( total!=-1 ) {
		val = (char *) fields_value( f, total, FIELDS_CHRP );
		output_tag( outptr, lvl2indent(incr_level(level,2)), "total", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
}
Ejemplo n.º 11
0
static void
output_dateissued( fields *f, FILE *outptr, int level, int pos[ NUM_DATE_TYPES ] )
{
	output_tag( outptr, lvl2indent(incr_level(level,1)), "dateIssued", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );
	if ( pos[ DATE_YEAR ]!=-1 || pos[ DATE_MONTH ]!=-1 || pos[ DATE_DAY ]!=-1 ) {
		output_datepieces( f, outptr, pos );
	} else {
		fprintf( outptr, "%s", (char *) fields_value( f, pos[ DATE_ALL ], FIELDS_CHRP ) );
	}
	fprintf( outptr, "</dateIssued>\n" );
}
Ejemplo n.º 12
0
static void
output_toc( fields *f, FILE *outptr, int level )
{
	char *val;
	int n;

	n = fields_find( f, "CONTENTS", level );
	if ( n!=-1 ) {
		val = (char *) fields_value( f, n, FIELDS_CHRP );
		output_tag( outptr, lvl2indent(level), "tableOfContents", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	}
}
Ejemplo n.º 13
0
static void
output_title( fields *f, FILE *outptr, int level )
{
	int ttl    = fields_find( f, "TITLE", level );
	int subttl = fields_find( f, "SUBTITLE", level );
	int shrttl = fields_find( f, "SHORTTITLE", level );
	int parttl = fields_find( f, "PARTTITLE", level );
	char *val;

	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_OPEN,      TAG_NEWLINE, NULL );
	output_fil( outptr, lvl2indent(incr_level(level,1)), "title",     f, ttl,    TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	output_fil( outptr, lvl2indent(incr_level(level,1)), "subTitle",  f, subttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	output_fil( outptr, lvl2indent(incr_level(level,1)), "partName",  f, parttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
	/* MODS output doesn't verify if we don't at least have a <title/> element */
	if ( ttl==-1 && subttl==-1 )
		output_tag( outptr, lvl2indent(incr_level(level,1)), "title", NULL,  TAG_SELFCLOSE, TAG_NEWLINE, NULL );
	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_CLOSE,     TAG_NEWLINE, NULL );

	/* output shorttitle if it's different from normal title */
	if ( shrttl!=-1 ) {
		val = (char *) fields_value( f, shrttl, FIELDS_CHRP );
		if ( ttl==-1 || subttl!=-1 || strcmp(f->data[ttl].data,val) ) {
			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_OPEN,      TAG_NEWLINE, "type", "abbreviated", NULL );
			output_tag( outptr, lvl2indent(incr_level(level,1)), "title",     val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );
			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
		}
	}
}
Ejemplo n.º 14
0
/* output_genre()
 *
 * <genre authority="marcgt">thesis</genre>
 * <genre>Diploma thesis</genre>
 */
static void
output_genre( fields *f, FILE *outptr, int level )
{
	char *value, *attr, *attrvalue="marcgt";
	int i, n;

	n = fields_num( f );
	for ( i=0; i<n; ++i ) {
		if ( fields_level( f, i ) != level ) continue;
		if ( !fields_match_tag( f, i, "GENRE" ) && !fields_match_tag( f, i, "NGENRE" ) ) continue;
		value = fields_value( f, i, FIELDS_CHRP );
		attr = ( marc_findgenre( value ) == -1 ) ? NULL : "authority";
		output_tag( outptr, lvl2indent(level), "genre", value, TAG_OPENCLOSE, TAG_NEWLINE, attr, attrvalue, NULL );
	}
}
Ejemplo n.º 15
0
void output_tag_contents(Context& ctx, std::string *out, const TreeNode& tag) {
	static int recursion_depth = 0;

	++recursion_depth;

	if (recursion_depth > 64)
		error(ctx, "recursion exceeded limits");

	std::list<TreeNode *>::const_iterator it(tag.mChildren.begin()), itEnd(tag.mChildren.end());
	for(; it!=itEnd; ++it) {
		output_tag(ctx, out, **it);
	}

	--recursion_depth;
}
Ejemplo n.º 16
0
int main(int argc, char **argv) {
	TreeNode::SetSupportsCDATA("p",		true);
	TreeNode::SetSupportsCDATA("h1",		true);
	TreeNode::SetSupportsCDATA("h2",		true);
	TreeNode::SetSupportsCDATA("h3",		true);
	TreeNode::SetSupportsCDATA("h4",		true);
	TreeNode::SetSupportsCDATA("h5",		true);
	TreeNode::SetSupportsCDATA("h6",		true);
	TreeNode::SetSupportsCDATA("td",		true);
	TreeNode::SetSupportsCDATA("th",		true);
	TreeNode::SetSupportsCDATA("li",		true);
	TreeNode::SetSupportsCDATA("style",	true);
	TreeNode::SetSupportsCDATA("script",	true);
	TreeNode::SetSupportsCDATA("title",	true);
	TreeNode::SetSupportsCDATA("div",		true);
	TreeNode::SetSupportsCDATA("dt",		true);
	TreeNode::SetSupportsCDATA("dd",		true);

	TreeDocument doc;
	TreeParser parser(&doc);

	parser.ParseFile(argv[1]);

//	dump_parse_tree(*doc.mpRoot);

	Context ctx;

	ctx.mpDocument = &doc;

	output_tag(ctx, NULL, *doc.mpRoot);

	// copy files

	tFileCopies::const_iterator it(g_fileCopies.begin()), itEnd(g_fileCopies.end());

	for(; it!=itEnd; ++it) {
		const tFileCopies::value_type& info = *it;

		copy_file(info.first, info.second);
	}

	printf("No errors.\n");
	return 0;
}
Ejemplo n.º 17
0
static void
output_name( FILE *outptr, char *p, int level )
{
	newstr family, part, suffix;
	int n=0;

	newstrs_init( &family, &part, &suffix, NULL );

	while ( *p && *p!='|' ) newstr_addchar( &family, *p++ );
	if ( *p=='|' ) p++;

	while ( *p ) {
		while ( *p && *p!='|' ) newstr_addchar( &part, *p++ );
		/* truncate periods from "A. B. Jones" names */
		if ( part.len ) {
			if ( part.len==2 && part.data[1]=='.' ) {
				part.len=1;
				part.data[1]='\0';
			}
			if ( n==0 )
				output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
			output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", part.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "given", NULL );
			n++;
		}
		if ( *p=='|' ) {
			p++;
			if ( *p=='|' ) {
				p++;
				while ( *p && *p!='|' ) newstr_addchar( &suffix, *p++ );
			}
			newstr_empty( &part );
		}
	}

	if ( family.len ) {
		if ( n==0 )
			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", family.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "family", NULL );
		n++;
	}

	if ( suffix.len ) {
		if ( n==0 )
			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", suffix.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "suffix", NULL );
	}

	newstrs_free( &part, &family, &suffix, NULL );
}
Ejemplo n.º 18
0
void output_special_tag(Context& ctx, std::string *out, const TreeNode& tag) {
	if (tag.mName == "lina:fireball") {
		const TreeAttribute *a1 = tag.Attrib("src");
		const TreeAttribute *a2 = tag.Attrib("dst");

		if (!a1 || !a2)
			error(ctx, "<lina:fireball> requires SRC and DST attributes");

		g_fileCopies[a2->mValue] = a1->mValue;
	} else if (tag.mName == "lina:write") {
		const TreeAttribute *a = tag.Attrib("file");

		if (!a)
			error(ctx, "<lina:write> must specify FILE");

		std::string s;

		std::list<TreeNode *> tempStack;
		ctx.construction_stack.swap(tempStack);
		int cdataCount = ctx.cdata_count;
		int preCount = ctx.pre_count;
		ctx.cdata_count = 0;
		ctx.pre_count = 0;
		bool bHoldingSpace = ctx.holding_space;
		bool bEatNextSpace = ctx.eat_next_space;
		ctx.holding_space = false;
		ctx.eat_next_space = true;
		output_tag_contents(ctx, &s, tag);
		ctx.holding_space = bHoldingSpace;
		ctx.eat_next_space = bEatNextSpace;
		ctx.pre_count = cdataCount;
		ctx.cdata_count = preCount;
		ctx.construction_stack.swap(tempStack);

		std::string filename(create_output_filename(a->mValue));

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create \"%s\"", a->mValue.c_str());
		fwrite(s.data(), s.length(), 1, f);
		fclose(f);

		printf("created file: %s\n", a->mValue.c_str());
	} else if (tag.mName == "lina:body") {

//		printf("outputting:\n");
//		dump_parse_tree(*ctx.invocation_stack.back(), 4);

		output_tag_contents(ctx, out, *ctx.invocation_stack.back());
	} else if (tag.mName == "lina:tag") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:tag> must have NAME attribute");

		ctx.construction_stack.push_back(ctx.mpDocument->AllocNode());
		TreeNode *new_tag = ctx.construction_stack.back();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mName = a->mValue;
		new_tag->mbIsText = false;
		new_tag->mbIsControl = false;

		// compatibility
		if (!new_tag->mName.compare(0, 2, "w:"))
			new_tag->mName.replace(0, 2, "lina:");

		output_tag_contents(ctx, NULL, tag);

		ctx.construction_stack.pop_back();
		output_tag(ctx, out, *new_tag);
	} else if (tag.mName == "lina:arg") {
		if (!out && ctx.construction_stack.empty())
			error(ctx, "<lina:arg> can only be used in an output context");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:arg> can only be used during macro expansion");

		std::list<const TreeNode *>::const_iterator it(ctx.invocation_stack.end());
		--it;

		int levels = 1;
		const char *name = a->mValue.c_str();
		while(*name == '^') {
			++levels;
			++name;

			if (it == ctx.invocation_stack.begin())
				error(ctx, "Number of up-scope markers in name exceeds macro nesting level");

			--it;
		}

		const TreeNode& macrotag = **it;
		const TreeAttribute *a2 = macrotag.Attrib(name);
		if (!a2)
			error(ctx, "macro invocation <%s> does not have an attribute \"%s\"", macrotag.mName.c_str(), name);

		if (out) {
			*out += a2->mValue;

			ctx.eat_next_space = false;
			ctx.holding_space = false;
		} else {
			TreeNode *t = ctx.mpDocument->AllocNode();

			t->mpLocation = tag.mpLocation;
			t->mLineno = tag.mLineno;
			t->mbIsControl = false;
			t->mbIsText = true;
			t->mName = a2->mValue;

			ctx.construction_stack.back()->mChildren.push_back(t);
		}
	} else if (tag.mName == "lina:if-arg") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-arg> can only be used during macro expansion");

		const TreeNode& macrotag = *ctx.invocation_stack.back();
		const TreeAttribute *a2 = macrotag.Attrib(a->mValue);
		if (a2)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:if-not-arg") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-not-arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-not-arg> can only be used during macro expansion");

		const TreeNode& macrotag = *ctx.invocation_stack.back();
		const TreeAttribute *a2 = macrotag.Attrib(a->mValue);
		if (!a2)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:attrib") {
		if (ctx.construction_stack.empty())
			error(ctx, "<lina:attrib> can only be used in a <lina:tag> element");

		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:attrib> must have NAME attribute");

		std::string s;
		std::list<TreeNode *> tempStack;
		ctx.construction_stack.swap(tempStack);
		++ctx.cdata_count;
		++ctx.pre_count;
		bool bHoldingSpace = ctx.holding_space;
		bool bEatNextSpace = ctx.eat_next_space;
		ctx.holding_space = false;
		ctx.eat_next_space = true;
		output_tag_contents(ctx, &s, tag);
		ctx.holding_space = bHoldingSpace;
		ctx.eat_next_space = bEatNextSpace;
		--ctx.pre_count;
		--ctx.cdata_count;
		ctx.construction_stack.swap(tempStack);

		TreeNode *t = ctx.construction_stack.back();
		TreeAttribute new_att;
		if (tag.Attrib("novalue")) {
			new_att.mbNoValue = true;
		} else {
			new_att.mbNoValue = false;
			new_att.mValue = s;
		}
		new_att.mName = a->mValue;
		t->mAttribs.push_back(new_att);
	} else if (tag.mName == "lina:pull") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:pull> can only be used during macro expansion");

		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:pull> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		
		if (!t)
			error(ctx, "cannot find tag <%s> referenced in <lina:pull>", a->mValue.c_str());

		output_tag_contents(ctx, out, *t);		
	} else if (tag.mName == "lina:for-each") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:for-each> must have NAME attribute");
		
		std::string node_name;
		const TreeNode *parent;
		if (ctx.invocation_stack.empty()) {
			if (!a->mValue.empty() && a->mValue[0] == '/')
				parent = ctx.mpDocument->mpRoot->ResolvePath(a->mValue.substr(1), node_name);
			else
				error(ctx, "path must be absolute if not in macro context");
		} else {
			std::list<const TreeNode *>::reverse_iterator it(ctx.invocation_stack.rbegin()), itEnd(ctx.invocation_stack.rend());
			
			for(; it!=itEnd; ++it) {
				parent = (*it)->ResolvePath(a->mValue, node_name);
				if(parent)
					break;
				if (!a->mValue.empty() && a->mValue[0] == '/')
					break;
			}
		}

		if (!parent)
			error(ctx, "cannot resolve path \"%s\"", a->mValue.c_str());

		std::list<TreeNode *>::const_iterator it2(parent->mChildren.begin()), it2End(parent->mChildren.end());

		ctx.invocation_stack.push_back(NULL);
		for(; it2!=it2End; ++it2) {
			if ((*it2)->mName == node_name) {
				ctx.invocation_stack.back() = *it2;
				output_tag_contents(ctx, out, tag);
			}
		}
		ctx.invocation_stack.pop_back();
	} else if (tag.mName == "lina:apply") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:apply> must have NAME attribute");

		std::map<std::string, TreeNode *>::const_iterator it(ctx.mpDocument->mMacros.find(a->mValue));

		if (it == ctx.mpDocument->mMacros.end())
			error(ctx, "macro \"%s\" undeclared", a->mValue.c_str());
		
		std::list<TreeNode *>::const_iterator it2(tag.mChildren.begin()), it2End(tag.mChildren.end());

		ctx.invocation_stack.push_back(NULL);
		for(; it2!=it2End; ++it2) {
			if (!(*it2)->mbIsText) {
				ctx.invocation_stack.back() = *it2;
				output_tag_contents(ctx, out, *(*it).second);
			}
		}
		ctx.invocation_stack.pop_back();
	} else if (tag.mName == "lina:if-present") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-present> can only be used during macro expansion");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-present> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		if (t)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:if-not-present") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-not-present> can only be used during macro expansion");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-not-present> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		if (!t)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:pre") {
		++ctx.pre_count;
		++ctx.cdata_count;
		if (!out)
			output_standard_tag(ctx, out, tag);
		else {
			output_tag_contents(ctx, out, tag);
		}
		--ctx.cdata_count;
		--ctx.pre_count;
	} else if (tag.mName == "lina:cdata") {
		++ctx.cdata_count;
		if (!out)
			output_standard_tag(ctx, out, tag);
		else
			output_tag_contents(ctx, out, tag);
		--ctx.cdata_count;
	} else if (tag.mName == "lina:delay") {
		std::list<TreeNode *>::const_iterator it(tag.mChildren.begin()), itEnd(tag.mChildren.end());
		for(; it!=itEnd; ++it) {
			output_standard_tag(ctx, out, **it);
		}
	} else if (tag.mName == "lina:dump-stack") {
		dump_stack(ctx);
	} else if (tag.mName == "lina:replace") {
		const TreeAttribute *a = tag.Attrib("from");
		if (!a || a->mbNoValue)
			error(ctx, "<lina:replace> must have FROM attribute");
		const TreeAttribute *a2 = tag.Attrib("to");
		if (!a2 || a2->mbNoValue)
			error(ctx, "<lina:replace> must have TO attribute");

		const std::string& x = a->mValue;
		const std::string& y = a2->mValue;

		std::string s, t;
		std::string::size_type i = 0;

		output_tag_contents(ctx, &s, tag);

		for(;;) {
			std::string::size_type j = s.find(x, i);
			if (j != i)
				t.append(s, i, j-i);
			if (j == std::string::npos)
				break;
			t.append(y);
			i = j + x.size();
		}

		TreeNode *new_tag = ctx.mpDocument->AllocNode();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mbIsText = true;
		new_tag->mbIsControl = false;
		new_tag->mName = t;

		output_tag(ctx, out, *new_tag);
	} else if (tag.mName == "lina:set-option") {
		const TreeAttribute *a_name = tag.Attrib("name");
		if (!a_name)
			error(ctx, "<lina:set-option> must have NAME attribute");

		if (a_name->mValue == "link-truncate") {
			const TreeAttribute *a_val = tag.Attrib("baseurl");
			if (!a_val || a_val->mbNoValue)
				error(ctx, "option \"link-truncate\" requires BASEURL attribute");

			bool bTruncate = !tag.Attrib("notruncate");

			g_truncateURLs.push_back(std::make_pair(a_val->mValue, bTruncate));
		} else if (a_name->mValue == "output-dir") {
			const TreeAttribute *a_val = tag.Attrib("target");
			if (!a_val || a_val->mbNoValue)
				error(ctx, "option \"output-dir\" requires TARGET attribute");

			g_outputDir = a_val->mValue;
		} else if (a_name->mValue == "tag-info") {
			const TreeAttribute *a_tagname = tag.Attrib("tag");
			if (!a_tagname || a_tagname->mbNoValue)
				error(ctx, "option \"tag-info\" requires TAG attribute");

			const TreeAttribute *a_cdata = tag.Attrib("cdata");

			if (!a_cdata || a_cdata->mbNoValue)
				error(ctx, "option \"tag-info\" requires CDATA attribute");

			TreeNode::SetSupportsCDATA(a_tagname->mValue, is_true(a_cdata->mValue));
		} else
			error(ctx, "option \"%s\" unknown\n", a_name->mValue.c_str());

	} else if (tag.mName == "lina:data") {
		// do nothing
	} else if (tag.mName == "lina:source") {
		if (out) {
			std::list<TreeNode *>::const_iterator itBegin(tag.mChildren.begin()), it(itBegin), itEnd(tag.mChildren.end());
			for(; it!=itEnd; ++it) {
				output_source_tags(ctx, out, **it);
			}
		}
	} else if (tag.mName == "lina:htmlhelp-toc") {
		const TreeAttribute *a_val = tag.Attrib("file");
		if (!a_val || a_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-toc> requires FILE attribute");

		const std::string filename(create_output_filename(a_val->mValue));

		// build new tag with TOC contents
		ctx.construction_stack.push_back(ctx.mpDocument->AllocNode());
		TreeNode *new_tag = ctx.construction_stack.back();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mName = a_val->mValue;
		new_tag->mbIsText = false;
		new_tag->mbIsControl = false;

		output_tag_contents(ctx, NULL, tag);

		ctx.construction_stack.pop_back();
		output_tag(ctx, out, *new_tag);

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create htmlhelp toc \"%s\"", a_val->mValue.c_str());
		output_toc(f, *new_tag);
		fclose(f);

	} else if (tag.mName == "lina:htmlhelp-project") {
		const TreeAttribute *file_val = tag.Attrib("file");
		if (!file_val || file_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires FILE attribute");

		const TreeAttribute *output_val = tag.Attrib("output");
		if (!output_val || output_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires OUTPUT attribute");

		const TreeAttribute *toc_val = tag.Attrib("toc");
		if (!toc_val || toc_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires TOC attribute");

		const TreeAttribute *title_val = tag.Attrib("title");
		if (!title_val || title_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires TITLE attribute");

		const std::string filename(create_output_filename(file_val->mValue));

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create htmlhelp project \"%s\"", file_val->mValue.c_str());
		fprintf(f,
			"[OPTIONS]\n"
			"Auto Index=Yes\n"
			"Compatibility=1.1 or later\n"
			"Compiled file=%s\n"
			"Contents file=%s\n"
			"Default topic=index.html\n"
			"Display compile progress=no\n"
			"Full-text search=Yes\n"
			, output_val->mValue.c_str()
			, toc_val->mValue.c_str()
			);


		const TreeAttribute *fullstop_val = tag.Attrib("fullstop");
		if (fullstop_val && !fullstop_val->mbNoValue)
			fprintf(f, "Full text search stop list file=%s\n", fullstop_val->mValue.c_str());

		fprintf(f,
			"Language=0x0409 English (United States)\n"
			"Title=%s\n"
			"\n"
			"[FILES]\n"
			, title_val->mValue.c_str()
			);

		std::list<std::string>::const_iterator it(g_htmlHelpFiles.begin()), itEnd(g_htmlHelpFiles.end());
		for(; it!=itEnd; ++it) {
			fprintf(f, "%s\n", (*it).c_str());
		}

		fclose(f);		
	} else if (tag.mName == "lina:htmlhelp-addfile") {
		const TreeAttribute *file_val = tag.Attrib("file");
		if (!file_val || file_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-addfile> requires FILE attribute");

		g_htmlHelpFiles.push_back(file_val->mValue);
	} else {
		std::string macroName(tag.mName, 5, std::string::npos);
		std::map<std::string, TreeNode *>::const_iterator it = ctx.mpDocument->mMacros.find(macroName);

		if (it == ctx.mpDocument->mMacros.end())
			error(ctx, "macro <lina:%s> not found", macroName.c_str());

//		dump_stack(ctx);
//		printf("executing macro: %s (%s:%d)\n", tag.mName.c_str(), tag.mLocation->name.c_str(), tag.mLineno);

		ctx.invocation_stack.push_back(&tag);
		output_tag_contents(ctx, out, *(*it).second);
		ctx.invocation_stack.pop_back();

//		printf("exiting macro: %s (%s:%d)\n", tag.mName.c_str(), tag.mLocation->name.c_str(), tag.mLineno);
	}
}
Ejemplo n.º 19
0
static void
try_output_partfooter( FILE *outptr, int wrote_header, int level )
{
	if ( wrote_header )
		output_tag( outptr, lvl2indent(level), "part", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
}
Ejemplo n.º 20
0
static void
output_names( fields *f, FILE *outptr, int level )
{
	convert   names[] = {
	  { "author",                              "AUTHOR",          0, MARC_AUTHORITY },
	  { "editor",                              "EDITOR",          0, MARC_AUTHORITY },
	  { "annotator",                           "ANNOTATOR",       0, MARC_AUTHORITY },
	  { "artist",                              "ARTIST",          0, MARC_AUTHORITY },
	  { "author",                              "2ND_AUTHOR",      0, MARC_AUTHORITY },
	  { "author",                              "3RD_AUTHOR",      0, MARC_AUTHORITY },
	  { "author",                              "SUB_AUTHOR",      0, MARC_AUTHORITY },
	  { "author",                              "COMMITTEE",       0, MARC_AUTHORITY },
	  { "author",                              "COURT",           0, MARC_AUTHORITY },
	  { "author",                              "LEGISLATIVEBODY", 0, MARC_AUTHORITY },
	  { "author of afterword, colophon, etc.", "AFTERAUTHOR",     0, MARC_AUTHORITY },
	  { "author of introduction, etc.",        "INTROAUTHOR",     0, MARC_AUTHORITY },
	  { "cartographer",                        "CARTOGRAPHER",    0, MARC_AUTHORITY },
	  { "collaborator",                        "COLLABORATOR",    0, MARC_AUTHORITY },
	  { "commentator",                         "COMMENTATOR",     0, MARC_AUTHORITY },
	  { "compiler",                            "COMPILER",        0, MARC_AUTHORITY },
	  { "degree grantor",                      "DEGREEGRANTOR",   0, MARC_AUTHORITY },
	  { "director",                            "DIRECTOR",        0, MARC_AUTHORITY },
	  { "event",                               "EVENT",           0, NO_AUTHORITY   },
	  { "inventor",                            "INVENTOR",        0, MARC_AUTHORITY },
	  { "organizer of meeting",                "ORGANIZER",       0, MARC_AUTHORITY },
	  { "patent holder",                       "ASSIGNEE",        0, MARC_AUTHORITY },
	  { "performer",                           "PERFORMER",       0, MARC_AUTHORITY },
	  { "producer",                            "PRODUCER",        0, MARC_AUTHORITY },
	  { "recipient",                           "RECIPIENT",       0, MARC_AUTHORITY },
	  { "redactor",                            "REDACTOR",        0, MARC_AUTHORITY },
	  { "reporter",                            "REPORTER",        0, MARC_AUTHORITY },
	  { "sponsor",                             "SPONSOR",         0, MARC_AUTHORITY },
	  { "translator",                          "TRANSLATOR",      0, MARC_AUTHORITY },
	  { "writer",                              "WRITER",          0, MARC_AUTHORITY },
	};
	int i, n, nfields, ntypes = sizeof( names ) / sizeof( convert );
	int f_asis, f_corp, f_conf;
	newstr role;

	newstr_init( &role );
	nfields = fields_num( f );
	for ( n=0; n<ntypes; ++n ) {
		for ( i=0; i<nfields; ++i ) {
			if ( fields_level( f, i )!=level ) continue;
			if ( f->data[i].len==0 ) continue;
			f_asis = f_corp = f_conf = 0;
			newstr_strcpy( &role, f->tag[i].data );
			if ( newstr_findreplace( &role, ":ASIS", "" )) f_asis=1;
			if ( newstr_findreplace( &role, ":CORP", "" )) f_corp=1;
			if ( newstr_findreplace( &role, ":CONF", "" )) f_conf=1;
			if ( strcasecmp( role.data, names[n].internal ) )
				continue;
			if ( f_asis ) {
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
			} else if ( f_corp ) {
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "corporate", NULL );
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
			} else if ( f_conf ) {
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "conference", NULL );
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
			} else {
				output_name(outptr, f->data[i].data, level);
			}
			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
			if ( names[n].code & MARC_AUTHORITY )
				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "authority", "marcrelator", "type", "text", NULL );
			else
				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
			output_tag( outptr, lvl2indent(level),               "name", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
			fields_setused( f, i );
		}
	}
	newstr_free( &role );
}