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 ); }
/* 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 ); }
/* 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 ); } }
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 ); } }
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 ); } }
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 ); }
/* 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 ); } } }
/* 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 ); }
/* 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; }
/* 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 ); }
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" ); }
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 ); } }
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 ); } } }
/* 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 ); } }
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; }
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; }
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 ); }
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); } }
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 ); }
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 ); }