1023 lines
25 KiB
C
1023 lines
25 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: MixedGen.C /main/10 1996/11/26 12:29:15 cde-hal $
|
|
*
|
|
* (c) Copyright 1996 Digital Equipment Corporation.
|
|
* (c) Copyright 1996 Hewlett-Packard Company.
|
|
* (c) Copyright 1996 International Business Machines Corp.
|
|
* (c) Copyright 1996 Sun Microsystems, Inc.
|
|
* (c) Copyright 1996 Novell, Inc.
|
|
* (c) Copyright 1996 FUJITSU LIMITED.
|
|
* (c) Copyright 1996 Hitachi.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
|
|
#include "dti_excs/Exceptions.hh"
|
|
#include "FlexBuffer.h"
|
|
#include "oliasdb/mmdb.h"
|
|
#include "oliasdb/asciiIn_filters.h"
|
|
#include "DataBase.h"
|
|
#include "BookCaseDB.h"
|
|
#include "StringList.h"
|
|
#include "GraphicsTask.h"
|
|
#include "Handler.h"
|
|
|
|
#include "BTCollectable.h"
|
|
|
|
#include "dti_cc/CC_String.h"
|
|
#include "dti_cc/cc_hdict.h"
|
|
// #include "BT_StrHashDict.h"
|
|
|
|
#define SKIP_CODE -1
|
|
#define NULL_OID "0.0"
|
|
#define NULL_LOCATOR "0"
|
|
|
|
#ifdef FISH_DEBUG
|
|
#include "dbug.h" /* Fred Fish's dbug.h */
|
|
#endif
|
|
|
|
extern void insert_remotelink( hashTable<CC_String,BTCollectable> *, char *,
|
|
size_t, FlexBuffer *);
|
|
static unsigned hash_func(const CC_String &str )
|
|
{
|
|
return( str.hash() );
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
static
|
|
void
|
|
checkTocLink( const char *toc_file_name,
|
|
hashTable<CC_String,int> &linkTab,
|
|
hashTable<CC_String,BTCollectable> &nodeTab )
|
|
{
|
|
int flag = 0;
|
|
|
|
char *ToCFileName = strdup ( toc_file_name );
|
|
|
|
hashTableIterator<CC_String,BTCollectable> nodeit( nodeTab );
|
|
while ( ++nodeit ) {
|
|
|
|
CC_String *key = (CC_String *)nodeit.key();
|
|
BTCollectable *value = (BTCollectable *)nodeit.value();
|
|
|
|
if ( !linkTab.contains( key ) ) {
|
|
flag = 1;
|
|
|
|
const char *file_name = value->filename();
|
|
int line_num = value->linenum();
|
|
|
|
cerr << "(ERROR) Section ID = " << (const char *)*key << endl
|
|
<< " of file = " << file_name << endl
|
|
<< " at line = " << line_num << endl
|
|
<< " does not have a corresponding link with the value = " << (const char *)*key << endl
|
|
<< " from the ToC file = " << ToCFileName << "\n\n";
|
|
|
|
}
|
|
}
|
|
|
|
hashTableIterator<CC_String,int> linkit( linkTab );
|
|
|
|
while ( ++linkit ) {
|
|
CC_String *link = linkit.key();
|
|
int *line_num = linkit.value();
|
|
|
|
if ( !nodeTab.contains( link ) ) {
|
|
flag = 1;
|
|
cerr << "(ERROR) IDREF = " << (const char *)*link << endl
|
|
<< " of ToC file = " << ToCFileName << endl
|
|
<< " at line = " << *line_num << endl
|
|
<< " is pointing to an unavailable node\n\n";
|
|
|
|
}
|
|
}
|
|
|
|
free(ToCFileName);
|
|
|
|
if ( flag ) {
|
|
throw(Unexpected("TOC validation failed\n"));
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
static
|
|
void
|
|
create_node_dict( hashTable<CC_String,BTCollectable> &dict,
|
|
BookCaseDB& db )
|
|
{
|
|
DBTable *nodeMeta = db.table(BookCaseDB::NodeMeta, DB::READ);
|
|
DBCursor cursor(*nodeMeta);
|
|
|
|
const char *bookLocator;
|
|
const char *nodeLocator;
|
|
const char *filename;
|
|
int line_num;
|
|
const char *title;
|
|
const char *stitle;
|
|
const char *style;
|
|
|
|
int throw_exception = 0;
|
|
while(cursor.next(STRING_CODE, &bookLocator,
|
|
STRING_CODE, &nodeLocator,
|
|
STRING_CODE, &filename,
|
|
INTEGER_CODE, &line_num,
|
|
SKIP_CODE, /* TOC num */
|
|
STRING_CODE, &title,
|
|
STRING_CODE, &stitle,
|
|
STRING_CODE, &style,
|
|
NULL)){
|
|
CC_String *key = new CC_String ( nodeLocator );
|
|
BTCollectable *value = new BTCollectable ( filename,line_num,bookLocator );
|
|
|
|
BTCollectable *val = (BTCollectable *)dict.findValue( key );
|
|
if ( !val ) {
|
|
dict.insertKeyAndValue( key, value );
|
|
}
|
|
else {
|
|
|
|
throw_exception = 1;
|
|
cerr << "(ERROR) Duplicate section ID = " << (const char *)*key << endl
|
|
<< " found in file = " << filename << endl
|
|
<< " at line = " << line_num << endl
|
|
<< " is in conflict with " << endl
|
|
<< " section ID = " << (const char *)*key << endl
|
|
<< " found in file = " << val->filename() << endl
|
|
<< " at line = " << val->linenum() << "\n\n";
|
|
|
|
delete key;
|
|
delete value;
|
|
}
|
|
}
|
|
|
|
if ( throw_exception ) {
|
|
throw(Unexpected("Duplicate section IDs are found"));
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static
|
|
void
|
|
node_table( DBCursor *node_meta_cursor,
|
|
const char *this_book,
|
|
hashTable<CC_String, BTCollectable> &this_node_table )
|
|
{
|
|
assert( node_meta_cursor != NULL );
|
|
assert( this_book != NULL );
|
|
|
|
const char *bookLocator;
|
|
const char *nodeLocator;
|
|
const char *file_name;
|
|
int line_num;
|
|
const char *title;
|
|
const char *stitle;
|
|
const char *style;
|
|
|
|
while ( node_meta_cursor->next(STRING_CODE, &bookLocator,
|
|
STRING_CODE, &nodeLocator,
|
|
STRING_CODE, &file_name,
|
|
INTEGER_CODE, &line_num,
|
|
SKIP_CODE, /* TOC num */
|
|
STRING_CODE, &title,
|
|
STRING_CODE, &stitle,
|
|
STRING_CODE, &style,
|
|
NULL)){
|
|
/* this book has changed */
|
|
if ( strcmp( bookLocator, this_book ) != 0 ) {
|
|
node_meta_cursor->undoNext();
|
|
break;
|
|
}
|
|
|
|
CC_String *key = new CC_String( nodeLocator );
|
|
BTCollectable *value = new BTCollectable( file_name,line_num,bookLocator );
|
|
this_node_table.insertKeyAndValue( key, value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
/* MMDB interfaces use char*; I like to use const char *
|
|
* whenever possible
|
|
* Plus, in TOCTask, we write "" to indicate "no locator",
|
|
* but the MMDB code expected "0".
|
|
* so we do the conversion here.
|
|
*
|
|
* Hmmm.... get_oid_2(... "0") doesn't seem to work. I'm going
|
|
* to bypass it and return "0.0" directly.
|
|
*/
|
|
static const char *
|
|
to_oid(info_lib *mmdb, const char *bcname, const char *str)
|
|
{
|
|
const char *ret = NULL_OID;
|
|
|
|
if(*str){
|
|
ret = get_oid_2(mmdb, (char*)bcname, (char*)str);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
static
|
|
void
|
|
locator_table( BookCaseDB& db,
|
|
hashTable<CC_String, BTCollectable> &hd)
|
|
{
|
|
|
|
|
|
DBTable *locTable = db.table(BookCaseDB::Locator, DB::READ);
|
|
|
|
DBCursor cursor(*locTable);
|
|
|
|
const char *locator;
|
|
const char *nodeloc;
|
|
const char *reflabel;
|
|
const char *filename;
|
|
int line_num;
|
|
|
|
int dup_count = 0;
|
|
|
|
while(cursor.next(STRING_CODE, &locator,
|
|
STRING_CODE, &nodeloc,
|
|
STRING_CODE, &reflabel,
|
|
STRING_CODE, &filename,
|
|
INTEGER_CODE, &line_num,
|
|
NULL)){
|
|
|
|
int buflen = strlen(nodeloc) + strlen(reflabel) + 2;
|
|
char *buf = new char[buflen];
|
|
snprintf(buf, buflen, "%s\t%s", nodeloc, reflabel);
|
|
|
|
CC_String *loc_collect = new CC_String( locator );
|
|
BTCollectable *node_collect = new BTCollectable( filename,
|
|
line_num,
|
|
buf );
|
|
|
|
delete[] buf;
|
|
|
|
BTCollectable *val = hd.findValue( loc_collect );
|
|
if ( !val ) {
|
|
hd.insertKeyAndValue( loc_collect, node_collect );
|
|
}
|
|
else {
|
|
|
|
delete loc_collect;
|
|
delete node_collect;
|
|
|
|
dup_count++;
|
|
|
|
|
|
cerr << "(ERROR) Duplicate ID = " << locator << endl
|
|
<< " found in file = " << filename << endl
|
|
<< " at line = " << line_num << endl
|
|
<< " is in conflict with " << endl
|
|
<< " ID = " << locator << endl
|
|
<< " found in file = " << val->filename() << endl
|
|
<< " at line = " << val->linenum() << "\n\n";
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( dup_count ) {
|
|
throw(Unexpected(form("Number of duplicate IDs found = %d\n",
|
|
dup_count)));
|
|
}
|
|
}
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeCCF(BookCaseDB& db,
|
|
info_lib *mmdb,
|
|
const char *bcname )
|
|
{
|
|
|
|
DBTable *bookMeta = db.table(BookCaseDB::BookMeta, DB::READ);
|
|
DBCursor cursor(*bookMeta);
|
|
DBTable *ccf = db.DB::table(DATABASE_STDIO,
|
|
DOC_CODE, BT_NUM_DOC_FIELDS,
|
|
DB::CREATE);
|
|
|
|
const char *bookLocator;
|
|
const char *stitle;
|
|
const char *title;
|
|
int seq_no;
|
|
int tabQty;
|
|
const char **tabLines;
|
|
const char *access;
|
|
|
|
/*
|
|
* First put the global node table into hash dictionary
|
|
*/
|
|
|
|
hashTable<CC_String,BTCollectable> global_node_tab(hash_func);
|
|
create_node_dict( global_node_tab , db); /* throw exception if duplicate
|
|
node locator is found */
|
|
|
|
int exception_flag = 0;
|
|
while(cursor.next(STRING_CODE, &bookLocator,
|
|
STRING_CODE, &stitle,
|
|
STRING_CODE, &title,
|
|
INTEGER_CODE, &seq_no,
|
|
SHORT_LIST_CODE, &tabQty, STRING_CODE, &tabLines,
|
|
STRING_CODE, &access,
|
|
NULL)){
|
|
|
|
StringList heap;
|
|
|
|
/* convert tab to oids in forst tabQty items in heap */
|
|
for(int i = 0; i < tabQty; i++){
|
|
|
|
char *t = (char *)tabLines[i];
|
|
|
|
const char *name = strtok( t, "\t" );
|
|
const char *loc = strtok( NULL, "\t");
|
|
const char *line = strtok( NULL, "\t");
|
|
const char *file_name = strtok( NULL, "\t");
|
|
|
|
int nameLen = strlen( name );
|
|
|
|
/*
|
|
* First check if the tab link is resolved
|
|
*/
|
|
|
|
CC_String key ( loc );
|
|
|
|
BTCollectable *tab_link = (BTCollectable *)global_node_tab.
|
|
findValue( &key );
|
|
|
|
|
|
if ( !tab_link ) {
|
|
cerr << "(ERROR) Tab ID = " << loc << endl
|
|
<< " of book = " << title << endl
|
|
<< " specified in file = " << file_name << endl
|
|
<< " at line = " << line << endl
|
|
<< " is not pointing to any section ID found in the book\n\n";
|
|
exception_flag = 1;
|
|
}
|
|
else {
|
|
/*
|
|
* see if it is a node locator within the same book
|
|
*/
|
|
if ( strcmp( tab_link->get_value(), bookLocator )) {
|
|
cerr << "(ERROR) Tab ID = " << loc << endl
|
|
<< " of book = " << title << endl
|
|
<< " specified in file = " << file_name << endl
|
|
<< " at line = " << line << endl
|
|
<< " is not pointing to any section ID found in the book\n\n";
|
|
|
|
exception_flag = 1;
|
|
}
|
|
}
|
|
|
|
// if exception_flag is set, calling to_oid will throw exception
|
|
// It will just loop through all the tabs, and report all the bad ones
|
|
if ( !exception_flag ) {
|
|
const char *tabOID = to_oid(mmdb, bcname, loc);
|
|
int resultlen = nameLen + 1 + strlen(tabOID) + 1;
|
|
char *result = new char[resultlen];
|
|
snprintf(result, resultlen, "%s\t%s", name, tabOID );
|
|
heap.add(result);
|
|
}
|
|
}
|
|
|
|
if ( !exception_flag ) {
|
|
|
|
const char *bookOID = heap.append(to_oid(mmdb, bcname, bookLocator));
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("CCF", ("Load Book: O:%s `%s'\n", bookOID, title));
|
|
#endif
|
|
|
|
ccf->insert(OID_CODE, bookOID,
|
|
STRING_CODE, stitle,
|
|
STRING_CODE, title,
|
|
INTEGER_CODE, seq_no,
|
|
SHORT_LIST_CODE, tabQty, STRING_CODE, heap.array(),
|
|
STRING_CODE, access,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
if ( exception_flag ) {
|
|
throw(Unexpected("Tab validation failed"));
|
|
}
|
|
|
|
delete ccf;
|
|
global_node_tab.clearAndDestroy();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeTOC(BookCaseDB &db,
|
|
info_lib *mmdb,
|
|
const char *bcname,
|
|
const char *thisBook,
|
|
DBCursor &toc_cursor )
|
|
{
|
|
DBTable *out = db.DB::table(DATABASE_STDIO,
|
|
TOC_CODE, NUM_TOC_FIELDS,
|
|
DB::CREATE);
|
|
const char *aBook;
|
|
const char *nodeLoc;
|
|
const char *parent;
|
|
int childQty;
|
|
char **children;
|
|
int treeSize;
|
|
|
|
while(toc_cursor.next(STRING_CODE, &aBook,
|
|
STRING_CODE, &nodeLoc,
|
|
STRING_CODE, &parent,
|
|
SHORT_LIST_CODE, &childQty, STRING_CODE, &children,
|
|
INTEGER_CODE, &treeSize,
|
|
NULL)){
|
|
StringList heap;
|
|
|
|
if(strcmp(aBook, thisBook) != 0){ /* book id has changed! We're done... */
|
|
toc_cursor.undoNext();
|
|
break;
|
|
}
|
|
|
|
for(int i = 0; i < childQty; i++){
|
|
heap.append(to_oid(mmdb, bcname, children[i]));
|
|
}
|
|
|
|
const char *nodeOID = heap.append(to_oid(mmdb, bcname, nodeLoc));
|
|
const char *parentOID = heap.append(to_oid(mmdb, bcname, parent));
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("TOC", ("TOC Entry: O:%s treesize: %d\n", nodeOID, treeSize));
|
|
#endif
|
|
|
|
out->insert(OID_CODE, nodeOID,
|
|
OID_CODE, parentOID,
|
|
INTEGER_CODE, treeSize,
|
|
/* first childQty strings in heap are oids for children */
|
|
OID_LIST_CODE, childQty, heap.array(),
|
|
NULL);
|
|
}
|
|
|
|
delete out;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeDLP(BookCaseDB &db, info_lib *mmdb,
|
|
const char *bcname,
|
|
const char *thisBook,
|
|
DBCursor &dlp_cursor,
|
|
hashTable<CC_String,BTCollectable> &node_tab)
|
|
{
|
|
DBTable *out = db.DB::table(DATABASE_STDIO,
|
|
DLP_CODE, 1,
|
|
DB::CREATE);
|
|
|
|
const char *aBook;
|
|
const char *nodeLoc;
|
|
int line_num;
|
|
const char *toc_file_name;
|
|
|
|
hashTable<CC_String, int> link_table(hash_func);
|
|
|
|
int record_pos = dlp_cursor.tell();
|
|
|
|
// create the link table
|
|
while(dlp_cursor.next(STRING_CODE, &aBook,
|
|
STRING_CODE, &nodeLoc,
|
|
INTEGER_CODE, &line_num,
|
|
STRING_CODE, &toc_file_name,
|
|
NULL)){
|
|
|
|
if(strcmp(aBook, thisBook) != 0){ /* book id has changed! We're done... */
|
|
dlp_cursor.undoNext();
|
|
break;
|
|
}
|
|
|
|
CC_String *key = new CC_String ( nodeLoc );
|
|
link_table.insertKeyAndValue( key, new int(line_num) );
|
|
|
|
#ifdef FISH_DEBUG
|
|
// DBUG_PRINT("DLP", ("DLP Entry: O:%s\n", nodeOID));
|
|
#endif
|
|
}
|
|
|
|
checkTocLink( toc_file_name, link_table, node_tab ); /* throw exception if
|
|
unresolved TOC links
|
|
are found */
|
|
link_table.clearAndDestroy();
|
|
|
|
dlp_cursor.seekToRec( record_pos );
|
|
out->start_list();
|
|
while ( dlp_cursor.next( STRING_CODE, &aBook,
|
|
STRING_CODE, &nodeLoc,
|
|
INTEGER_CODE, &line_num,
|
|
STRING_CODE, &toc_file_name,
|
|
NULL)) {
|
|
|
|
if(strcmp(aBook, thisBook) != 0){ /* book id has changed! We're done... */
|
|
dlp_cursor.undoNext();
|
|
break;
|
|
}
|
|
const char *nodeOID = to_oid(mmdb, bcname, nodeLoc);
|
|
out->insert_untagged(OID_CODE, nodeOID,
|
|
NULL);
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("DLP", ("DLP Entry: O:%s\n", nodeOID));
|
|
#endif
|
|
}
|
|
|
|
out->end_list();
|
|
|
|
/* exception thrown in this if failed */
|
|
delete out;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
// Parsing functions for LAST indicator determination
|
|
//------------------------------------------------------------
|
|
char *
|
|
getGI( char * bufptr )
|
|
{
|
|
char* cptr;
|
|
for (cptr = bufptr; *cptr != '>'; cptr++) {
|
|
}
|
|
*cptr = '\0';
|
|
char * retval = strdup(bufptr);
|
|
*cptr = '>';
|
|
return(retval);
|
|
}
|
|
|
|
char *
|
|
getIndicator( char * bufptr )
|
|
{
|
|
char *iptr = bufptr;
|
|
// Find the end of attributes, assuming that every start tag now has
|
|
// attributes because of the last indicator at least.
|
|
while ((*iptr != '<') ||
|
|
(*(iptr+1) != '/') ||
|
|
(*(iptr+2) != '#') ||
|
|
(*(iptr+3) != '>')) {
|
|
iptr++;
|
|
}
|
|
// Work back to the indicator value (subtract "</#LAST>" and 1 for the
|
|
// digit)
|
|
iptr = iptr - 9;
|
|
return(iptr);
|
|
}
|
|
|
|
void
|
|
lookahead( char * bufptr, char * currentgi, char * indpos)
|
|
{
|
|
char * laptr = bufptr;
|
|
while (*laptr != '<') {
|
|
laptr++;
|
|
}
|
|
laptr++;
|
|
if (*laptr == '/') {
|
|
// end tag ahead so the current indicator must be changed to say last
|
|
// on level.
|
|
*indpos = '2'; // LASTONLEVEL
|
|
} else {
|
|
// get the startag gi and compare it against the one passed in
|
|
char * nextgi = getGI(laptr);
|
|
if (strcmp(currentgi, nextgi) != 0) {
|
|
// next start tag is different, so the current GI is the last sibling
|
|
*indpos = '1'; // LASTSIBLING
|
|
}
|
|
// otherwise the next start tag is the same as the current one, so no
|
|
// change to the indicator is needed.
|
|
free(nextgi);
|
|
}
|
|
return;
|
|
}
|
|
|
|
char *
|
|
parse4last( char * bufptr )
|
|
{
|
|
char
|
|
*startname,
|
|
*indicator;
|
|
|
|
while (*bufptr != 0) {
|
|
if (*bufptr == '<') {
|
|
// TAG
|
|
bufptr++;
|
|
if (*bufptr != '/') {
|
|
// START TAG
|
|
startname = getGI(bufptr);
|
|
bufptr = bufptr + strlen(startname);
|
|
indicator = getIndicator(bufptr);
|
|
// move buffer pointer past the end of the attributes. Assuming
|
|
// that indicator is pointing at the character position where the
|
|
// value is stored we need to move past it and the characters
|
|
// "</#LAST></#>"
|
|
bufptr = indicator + 13;
|
|
// parse the content of this tag past its end tag and when it
|
|
// returns get to the end of where that parse got to.
|
|
bufptr = parse4last( bufptr );
|
|
// Handle the end tag
|
|
if (*bufptr == 0) {
|
|
// end of the buffer, so it is automatically last...
|
|
*indicator = '2'; // LASTONLEVEL
|
|
} else {
|
|
lookahead(bufptr, startname, indicator);
|
|
}
|
|
free(startname);
|
|
} else {
|
|
// END TAG
|
|
for ( ; *bufptr != '>'; bufptr++) {
|
|
// Just move the pointer past the tag name.
|
|
}
|
|
bufptr++; // Get past the '>'
|
|
return(bufptr);
|
|
}
|
|
} else {
|
|
// Data
|
|
bufptr++;
|
|
}
|
|
}
|
|
return(bufptr);
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeSGML(BookCaseDB &db,
|
|
const char *thisBook,
|
|
DBCursor &sgml_cursor,
|
|
hashTable<CC_String,BTCollectable> &hd)
|
|
{
|
|
DBTable *out = db.DB::table(DATABASE_STDIO,
|
|
SGML_CONTENT_CODE, 2,
|
|
DB::CREATE);
|
|
|
|
const char *aBook;
|
|
const char *nodeLoc;
|
|
size_t dataLen;
|
|
const char *data;
|
|
char *bufptr; // Walk through SGML data stream and update LAST fields
|
|
|
|
while(sgml_cursor.next(STRING_CODE, &aBook,
|
|
STRING_CODE, &nodeLoc,
|
|
-STRING_CODE, &data, &dataLen,
|
|
NULL)){
|
|
|
|
if(strcmp(aBook, thisBook) != 0){ /* book id has changed! We're done... */
|
|
sgml_cursor.undoNext();
|
|
break;
|
|
}
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("SGML", ("SGML data for: ::%s `%.40s...' \n",
|
|
nodeLoc, data));
|
|
#endif
|
|
|
|
FlexBuffer new_node_buffer;
|
|
|
|
bufptr = (char *) data;
|
|
parse4last( bufptr );
|
|
|
|
insert_remotelink( &hd, (char *)data, dataLen, &new_node_buffer);
|
|
|
|
out->insert_untagged(STRING_CODE, nodeLoc,
|
|
-STRING_CODE,
|
|
new_node_buffer.GetBuffer(),
|
|
(size_t)new_node_buffer.GetSize(),
|
|
NULL);
|
|
}
|
|
|
|
delete out;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeGraphics(BookCaseDB &db, const char *thisBook, DBCursor &gr_cursor,
|
|
int compressed, char *comp_agent)
|
|
{
|
|
DBTable *out = db.DB::table(DATABASE_STDIO,
|
|
GRAPHIC_CODE, BT_NUM_GRAPHIC_FIELDS,
|
|
DB::CREATE);
|
|
|
|
const char *aBook;
|
|
const char *gid;
|
|
const char *name;
|
|
const char *version;
|
|
const char *typeInfo;
|
|
const char *data;
|
|
size_t len;
|
|
const char *title;
|
|
|
|
while(gr_cursor.next(STRING_CODE, &aBook,
|
|
STRING_CODE, &gid,
|
|
STRING_CODE, &name,
|
|
STRING_CODE, &version,
|
|
STRING_CODE, &typeInfo,
|
|
-STRING_CODE, &data, &len,
|
|
STRING_CODE, &title,
|
|
NULL)){
|
|
|
|
|
|
if(strcmp(aBook, thisBook) != 0){ /* book id has changed! We're done... */
|
|
gr_cursor.undoNext();
|
|
break;
|
|
}
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("Graphics", ("Graphics data for: ::%s `%.40s...' \n",
|
|
gid, data));
|
|
#endif
|
|
|
|
if ( typeInfo[0] - '0' == GR_TYPE_POSTSCRIPT &&
|
|
compressed ) {
|
|
|
|
out->insert(STRING_CODE, gid,
|
|
STRING_CODE, name,
|
|
STRING_CODE, version,
|
|
STRING_CODE, typeInfo,
|
|
-COMPRESSED_STRING_CODE, comp_agent, data, len,
|
|
STRING_CODE, title,
|
|
NULL);
|
|
}
|
|
else {
|
|
out->insert(STRING_CODE, gid,
|
|
STRING_CODE, name,
|
|
STRING_CODE, version,
|
|
STRING_CODE, typeInfo,
|
|
-STRING_CODE, data, len,
|
|
STRING_CODE, title,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
delete out;
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeBooks(BookCaseDB& db,
|
|
info_lib *mmdb,
|
|
const char *bcname,
|
|
DBCursor *node_meta_cursor,
|
|
int compressed,
|
|
char *comp_agent,
|
|
hashTable<CC_String,BTCollectable> &hd)
|
|
{
|
|
DBTable *bookMeta = db.table(BookCaseDB::BookMeta, DB::READ);
|
|
DBCursor BookCursor(*bookMeta);
|
|
|
|
DBTable *toc = db.table(BookCaseDB::TOCTree, DB::READ);
|
|
DBCursor TocCursor(*toc);
|
|
|
|
DBTable *dlp = db.table(BookCaseDB::TOCPath, DB::READ);
|
|
DBCursor DlpCursor(*dlp);
|
|
|
|
DBTable *sgml = db.table(BookCaseDB::NodeSGML, DB::READ);
|
|
DBCursor SgmlCursor(*sgml);
|
|
|
|
DBCursor *GraphicsCursorPtr = NULL;
|
|
|
|
int process_graphics = 1;
|
|
mtry {
|
|
DBTable *graphics = db.table(BookCaseDB::Graphics, DB::READ);
|
|
GraphicsCursorPtr = new DBCursor( *graphics );
|
|
}
|
|
mcatch (PosixError&, p){
|
|
/* error opening graphics stuff... skip graphics */
|
|
|
|
process_graphics = 0;
|
|
}end_try
|
|
|
|
const char *bookLocator;
|
|
int tabQty;
|
|
char **tabLines;
|
|
|
|
while(BookCursor.next(STRING_CODE, &bookLocator,
|
|
SKIP_CODE,
|
|
SKIP_CODE,
|
|
SKIP_CODE,
|
|
/* @# skipping shortlists not suported yet... */
|
|
SHORT_LIST_CODE, &tabQty, STRING_CODE, &tabLines,
|
|
SKIP_CODE, /* skip access data */
|
|
NULL)){
|
|
|
|
hashTable<CC_String,BTCollectable> node_tab(hash_func);
|
|
node_table( node_meta_cursor, bookLocator, node_tab);
|
|
|
|
writeDLP(db, mmdb, bcname, bookLocator, DlpCursor, node_tab);
|
|
writeTOC(db, mmdb, bcname, bookLocator, TocCursor);
|
|
writeSGML(db, bookLocator, SgmlCursor, hd);
|
|
|
|
if ( process_graphics ) {
|
|
writeGraphics(db, bookLocator, *GraphicsCursorPtr,
|
|
compressed, comp_agent );
|
|
}
|
|
|
|
node_tab.clearAndDestroy();
|
|
|
|
}
|
|
|
|
if ( process_graphics ) { delete GraphicsCursorPtr; }
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
writeLCF(BookCaseDB& db, info_lib *mmdb,
|
|
const char *bcname,
|
|
hashTable<CC_String,BTCollectable> &hd)
|
|
{
|
|
|
|
DBTable *out = db.DB::table(DATABASE_STDIO,
|
|
LOCATOR_CODE, BT_NUM_LOCATOR_FIELDS,
|
|
DB::CREATE);
|
|
|
|
hashTableIterator<CC_String,BTCollectable> loc_it( hd );
|
|
|
|
while ( ++loc_it ) {
|
|
CC_String *locator_str = ( CC_String *)loc_it.key();
|
|
const char *locator = (const char *)*locator_str;
|
|
|
|
BTCollectable *loc_val = ( BTCollectable *)loc_it.value();
|
|
const char *opaque, *nodeloc;
|
|
char* reflabel;
|
|
nodeloc = opaque = (const char *)loc_val->get_value();
|
|
reflabel = strchr((char*)opaque, '\t');
|
|
*reflabel++ = 0;
|
|
|
|
const char *nodeOID = to_oid(mmdb, bcname, nodeloc);
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PRINT("LCF", ("LCF entry: L:%s->O:%s\n",
|
|
locator, nodeOID));
|
|
#endif
|
|
out->insert(STRING_CODE, locator,
|
|
OID_CODE, nodeOID,
|
|
STRING_CODE, reflabel,
|
|
NULL);
|
|
|
|
}
|
|
|
|
delete out;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
split_path(char * path, const char*& dir, const char*& name)
|
|
{
|
|
char *p = strrchr(path, '/');
|
|
|
|
if(p){
|
|
*p = 0;
|
|
dir = path;
|
|
name = p+1;
|
|
}else{
|
|
dir = name = path;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------
|
|
static void
|
|
usage(const char *progname)
|
|
{
|
|
fprintf(stderr,
|
|
"usage: %s [-compressed] <tmpBCdir> <infobasedir>\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
INIT_EXCEPTIONS();
|
|
|
|
set_new_handler ( FreeStoreException );
|
|
|
|
int ret = 1;
|
|
const char *progname = argv[0];
|
|
int compressed = 0;
|
|
|
|
#ifdef FISH_DEBUG
|
|
DBUG_PROCESS(argv[0]);
|
|
if(getenv("FISH_DBUG")) DBUG_PUSH(getenv("FISH_DBUG"));
|
|
#endif
|
|
|
|
argv++;
|
|
argc--;
|
|
|
|
while(argc > 0 && argv[0][0] == '-'){
|
|
const char *opt = argv[0];
|
|
argv++;
|
|
argc--;
|
|
|
|
if(strcmp(opt, "-compressed") == 0){
|
|
compressed = 1;
|
|
}
|
|
else{
|
|
usage(progname);
|
|
}
|
|
}
|
|
|
|
if(argc == 2){
|
|
char *bookcaseDir = argv[0];
|
|
char *infobaseDir = argv[1];
|
|
|
|
mtry{
|
|
BookCaseDB db(bookcaseDir);
|
|
|
|
const char *infolibDir;
|
|
const char *bcname;
|
|
split_path(infobaseDir, infolibDir, bcname);
|
|
|
|
OLIAS_DB mmdb_handle;
|
|
info_lib *mmdb = mmdb_handle.openInfoLib(infolibDir, bcname);
|
|
|
|
// 30 will be enough for now
|
|
#define COMPRESSED_AGENT_SIZE 30
|
|
|
|
char comp_agent[ COMPRESSED_AGENT_SIZE ];
|
|
|
|
if ( compressed ) {
|
|
for ( int i = 0; i < COMPRESSED_AGENT_SIZE; i++ ) {
|
|
comp_agent[i] = 0;
|
|
}
|
|
|
|
ostringstream str_buf( comp_agent );
|
|
|
|
info_base *bcptr = mmdb->get_info_base(bcname);
|
|
handler *x =
|
|
(bcptr->get_obj_dict()).get_handler(
|
|
form("%s.%s", bcname, "ps.dict"));
|
|
|
|
x->its_oid().asciiOut(str_buf);
|
|
memcpy(comp_agent, str_buf.str().c_str(), COMPRESSED_AGENT_SIZE);
|
|
}
|
|
|
|
hashTable<CC_String, BTCollectable> hd(hash_func);
|
|
locator_table( db, hd); /* throw exception if duplicate
|
|
locator is found */
|
|
|
|
DBTable *nodeMeta = db.table(BookCaseDB::NodeMeta, DB::READ);
|
|
DBCursor node_cursor( *nodeMeta );
|
|
|
|
writeCCF(db, mmdb, bcname);
|
|
writeBooks(db, mmdb, bcname, &node_cursor, compressed, comp_agent, hd);
|
|
writeLCF(db, mmdb, bcname, hd);
|
|
|
|
hd.clearAndDestroy();
|
|
ret = 0;
|
|
|
|
}
|
|
mcatch(PosixError&, pe){
|
|
fprintf(stderr, "%s: error on %s: %s\n",
|
|
progname, bookcaseDir, pe.msg());
|
|
}
|
|
mcatch(Unexpected&, pe) {
|
|
fprintf(stderr, "(ERROR) %s\n\n", pe.msg() );
|
|
exit(1);
|
|
}end_try;
|
|
|
|
}else{
|
|
usage(progname);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|